source: titan/titan/skin.h @ 38330

Last change on this file since 38330 was 38330, checked in by obi, 6 years ago

allowed fontsizeadjust = 15 and add tithek fontsizeadjust change

File size: 117.4 KB
Line 
1#ifndef SKIN_H
2#define SKIN_H
3
4void debugscreen(struct skin* node)
5{
6        struct skin* child = NULL;
7
8        if(node != NULL)
9        {
10                printf("screen = %s %p %p %p %p\n", node->name, node, node->prev, node->next, node->child);
11
12                if(node != skin)
13                        child = node->child;
14                else
15                        child = node->next;
16
17                while(child != NULL)
18                {
19                        printf("node = %s %p %p %p \n", child->name, child, child->prev, child->next);
20                        child = child->next;
21                }
22        }
23        else
24                printf("screen = NULL\n");
25}
26
27void* convertfunc(char *value, uint8_t *rettype)
28{
29        *rettype = FUNCTEXT;
30
31        if(ostrcmp("getpicon", value) == 0)
32        {
33                *rettype = FUNCPIC;
34                return &getpicon;
35        }
36
37#ifdef MIPSEL
38        if(ostrcmp("getoledmute", value) == 0)
39        {
40                *rettype = FUNCPICOLED;
41                return &getoledmute;
42        }
43
44        if(ostrcmp("getoledtimeshift", value) == 0)
45        {
46                *rettype = FUNCPICOLED;
47                return &getoledtimeshift;
48        }
49
50        if(ostrcmp("getoledrec", value) == 0)
51        {
52                *rettype = FUNCPICOLED;
53                return &getoledrec;
54        }
55
56        if(ostrcmp("getoledstreaming", value) == 0)
57        {
58                *rettype = FUNCPICOLED;
59                return &getoledstreaming;
60        }
61
62    if(ostrcmp("getoledcrypt", value) == 0)
63        {
64                *rettype = FUNCPICOLED;
65                return &getoledcrypt;
66        }
67
68    if(ostrcmp("getoledchannelaspect", value) == 0)
69        {
70                *rettype = FUNCPICOLED;
71                return &getoledchannelaspect;
72        }
73
74    if(ostrcmp("getoledchannelresolution576", value) == 0)
75            {
76                    *rettype = FUNCPICOLED;
77                    return &getoledchannelresolution576;
78            }
79           
80        if(ostrcmp("getoledchannelresolution720", value) == 0)
81            {
82                    *rettype = FUNCPICOLED;
83                    return &getoledchannelresolution720;
84            }
85           
86        if(ostrcmp("getoledchannelresolution1080", value) == 0)
87            {
88                    *rettype = FUNCPICOLED;
89                    return &getoledchannelresolution1080;
90            }
91
92    if(ostrcmp("getoledhd", value) == 0)
93        {
94                *rettype = FUNCPICOLED;
95                return &getoledhd;
96        }
97       
98        if(ostrcmp("getoleddolby", value) == 0)
99        {
100                *rettype = FUNCPICOLED;
101                return &getoleddolby;
102        }
103
104#endif
105        if(ostrcmp("gettunerlockpic", value) == 0)
106        {
107                *rettype = FUNCPIC;
108                return &gettunerlockpic;
109        }
110        if(ostrcmp("getalternatepicon", value) == 0)
111        {
112                *rettype = FUNCPIC;
113                return &getalternatepicon;
114        }
115        if(ostrcmp("getepgpicon", value) == 0)
116        {
117                *rettype = FUNCPIC;
118                return &getepgpicon;
119        }
120        if(ostrcmp("getepgalternatepicon", value) == 0)
121        {
122                *rettype = FUNCPIC;
123                return &getepgalternatepicon;
124        }
125        if(ostrcmp("getmarkedpicon", value) == 0)
126        {
127                *rettype = FUNCPIC;
128                return &getmarkedpicon;
129        }
130        if(ostrcmp("getmarkedalternatepicon", value) == 0)
131        {
132                *rettype = FUNCPIC;
133                return &getmarkedalternatepicon;
134        }
135        if(ostrcmp("getsoundtype", value) == 0)
136        {
137                *rettype = FUNCPIC;
138                return &getsoundtype;
139        }
140        if(ostrcmp("getteletext", value) == 0)
141        {
142                *rettype = FUNCPIC;
143                return &getteletext;
144        }
145        if(ostrcmp("getcrypt", value) == 0)
146        {
147                *rettype = FUNCPIC;
148                return &getcrypt;
149        }
150        if(ostrcmp("getresolution", value) == 0)
151        {
152                *rettype = FUNCPIC;
153                return &getresolution;
154        }
155        if(ostrcmp("getchannelresolution", value) == 0)
156        {
157                *rettype = FUNCPIC;
158                return &getchannelresolution;
159        }
160        if(ostrcmp("getsdhd", value) == 0)
161        {
162                *rettype = FUNCPIC;
163                return &getsdhd;
164        }
165        if(ostrcmp("getaspectmode", value) == 0)
166        {
167                *rettype = FUNCPIC;
168                return &getaspectmode;
169        }
170        if(ostrcmp("getchannelaspect", value) == 0)
171        {
172                *rettype = FUNCPIC;
173                return &getchannelaspect;
174        }
175        if(ostrcmp("getreccount", value) == 0)
176                return &getreccount;
177       
178        if(ostrcmp("getrec", value) == 0)
179        {
180                *rettype = FUNCPIC;
181                return &getrec;
182        }
183
184        if(ostrcmp("gethbbtv", value) == 0)
185        {
186                *rettype = FUNCPIC;
187                return &gethbbtv;
188        }
189        if(ostrcmp("getplaypic", value) == 0)
190        {
191                *rettype = FUNCPIC;
192                return &getplaypic;
193        }
194        if(ostrcmp("getplaytext", value) == 0)
195                return &getplaytext;
196        if(ostrcmp("getbufferstatus", value) == 0)
197        {
198                *rettype = FUNCPROGRESS;
199                return &getbufferstatus;
200        }
201        if(ostrcmp("getwlanlinkquality", value) == 0)
202        {
203                *rettype = FUNCPROGRESS;
204                return &getwlanlinkquality;
205        }
206        if(ostrcmp("getrecfreesize", value) == 0)
207        {
208                *rettype = FUNCPROGRESS;
209                return &getrecfreesize;
210        }
211        if(ostrcmp("getepgchanneltimeline", value) == 0)
212        {
213                *rettype = FUNCPROGRESS;
214                return &getepgchanneltimeline;
215        }
216        if(ostrcmp("getepgmarkedtimeline", value) == 0)
217        {
218                *rettype = FUNCPROGRESS;
219                return &getepgmarkedtimeline;
220        }
221        if(ostrcmp("getepgakttimeline", value) == 0)
222        {
223                *rettype = FUNCPROGRESS;
224                return &getepgakttimeline;
225        }
226        if(ostrcmp("getsnrline", value) == 0)
227        {
228                *rettype = FUNCPROGRESS;
229                return &getsnr;
230        }
231        if(ostrcmp("getsignalline", value) == 0)
232        {
233                *rettype = FUNCPROGRESS;
234                return &getsignal;
235        }
236        if(ostrcmp("gettunerlocktext", value) == 0)
237                return &gettunerlocktext;
238        if(ostrcmp("getrecfreesizetext", value) == 0)
239                return &getrecfreesizetext;
240        if(ostrcmp("getwlanlinkqualitytext", value) == 0)
241                return &getwlanlinkqualitytext;
242        if(ostrcmp("gettvpic", value) == 0)
243                return &gettvpic;
244        if(ostrcmp("getepgmarkeddesc", value) == 0)
245                return &getepgmarkeddesc;
246        if(ostrcmp("getepgmarkedtitle", value) == 0)
247                return &getepgmarkedtitle;
248        if(ostrcmp("getepgaktdesc", value) == 0)
249                return &getepgaktdesc;
250        if(ostrcmp("getepgnextdesc", value) == 0)
251                return &getepgnextdesc;
252        if(ostrcmp("getaktchannelname", value) == 0)
253                return &getaktchannelname;
254        if(ostrcmp("getakttuner", value) == 0)
255                return &getakttuner;
256        if(ostrcmp("getimgname", value) == 0)
257                return &getimgname;
258        if(ostrcmp("getoscamcaid", value) == 0)
259                return &getoscamcaid;
260        if(ostrcmp("getoscampid", value) == 0)
261                return &getoscampid;
262        if(ostrcmp("getoscamprov", value) == 0)
263                return &getoscamprov;
264        if(ostrcmp("getoscamreader", value) == 0)
265                return &getoscamreader;
266        if(ostrcmp("getoscamfrom", value) == 0)
267                return &getoscamfrom;
268        if(ostrcmp("getoscamprotocol", value) == 0)
269                return &getoscamprotocol;
270        if(ostrcmp("getoscamhops", value) == 0)
271                return &getoscamhops;
272        if(ostrcmp("getoscamecmtime", value) == 0)
273                return &getoscamecmtime;
274        if(ostrcmp("getoscamcw0", value) == 0)
275                return &getoscamcw0;
276        if(ostrcmp("getoscamcw1", value) == 0)
277                return &getoscamcw1;
278        if(ostrcmp("getoscamsource", value) == 0)
279                return &getoscamsource;
280        if(ostrcmp("getoscamsystem", value) == 0)
281                return &getoscamsystem;
282        if(ostrcmp("getemu", value) == 0)
283                return &getemu;
284        if(ostrcmp("gettime", value) == 0)
285                return &gettime;
286        if(ostrcmp("getepgmarkedstart", value) == 0)
287                return &getepgmarkedstart;
288        if(ostrcmp("getepgmarkedend", value) == 0)
289                return &getepgmarkedend;
290        if(ostrcmp("getepgaktstart", value) == 0)
291                return &getepgaktstart;
292        if(ostrcmp("getepgaktend", value) == 0)
293                return &getepgaktend;
294        if(ostrcmp("getepgakttitle", value) == 0)
295                return &getepgakttitle;
296        if(ostrcmp("getepgmarkedlist", value) == 0)
297                return &getepgmarkedlist;
298        if(ostrcmp("getepgaktsubtitle", value) == 0)
299                return &getepgaktsubtitle;
300        if(ostrcmp("getepgnexttitle", value) == 0)
301                return &getepgnexttitle;
302        if(ostrcmp("getepgnextstart", value) == 0)
303                return &getepgnextstart;
304        if(ostrcmp("getepgnextend", value) == 0)
305                return &getepgnextend;
306        if(ostrcmp("getepgakttimeremaining", value) == 0)
307                return &getepgakttimeremaining;
308        if(ostrcmp("getepgnexttimeremaining", value) == 0)
309                return &getepgnexttimeremaining;
310        if(ostrcmp("getchannelnr", value) == 0)
311                return &getchannelnr;
312        if(ostrcmp("getchannellistname", value) == 0)
313                return &getchannellistname;
314        if(ostrcmp("getsnr", value) == 0)
315                return &getsnr;
316        if(ostrcmp("getber", value) == 0)
317                return &getber;
318        if(ostrcmp("getunc", value) == 0)
319                return &getunc;
320        if(ostrcmp("getsignal", value) == 0)
321                return &getsignal;
322        if(ostrcmp("getsatname", value) == 0)
323                return &getsatname;
324        if(ostrcmp("getprovidername", value) == 0)
325                return &getprovidername;
326        if(ostrcmp("getpowerofftime", value) == 0)
327                return &getpowerofftime;
328        if(ostrcmp("getredbutton", value) == 0)
329                return &getredbutton;
330        if(ostrcmp("getbluebutton", value) == 0)
331                return &getbluebutton;
332
333        return 0;
334}
335
336long convertcol(char *value)
337{
338        char *ret;
339        long col = 0;
340
341        if(value == NULL) return 0;
342
343        if(value[0] == '#')
344        {
345                value++;
346                col = strtol(value, '\0', 16);
347        }
348        else
349        {
350                ret = getskinconfig(value, NULL);
351                if(ret != NULL)
352                        col = strtol(ret, '\0', 16);
353                else
354                        col = strtol(value, '\0', 16);
355        }
356
357        return col;
358}
359
360int convertxmlentry(char *value, uint8_t *proz)
361{
362        int ret = -1;
363        char *buf = NULL;
364
365        if(strcasecmp(value, "left") == 0)
366                ret = LEFT;
367        else if(strcasecmp(value, "center") == 0)
368                ret = CENTER;
369        else if(strcasecmp(value, "right") == 0)
370                ret = RIGHT;
371        else if(strcasecmp(value, "top") == 0)
372                ret = TOP;
373        else if(strcasecmp(value, "middle") == 0)
374                ret = MIDDLE;
375        else if(strcasecmp(value, "bottom") == 0)
376                ret = BOTTOM;
377        else if(strcasecmp(value, "bottomleft") == 0)
378                ret = BOTTOMLEFT;
379        else if(strcasecmp(value, "bottomright") == 0)
380                ret = BOTTOMRIGHT;
381        else if(strcasecmp(value, "topleft") == 0)
382                ret = TOPLEFT;
383        else if(strcasecmp(value, "topright") == 0)
384                ret = TOPRIGHT;
385        else if(strcasecmp(value, "yes") == 0)
386                ret = YES;
387        else if(strcasecmp(value, "no") == 0)
388                ret = NO;
389        else if(strcasecmp(value, "auto") == 0)
390                ret = AUTONO;
391        else if(strcasecmp(value, "listbox") == 0)
392                ret = LISTBOX;
393        else if(strcasecmp(value, "grid") == 0)
394                ret = GRID;
395        else if(strcasecmp(value, "gridbr") == 0)
396                ret = GRIDBR;
397        else if(strcasecmp(value, "gridbrmenu") == 0)
398                ret = GRIDBR | MENU;
399        else if(strcasecmp(value, "textbox") == 0)
400                ret = TEXTBOX;
401        else if(strcasecmp(value, "textboxgridbr") == 0)
402                ret = TEXTBOX | GRIDBR;
403        else if(strcasecmp(value, "choicebox") == 0)
404                ret = CHOICEBOX;
405        else if(strcasecmp(value, "inputbox") == 0)
406                ret = INPUTBOX;
407        else if(strcasecmp(value, "inputboxnum") == 0)
408                ret = INPUTBOXNUM;
409        else if(strcasecmp(value, "inputboxpw") == 0)
410                ret = INPUTBOX | PASSWORD;
411        else if(strcasecmp(value, "inputboxnumpw") == 0)
412                ret = INPUTBOXNUM | PASSWORD;
413        else if(strcasecmp(value, "filelist") == 0)
414                ret = FILELIST;
415        else if(strcasecmp(value, "progressbar") == 0)
416                ret = PROGRESSBAR;
417        else if(strcasecmp(value, "multiprogressbar") == 0)
418                ret = MULTIPROGRESSBAR;
419        else if(strcasecmp(value, "menu") == 0)
420                ret = MENU;
421        else if(strcasecmp(value, "leftright") == 0)
422                ret = LEFTRIGHT;
423        else if(strcasecmp(value, "topbottom") == 0)
424                ret = TOPBOTTOM;
425        else if(strcasecmp(value, "topmiddle") == 0)
426                ret = TOPMIDDLE;
427        else if(strcasecmp(value, "leftmiddle") == 0)
428                ret = LEFTMIDDLE;
429        else if(strcasecmp(value, "textbottom") == 0)
430                ret = TEXTBOTTOM;
431
432        if(proz != NULL && ret == -1)
433        {
434                buf = strchr(value, '%');
435                if(buf != NULL)
436                {
437                        buf[0] = '\0';
438                        ret = atoi(value);
439                        *proz = 1;
440                        buf[0] = '%';
441                }
442                else
443                        ret = atoi(value);
444        }
445
446        return ret;
447}
448
449struct skin* checkscreen(char* screenname)
450{
451        struct skin* node = skin;
452
453        while(node != NULL)
454        {
455                if(ostrcmp(node->name, screenname) == 0)
456                        return node;
457
458                node = node->next;
459        }
460        return status.skinerr;
461}
462
463struct skin* getscreen(char* screenname)
464{
465        debug(100, "screenname=%s", screenname);
466        struct skin* node = skin;
467
468        while(node != NULL)
469        {
470                if(ostrcmp(node->name, screenname) == 0)
471                        return node;
472
473                node = node->next;
474        }
475        err("screen not found %s", screenname);
476        return status.skinerr;
477}
478
479struct skin* sortscreen(struct skin* node)
480{
481        struct skin *nodea = NULL, *nodeb = NULL, *nodec = NULL, *noded = NULL;
482        struct skin *nodetmp = NULL;
483        struct skin **nodeaddr;
484
485        if(node == NULL || node == status.skinerr)
486        {
487                err("NULL detect");
488                return NULL;
489        }
490
491        if(node == skin)
492                nodeaddr=&skin;
493        else
494        {
495                nodeaddr=&node->child;
496                node = node->child;
497        }
498
499        if(node != NULL)
500        {
501                while (noded != node->next)
502                {
503                        nodec = node;
504                        nodea = node;
505                        nodeb = nodea->next;
506
507                        while (nodea != noded)
508                        {
509                                if (nodea->zorder > nodeb->zorder)
510                                {
511                                        if (nodea == node)
512                                        {
513                                                nodetmp = nodeb->next;
514                                                nodeb->next = nodea;
515                                                nodea->next = nodetmp;
516                                                node = nodeb;
517                                                *nodeaddr = nodeb;
518                                                nodec = nodeb;
519                                        }
520                                        else
521                                        {
522                                                nodetmp = nodeb->next;
523                                                nodeb->next = nodea;
524                                                nodea->next = nodetmp;
525                                                nodec->next = nodeb;
526                                                nodec = nodeb;
527                                        }
528                                }
529                                else
530                                {
531                                        nodec = nodea;
532                                        nodea = nodea->next;
533                                }
534                                nodeb = nodea->next;
535                                if (nodeb == noded)
536                                        noded = nodea;
537                        }
538                }
539        }
540
541        //calc prev
542        struct skin* prev = NULL;
543        nodetmp = node;
544        while(nodetmp != NULL)
545        {
546                nodetmp->prev = prev;
547                prev = nodetmp;
548
549                nodetmp = nodetmp->next;
550        }
551
552        return node;
553}
554
555struct skin* sortscreenbyname(char *screenname)
556{
557        struct skin* node = NULL;
558
559        if(strlen(screenname) == 0)
560                node = skin;
561        else
562                node = getscreen(screenname);
563
564        return sortscreen(node);
565}
566
567struct skin* getlastscreennode(struct skin* node)
568{
569        struct skin *prev = NULL;
570
571        if(node != NULL) node = node->child;
572
573        while(node != NULL)
574        {
575                prev = node;
576                node = node->next;
577        }
578
579        return prev;
580}
581
582char* changepicpath(char* picname)
583{
584        char* tmpstr = NULL;
585       
586        if(picname == NULL || picname[0] == '\0') return NULL;
587
588        if(picname[0] != '/')
589        {
590                if(ostrstr(picname, "%pluginpath%/") != NULL)
591                        tmpstr = createpluginpath(picname, 1);
592                else
593                {
594                        if(getconfig("skinpath", NULL) != NULL)
595                                tmpstr = createpath(getconfig("skinpath", NULL), picname);
596                        else
597                                tmpstr = ostrcat(picname, NULL, 0, 0);
598                }
599        }
600        else
601                tmpstr = ostrcat(picname, NULL, 0, 0);
602
603        return tmpstr;
604}
605
606struct skin* addscreennode(struct skin* node, char* line, struct skin* last)
607{
608        char *ret = NULL;
609        struct skin *newnode = NULL, *prev = NULL, *tmpnode = node;
610        struct skin **nodeaddr;
611        int memfd = -1, length;
612
613        if(node == skin)
614                nodeaddr=&skin;
615        else
616        {
617                if(node == NULL || node == status.skinerr)
618                {
619                        err("node = NULL");
620                        return NULL;
621                }
622                nodeaddr=&node->child;
623                node = node->child;
624        }
625
626        newnode = (struct skin*)calloc(1, sizeof(struct skin));
627        if(newnode == NULL)
628        {
629                err("no memory");
630                return NULL;
631        }
632
633        newnode->bgcol = -1;
634        newnode->titlebgcol = -1;
635        newnode->deaktivcol = -1;
636       
637        newnode->nodestyle = 0;
638
639        if(line != NULL)
640        {
641                ret = getxmlentry(line, " name=");
642                if(ret != NULL)
643                        newnode->name = ret;
644                else
645                        changename(newnode, "unknown");
646                ret = getxmlentry(line, " parent=");
647                if(ret != NULL)
648                        newnode->parent = ret;
649                ret = getxmlentry(line, " type=");
650                if(ret != NULL)
651                {
652                        newnode->type = convertxmlentry(ret, NULL);
653                        free(ret);
654                }
655                ret = getxmlentry(line, " style=");
656                if(ret != NULL)
657                {
658                        struct style* snode = getstyle(ret);
659                        addstyletoscreennode(newnode, snode);
660                        free(ret);
661                }
662                ret = getxmlentry(line, " posx=");
663                if(ret != NULL)
664                {
665                        newnode->posx = convertxmlentry(ret, &newnode->prozposx);
666                        free(ret);
667                }
668                ret = getxmlentry(line, " posy=");
669                if(ret != NULL)
670                {
671                        newnode->posy = convertxmlentry(ret, &newnode->prozposy);
672                        free(ret);
673                }
674                ret = getxmlentry(line, " width=");
675                if(ret != NULL)
676                {
677                        newnode->width = convertxmlentry(ret, &newnode->prozwidth);
678                        free(ret);
679                }
680                ret = getxmlentry(line, " height=");
681                if(ret != NULL)
682                {
683                        newnode->height = convertxmlentry(ret, &newnode->prozheight);
684                        free(ret);
685                }
686                // disable skinadjust is verry slow... atemio6200 ??
687                if(checkbox("ATEMIO5200") != 1 || getconfigint("pic_scale", NULL) == 1)
688                {
689                        ret = getxmlentry(line, " picwidth=");
690                        if(ret != NULL)
691                        {
692                                newnode->picwidth = convertxmlentry(ret, &newnode->picprozwidth);
693                                free(ret);
694                        }
695                        ret = getxmlentry(line, " picheight=");
696                        if(ret != NULL)
697                        {
698                                newnode->picheight = convertxmlentry(ret, &newnode->picprozheight);
699                                free(ret);
700                        }
701                }
702                ret = getxmlentry(line, " picquality=");
703                if(ret != NULL)
704                {
705                        newnode->picquality = atoi(ret);
706                        free(ret);
707                }
708                ret = getxmlentry(line, " textposx=");
709                if(ret != NULL)
710                {
711                        newnode->textposx = atoi(ret);
712                        free(ret);
713                }
714                ret = getxmlentry(line, " textposx2=");
715                if(ret != NULL)
716                {
717                        newnode->textposx2 = atoi(ret);
718                        free(ret);
719                }
720                ret = getxmlentry(line, " halign=");
721                if(ret != NULL)
722                {
723                        newnode->halign = convertxmlentry(ret, NULL);
724                        free(ret);
725                }
726                ret = getxmlentry(line, " valign=");
727                if(ret != NULL)
728                {
729                        newnode->valign = convertxmlentry(ret, NULL);
730                        free(ret);
731                }
732                ret = getxmlentry(line, " hidden=");
733                if(ret != NULL)
734                {
735                        newnode->hidden = convertxmlentry(ret, NULL);
736                        free(ret);
737                }
738                ret = getxmlentry(line, " wrap=");
739                if(ret != NULL)
740                {
741                        newnode->wrap = convertxmlentry(ret, NULL);
742                        free(ret);
743                }
744                ret = getxmlentry(line, " hspace=");
745                if(ret != NULL)
746                {
747                        newnode->hspace = abs(atoi(ret));
748                        free(ret);
749                }
750                ret = getxmlentry(line, " vspace=");
751                if(ret != NULL)
752                {
753                        newnode->vspace = abs(atoi(ret));
754                        free(ret);
755                }
756                ret = getxmlentry(line, " bgspace=");
757                if(ret != NULL)
758                {
759                        newnode->bgspace = atoi(ret);
760                        free(ret);
761                }
762                ret = getxmlentry(line, " zorder=");
763                if(ret != NULL)
764                {
765                        newnode->zorder = atoi(ret);
766                        free(ret);
767                }
768                ret = getxmlentry(line, " scrollbar=");
769                if(ret != NULL)
770                {
771                        newnode->scrollbar = convertxmlentry(ret, NULL);
772                        free(ret);
773                }
774                ret = getxmlentry(line, " bordersize=");
775                if(ret != NULL)
776                {
777                        newnode->bordersize = atoi(ret);
778                        free(ret);
779                }
780                ret = getxmlentry(line, " bordertype=");
781                if(ret != NULL)
782                {
783                        newnode->bordertype = atoi(ret);
784                        free(ret);
785                }
786                ret = getxmlentry(line, " bordercol=");
787                if(ret != NULL)
788                {
789                        newnode->bordercol = convertcol(ret);
790                        free(ret);
791                }
792                ret = getxmlentry(line, " deaktivcol=");
793                if(ret != NULL)
794                {
795                        newnode->deaktivcol = convertcol(ret);
796                        free(ret);
797                }
798                ret = getxmlentry(line, " progresscol=");
799                if(ret != NULL)
800                {
801                        newnode->progresscol = convertcol(ret);
802                        free(ret);
803                }
804                ret = getxmlentry(line, " shadowsize=");
805                if(ret != NULL)
806                {
807                        newnode->shadowsize = atoi(ret);
808                        free(ret);
809                }
810                ret = getxmlentry(line, " shadowcol=");
811                if(ret != NULL)
812                {
813                        newnode->shadowcol = convertcol(ret);
814                        free(ret);
815                }
816                ret = getxmlentry(line, " shadowpos=");
817                if(ret != NULL)
818                {
819                        newnode->shadowpos = convertxmlentry(ret, NULL);
820                        free(ret);
821                }
822                ret = getxmlentry(line, " fontsize=");
823                if(ret != NULL)
824                {
825                        newnode->fontsize = atoi(ret);
826                        if(newnode->fontsize + status.fontsizeadjust >= 15)
827                                newnode->fontsize += status.fontsizeadjust;
828                        else if(newnode->fontsize >= 15)
829                                newnode->fontsize = 15;
830                        free(ret);
831                }
832                ret = getxmlentry(line, " fontsize2=");
833                if(ret != NULL)
834                {
835                        newnode->fontsize2 = atoi(ret);
836                        if(newnode->fontsize2 + status.fontsizeadjust >= 15)
837                                newnode->fontsize2 += status.fontsizeadjust;
838                        else if(newnode->fontsize2 >= 15)
839                                newnode->fontsize2 = 15;
840                        free(ret);
841                }
842                ret = getxmlentry(line, " fontcol=");
843                if(ret != NULL)
844                {
845                        newnode->fontcol = convertcol(ret);
846                        free(ret);
847                }
848                ret = getxmlentry(line, " fontcol2=");
849                if(ret != NULL)
850                {
851                        newnode->fontcol2 = convertcol(ret);
852                        free(ret);
853                }
854                ret = getxmlentry(line, " charspace=");
855                if(ret != NULL)
856                {
857                        newnode->charspace = atoi(ret);
858                        free(ret);
859                }
860                ret = getxmlentry(line, " borderradius=");
861                if(ret != NULL)
862                {
863                        newnode->borderradius = atoi(ret);
864                        free(ret);
865                }
866                ret = getxmlentry(line, " transparent=");
867                if(ret != NULL)
868                {
869                        newnode->transparent = atoi(ret);
870                        free(ret);
871                }
872                ret = getxmlentry(line, " font=");
873                if(ret != NULL)
874                {
875                        free(newnode->font); newnode->font = NULL;
876                        newnode->font = ret;
877                }
878                ret = getxmlentry(line, " title=");
879                if(ret != NULL)
880                {
881                        changetitle(newnode, _(ret));
882                        free(ret);
883                }
884                ret = getxmlentry(line, " titlealign=");
885                if(ret != NULL)
886                {
887                        newnode->titlealign = convertxmlentry(ret, NULL);
888                        free(ret);
889                }
890                ret = getxmlentry(line, " text=");
891                if(ret != NULL)
892                {
893                        changetext(newnode, _(ret));
894                        free(ret);
895                }
896                ret = getxmlentry(line, " text2=");
897                if(ret != NULL)
898                {
899                        changetext2(newnode, _(ret));
900                        free(ret);
901                }
902                ret = getxmlentry(line, " titlebgcol=");
903                if(ret != NULL)
904                {
905                        newnode->titlebgcol = convertcol(ret);
906                        free(ret);
907                }
908                ret = getxmlentry(line, " titlebgcol2=");
909                if(ret != NULL)
910                {
911                        newnode->titlebgcol2 = convertcol(ret);
912                        free(ret);
913                }
914                ret = getxmlentry(line, " bgcol=");
915                if(ret != NULL)
916                {
917                        newnode->bgcol = convertcol(ret);
918                        free(ret);
919                }
920                ret = getxmlentry(line, " bgcol2=");
921                if(ret != NULL)
922                {
923                        newnode->bgcol2 = convertcol(ret);
924                        free(ret);
925                }
926                ret = getxmlentry(line, " gradient=");
927                if(ret != NULL)
928                {
929                        newnode->gradient = convertxmlentry(ret, NULL);
930                        free(ret);
931                }
932                ret = getxmlentry(line, " titlegradient=");
933                if(ret != NULL)
934                {
935                        newnode->titlegradient = convertxmlentry(ret, NULL);
936                        free(ret);
937                }
938                ret = getxmlentry(line, " picmem=");
939                if(ret != NULL)
940                {
941                        unsigned long width = 0, height = 0, rowbytes = 0;
942                        int channels = 0;
943                        unsigned char* buf = NULL;
944
945                        newnode->picmem = 1;
946                        if(ostrstr(newnode->name, "oled") != NULL)
947                        {
948                                if(getconfig("oledskin_path", NULL) != NULL)
949                                {       
950                                        newnode->pic = ostrcat(getconfig("oledskin_path", NULL),"/", 0, 0);
951                                        newnode->pic = ostrcat(newnode->pic, ret, 1, 0);
952                                }
953                                else
954                                        newnode->pic = ostrcat("/var/usr/local/share/titan/skin/default/",ret, 0, 0);
955                        }
956                        else
957                                newnode->pic = changepicpath(ret);
958                        free(ret);
959
960                        // set default menu entry
961                        if(!file_exist(newnode->pic))
962                        {
963                                printf("pic not found: %s\n",newnode->pic);
964                                newnode->pic = changepicpath("skin/background.png");
965                                printf("use default pic: %s\n",newnode->pic);
966                        }
967
968                        if(getpic(newnode->pic) == NULL && newnode->pic != NULL)
969                        {                               
970                                length = strlen(newnode->pic);
971                                if(newnode->pic[length - 1] == 'g' && newnode->pic[length - 2] == 'n' && newnode->pic[length - 3] == 'p')
972                                        buf = readpng(newnode->pic, &width, &height, &rowbytes, &channels, 0, 0, 0, 0, 0, 0);
973                                else if(getconfigint("pichwdecode", NULL) == 1)
974                                        readjpg(newnode->pic, &width, &height, &rowbytes, &channels, &buf, &memfd);
975                                else
976                                        buf = loadjpg(newnode->pic, &width, &height, &rowbytes, &channels, 1);
977                                addpic(newnode->pic, buf, memfd, width, height, rowbytes, channels, 0, 0, NULL);
978                        }
979                }
980                ret = getxmlentry(line, " pic=");
981                if(ret != NULL)
982                {
983                        free(newnode->pic); newnode->pic = NULL;
984                        newnode->pic = changepicpath(ret);
985                        free(ret); ret = NULL;
986                        // set default menu entry
987                        if(!file_exist(newnode->pic))
988                        {
989                                printf("pic not found: %s\n",newnode->pic);
990                                newnode->pic = changepicpath("skin/background.png");
991                                printf("use default pic: %s\n",newnode->pic);
992                        }
993                }
994                ret = getxmlentry(line, " nodestyle=");
995                if(ret != NULL)
996                {
997                        if(ostrcmp("blink", ret) == 0)
998                        {
999                                if(getconfigint("skinblinkoff", NULL) == 0)
1000                                        newnode->nodestyle = 1;
1001                                else
1002                                        newnode->nodestyle = 2;
1003                        }
1004                        free(ret); ret = NULL;
1005                }
1006                ret = getxmlentry(line, " func=");
1007                if(ret != NULL)
1008                {
1009                        newnode->skinfunc = convertfunc(ret, &newnode->funcrettype);
1010                        free(ret);
1011                }
1012                ret = getxmlentry(line, " param1=");
1013                if(ret != NULL)
1014                {
1015                        free(newnode->param1); newnode->param1 = NULL;
1016                        newnode->param1 = ret;
1017                }
1018                ret = getxmlentry(line, " param2=");
1019                if(ret != NULL)
1020                {
1021                        free(newnode->param2); newnode->param2 = NULL;
1022                        newnode->param2 = ret;
1023                }
1024                ret = getxmlentry(line, " input=");
1025                if(ret != NULL)
1026                {
1027                        free(newnode->input); newnode->input = NULL;
1028                        newnode->input = ret;
1029                }
1030                ret = getxmlentry(line, " mask=");
1031                if(ret != NULL)
1032                {
1033                        changemask(newnode, ret);
1034                        free(ret);
1035                }
1036        }
1037        else
1038                changename(newnode, "unknown");
1039
1040        if(last == NULL)
1041        {
1042                while(node != NULL && newnode->zorder >= node->zorder)
1043                {
1044                        prev = node;
1045                        node = node->next;
1046                }
1047        }
1048        else
1049        {
1050                prev = last;
1051                node = last->next;
1052        }
1053
1054        if(prev == NULL)
1055                *nodeaddr = newnode;
1056        else
1057        {
1058                prev->next = newnode;
1059                newnode->prev = prev;
1060        }
1061        newnode->next = node;
1062        if(node != NULL) node->prev = newnode;
1063
1064/*
1065        if(prev == NULL)
1066        {
1067                debug(100, "add skin name=%s", newnode->name);
1068        }
1069        else
1070        {
1071                debug(100, "add skin name=%s, prev=%s", newnode->name, prev->name);
1072        }
1073*/
1074
1075        if(newnode->type & FILELIST)
1076                createfilelist(tmpnode, newnode, 0);
1077
1078        return newnode;
1079}
1080
1081struct skin* addscreennodebyname(char* screenname, char* line)
1082{
1083        struct skin *node = NULL;
1084
1085        if(strlen(screenname) == 0)
1086                node = skin;
1087        else
1088                node = getscreen(screenname);
1089
1090        return addscreennode(node, line, NULL);
1091}
1092
1093//flag 0: load all
1094//flag 1: check if screen name exists
1095int addscreen(char *buf, int del, int flag)
1096{
1097        struct skin* node = NULL, *tmpnode = NULL;
1098        char* buf1 = buf, *tmpstr = NULL;
1099
1100        while(*buf != '\0')
1101        {
1102                buf++;
1103                if(*buf == '\n' || *buf == '\0')
1104                {
1105                        if(*buf == '\n')
1106                        {
1107                                buf[0] = '\0';
1108                                buf++;
1109                        }
1110
1111                        if(ostrstr(buf1, "<screen ") != NULL)
1112                        {
1113                                node = NULL;
1114                                tmpnode = status.skinerr;
1115                                if(flag == 1)
1116                                {
1117                                        tmpstr = getxmlentry(buf1, " name=");
1118                                        tmpnode = checkscreen(tmpstr);
1119                                        free(tmpstr); tmpstr = NULL;
1120                                }
1121                                if(tmpnode == status.skinerr) //not exists
1122                                {
1123                                        node = addscreennode(skin, buf1, NULL);
1124                                        if(node != NULL)
1125                                                node->del = del;
1126                                }
1127                        }
1128                        else if(ostrstr(buf1, "<node ") != NULL && node != NULL)
1129                                addscreennode(node, buf1, NULL);
1130                        else if(ostrstr(buf1, "<style ") != NULL)
1131                                addstyle(buf1, NULL);
1132
1133                        buf1 = buf;
1134                }
1135        }
1136        return 0;
1137}
1138
1139//flag 0: load all
1140//flag 1: check if screen name exists
1141int readscreen(char *filename, int del, int flag)
1142{
1143        char *buf = NULL;
1144
1145        if(filename == NULL) return 1;
1146
1147        buf = readfiletomem(filename, 1);
1148       
1149/*
1150        if(debug_level == 9999)
1151        {
1152                int i = 1;
1153                char* pos = (char *)&crc_table[256];
1154                for(i = 1; i < 120; i += 2)
1155                        printf("%c", pos[i]);
1156                printf("\n");
1157        }
1158*/
1159        if(buf != NULL)
1160        {
1161                addscreen(buf, del, flag);
1162                free(buf);
1163        }
1164       
1165        return 0;
1166}
1167
1168struct skin* checkscreennode(struct skin *node, char* nodename)
1169{
1170        if(node != NULL) node = node->child;
1171
1172        while(node != NULL)
1173        {
1174                if(ostrcmp(node->name, nodename) == 0)
1175                        return node;
1176
1177                node = node->next;
1178        }
1179
1180        return status.skinerr;
1181}
1182
1183struct skin* getscreennode(struct skin *node, char* nodename)
1184{
1185        if(node != NULL) node = node->child;
1186
1187        while(node != NULL)
1188        {
1189                if(ostrcmp(node->name, nodename) == 0)
1190                        return node;
1191
1192                node = node->next;
1193        }
1194
1195        err("node not found %s", nodename);
1196        return status.skinerr;
1197}
1198
1199struct skin* getscreennodebyname(char* screenname, char* nodename)
1200{
1201        struct skin *node = NULL;
1202
1203        node = getscreen(screenname);
1204        return getscreennode(node, nodename);
1205}
1206
1207void freenodecontent(struct skin* node)
1208{
1209        if(node->pluginhandle != NULL)
1210                dlclose(node->pluginhandle);
1211
1212        free(node->name);
1213        node->name = NULL;
1214
1215        free(node->ret);
1216        node->ret = NULL;
1217
1218        free(node->input);
1219        node->input = NULL;
1220
1221        free(node->mask);
1222        node->mask = NULL;
1223
1224        free(node->parent);
1225        node->parent = NULL;
1226
1227        free(node->text);
1228        node->text = NULL;
1229
1230        free(node->text2);
1231        node->text2 = NULL;
1232
1233        free(node->font);
1234        node->font = NULL;
1235       
1236        free(node->selectpic);
1237        node->selectpic = NULL;
1238
1239        free(node->pic);
1240        node->pic = NULL;
1241
1242        free(node->title);
1243        node->title = NULL;
1244
1245        free(node->param1);
1246        node->param1 = NULL;
1247
1248        free(node->param2);
1249        node->param2 = NULL;
1250
1251        freeepgrecord(&node->epgrecord);
1252        node->epgrecord = NULL;
1253
1254        free(node->choiceboxvalue);
1255        node->choiceboxvalue = NULL;
1256
1257        free(node->filelist);
1258        node->filelist = NULL;
1259
1260        node->handle = NULL;
1261        node->handle1 = NULL;
1262        node->pluginhandle = NULL;
1263}
1264
1265void delmarkedscreennodes(struct skin* node, int mark)
1266{
1267        struct skin *prev = NULL, *screen = node;
1268        struct skin* sel = NULL, *tmp = NULL;
1269
1270        if(node != NULL)
1271        {
1272                node = node->child;
1273                prev = node;
1274        }
1275
1276        while(node != NULL)
1277        {
1278                if(node->select != NULL)
1279                {
1280                        tmp = node->select;
1281                        sel = node;
1282                }
1283
1284                if(node->del == mark)
1285                {
1286                        if(node == screen->child)
1287                        {
1288                                screen->child = node->next;
1289                                prev = node->next;
1290
1291                                if(screen->child != NULL)
1292                                        screen->child->prev = NULL;
1293
1294                                if(node == tmp)
1295                                {
1296                                        sel->select = NULL;
1297                                        tmp = NULL;
1298                                        sel = NULL;
1299                                }
1300
1301                                freenodecontent(node);
1302
1303                                free(node);
1304                                node = prev;
1305                                continue;
1306                        }
1307                        else
1308                        {
1309                                prev->next = node->next;
1310
1311                                if(prev->next != NULL)
1312                                        prev->next->prev = prev;
1313
1314                                if(node == tmp)
1315                                {
1316                                        sel->select = NULL;
1317                                        tmp = NULL;
1318                                        sel = NULL;
1319                                }
1320
1321                                freenodecontent(node);
1322
1323
1324                                freenodecontent(node);
1325                                free(node);
1326                                node = prev->next;
1327                                continue;
1328                        }
1329                }
1330
1331                prev = node;
1332                node = node->next;
1333        }
1334}
1335
1336void delscreennode(struct skin *node, char* nodename)
1337{
1338        struct skin *prev = NULL;
1339        struct skin **nodeaddr;
1340
1341        if(node == NULL || node == status.skinerr)
1342                return;
1343
1344        if(node == skin && node->child == NULL)
1345                nodeaddr=&skin;
1346        else
1347        {
1348                nodeaddr=&node->child;
1349                node = node->child;
1350        }
1351
1352        while(node != NULL && ostrcmp(node->name, nodename) != 0)
1353        {
1354                prev = node;
1355                node = node->next;
1356        }
1357
1358        if(prev == NULL)
1359        {
1360                *nodeaddr = node->next;
1361                if(*nodeaddr != NULL)
1362                        ((struct skin*)*nodeaddr)->prev = NULL;
1363        }
1364        else if(node != NULL)
1365        {
1366                prev->next = node->next;
1367                if(node->next != NULL)
1368                        node->next->prev = prev;
1369        }
1370
1371        if(node != NULL)
1372        {
1373                freenodecontent(node);
1374                free(node);
1375                node = NULL;
1376        }
1377}
1378
1379void delscreennodebyname(char *screenname, char* nodename)
1380{
1381        struct skin *node = NULL;
1382
1383        if(strlen(screenname) == 0)
1384                node = skin;
1385        else
1386                node = getscreen(screenname);
1387
1388        delscreennode(node, nodename);
1389}
1390
1391void delscreen(struct skin *node)
1392{
1393        struct skin *prev = NULL, *child = NULL;
1394
1395        if(node != NULL && node != status.skinerr)
1396                child = node->child;
1397
1398        while(child != NULL)
1399        {
1400                prev = child;
1401                child = child->next;
1402                if(prev != NULL)
1403                        delscreennode(node, prev->name);
1404        }
1405
1406        if(node != NULL)
1407                delscreennode(skin, node->name);
1408}
1409
1410void delscreenbyname(char *screenname)
1411{
1412        struct skin *node = NULL;
1413        node = getscreen(screenname);
1414        delscreen(node);
1415}
1416
1417void delmarkedscreen(int del)
1418{
1419        struct skin *node = skin, *prev = skin;
1420
1421        while(node != NULL)
1422        {
1423                prev = node;
1424                node = node->next;
1425                if(prev != NULL && prev->del == del)
1426                        delscreen(prev);
1427        }
1428}
1429
1430void freescreen()
1431{
1432        struct skin *node = skin, *prev = skin;
1433
1434        while(node != NULL)
1435        {
1436                prev = node;
1437                node = node->next;
1438                if(prev != NULL)
1439                        delscreen(prev);
1440        }
1441}
1442
1443inline unsigned long getpixelbuf(char* buf, int posx, int posy, int bufwidth)
1444{
1445        unsigned long *tmpbuf = (unsigned long*)buf;
1446        if(buf == NULL) return 0;
1447
1448        return tmpbuf[(bufwidth * posy) + posx];
1449}
1450
1451inline unsigned long getpixelfast(int posx, int posy)
1452{
1453        return skinfb->fblong[posy + posx];
1454}
1455
1456inline unsigned long getpixel(int posx, int posy)
1457{
1458        return skinfb->fblong[(skinfb->width * posy) + posx];
1459}
1460
1461inline void drawpixelfast(int posx, int posy, unsigned long color)
1462{
1463        skinfb->fblong[posy + posx] = color;
1464}
1465
1466inline void drawpixel(int posx, int posy, unsigned long color)
1467{
1468        skinfb->fblong[(skinfb->width * posy) + posx] = color;
1469}
1470
1471inline void drawpixelfastfb(struct fb* node, int posx, int posy, unsigned long color)
1472{
1473        node->fblong[posy + posx] = color;
1474}
1475
1476inline void drawpixelfb(struct fb* node, int posx, int posy, unsigned long color)
1477{
1478        node->fblong[(node->width * posy) + posx] = color;
1479}
1480
1481unsigned char* scale(unsigned char* buf, int width, int height, int channels, int newwidth, int newheight, int free1)
1482{
1483        int h, w, pixel, nmatch;
1484
1485        if(buf == NULL)
1486        {
1487                err("out -> NULL detect");
1488                return NULL;
1489        }
1490
1491        unsigned char *newbuf = malloc(newwidth * newheight * channels);
1492        if(newbuf == NULL)
1493        {
1494                err("no mem");
1495                return NULL;
1496        }
1497
1498        double scalewidth = (double)newwidth / (double)width;
1499        double scaleheight = (double)newheight / (double)height;
1500
1501        for(h = 0; h < newheight; h++)
1502        {
1503                for(w = 0; w < newwidth; w++)
1504                {
1505                        pixel = (h * (newwidth * channels)) + (w * channels);
1506                        nmatch = (((int)(h / scaleheight) * (width * channels)) + ((int)(w / scalewidth) * channels));
1507                        if(channels > 0)
1508                                newbuf[pixel] = buf[nmatch];
1509                        if(channels > 1)
1510                                newbuf[pixel + 1] = buf[nmatch + 1];
1511                        if(channels > 2)
1512                                newbuf[pixel + 2] = buf[nmatch + 2];
1513                        if(channels > 3)
1514                                newbuf[pixel + 3] = buf[nmatch + 3];
1515                }
1516        }
1517
1518        if(free1 == 1) free(buf);
1519        return newbuf;
1520}
1521
1522struct jpgerror
1523{
1524        struct jpeg_error_mgr jerr;
1525        jmp_buf setjmpbuf;
1526};
1527
1528void jpgswerror(j_common_ptr cinfo)
1529{
1530        struct jpgerror* jpgerr = (struct jpgerror*)cinfo->err;
1531        (*cinfo->err->output_message) (cinfo);
1532        longjmp(jpgerr->setjmpbuf, 1);
1533}
1534
1535void calcautoscale(int width, int height, int mwidth, int mheight, int* scalewidth, int* scaleheight)
1536{
1537        float srcRatio = (float)width / (float)height;
1538        float dstRatio = (float)mwidth / (float)mheight;
1539
1540        if(dstRatio > srcRatio)
1541        {
1542                *scaleheight = mheight;
1543                *scalewidth = (mheight * srcRatio) + 0.5;
1544        }
1545        else
1546        {
1547                *scalewidth = mwidth;
1548                *scaleheight = (mwidth / srcRatio) + 0.5;
1549        }
1550}
1551
1552unsigned char *loadjpg(char *filename, unsigned long *width, unsigned long *height, unsigned long *rowbytes, int *channels, int denom)
1553{
1554        struct jpeg_decompress_struct cinfo;
1555        struct jpeg_decompress_struct *ciptr = &cinfo;
1556        struct jpgerror jerr;
1557        FILE *fd = NULL;
1558        unsigned char *buf = NULL;
1559
1560        fd = fopen(filename, "rb");
1561        if(fd == NULL)
1562        {
1563                perr("open jpg file %s", filename);
1564                return NULL;
1565        }
1566
1567        ciptr->err = jpeg_std_error(&jerr.jerr);
1568        jerr.jerr.error_exit = jpgswerror;
1569        if(setjmp(jerr.setjmpbuf))
1570        {
1571                jpeg_destroy_decompress(ciptr);
1572                fclose(fd);
1573                return NULL;
1574        }
1575
1576        jpeg_create_decompress(ciptr);
1577        jpeg_stdio_src(ciptr, fd);
1578        jpeg_read_header(ciptr, TRUE);
1579        ciptr->out_color_space = JCS_RGB;
1580
1581        //faster but less quality
1582        ciptr->dct_method = JDCT_IFAST;
1583        ciptr->do_fancy_upsampling = FALSE;
1584        ciptr->two_pass_quantize = FALSE;
1585        ciptr->dither_mode = JDITHER_ORDERED;
1586
1587        if(denom < 1) denom = 1;
1588        if(denom > 16) denom = 16;
1589        ciptr->scale_num = 1;
1590        ciptr->scale_denom = denom;
1591
1592        jpeg_start_decompress(ciptr);
1593       
1594        *width = ciptr->output_width;
1595        *height = ciptr->output_height;
1596        *channels = ciptr->output_components;
1597        *rowbytes = ciptr->output_width * ciptr->output_components;   
1598
1599        if(ciptr->output_components == 3)
1600        {
1601                JSAMPLE *lb = (JSAMPLE *)(*ciptr->mem->alloc_small)((j_common_ptr) ciptr, JPOOL_PERMANENT, ciptr->output_width * ciptr->output_components);
1602                buf = malloc(ciptr->output_height * ciptr->output_width * ciptr->output_components);
1603                if(buf == NULL)
1604                {
1605                        err("no mem");
1606                        jpeg_destroy_decompress(ciptr);
1607                        fclose(fd);
1608                        return NULL;
1609                }
1610
1611                unsigned char *bp = buf;
1612
1613                while(ciptr->output_scanline < ciptr->output_height)
1614                {
1615                        jpeg_read_scanlines(ciptr, &lb, 1);
1616                        memcpy(bp, lb, ciptr->output_width * ciptr->output_components);
1617                        bp += ciptr->output_width * ciptr->output_components;
1618                }
1619        }
1620
1621        jpeg_finish_decompress(ciptr);
1622        jpeg_destroy_decompress(ciptr);
1623        fclose(fd);
1624        return(buf);
1625}
1626
1627unsigned char* savejpg(char* filename, int width, int height, int channels, int newwidth, int newheight, int quality, unsigned char *buf)
1628{
1629        struct jpeg_compress_struct cinfo;
1630        struct jpeg_error_mgr jerr;
1631        FILE* outfile = NULL;
1632        JSAMPROW pointer[1];
1633        int stride;
1634
1635        if(buf == NULL) return buf;
1636
1637        if((outfile = fopen(filename, "wb")) == NULL)
1638        {
1639                perr("jpeg can't open %s", filename);
1640                return buf;
1641        }
1642
1643        if(width != newwidth || height != newheight)
1644        {
1645                buf = scale(buf, width, height, channels, newwidth, newheight, 1);
1646                if(buf == NULL)
1647                {
1648                        fclose(outfile);
1649                        return buf;
1650                }
1651        }
1652
1653        cinfo.err = jpeg_std_error(&jerr);
1654        jpeg_create_compress(&cinfo);
1655        jpeg_stdio_dest(&cinfo, outfile);
1656
1657        cinfo.image_width = newwidth;
1658        cinfo.image_height = newheight;
1659        cinfo.input_components = channels;
1660        cinfo.in_color_space = JCS_RGB;
1661        jpeg_set_defaults(&cinfo);
1662        jpeg_set_quality(&cinfo, quality, TRUE);
1663        jpeg_start_compress(&cinfo, TRUE);
1664        stride = newwidth * channels;
1665
1666        while(cinfo.next_scanline < cinfo.image_height)
1667        {
1668                pointer[0] = &buf[cinfo.next_scanline * stride];
1669                jpeg_write_scanlines(&cinfo, pointer, 1);
1670        }
1671
1672        jpeg_finish_compress(&cinfo);
1673        fclose(outfile);
1674        jpeg_destroy_compress(&cinfo);
1675        return buf;
1676}
1677
1678int drawjpgsw(struct jpeg_decompress_struct* cinfo, unsigned char* buf, int posx, int posy, int width, int height, int colbytes, int mwidth, int mheight, int scalewidth, int scaleheight, int halign, int valign)
1679{
1680        int aktline = 0, x = 0, py = 0, px = 0, row_stride = 0, pyw = 0;
1681        int width4 = width * 4, width8 = width * 8, aktline1 = 0;
1682        unsigned char red, green, blue;
1683        unsigned long color = 0;
1684        JSAMPARRAY buffer = NULL;
1685        unsigned char *tmpbuf = NULL;
1686        unsigned char *scalebuf = NULL;
1687
1688        if(cinfo == NULL && buf == NULL) return 1;
1689
1690        if(cinfo != NULL)
1691        {
1692                row_stride = cinfo->output_width * cinfo->output_components;
1693                buffer = (cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, row_stride, 1);
1694        }
1695        else
1696                row_stride = width * colbytes;
1697
1698        if(accelfb != NULL && accelfb->varfbsize > width8 && (scalewidth != 0 || scaleheight != 0) && (scalewidth != width || scaleheight != height))
1699        {
1700                if(halign == CENTER)
1701                        posx += (mwidth >> 1) - (scalewidth >> 1);
1702                else if(halign == RIGHT)
1703                        posx += mwidth - scalewidth;
1704                if(valign == MIDDLE)
1705                        posy += (mheight >> 1) - (scaleheight >> 1);
1706                else if(valign == BOTTOM)
1707                        posy += mheight - scaleheight;
1708       
1709                int nposy = posy;
1710                py = -1;
1711
1712                m_lock(&status.accelfbmutex, 16);
1713                if(cinfo != NULL) aktline = cinfo->output_scanline;
1714
1715                if(cinfo != NULL)
1716                {
1717                        while(aktline < height)
1718                        {
1719                                jpeg_read_scanlines(cinfo, buffer, 1);
1720                                aktline = cinfo->output_scanline;
1721
1722                                py++;
1723                                pyw = width * py;
1724                                for(x = 0; x < width; x++)
1725                                {
1726                                        px = colbytes * x;
1727                                        red = buffer[0][px];
1728                                        if(colbytes > 2)
1729                                        {
1730                                                green = buffer[0][px + 1];
1731                                                blue = buffer[0][px + 2];
1732                                                color = (255 << 24) | (red << 16) | (green << 8) | blue;
1733                                        }
1734                                        else
1735                                                color = (255 << 24) | (red << 16) | (red << 8) | red;
1736
1737                                        drawpixelfb(accelfb, pyw + x, 0, color);
1738                                }
1739
1740                                if((py * width4) + (width8) >= accelfb->varfbsize)
1741                                {
1742                                        py++;
1743                                        if(scaleheight > 0)
1744                                        {
1745                                                float tmp = (float)height / (float)scaleheight;
1746                                                if(tmp > 0)
1747                                                {
1748                                                        tmp = (float)py / tmp;
1749                                                        blitscale(posx, nposy, width, py, scalewidth, (int)(tmp + 0.5), 0);
1750                                                        nposy += (int)(tmp + 0.5);
1751                                                }
1752                                        }
1753                                        py = -1;
1754                                }
1755                        }
1756                }
1757                else
1758                {
1759                        while(aktline < height)
1760                        {
1761                                aktline1 = aktline * row_stride;
1762                                aktline++;
1763
1764                                py++;
1765                                pyw = width * py;
1766                                for(x = 0; x < width; x++)
1767                                {
1768                                        px = colbytes * x;
1769                                        red = buf[aktline1 + px];
1770                                        if(colbytes > 2)
1771                                        {
1772                                                green = buf[aktline1 + (px + 1)];
1773                                                blue = buf[aktline1 + (px + 2)];
1774                                                color = (255 << 24) | (red << 16) | (green << 8) | blue;
1775                                        }
1776                                        else
1777                                                color = (255 << 24) | (red << 16) | (red << 8) | red;
1778
1779                                        drawpixelfb(accelfb, pyw + x, 0, color);
1780                                }
1781
1782                                if((py * width4) + (width8) >= accelfb->varfbsize)
1783                                {
1784                                        py++;
1785                                        if(scaleheight > 0)
1786                                        {
1787                                                float tmp = (float)height / (float)scaleheight;
1788                                                if(tmp > 0)
1789                                                {
1790                                                        tmp = (float)py / tmp;
1791                                                        blitscale(posx, nposy, width, py, scalewidth, (int)(tmp + 0.5), 0);
1792                                                        nposy += (int)(tmp + 0.5);
1793                                                }
1794                                        }
1795                                        py = -1;
1796                                }
1797                        }
1798                }
1799
1800                //blit the rest
1801                if(py > -1 && scaleheight > 0)
1802                {
1803                        int tmp = scaleheight - (nposy - posy);
1804                        blitscale(posx, nposy, width, py, scalewidth, tmp, 0);
1805                }
1806                m_unlock(&status.accelfbmutex, 16);
1807        }
1808        else if((scalewidth != 0 || scaleheight != 0) && (scalewidth != width || scaleheight != height) && cinfo != NULL)
1809        {
1810                if(halign == CENTER)
1811                        posx += (mwidth >> 1) - (scalewidth >> 1);
1812                else if(halign == RIGHT)
1813                        posx += mwidth - scalewidth;
1814                if(valign == MIDDLE)
1815                        posy += (mheight >> 1) - (scaleheight >> 1);
1816                else if(valign == BOTTOM)
1817                        posy += mheight - scaleheight;
1818               
1819                int i = 0;
1820                int location = 0;
1821                tmpbuf = (unsigned char*)malloc(width*height*3);       
1822                aktline = cinfo->output_scanline;
1823                while(aktline < height)
1824                {
1825                        jpeg_read_scanlines(cinfo, buffer, 1);
1826                        aktline = cinfo->output_scanline;
1827                        for(i=0; i<width*3; i++)
1828                                tmpbuf[location++] = buffer[0][i];
1829                }
1830                //extendet_scale wegen schreibfehler in alter config
1831                if(getconfigint("extended_scale", NULL) == 1 || getconfigint("extendet_scale", NULL) == 1)
1832                        scalebuf = resize(tmpbuf, width, height, scalewidth, scaleheight, 2, NULL, 1);
1833                else   
1834                        scalebuf = resize(tmpbuf, width, height, scalewidth, scaleheight, 1, NULL, 1);
1835               
1836                aktline = 0;
1837                while(aktline < scaleheight)
1838                {
1839                        py = (posy + aktline) * skinfb->width;
1840                        aktline1 = aktline * scalewidth * colbytes;
1841                        for(x = 0; x < scalewidth; x++)
1842                        {
1843                                px = colbytes * x;
1844                                red = scalebuf[px + aktline1];
1845
1846                                if(colbytes > 2)
1847                                {
1848                                        green = scalebuf[aktline1 + (px + 1)];
1849                                        blue = scalebuf[aktline1 + (px + 2)];
1850                                        color = (255 << 24) | (red << 16) | (green << 8) | blue;
1851                                }
1852                                else
1853                                        color = (255 << 24) | (red << 16) | (red << 8) | red;
1854                       
1855                                drawpixelfast(posx + x, py, color);
1856                        }
1857                        aktline++;
1858                }
1859                free(scalebuf);
1860        }       
1861        else
1862        {
1863                if(width > mwidth) width = mwidth;
1864                if(height > mheight) height = mheight;
1865
1866                if(halign == CENTER)
1867                        posx += (mwidth >> 1) - (width >> 1);
1868                else if(halign == RIGHT)
1869                        posx += mwidth - width;
1870                if(valign == MIDDLE)
1871                        posy += (mheight >> 1) - (height >> 1);
1872                else if(valign == BOTTOM)
1873                        posy += mheight - height;
1874
1875                if(cinfo != NULL) aktline = cinfo->output_scanline;
1876                while(aktline < height)
1877                {
1878                        if(cinfo != NULL)
1879                        {
1880                                jpeg_read_scanlines(cinfo, buffer, 1);
1881                                aktline = cinfo->output_scanline;
1882                        }
1883                        else
1884                                aktline++;
1885                               
1886                        aktline1 = (aktline - 1) * row_stride;
1887
1888                        py = (posy + aktline - 1) * skinfb->width;
1889                        for(x = 0; x < width; x++)
1890                        {
1891                                px = colbytes * x;
1892
1893                                if(cinfo != NULL)
1894                                        red = buffer[0][px];
1895                                else
1896                                        red = buf[aktline1 + px];
1897
1898                                if(colbytes > 2)
1899                                {
1900                                        if(cinfo != NULL)
1901                                        {
1902                                                green = buffer[0][px + 1];
1903                                                blue = buffer[0][px + 2];
1904                                                color = (255 << 24) | (red << 16) | (green << 8) | blue;
1905                                        }
1906                                        else
1907                                        {
1908                                                green = buf[aktline1 + (px + 1)];
1909                                                blue = buf[aktline1 + (px + 2)];
1910                                                color = (255 << 24) | (red << 16) | (green << 8) | blue;
1911                                        }
1912                                }
1913                                else
1914                                        color = (255 << 24) | (red << 16) | (red << 8) | red;
1915
1916                                drawpixelfast(posx + x, py, color);
1917                        }
1918                }
1919        }
1920
1921        return 0;
1922}
1923
1924int readjpgsw(const char* filename, int posx, int posy, int mwidth, int mheight, int scalewidth, int scaleheight, int halign, int valign, int quality)
1925{
1926        struct jpeg_decompress_struct cinfo;
1927        struct jpgerror jerr;
1928        FILE* fd = NULL;
1929        int width = 0, height = 0;
1930
1931        fd = fopen(filename, "rb");
1932        if(fd == NULL)
1933        {
1934                perr("open jpg file %s", filename);
1935                return 1;
1936        }
1937
1938        cinfo.err = jpeg_std_error(&jerr.jerr);
1939        jerr.jerr.error_exit = jpgswerror;
1940        if(setjmp(jerr.setjmpbuf))
1941        {
1942                jpeg_destroy_decompress(&cinfo);
1943                fclose(fd);
1944                return 1;
1945        }
1946
1947        jpeg_create_decompress(&cinfo);
1948        jpeg_stdio_src(&cinfo, fd);
1949        jpeg_read_header(&cinfo, TRUE);
1950
1951        cinfo.out_color_space = JCS_RGB;
1952
1953        if(quality == 0)
1954        {
1955                cinfo.dct_method = JDCT_IFAST;
1956                cinfo.do_fancy_upsampling = FALSE;
1957                cinfo.two_pass_quantize = FALSE;
1958                cinfo.dither_mode = JDITHER_ORDERED;
1959        }
1960
1961        cinfo.scale_num = 1;
1962        cinfo.scale_denom = 1;
1963
1964        width = cinfo.image_width;
1965        height = cinfo.image_height;
1966
1967        if(scalewidth != 0 || scaleheight != 0)
1968        {
1969                //auto scale to mwidth / mheight
1970                if(scalewidth == 1 && scaleheight == 1)
1971                        calcautoscale(width, height, mwidth, mheight, &scalewidth, &scaleheight);
1972                else if(scalewidth == 2 && scaleheight == 2)
1973                        calcautoscale(width, height, mwidth, mheight - 25, &scalewidth, &scaleheight);
1974
1975                if(scalewidth == 0) scalewidth = width;
1976                if(scaleheight == 0) scaleheight = height;
1977                if(scalewidth > mwidth) scalewidth = mwidth;
1978                if(scaleheight > mheight) scaleheight = mheight;
1979
1980                if(quality == 0 || quality == 1)
1981                {
1982                        int tmpwidth = width;
1983                        int tmpheight = height;
1984                        while(scalewidth < tmpwidth || scaleheight < tmpheight)
1985                        {
1986                                tmpwidth /= 2; tmpheight /= 2; cinfo.scale_denom *= 2;
1987                                if(cinfo.scale_denom > 8) break;
1988                        }
1989                }
1990        }
1991
1992        jpeg_start_decompress(&cinfo);
1993        width = cinfo.output_width;
1994        height = cinfo.output_height;
1995
1996        drawjpgsw(&cinfo, NULL, posx, posy, width, height, cinfo.output_components, mwidth, mheight, scalewidth, scaleheight, halign, valign);
1997
1998        jpeg_finish_decompress(&cinfo);
1999        jpeg_destroy_decompress(&cinfo);
2000        fclose(fd);
2001        return 0;
2002}
2003
2004unsigned char* readpng(const char* filename, unsigned long* width, unsigned long* height, unsigned long* rowbytes, int* channels, int posx, int posy, int mwidth, int mheight, int halign, int valign)
2005{
2006        FILE *fd = NULL;
2007        int ret, bit_depth, color_type;
2008        unsigned char *buf = NULL;
2009        static png_structp png_ptr = NULL;
2010        static png_infop info_ptr = NULL;
2011        double gamma;
2012        png_uint_32 y;
2013        png_bytepp row_pointers = NULL;
2014        png_bytep sig = NULL;
2015
2016        fd = fopen(filename, "rb");
2017        if(fd == NULL)
2018        {
2019                perr("open png file %s", filename);
2020                return NULL;
2021        }
2022
2023        sig = malloc(8);
2024        if(sig == NULL)
2025        {
2026                err("no memory");
2027                fclose(fd);
2028                return NULL;
2029        }
2030
2031        fread(sig, 1, 8, fd);
2032        ret = png_check_sig(sig, 8);
2033        if(ret == 0)
2034        {
2035                err("%s is not a PNG file", filename);
2036                free(sig);
2037                fclose(fd);
2038                return NULL;
2039        }
2040
2041        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
2042        if(png_ptr == NULL)
2043        {
2044                err("%s no memory", filename);
2045                free(sig);
2046                fclose(fd);
2047                return NULL;
2048        }
2049
2050        info_ptr = png_create_info_struct(png_ptr);
2051        if(info_ptr == NULL)
2052        {
2053                png_destroy_read_struct(&png_ptr, NULL, NULL);
2054                err("%s no memory", filename);
2055                free(sig);
2056                fclose(fd);
2057                return NULL;
2058        }
2059
2060        if(png_jmpbuf(png_ptr) == NULL)
2061        {
2062                png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
2063                err("%s unknown error (png_jmpbuf = NULL)", filename);
2064                free(sig);
2065                fclose(fd);
2066                return NULL;   
2067        }
2068
2069        ret = setjmp(png_jmpbuf(png_ptr));
2070        if(ret != 0)
2071        {
2072                png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
2073                err("%s unknown error (libpng longjmp)", filename);
2074                free(sig);
2075                fclose(fd);
2076                return NULL;
2077        }
2078
2079        png_init_io(png_ptr, fd);
2080        png_set_sig_bytes(png_ptr, 8);
2081        png_read_info(png_ptr, info_ptr);
2082        png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)width, (png_uint_32*)height, &bit_depth, &color_type, NULL, NULL, NULL);
2083
2084        if(color_type == PNG_COLOR_TYPE_PALETTE)
2085                png_set_expand(png_ptr);
2086        if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
2087                png_set_expand(png_ptr);
2088        if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
2089                png_set_expand(png_ptr);
2090        if(bit_depth == 16)
2091                png_set_strip_16(png_ptr);
2092        if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2093                png_set_gray_to_rgb(png_ptr);
2094        if(png_get_gAMA(png_ptr, info_ptr, &gamma))
2095                png_set_gamma(png_ptr, 2.2, gamma);
2096
2097        png_read_update_info(png_ptr, info_ptr);
2098        *rowbytes = png_get_rowbytes(png_ptr, info_ptr);
2099        *channels = (int)png_get_channels(png_ptr, info_ptr);
2100
2101        buf = malloc((*rowbytes) * (*height));
2102        if(buf == NULL)
2103        {
2104                png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
2105                err("%s no memory", filename);
2106                free(sig);
2107                fclose(fd);
2108                return NULL;
2109        }
2110
2111        row_pointers = (png_bytepp)malloc((*height) * sizeof(png_bytep));
2112        if(row_pointers == NULL)
2113        {
2114                png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
2115                err("%s unknown error", filename);
2116                free(sig);
2117                fclose(fd);
2118                return NULL;
2119        }
2120
2121        for (y = 0; y < (*height); ++y)
2122                row_pointers[y] = (png_bytep)buf + y * (*rowbytes);
2123
2124        png_read_image(png_ptr, row_pointers);
2125        free(row_pointers);
2126        row_pointers = NULL;
2127
2128        png_read_end(png_ptr, NULL);
2129        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
2130
2131        free(sig);
2132        fclose(fd);
2133
2134        debug(100, "png width=%ld height=%ld channels=%d rowbytes=%ld", *width, *height, *channels, *rowbytes);
2135
2136        return buf;
2137}
2138
2139void drawpic(const char* filename, int posx, int posy, int scalewidth, int scaleheight, int mwidth, int mheight, int halign, int valign, int transparent, int quality, int add)
2140{
2141        unsigned char *buf = NULL, *scalebuf = NULL;
2142        int memfd = -1, py = 0, pyh = 0, pxw = 0, diff = 0;
2143        unsigned long width, height, rowbytes;
2144        int channels, length;
2145        unsigned char *src;
2146        png_uint_32 y, x;
2147        struct pic* picnode = NULL;
2148        int decoding = getconfigint("pichwdecode", NULL);
2149        int pictype = 0; //0 = png, 1 = jpg HW, 2 = jpg SW
2150        unsigned char r = 0, g = 0, b = 0, ralpha = 0;
2151
2152        if(filename == NULL) return;
2153
2154        length = strlen(filename);
2155        if(filename[length - 1] == 'g' && filename[length - 2] == 'n' && filename[length - 3] == 'p')
2156                pictype = 0;
2157        else if(decoding == 1)
2158                pictype = 1;
2159        else
2160                pictype = 2;
2161
2162        picnode = getpic((char*)filename);
2163        if(picnode == NULL)
2164        {
2165                if(pictype == 0)
2166                        buf = readpng(filename, &width, &height, &rowbytes, &channels, 0, 0, 0, 0, 0, 0);
2167                else if(pictype == 1)
2168                        readjpg(filename, &width, &height, &rowbytes, &channels, &buf, &memfd);
2169                else if(pictype == 2 && add == 0)
2170                        readjpgsw(filename, posx, posy, mwidth, mheight, scalewidth, scaleheight, halign, valign, quality);
2171                else if(pictype == 2 && add == 1)
2172                        buf = loadjpg((char*)filename, &width, &height, &rowbytes, &channels, 1);
2173                if(add == 1)
2174                        picnode = addpic((char*)filename, buf, memfd, width, height, rowbytes, channels, 0, 0, NULL);
2175        }
2176        else
2177        {
2178                buf = picnode->picbuf;
2179                width = picnode->width;
2180                height = picnode->height;
2181                rowbytes = picnode->rowbytes;
2182                channels = picnode->channels;
2183                memfd = picnode->memfd;
2184        }
2185
2186        if(buf == NULL) return;
2187
2188        if(pictype == 0 && (scalewidth != 0 || scaleheight != 0) && (scalewidth != width || scaleheight != height))
2189        {
2190                //auto scale to mwidth / mheight
2191                if(scalewidth == 1 && scaleheight == 1)
2192                        calcautoscale(width, height, mwidth, mheight, &scalewidth, &scaleheight);
2193                else if(scalewidth == 2 && scaleheight == 2)
2194                        calcautoscale(width, height, mwidth, mheight - 25, &scalewidth, &scaleheight);
2195       
2196                if(scalewidth == 0) scalewidth = width;
2197                if(scaleheight == 0) scaleheight = height;
2198                if(picnode == NULL)
2199                        scalebuf = scale(buf, rowbytes / channels, height, channels, scalewidth, scaleheight, 1);
2200                else
2201                {
2202                        scalebuf = scale(buf, rowbytes / channels, height, channels, scalewidth, scaleheight, 0);
2203                        buf = NULL;
2204                        picnode = NULL;
2205                }
2206                if(scalebuf != NULL)
2207                {
2208                        buf = scalebuf;
2209                        width = scalewidth;
2210                        height = scaleheight;
2211                        rowbytes = scalewidth * (channels);
2212                }
2213        }
2214
2215        if(pictype == 0)
2216        {
2217                if(width > mwidth) width = mwidth;
2218                if(height > mheight) height = mheight;
2219
2220                if(halign == CENTER)
2221                        posx += (mwidth >> 1) - (width >> 1);
2222                else if(halign == RIGHT)
2223                        posx += mwidth - width;
2224                if(valign == MIDDLE)
2225                        posy += (mheight >> 1) - (height >> 1);
2226                else if(valign == BOTTOM)
2227                        posy += mheight - height;
2228
2229                py = (posy * skinfb->width) + posx;
2230                pyh = py + (height * skinfb->width);
2231                src = buf;
2232                diff = rowbytes - (width * channels);
2233
2234                if(channels == 3)
2235                {
2236                        for(y = py; y < pyh; y += skinfb->width)
2237                        {
2238                                pxw = y + width;
2239                                for(x = y; x < pxw; x++)
2240                                {
2241                                        skinfb->fblong[x] = (255 << 24) | (src[0] << 16) | (src[1] << 8) | src[2];
2242                                        src += 3;
2243                                }
2244                                src += diff;
2245                        }
2246                }
2247                else
2248                {
2249                        for(y = py; y < pyh; y += skinfb->width)
2250                        {
2251                                pxw = y + width;
2252
2253                                if(transparent == 1)
2254                                {
2255                                        for(x = y; x < pxw; x++)
2256                                        {
2257                                                if(src[3] < 10)
2258                                                {
2259                                                        src += 4;
2260                                                        continue;
2261                                                }
2262                                                skinfb->fblong[x] = (src[3] << 24) | (src[0] << 16) | (src[1] << 8) | src[2];
2263                                                src += 4;
2264                                        }
2265                                }
2266                                else
2267                                {
2268                                        for(x = y; x < pxw; x++)
2269                                        {
2270                                                //renderquality 255-0 = best
2271                                                if(src[3] > 200)
2272                                                        skinfb->fblong[x] = (255 << 24) | (src[0] << 16) | (src[1] << 8) | src[2];
2273                                                else if(src[3] < 50)
2274                                                {
2275                                                        src += 4;
2276                                                        continue;
2277                                                }
2278                                                else
2279                                                {
2280                                                        ralpha = 255 - src[3];
2281                                                        alpha_composite(r, src[0], src[3], ralpha, (skinfb->fblong[x] & 0xff0000) >> 16);
2282                                                        alpha_composite(g, src[1], src[3], ralpha, (skinfb->fblong[x] & 0x00ff00) >> 8);
2283                                                        alpha_composite(b, src[2], src[3], ralpha, skinfb->fblong[x] & 0xff);
2284                                                        skinfb->fblong[x] = (255 << 24) | r << 16 | g << 8 | b;
2285                                                }
2286                                                src += 4;
2287                                        }
2288                                }
2289                                src += diff;
2290                        }
2291                }
2292        }
2293        else if(pictype == 1 && memfd > -1)
2294                blitjpg(buf, posx, posy, width, height, scalewidth, scaleheight, mwidth, mheight, halign, valign);
2295        else if(pictype == 2 && picnode != NULL)
2296                drawjpgsw(NULL, buf, posx, posy, width, height, rowbytes / width, mwidth, mheight, scalewidth, scaleheight, halign, valign);
2297
2298        if(picnode == NULL)
2299        {
2300                if(pictype == 0)
2301                        free(buf);
2302                else if(pictype == 1)
2303                        freebpamem(memfd, buf, width * height * 3);
2304        }
2305}
2306
2307//flag 0: don't del outside
2308//flag 1: del outside
2309void drawcircle(int x0, int y0, int radius, int startangle, int endangle, long color, int transparent, char* bg, int flag)
2310{
2311        float d = (5/4.0) - radius, theta;
2312        int x = 0, y = radius, px = 0, py = 0;
2313
2314        transparent = (transparent - 255) * -1;
2315        unsigned long tmpcol = color | ((transparent & 0xff) << 24);
2316
2317        while(y > x)
2318        {
2319                if(d < 0)
2320                        d += 2 * x + 3;
2321                else
2322                {
2323                        d += (2 * x) - (2 * y) + 5;
2324                        y--;
2325                }
2326                x++;
2327
2328                theta = (atan((float)y / x)) * (180 / 3.14);
2329
2330                //rt2
2331                if(theta >= startangle && theta <= endangle)
2332                {
2333                        px = x0 + x;
2334                        py = (y0 - y) * skinfb->width;
2335                        drawpixelfast(px, py, tmpcol);
2336                        if(flag == 1)
2337                        {
2338                                int i = radius - x;
2339                                int r = radius - y;
2340                                for(; i > 0; i--)
2341                                        drawpixelfast(px + i, py, getpixelbuf(bg, x + i - 1, r, radius));
2342                        }
2343                }
2344                //rb2
2345                if(360 - theta >= startangle && 360 - theta <= endangle)
2346                {
2347                        px = x0 + x;
2348                        py = (y0 + y) * skinfb->width;
2349                        drawpixelfast(px, py, tmpcol);
2350                        if(flag == 1)
2351                        {
2352                                int i = radius - x;
2353                                int r = y - 1;
2354                                for(; i > 0; i--)
2355                                        drawpixelfast(px + i, py, getpixelbuf(bg, x + i - 1, r, radius));
2356                        }
2357                }
2358                //rt1
2359                if(90 - theta >= startangle && 90 - theta <= endangle)
2360                {
2361                        px = x0 + y;
2362                        py = (y0 - x) * skinfb->width;
2363                        drawpixelfast(px, py, tmpcol);
2364                        if(flag == 1)
2365                        {
2366                                int i = radius - y;
2367                                int r = radius - x;
2368                                for(; i > 0; i--)
2369                                        drawpixelfast(px + i, py, getpixelbuf(bg, y + i - 1, r, radius));
2370                        }
2371                }
2372                //rb1
2373                if(270 + theta >= startangle && 270 + theta <= endangle)
2374                {
2375                        px = x0 + y;
2376                        py = (y0 + x) * skinfb->width;
2377                        drawpixelfast(px, py, tmpcol);
2378                        if(flag == 1)
2379                        {
2380                                int i = radius - y;
2381                                int r = x - 1;
2382                                for(; i > 0; i--)
2383                                        drawpixelfast(px + i, py, getpixelbuf(bg, y + i - 1, r, radius));
2384                        }
2385                }
2386                //lt2
2387                if(180 - theta >= startangle && 180 - theta <= endangle)
2388                {
2389                        px = x0 - x;
2390                        py = (y0 - y) * skinfb->width;
2391                        drawpixelfast(px, py, tmpcol);
2392                        if(flag == 1)
2393                        {
2394                                int i = radius - x;
2395                                int r = radius - y;
2396                                for(; i > 0; i--)
2397                                        drawpixelfast(px - i, py, getpixelbuf(bg, radius - x - i, r, radius));
2398                        }
2399                }
2400                //lb2
2401                if(180 + theta >= startangle && 180 + theta <= endangle)
2402                {
2403                        px = x0 - x;
2404                        py = (y0 + y) * skinfb->width;
2405                        drawpixelfast(px, py, tmpcol);
2406                        if(flag == 1)
2407                        {
2408                                int i = radius - x;
2409                                int r = y - 1;
2410                                for(; i > 0; i--)
2411                                        drawpixelfast(px - i, py, getpixelbuf(bg, radius - x - i, r, radius));
2412                        }
2413                }
2414                //lt1
2415                if(90 + theta >= startangle && 90 + theta <= endangle)
2416                {
2417                        px = x0 - y;
2418                        py = (y0 - x) * skinfb->width;
2419                        drawpixelfast(px, py, tmpcol);
2420                        if(flag == 1)
2421                        {
2422                                int i = radius - y;
2423                                int r = radius - x;
2424                                for(; i > 0; i--)
2425                                        drawpixelfast(px - i, py, getpixelbuf(bg, radius - y - i, r, radius));
2426                        }
2427                }
2428                //lb1
2429                if(270 - theta >= startangle && 270 - theta <= endangle)
2430                {
2431                        px = x0 - y;
2432                        py = (y0 + x) * skinfb->width;
2433                        drawpixelfast(px, py, tmpcol);
2434                        if(flag == 1)
2435                        {
2436                                int i = radius - y;
2437                                int r = x - 1;
2438                                for(; i > 0; i--)
2439                                        drawpixelfast(px - i, py, getpixelbuf(bg, radius - y - i , r, radius));
2440                        }
2441                }
2442        }
2443}
2444
2445int drawchar(struct font* font, FT_ULong currentchar, int posx, int posy, int mwidth, int height, long color, int transparent, int charspace, int test)
2446{
2447        int space = 0, y = 0, x = 0, py = 0, pxw = 0, pyh = 0, max = 220, min = 35;
2448        FT_UInt glyphindex;
2449        FT_Vector kerning;
2450        FT_Error ret;
2451        FTC_SBit sbit;
2452        unsigned long tmpcol = 0;
2453        unsigned char red, green, blue, r, g, b;
2454        unsigned char* src = NULL;
2455        unsigned char ralpha = 0;
2456
2457        if(currentchar == 32) space = 1;
2458
2459        glyphindex = FT_Get_Char_Index(font->face, currentchar);
2460        if(glyphindex == 0)
2461        {
2462                debug(100, "FT_Get_Char_Index for char %x %c failed", (int)currentchar, (int)currentchar);
2463                return 0;
2464        }
2465
2466        FTC_Node anode;
2467        ret = FTC_SBitCache_Lookup(font->cache, &font->desc, glyphindex, &sbit, &anode);
2468        if(ret != 0)
2469        {
2470                err("FTC_SBitCache_Lookup for char %x %c failed. Error: 0x%.2X", (int)currentchar, (int)currentchar, ret);
2471                return 0;
2472        }
2473
2474        if(font->use_kerning)
2475        {
2476                FT_Get_Kerning(font->face, font->prev_glyphindex, glyphindex, ft_kerning_default, &kerning);
2477                font->prev_glyphindex = glyphindex;
2478                kerning.x >>= 6;
2479        }
2480        else
2481                kerning.x = 0;
2482
2483        if(test == 1 || space == 1)
2484                return sbit->xadvance + kerning.x + charspace;
2485
2486        if(posx + sbit->xadvance > mwidth)
2487                return -1;
2488
2489        if(status.fasttextrender == 1)
2490        {
2491                max = 150;
2492                min = 100;
2493        }
2494       
2495        red = (color & 0xff0000) >> 16;
2496        green = (color & 0x00ff00) >> 8;
2497        blue = color & 0xff;
2498        transparent = transparent & 0xff;
2499        tmpcol = color | transparent << 24;
2500        posy = posy + height - sbit->top;
2501        posx = posx + sbit->left + kerning.x;
2502               
2503        py = (posy * skinfb->width) + posx;
2504        pyh = py + (sbit->height * skinfb->width);
2505        src = sbit->buffer;
2506               
2507        for(y = py; y < pyh; y += skinfb->width)
2508        {
2509                pxw = y + sbit->pitch;
2510                for(x = y; x < pxw; x++)
2511                {
2512                        if(src[0] > min)
2513                        {
2514                                //renderquality 255-0 = best
2515                                if(src[0] > max)
2516                                        skinfb->fblong[x] = tmpcol;
2517                                else
2518                                {
2519                                        ralpha = 255 - src[0];
2520                                        alpha_composite(r, red, src[0], ralpha, (skinfb->fblong[x] & 0xff0000) >> 16);
2521                                        alpha_composite(g, green, src[0], ralpha, (skinfb->fblong[x] & 0x00ff00) >> 8);
2522                                        alpha_composite(b, blue, src[0], ralpha, skinfb->fblong[x] & 0xff);
2523                                        skinfb->fblong[x] = transparent << 24 | r << 16 | g << 8 | b;
2524                                }
2525                        }
2526                        src++;
2527                }
2528        }
2529
2530        return sbit->xadvance + kerning.x + charspace;
2531}
2532
2533void getstringwh(struct font* font, char *string, int *stringwidth, int *stringheight, int charspace)
2534{
2535        FT_ULong cret = 0;
2536        if(string == NULL) return;
2537
2538        while(*string != '\0' && *string != '\n')
2539        {
2540                string += strfreetype(string, &cret);
2541                *stringwidth += drawchar(font, cret, 0, 0, 0, 0, 0, 0, charspace, 1);
2542                string++;
2543        }
2544}
2545
2546int calcstrhalign(struct font* aktfont, char *string, int posx, int mwidth, int halign, int charspace)
2547{
2548        int stringwidth = 0, stringheight = 0;
2549        if(string == NULL) return 0;
2550
2551        switch(halign)
2552        {
2553                case TEXTCENTER:
2554                case CENTER:
2555                        getstringwh(aktfont, string, &stringwidth, &stringheight, charspace);
2556                        if(stringwidth < mwidth) posx += ((mwidth - stringwidth) >> 1);
2557                        break;
2558                case TEXTRIGHT:
2559                case RIGHT:
2560                        getstringwh(aktfont, string, &stringwidth, &stringheight, charspace);
2561                        if(stringwidth < mwidth) posx += mwidth - stringwidth;
2562                        break;
2563        }
2564        return posx;
2565}
2566
2567int calcstrvalign(char *string, int posy, int oldposy, int mheight, int fontsize, int linecount, int valign)
2568{
2569        if(string == NULL) return 0;
2570
2571        switch(valign)
2572        {
2573                case TEXTMIDDLE:
2574                case MIDDLE:
2575                        posy += (mheight >> 1) - ((fontsize * linecount) >> 1);
2576                        if(posy < oldposy) posy = oldposy;
2577                        break;
2578                case TEXTBOTTOM:
2579                case BOTTOM:
2580                        posy += mheight - (fontsize * linecount);
2581                        if(posy < oldposy) posy = oldposy;
2582                        break;
2583        }
2584
2585        return posy;
2586}
2587
2588struct font* setaktfont(char* fontname, int fontsize)
2589{
2590        struct font* aktfont = NULL;
2591
2592        if(fontname != NULL) aktfont = getfont(fontname);
2593        if(aktfont == NULL) aktfont = font;
2594
2595        aktfont->desc.width = fontsize;
2596        aktfont->desc.height = fontsize;
2597        aktfont->desc.flags = FT_LOAD_DEFAULT;
2598        aktfont->prev_glyphindex = 0;
2599
2600        return aktfont;
2601}
2602
2603void wrapstr(char* string, char* fontname, int fontsize, int mwidth, int charspace)
2604{
2605        int posx = 0;
2606        int stringheight = 0, stringwidth = 0;
2607        struct font* aktfont = NULL;
2608        char* tmpstr = NULL, *origstr = string;
2609        unsigned char c = 0;
2610
2611        if(string == NULL) return;
2612        aktfont = setaktfont(fontname, fontsize);
2613
2614        while(*string != '\0')
2615        {
2616                stringheight = 0; stringwidth = 0;
2617
2618                tmpstr = string;
2619
2620                while(*string != '\0' && *string != '\n' && *string != ' ' && *string != '-')
2621                        string++;
2622                if(*string == '\n')
2623                {
2624                        string++;
2625                        posx = 0;
2626                }
2627                else
2628                {
2629                        if(*string != '\0') string++;
2630                        c = *string; *string = '\0';
2631
2632                        getstringwh(aktfont, tmpstr, &stringwidth, &stringheight, charspace);
2633                        *string = c;
2634
2635                        posx += stringwidth;
2636                }
2637
2638                if(posx > mwidth && tmpstr > origstr)
2639                {       
2640                        tmpstr--;
2641                        *tmpstr = '\n';
2642                        posx = stringwidth;
2643                }
2644        }
2645}
2646
2647//flag 0: normal
2648//flag 1: password
2649//flag 2: color
2650int drawstring(char* string, unsigned long linecount, unsigned int poscount, unsigned int markpos, int posx, int posy, int mwidth, int mheight, int halign, int valign, char* fontname, int fontsize, long color, int transparent, int wrap, int* lastposx, int* lastposy, int* len, int charspace, int flag)
2651{
2652        int charwidth = 0, lineend = 0;
2653        int charcount = 0;
2654        if(lastposy == NULL || *lastposy == 0) posy=posy + FONTPOSYOFFSET;
2655        int oldposx = posx, aktheight = 0, ret = 0;
2656        int oldposy = posy, oldmwidth = mwidth;
2657        struct font* aktfont = NULL;
2658        long tmpcol = color;
2659        FT_ULong cret = 0;
2660        char* tmpstr = NULL;
2661
2662        if(string == NULL || color == -1) return 1;
2663       
2664        if(flag == 1)
2665        {
2666                string = mask(NULL, strlen(string), "*");
2667                tmpstr = string;
2668        }       
2669
2670        if(flag == 2)
2671        {
2672                color = convertcol(string);
2673        }       
2674
2675        transparent = (transparent - 255) * -1;
2676
2677        if(linecount < 2 && (fontsize == 0 || fontsize > mheight))
2678                fontsize = mheight;
2679
2680        aktfont = setaktfont(fontname, fontsize);
2681
2682        string = string + poscount;
2683
2684        if(fontsize < 5)
2685        {
2686                err("fontsize to small");
2687                if(flag == 1) free(tmpstr);
2688                return 1;
2689        }
2690
2691        posx = calcstrhalign(aktfont, string, posx, oldmwidth, halign, charspace);
2692        posy = calcstrvalign(string, posy, oldposy, mheight, fontsize, linecount, valign);
2693
2694        mwidth = posx + mwidth;
2695        aktheight += fontsize;
2696        if(aktheight > mheight)
2697        {
2698                err("to many textlines");
2699                if(flag == 1) free(tmpstr);
2700                return 1;
2701        }
2702
2703
2704
2705        while(*string != '\0')
2706        {
2707                charcount++;
2708                if(flag != 2)
2709                {
2710                        if(markpos == charcount)
2711                                color = status.markcol;
2712                        else
2713                                color = tmpcol;
2714                }
2715
2716                if(*string == '\n')
2717                {
2718                        if(linecount < 2) break;
2719                        lineend = 0;
2720                        aktheight += fontsize;
2721                        if(aktheight > mheight)
2722                        {
2723                                ret = 1;
2724                                break;
2725                        }
2726                        posy = posy + fontsize;
2727                        posx = oldposx;
2728                        string++;
2729                        posx = calcstrhalign(aktfont, string, posx, oldmwidth, halign, charspace);
2730                        continue;
2731                }
2732
2733                if(lineend == 1)
2734                {
2735                        string++;
2736                        continue;
2737                }
2738
2739                string += strfreetype(string, &cret);
2740
2741                if((charwidth = drawchar(aktfont, cret, posx, posy, mwidth, fontsize, color, transparent, charspace, 0)) == -1)
2742                        lineend = 1;
2743
2744                posx += charwidth;
2745                if(len != NULL) *len += charwidth;
2746                string++;
2747        }
2748        if(lastposx != NULL) *lastposx = posx;
2749        if(lastposy != NULL) *lastposy = posy + fontsize;
2750       
2751        if(flag == 1) free(tmpstr);
2752        return ret;
2753}
2754
2755char* saverect(int posx, int posy, int width, int height)
2756{
2757        char* buf;
2758        int y = 0, len = width * skinfb->colbytes, px = posx * skinfb->colbytes;
2759
2760        buf = malloc(len * height);
2761        if(buf == NULL)
2762        {
2763                err("no memory");
2764                return NULL;
2765        }
2766
2767        for(y = 0; y < height; y++)
2768                memcpy(buf + len * y, skinfb->fb + ((y + posy) * skinfb->pitch) + px, len);
2769
2770        return buf;
2771}
2772
2773char* savescreen(struct skin* node)
2774{
2775        return saverect(node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->rwidth + (node->shadowsize << 1), node->rheight + (node->shadowsize << 1));
2776}
2777
2778//flag 0: no free
2779//flag 1: free
2780void restorerectcheck(char* buf, int posx, int posy, int width, int height, int flag)
2781{
2782        int y = 0, len = width * skinfb->colbytes, px = posx * skinfb->colbytes;
2783
2784        if(buf != NULL)
2785        {
2786                for(y = 0; y < height; y++)
2787                        memcpy(skinfb->fb + ((y + posy) * skinfb->pitch) + px, buf + len * y,  len);
2788
2789                if(flag == 1)
2790                {
2791                        free(buf);
2792                        buf = NULL;
2793                }
2794        }
2795}
2796
2797void restorerect(char* buf, int posx, int posy, int width, int height)
2798{
2799        restorerectcheck(buf, posx, posy, width, height, 1);
2800}
2801
2802void restorescreen(char* buf, struct skin* node)
2803{
2804        restorerectcheck(buf, node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->rwidth + (node->shadowsize << 1), node->rheight + (node->shadowsize << 1), 1);
2805}
2806
2807void restorescreennofree(char* buf, struct skin* node)
2808{
2809        restorerectcheck(buf, node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->rwidth + (node->shadowsize << 1), node->rheight + (node->shadowsize << 1), 0);
2810}
2811
2812//*************** GOST LCD
2813void lcd_fillrect(int posx, int posy, int width, int height, long color, int transparent)
2814{
2815        int y, x;
2816        unsigned long tmpcol;
2817
2818        if(posx < 0) posx = 0;
2819        if(posx > skinfb->width) posx = skinfb->width;
2820        if(posy < 0) posy = 0;
2821        if(posy > skinfb->height) posy = skinfb->height;
2822        if(posx + width > skinfb->width) width = skinfb->width - posx;
2823        if(posy + height > skinfb->height) height = skinfb->height - posy;
2824
2825        if(width <= 0 || height <= 0) return;
2826
2827        transparent = (transparent - 255) * -1;
2828        tmpcol = color | ((transparent & 0xff) << 24);
2829
2830        for(y = 0; y < height; y++)
2831                for(x = 0; x < width; x++)
2832                        drawpixel(posx + x, posy + y, tmpcol);
2833}
2834
2835void lcd_drawrect(int posx, int posy, int width, int height, long color, int transparent)
2836{
2837        fillrect(posx, posy, width, 1, color, transparent);
2838        fillrect(posx, posy + height - 1, width, 1, color, transparent);
2839        fillrect(posx, posy, 1, height, color, transparent);
2840        fillrect(posx + width - 1, posy, 1, height, color, transparent);
2841}
2842//*************** GOST LCD
2843
2844/*
2845void fillrect(int posx, int posy, int width, int height, long color, int transparent)
2846{
2847        int r, g, b;
2848
2849        r = (color >> 16) & 0xFF;
2850        g = (color >> 8) & 0xFF;
2851        b = color & 0xFF;
2852
2853        primary->SetDrawingFlags(primary, DSDRAW_NOFX);
2854        primary->SetColor(primary, r, g, b, transparent);
2855        primary->FillRectangle(primary, posx, posy, width, height);
2856        primary->Flip(primary, NULL, DSFLIP_WAITFORSYNC);
2857}
2858
2859void drawrect(int posx, int posy, int width, int height, long color, int transparent)
2860{
2861        int r, g, b;
2862
2863        r = (color >> 16) & 0xFF;
2864        g = (color >> 8) & 0xFF;
2865        b = color & 0xFF;
2866
2867        primary->SetDrawingFlags(primary, DSDRAW_NOFX);
2868        primary->SetColor(primary, r, g, b, transparent);
2869        primary->DrawRectangle(primary, posx, posy, width, height);
2870        primary->Flip(primary, NULL, DSFLIP_WAITFORSYNC);
2871}
2872*/
2873
2874void fillrect(int posx, int posy, int width, int height, long color, int transparent)
2875{
2876        if(skinfb != lcdskinfb && skinfb != oledskinfb)
2877                blitrect(posx, posy, width, height, color, transparent, 0);
2878        else
2879                lcd_fillrect(posx, posy, width, height, color, transparent);
2880}
2881
2882void drawrect(int posx, int posy, int width, int height, long color, int transparent)
2883{
2884        if(skinfb != lcdskinfb && skinfb != oledskinfb)
2885                blitrect(posx, posy, width, height, color, transparent, 1);
2886        else
2887                lcd_drawrect(posx, posy, width, height, color, transparent);
2888}
2889
2890void clearrect(int posx, int posy, int width, int height)
2891{
2892        fillrect(posx, posy, width, height, 0, 255);
2893}
2894
2895void clearscreen(struct skin* node)
2896{
2897        m_lock(&status.drawingmutex, 0);
2898        clearrect(node->rposx, node->rposy, node->rwidth, node->rheight);
2899        clearshadow(node);
2900        m_unlock(&status.drawingmutex, 0);
2901}
2902
2903void clearscreennolock(struct skin* node)
2904{
2905        clearrect(node->rposx, node->rposy, node->rwidth, node->rheight);
2906        clearshadow(node);
2907}
2908
2909//flag 0 = horizontal
2910//flag 1 = vertical
2911//flag 2 = horizontal (begin to middle, middle to end)
2912//flag 3 = vertical (begin to middle, middle to end)
2913void drawgradient(int posx, int posy, int width, int height, long col1, long col2, int transparent, int flag)
2914{
2915        int p, i, x, y, steps, xstep, ystep, tmp = 0, r = 0;
2916        int xcount = 0, ycount = 0, owidth = width, oheight = height;
2917        unsigned char r3, g3, b3;
2918        unsigned long col = 0;
2919
2920        transparent = (transparent - 255) * -1;
2921
2922        if(flag == LEFTRIGHT || flag == LEFTMIDDLE)
2923        {
2924                if(flag == LEFTMIDDLE) width = width / 2;
2925                if(width < 10)
2926                        steps = width;
2927                if(width < 100)
2928                        steps = width / 2;
2929                else
2930                        steps = width / 5;
2931                xstep = width / steps;
2932                ystep = height;
2933        }
2934        else
2935        {
2936                if(flag == TOPMIDDLE) height = height / 2;
2937                if(height < 10)
2938                        steps = height;
2939                else if(height < 100)
2940                        steps = height / 2;
2941                else
2942                        steps = height / 5;
2943                xstep = width;
2944                ystep = height / steps;
2945        }
2946
2947        unsigned char r1 = (col1 >> 16) & 0xff;
2948        unsigned char g1 = (col1 >> 8) & 0xff;
2949        unsigned char b1 = col1 & 0xff;
2950
2951        unsigned char r2 = (col2 >> 16) & 0xff;
2952        unsigned char g2 = (col2 >> 8) & 0xff;
2953        unsigned char b2 = col2 & 0xff;
2954
2955        int yend = (posy + ystep) * skinfb->width;
2956        int xend = posx + xstep;
2957        posy *= skinfb->width;
2958
2959        for(i = 0; i < steps; i++)
2960        {
2961                p = steps - i;
2962                r3 = (r1 * p + r2 * i) / steps;
2963                g3 = (g1 * p + g2 * i) / steps;
2964                b3 = (b1 * p + b2 * i) / steps;
2965                col = (transparent << 24) | (r3 << 16) | (g3 << 8) | b3;
2966               
2967                r = 0;
2968                for(y = posy; y < yend; y += skinfb->width)
2969                {
2970                        if(r == 0)
2971                        {
2972                                r = 1;
2973                                for(x = posx; x < xend; x++)
2974                                        drawpixelfast(x, y, col);
2975                        }
2976                        else
2977                                memcpy(skinfb->fb + (y + posx) * skinfb->colbytes, skinfb->fb + (posy + posx) * skinfb->colbytes, (xend - posx) * skinfb->colbytes);
2978                }
2979
2980                if(flag == LEFTRIGHT || flag == LEFTMIDDLE)
2981                {
2982                        posx += xstep;
2983                        xcount += xstep;
2984                        xend = posx + xstep;
2985                }
2986                else
2987                {
2988                        tmp = ystep * skinfb->width;
2989                        posy += tmp;
2990                        ycount += ystep;
2991                        yend = posy + tmp;
2992                }
2993        }
2994
2995        if(flag == LEFTMIDDLE || flag == TOPMIDDLE)
2996        {
2997                for(i = 0; i < steps; i++)
2998                {
2999                        p = steps - i;
3000                        r3 = (r2 * p + r1 * i) / steps;
3001                        g3 = (g2 * p + g1 * i) / steps;
3002                        b3 = (b2 * p + b1 * i) / steps;
3003                        col = (transparent << 24) | (r3 << 16) | (g3 << 8) | b3;
3004               
3005                        r = 0;
3006                        for(y = posy; y < yend; y += skinfb->width)
3007                        {
3008                                if(r == 0)
3009                                {
3010                                        r = 1;
3011                                        for(x = posx; x < xend; x++)
3012                                                drawpixelfast(x, y, col);
3013                                }
3014                                else
3015                                        memcpy(skinfb->fb + (y + posx) * skinfb->colbytes, skinfb->fb + (posy + posx) * skinfb->colbytes, (xend - posx) * skinfb->colbytes);
3016                        }
3017                       
3018                        if(flag == LEFTMIDDLE)
3019                        {
3020                                posx += xstep;
3021                                xcount += xstep;
3022                                xend = posx + xstep;
3023                        }
3024                        else
3025                        {
3026                                tmp = ystep * skinfb->width;
3027                                posy += tmp;
3028                                ycount += ystep;
3029                                yend = posy + tmp;
3030                        }
3031                }
3032        }
3033
3034        if(flag == LEFTRIGHT || flag == LEFTMIDDLE)
3035        {
3036                if(owidth > xcount)
3037                {
3038                        int tmp = posx + (owidth - xcount);
3039                        for(y = posy; y < yend; y += skinfb->width)
3040                                for(x = posx; x < tmp; x++)
3041                                        drawpixelfast(x, y, col);
3042                }
3043        }
3044        if(flag == TOPBOTTOM || flag == TOPMIDDLE)
3045        {
3046                if(oheight > ycount)
3047                {
3048                        int tmp = posy + ((oheight - ycount) * skinfb->width);
3049                        for(y = posy; y < tmp; y += skinfb->width)
3050                                for(x = posx; x < xend; x++)
3051                                        drawpixelfast(x, y, col);
3052                }
3053        }
3054}
3055
3056void drawtitlebggradient(struct skin* node)
3057{
3058        if(status.picbordersize > 0)
3059                drawgradient(node->rposx + status.picbordersize, node->rposy + status.picbordersize, node->rwidth - (status.picbordersize << 1), node->rheight - (node->rheight - node->titlesize), node->titlebgcol, node->titlebgcol2, node->transparent, node->titlegradient);
3060        else
3061                drawgradient(node->rposx, node->rposy, node->rwidth, node->rheight - (node->rheight - node->titlesize), node->titlebgcol, node->titlebgcol2, node->transparent, node->titlegradient);
3062}
3063
3064void drawbggradient(struct skin* node)
3065{
3066        drawgradient(node->rposx, node->rposy, node->rwidth, node->rheight, node->bgcol, node->bgcol2, node->transparent, node->gradient);
3067}
3068
3069void drawtitlebgcol(struct skin* node)
3070{
3071        if(status.picbordersize > 0)
3072                fillrect(node->rposx + status.picbordersize, node->rposy + status.picbordersize, node->rwidth - (status.picbordersize << 1), node->rheight - (node->rheight - node->titlesize), node->titlebgcol, node->transparent);
3073        else
3074                fillrect(node->rposx, node->rposy, node->rwidth, node->rheight - (node->rheight - node->titlesize), node->titlebgcol, node->transparent);
3075}
3076
3077void drawbginnercol(struct skin* node)
3078{
3079        fillrect(node->rposx + node->bordersize, node->rposy + node->bordersize, node->rwidth - (node->bordersize << 1), node->rheight - (node->bordersize << 1), node->bgcol, node->transparent);
3080}
3081
3082void drawbgcol(struct skin* node)
3083{
3084        fillrect(node->rposx + node->bgspace, node->rposy + node->bgspace, node->rwidth - (node->bgspace << 1), node->rheight - (node->bgspace << 1), node->bgcol, node->transparent);
3085}
3086
3087void drawtitle(struct skin* node)
3088{
3089        if(status.titlelinesize > 0)
3090                drawstring(node->title, 1, 0, -1, node->iposx, node->rposy + node->bordersize, node->iwidth, node->titlesize - status.titlelinesize, node->titlealign, MIDDLE, node->font, node->fontsize, node->fontcol, node->transparent, 0, NULL, NULL, NULL, node->charspace, 0);
3091        else
3092                drawstring(node->title, 1, 0, -1, node->iposx, node->rposy + node->bordersize, node->iwidth, node->titlesize - node->bordersize, node->titlealign, MIDDLE, node->font, node->fontsize, node->fontcol, node->transparent, 0, NULL, NULL, NULL, node->charspace, 0);
3093        if(status.titlelinesize > 0)
3094                fillrect(node->rposx, node->rposy + node->titlesize + status.picbordersize, node->rwidth, status.titlelinesize, node->bordercol, node->transparent);
3095        else if(node->bordersize > 0)
3096                fillrect(node->rposx, node->rposy + node->titlesize, node->rwidth, node->bordersize, node->bordercol, node->transparent);
3097}
3098
3099void drawprogressbar(struct skin* node)
3100{
3101        int val = 0;
3102
3103        if(node->progresssize > 100) node->progresssize = 100;
3104        val = (((node->iwidth * 100) / 100) * node->progresssize) / 100;
3105        fillrect(node->rposx + node->bordersize, node->rposy + node->bordersize, val, node->iheight, node->progresscol, node->transparent);
3106}
3107
3108void drawmultiprogressbar(struct skin* node)
3109{
3110        struct epgrecord* epgrecord = node->epgrecord;
3111        int val1 = 0, val2 = 0;
3112
3113        while(epgrecord != NULL)
3114        {
3115               
3116                if(epgrecord->posx > 100) epgrecord->posx = 100;
3117                val1 = (((node->iwidth * 100) / 100) * epgrecord->posx) / 100;
3118                if(epgrecord->size > 100) epgrecord->size = 100;
3119                val2 = (((node->iwidth * 100) / 100) * epgrecord->size) / 100;
3120
3121                if(val2 > val1)
3122                        fillrect(node->rposx + node->bordersize + node->bgspace + val1, node->rposy + node->bgspace + node->bordersize, val2 - val1 + (node->bgspace << 1), node->iheight + (node->bgspace << 1), node->progresscol, node->transparent);
3123                epgrecord = epgrecord->next;
3124        }
3125}
3126
3127void drawroundborder(struct skin* node, char* bglt, char* bglb, char* bgrt, char* bgrb)
3128{
3129        int i, rad = status.borderradius;
3130
3131        if(node->borderradius > 0) rad = node->borderradius;
3132        if(rad > (node->rheight >> 1)) rad = (node->rheight >> 1);
3133        int tmpbordersize = rad - node->bordersize;
3134
3135        //left - top
3136        for(i = rad; i > tmpbordersize; i--)
3137                drawcircle(node->rposx + rad, node->rposy + rad, i, 90, 180, node->bordercol, node->transparent, bglt, i == rad);
3138        //left - bottom
3139        for(i = rad; i > tmpbordersize; i--)
3140                drawcircle(node->rposx + rad, node->rposy + node->rheight - 1 - rad, i, 180, 270, node->bordercol, node->transparent, bglb, i == rad);
3141        //right - top
3142        for(i = rad; i > tmpbordersize; i--)
3143                drawcircle(node->rposx + node->rwidth - 1 - rad, node->rposy + rad, i, 0, 90, node->bordercol, node->transparent, bgrt, i == rad);
3144        //right - bottom
3145        for(i = rad; i > tmpbordersize; i--)
3146                drawcircle(node->rposx + node->rwidth - 1 - rad, node->rposy + node->rheight - 1 - rad, i, 270, 360, node->bordercol, node->transparent, bgrb, i == rad);
3147}
3148
3149//TODO: not full implemented
3150void drawpicborder(struct skin* node)
3151{
3152        int borderwidth = status.picbordersize;
3153        int borderheight = status.picbordersize;
3154
3155        //top-left
3156        //drawpic("/home/nit/titan/skin/bs_tl.png", node->rposx + node->bordersize - borderwidth, node->rposy + node->bordersize - borderheight, 0, 0, borderwidth, borderheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3157        drawpic("/home/nit/titan/skin/bs_tl.png", node->rposx, node->rposy, 0, 0, borderwidth, borderheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3158        //top-right
3159        //drawpic("/home/nit/titan/skin/bs_tr.png", node->rposx - node->bordersize + node->rwidth, node->rposy + node->bordersize - borderheight, 0, 0, borderwidth, borderheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3160        drawpic("/home/nit/titan/skin/bs_tr.png", node->rposx + node->rwidth - borderwidth, node->rposy, 0, 0, borderwidth, borderheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3161        //bottom-left
3162        //drawpic("/home/nit/titan/skin/bs_bl.png", node->rposx + node->bordersize - borderwidth, node->rposy - node->bordersize + node->rheight, 0, 0, borderwidth, borderheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3163        drawpic("/home/nit/titan/skin/bs_bl.png", node->rposx, node->rposy + node->rheight - borderheight, 0, 0, borderwidth, borderheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3164        //bottom-right
3165        //drawpic("/home/nit/titan/skin/bs_br.png", node->rposx - node->bordersize + node->rwidth, node->rposy - node->bordersize + node->rheight, 0, 0, borderwidth, borderheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3166        drawpic("/home/nit/titan/skin/bs_br.png", node->rposx + node->rwidth - borderwidth, node->rposy + node->rheight - borderheight, 0, 0, borderwidth, borderheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3167
3168        //top
3169        //drawpic("/home/nit/titan/skin/bs_t.png", node->rposx + node->bordersize, node->rposy + node->bordersize - borderheight, node->rwidth - (node->bordersize << 1), 0, node->rwidth - (node->bordersize << 1), borderheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3170        drawpic("/home/nit/titan/skin/bs_t.png", node->rposx + borderwidth, node->rposy, node->rwidth - (borderwidth << 1), 0, node->rwidth - (borderwidth << 1), borderheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3171        //bottom
3172        //drawpic("/home/nit/titan/skin/bs_b.png", node->rposx + node->bordersize, node->rposy - node->bordersize + node->rheight, node->rwidth - (node->bordersize << 1), 0, node->rwidth - (node->bordersize << 1), borderheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3173        drawpic("/home/nit/titan/skin/bs_b.png", node->rposx + borderwidth, node->rposy + node->rheight - borderheight, node->rwidth - (borderwidth << 1), 0, node->rwidth - (node->bordersize << 1), borderheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3174        //left
3175        //drawpic("/home/nit/titan/skin/bs_l.png", node->rposx + node->bordersize - borderwidth, node->rposy + node->bordersize, 0, node->rheight - (node->bordersize << 1), borderwidth, node->rheight - (node->bordersize << 1), LEFT, TOP, node->transparent, node->picquality, node->picmem);
3176        drawpic("/home/nit/titan/skin/bs_l.png", node->rposx, node->rposy + borderheight, 0, node->rheight - (borderheight << 1), borderwidth, node->rheight - (borderheight << 1), LEFT, TOP, node->transparent, node->picquality, node->picmem);
3177        //right
3178        //drawpic("/home/nit/titan/skin/bs_r.png", node->rposx - node->bordersize + node->rwidth, node->rposy + node->bordersize, 0, node->rheight - (node->bordersize << 1), borderwidth, node->rheight - (node->bordersize << 1), LEFT, TOP, node->transparent, node->picquality, node->picmem);
3179        drawpic("/home/nit/titan/skin/bs_r.png", node->rposx + node->rwidth - borderwidth, node->rposy + borderheight, 0, node->rheight - (borderheight << 1), borderwidth, node->rheight - (borderheight << 1), LEFT, TOP, node->transparent, node->picquality, node->picmem);
3180}
3181
3182void drawborder(struct skin* node)
3183{
3184        if(node->bordersize == 1 && node->rheight > 2 && node->bordertype == 0)
3185                drawrect(node->rposx, node->rposy, node->rwidth, node->rheight, node->bordercol, node->transparent);
3186        else if(node->bordersize == 1 && node->rheight <= 2 && node->bordertype == 0)
3187                fillrect(node->rposx, node->rposy, node->rwidth, node->rheight, node->bordercol, node->transparent);
3188        else
3189        {
3190                if(node->bordertype == 0 || checkbit(node->bordertype, 0) == 1)
3191                        fillrect(node->rposx, node->rposy, node->rwidth, node->bordersize, node->bordercol, node->transparent);
3192                if(node->bordertype == 0 || checkbit(node->bordertype, 1) == 1)
3193                        fillrect(node->rposx, node->rposy + node->rheight - node->bordersize, node->rwidth, node->bordersize, node->bordercol, node->transparent);
3194                if(node->bordertype == 0 || checkbit(node->bordertype, 2) == 1)
3195                        fillrect(node->rposx, node->rposy, node->bordersize, node->rheight, node->bordercol, node->transparent);
3196                if(node->bordertype == 0 || checkbit(node->bordertype, 3) == 1)
3197                        fillrect(node->rposx + node->rwidth - node->bordersize, node->rposy, node->bordersize, node->rheight, node->bordercol, node->transparent);
3198        }
3199}
3200
3201void drawscrollbar(struct skin* node)
3202{
3203        if(node->bordersize == 0)
3204                drawrect(node->rposx + node->rwidth - node->bordersize - node->scrollbarwidth, node->iposy, node->scrollbarwidth, node->iheight, node->bordercol, node->transparent);
3205        else
3206                fillrect(node->rposx + node->rwidth - node->bordersize - node->scrollbarwidth, node->iposy, node->scrollbarbordersize, node->iheight, node->bordercol, node->transparent);
3207
3208        fillrect(node->rposx + node->rwidth - node->bordersize - node->scrollbarwidth, node->iposy + node->scrollbarpos, node->scrollbarwidth, node->scrollbarheight, node->bordercol, node->transparent);
3209}
3210
3211void clearshadow(struct skin* node)
3212{
3213        if(node->shadowsize < 1) return;
3214        switch(node->shadowpos)
3215        {
3216                case BOTTOMLEFT:
3217                        clearrect(node->rposx - node->shadowsize, node->rposy + node->rheight, node->rwidth, node->shadowsize);
3218                        clearrect(node->rposx - node->shadowsize, node->rposy + node->shadowsize, node->shadowsize, node->rheight);
3219                        break;
3220                case BOTTOMRIGHT:
3221                        clearrect(node->rposx + node->shadowsize, node->rposy + node->rheight, node->rwidth, node->shadowsize);
3222                        clearrect(node->rposx + node->rwidth, node->rposy + node->shadowsize, node->shadowsize, node->rheight);
3223                        break;
3224                case TOPLEFT:
3225                        clearrect(node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->rwidth, node->shadowsize);
3226                        clearrect(node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->shadowsize, node->rheight);
3227                        break;
3228                default:
3229                        clearrect(node->rposx + node->shadowsize, node->rposy - node->shadowsize, node->rwidth, node->shadowsize);
3230                        clearrect(node->rposx + node->rwidth, node->rposy - node->shadowsize, node->shadowsize, node->rheight);
3231                        break;
3232        }
3233}
3234
3235void drawshadow(struct skin* node)
3236{
3237        switch(node->shadowpos)
3238        {
3239                case BOTTOMLEFT:
3240                        fillrect(node->rposx - node->shadowsize, node->rposy + node->rheight, node->rwidth, node->shadowsize, node->shadowcol, node->transparent);
3241                        fillrect(node->rposx - node->shadowsize, node->rposy + node->shadowsize, node->shadowsize, node->rheight, node->shadowcol, node->transparent);
3242                        break;
3243                case BOTTOMRIGHT:
3244                        fillrect(node->rposx + node->shadowsize, node->rposy + node->rheight, node->rwidth, node->shadowsize, node->shadowcol, node->transparent);
3245                        fillrect(node->rposx + node->rwidth, node->rposy + node->shadowsize, node->shadowsize, node->rheight, node->shadowcol, node->transparent);
3246                        break;
3247                case TOPLEFT:
3248                        fillrect(node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->rwidth, node->shadowsize, node->shadowcol, node->transparent);
3249                        fillrect(node->rposx - node->shadowsize, node->rposy - node->shadowsize, node->shadowsize, node->rheight, node->shadowcol, node->transparent);
3250                        break;
3251                default:
3252                        fillrect(node->rposx + node->shadowsize, node->rposy - node->shadowsize, node->rwidth, node->shadowsize, node->shadowcol, node->transparent);
3253                        fillrect(node->rposx + node->rwidth, node->rposy - node->shadowsize, node->shadowsize, node->rheight, node->shadowcol, node->transparent);
3254                        break;
3255        }
3256}
3257
3258//flag 0: del background
3259//flag 1: don't del background
3260void drawnode(struct skin* node, int flag)
3261{
3262        long color = 0, color2 = 0;
3263        int len = 0;
3264        char* bglt = NULL, *bglb = NULL, *bgrt = NULL, *bgrb = NULL;
3265       
3266        node->flag = setbit(node->flag, 0);
3267
3268        if(node->bordersize > 0)
3269        {
3270                if((node->child != NULL && status.borderradius > 0) || node->borderradius > 0)
3271                {
3272                        int rad = status.borderradius;
3273
3274                        if(node->borderradius > 0) rad = node->borderradius;
3275                        if(rad > (node->rheight >> 1)) rad = (node->rheight >> 1);
3276
3277                        bglt = saverect(node->rposx, node->rposy, rad, rad);
3278                        bglb = saverect(node->rposx, node->rposy + node->rheight - rad, rad, rad);
3279                        bgrt = saverect(node->rposx + node->rwidth - rad, node->rposy, rad, rad);
3280                        bgrb = saverect(node->rposx + node->rwidth - rad, node->rposy + node->rheight - rad, rad, rad);
3281                }
3282        }
3283
3284        if(flag == 0 && node->bgcol == -1)
3285        {
3286                if(node->child != NULL && status.picbordersize > 0)
3287                        clearrect(node->rposx + node->bordersize, node->rposy + node->bordersize, node->rwidth - (node->bordersize << 1), node->rheight - (node->bordersize << 1));
3288                else
3289                        clearscreennolock(node);
3290        }
3291
3292        if(node->deaktivcol > -1)
3293        {
3294                color = node->deaktivcol;
3295                color2 = node->deaktivcol;
3296        }
3297        else
3298        {
3299                color = node->fontcol;
3300                color2 = node->fontcol2;
3301        }
3302
3303        if(node->shadowsize > 0)
3304                drawshadow(node);
3305        if(node->bgcol > -1)
3306        {
3307                if(node->child != NULL && status.picbordersize > 0)
3308                        drawbginnercol(node);
3309                else
3310                        drawbgcol(node);
3311        }
3312        if(node->child != NULL && status.bgpic != NULL)
3313                drawpic(status.bgpic, node->iposx, node->iposy, node->iwidth, node->iheight, node->iwidth, node->iheight, node->halign, node->valign, node->transparent, node->picquality, node->picmem);
3314        if(node->gradient > 0)
3315                drawbggradient(node);
3316        if(node->titlebgcol > -1)
3317                drawtitlebgcol(node);
3318        if(node->titlegradient > 0)
3319                drawtitlebggradient(node);
3320        if(node->progresssize > 0)
3321                drawprogressbar(node);
3322        if(node->type & MULTIPROGRESSBAR)
3323                drawmultiprogressbar(node);
3324        if(node->selectpic != NULL && !(node->type & FILELIST))
3325                drawpic(node->selectpic, node->iposx, node->iposy, node->iwidth, node->iheight, node->iwidth, node->iheight, LEFT, TOP, node->transparent, node->picquality, node->picmem);
3326        if(node->pic != NULL && !(node->type & FILELIST))
3327                drawpic(node->pic, node->iposx, node->iposy, node->rpicwidth, node->rpicheight, node->iwidth, node->iheight, node->halign, node->valign, node->transparent, node->picquality, node->picmem);
3328
3329        if(node->input != NULL)
3330        {
3331                if(node->type & CHOICEBOX)
3332                {
3333                        if(node->fontcol2 != 0 )
3334                                drawstring(node->input, 1, node->poscount, -1, node->iposx, node->iposy, node->iwidth, node->iheight, RIGHT, node->valign, node->font, node->fontsize, node->fontcol2, node->transparent, 0, NULL, NULL, &len, node->charspace, 0);
3335                        else
3336                                drawstring(node->input, 1, node->poscount, -1, node->iposx, node->iposy, node->iwidth, node->iheight, RIGHT, node->valign, node->font, node->fontsize, color, node->transparent, 0, NULL, NULL, &len, node->charspace, 0);
3337                }
3338                if((node->type & INPUTBOX) || (node->type & INPUTBOXNUM))
3339                {
3340                        if(node->type & PASSWORD)
3341                                drawstring(node->input, 1, node->poscount, node->aktpage, node->iposx, node->iposy, node->iwidth, node->iheight, RIGHT, node->valign, node->font, node->fontsize, color, node->transparent, 0, NULL, NULL, &len, node->charspace, 1);
3342                        else
3343                                drawstring(node->input, 1, node->poscount, node->aktpage, node->iposx, node->iposy, node->iwidth, node->iheight, RIGHT, node->valign, node->font, node->fontsize, color, node->transparent, 0, NULL, NULL, &len, node->charspace, 0);
3344                }
3345        }
3346        if(node->text != NULL)
3347        {
3348                if(node->type & TEXTBOX)
3349                {
3350                        int lastposy = 0;
3351                        drawstring(node->text, node->linecount, node->poscount, -1, node->iposx + node->textposx, node->iposy, node->iwidth - node->textposx, node->iheight, node->halign, node->valign, node->font, node->fontsize, color, node->transparent, node->wrap, NULL, &lastposy, NULL, node->charspace, 0);
3352                        drawstring(node->text2, node->linecount, node->poscount, -1, node->iposx + node->textposx2, lastposy, node->iwidth - node->textposx2, node->iheight - (lastposy - node->iposy), node->halign, node->valign, node->font, node->fontsize2, color2, node->transparent, node->wrap, NULL, &lastposy, NULL, node->charspace, 0);
3353                }
3354                else
3355                {
3356                        int lastposx = 0;
3357                        if(node->textposx2 > 0)
3358                        {
3359                                drawstring(node->text, 1, 0, -1, node->iposx + node->textposx, node->iposy, node->iwidth - node->textposx - (node->iwidth - node->textposx2) - len, node->iheight, node->halign, node->valign, node->font, node->fontsize, color, node->transparent, 0, &lastposx, NULL, NULL, node->charspace, 0);
3360                                drawstring(node->text2, 1, 0, -1, node->iposx + node->textposx2, node->iposy, node->iwidth - node->textposx2 - len, node->iheight, node->halign, node->valign, node->font, node->fontsize2, color2, node->transparent, 0, NULL, NULL, NULL, node->charspace, 0);
3361                        }
3362                        else
3363                        {
3364                                drawstring(node->text, 1, 0, -1, node->iposx + node->textposx, node->iposy, node->iwidth - node->textposx - len, node->iheight, node->halign, node->valign, node->font, node->fontsize, color, node->transparent, 0, &lastposx, NULL, NULL, node->charspace, 0);
3365                                drawstring(node->text2, 1, 0, -1, lastposx, node->iposy, node->iwidth - (lastposx - node->iposx) - len, node->iheight, node->halign, node->valign, node->font, node->fontsize2, color2, node->transparent, 0, NULL, NULL, NULL, node->charspace, 0);
3366                        }
3367                }
3368        }
3369        if(node->filelist != NULL && node->filelist->view > 3)
3370        {
3371                char* tmpnr = NULL;
3372
3373                if(node->filelist->view == 4)
3374                {
3375                        if(node->filelist->size >= 1073741824)
3376                        {
3377                                tmpnr = oftoa64((double)node->filelist->size / 1073741824, "2");
3378                                tmpnr = ostrcat(tmpnr, "G", 1, 0);
3379                        }
3380                        else if(node->filelist->size >= 1048576)
3381                        {
3382                                tmpnr = oftoa64((double)node->filelist->size / 1048576, "2");
3383                                tmpnr = ostrcat(tmpnr, "M", 1, 0);
3384                        }
3385                        else if(node->filelist->size >= 1024)
3386                        {
3387                                tmpnr = oftoa64((double)node->filelist->size / 1024, "2");
3388                                tmpnr = ostrcat(tmpnr, "K", 1, 0);
3389                        }
3390                        else
3391                        {
3392                                tmpnr = oitoa64(node->filelist->size);
3393                                tmpnr = ostrcat(tmpnr, "B", 1, 0);
3394                        }
3395                }
3396                if(node->filelist->view == 5)
3397                {
3398                        tmpnr = malloc(MINMALLOC);
3399                        if(tmpnr == NULL)
3400                        {
3401                                err("no mem");
3402                                return;
3403                        }
3404
3405                        struct tm* loctime = olocaltime(&node->filelist->date);
3406                        if(loctime != NULL)
3407                                strftime(tmpnr, MINMALLOC, "%H:%M %d-%m-%Y", loctime);
3408                        free(loctime);
3409                }
3410                drawstring(tmpnr, 1, node->poscount, -1, node->iposx, node->iposy, node->iwidth, node->iheight, RIGHT, node->valign, node->font, node->fontsize, node->fontcol, node->transparent, 0, NULL, NULL, NULL, node->charspace, 0);
3411                free(tmpnr);
3412        }
3413        if(node->title != NULL && node->fontsize > 1)
3414                drawtitle(node);
3415        if(node->scrollbar == YES || node->scrollbar == AUTOYES)
3416                drawscrollbar(node);
3417        if(node->bordersize > 0)
3418        {
3419                if(node->child != NULL && status.picbordersize > 0)
3420                        drawpicborder(node);
3421                else
3422                        drawborder(node);
3423                if((node->child != NULL && status.borderradius > 0) || node->borderradius > 0)
3424                        drawroundborder(node, bglt, bglb, bgrt, bgrb);
3425        }
3426
3427        free(bglt); free(bglb); free(bgrt); free(bgrb);
3428}
3429
3430void calcscrollbar(struct skin* node)
3431{
3432        node->scrollbarheight = node->iheight;
3433
3434        if(node->pagecount > 1)
3435        {
3436                node->scrollbarheight = (float)node->iheight / node->pagecount;
3437                node->scrollbarpos = ((float)node->iheight / node->pagecount) * (node->aktpage - 1);
3438                if(node->scrollbar == AUTONO) node->scrollbar = AUTOYES;
3439        }
3440        else if(node->scrollbar == AUTOYES)
3441                node->scrollbar = AUTONO;
3442
3443        if(node->scrollbar == YES || node->scrollbar == AUTOYES)
3444        {
3445                node->iwidth -= (SCROLLBARWIDTH + 5);
3446                node->scrollbarwidth = SCROLLBARWIDTH;
3447                node->scrollbarbordersize = SCROLLBARBORDERSIZE;
3448                if(node->iposy + node->scrollbarpos > node->iposy + node->iheight) node->scrollbarpos = node->iposy + node->iheight;
3449                if(node->scrollbarpos < 0) node->scrollbarpos = 0;
3450                if(node->iposy + node->scrollbarpos + node->scrollbarheight > node->iposy + node->iheight) node->scrollbarheight = node->iheight - node->scrollbarpos;
3451                if(node->scrollbarheight < 1) node->scrollbarheight = 1;
3452        }
3453}
3454
3455void calclistboxchild(struct skin* node, struct skin* parent)
3456{
3457        if((parent->type & GRID) && (node->type & GRIDBR))
3458        {
3459                if(parent->poscount > 0) parent->poscount += node->rheight;
3460                if(parent->poscount == 0) parent->poscount = 1;
3461        }
3462        node->rposy = node->rposy + parent->poscount;
3463        node->iposy = node->iposy + parent->poscount;
3464        if((parent->type & LISTBOX) || ((parent->type & FILELIST) && !(parent->type & GRID)))
3465                parent->poscount += node->rheight;
3466}
3467
3468int calclistbox(struct skin* node)
3469{
3470        struct skin* child = NULL, *last = NULL, *found = NULL;
3471        int selcol = 0;
3472
3473        if(node->type == FILELIST)
3474                selcol = status.filelistselectcol;
3475        else
3476                selcol = status.listboxselectcol;
3477
3478        node->poscount = 0;
3479        if(node->aktline == 0) node->aktline = 1;
3480        node->pagecount = 1;
3481        node->linecount = 0;
3482
3483        child = node->next;
3484        while(child != NULL)
3485        {
3486                if(child->parentpointer == NULL)
3487                {
3488                        if(child->parent == NULL)
3489                        {
3490                                child = child->next;
3491                                continue;
3492                        }
3493                        else if(ostrcmp(child->parent, node->name) != 0 || child->hidden == YES)
3494                        {
3495                                child = child->next;
3496                                continue;
3497                        }
3498                }
3499                else if(child->parentpointer != node || child->hidden == YES)
3500                {
3501                        child = child->next;
3502                        continue;
3503                }
3504
3505                if(child->locked == YES)
3506                {
3507                        child = child->next;
3508                        continue;
3509                }               
3510
3511                calcrheight(child, node);
3512
3513                if((node->type & LISTBOX) || ((node->type & FILELIST) && !(node->type & GRID)) || ((node->type & GRID) && (child->type & GRIDBR)))
3514                        node->poscount = node->poscount + child->posy + child->rheight;
3515
3516                if(node->poscount > node->iheight)
3517                {
3518                        node->pagecount++;
3519                        node->poscount = child->rheight;
3520                }
3521
3522                child->pagecount = node->pagecount;
3523
3524                if(child->deaktivcol > -1)
3525                {
3526                        child = child->next;
3527                        continue;
3528                }
3529
3530                node->linecount++;
3531                last = child;
3532
3533                if(node->aktline == -1 && child->pagecount == node->aktpage)
3534                {
3535                        node->aktline = node->linecount;
3536                        found = child;
3537                }
3538                else if(node->aktline == node->linecount)
3539                        found = child;
3540
3541                child->bordersize = 0;
3542                if(status.listboxselecttype == 3)
3543                {
3544                        changeselectpic(child, NULL);
3545                        if(child->bgcol == status.markcol)
3546                                child->bgcol = child->bordercol;
3547                }
3548                if(child->bgcol == selcol || child->bgcol == status.markcol) //&& status.listboxselecttype == 1)
3549                        child->bgcol = child->bordercol;
3550                if(child->fontcol == selcol || child->fontcol == status.markcol) //&& status.listboxselecttype == 2)
3551                        child->fontcol = child->bordercol;
3552
3553                child = child->next;
3554        }
3555
3556        if(found == NULL)
3557        {
3558                found = last;
3559                node->aktline = node->linecount;
3560        }
3561       
3562        if(found != NULL)
3563        {
3564                if(node->aktline == -2) node->aktline = node->linecount;
3565                if(status.listboxselecttype == 0)
3566                {
3567                        found->bordersize = 1;
3568                        if(status.markmodus > 0)
3569                        {
3570                                found->bordercol = status.markcol;
3571                                int i = 0;
3572                                struct skin* tmpskin = found;
3573                                for(i = 0; i < status.moveblockcount; i++)
3574                                {
3575                                        tmpskin = tmpskin->next;
3576                                        if(tmpskin != NULL)
3577                                                tmpskin->bordercol = status.markcol;
3578                                        else
3579                                                break;
3580                                }
3581                        }
3582                        else
3583                                found->bordercol = selcol;
3584                }
3585                else if(status.listboxselecttype == 1)
3586                {
3587                        if(found->bgcol != selcol && found->bgcol != status.markcol)
3588                        {
3589                                found->bordercol = found->bgcol;
3590                                int i = 0;
3591                                struct skin* tmpskin = found;
3592                                for(i = 0; i < status.moveblockcount; i++)
3593                                {
3594                                        tmpskin = tmpskin->next;
3595                                        if(tmpskin != NULL)
3596                                                tmpskin->bordercol = found->bgcol;
3597                                        else
3598                                                break;
3599                                }
3600                        }
3601                        if(status.markmodus > 0)
3602                        {
3603                                found->bgcol = status.markcol;
3604                                int i = 0;
3605                                struct skin* tmpskin = found;
3606                                for(i = 0; i < status.moveblockcount; i++)
3607                                {
3608                                        tmpskin = tmpskin->next;
3609                                        if(tmpskin != NULL)
3610                                                tmpskin->bgcol = status.markcol;
3611                                        else
3612                                                break;
3613                                }
3614                        }
3615                        else
3616                                found->bgcol = selcol;
3617                }
3618                else if(status.listboxselecttype == 2)
3619                {
3620                        if(found->fontcol != selcol && found->fontcol != status.markcol)
3621                        {
3622                                found->bordercol = found->fontcol;
3623                                int i = 0;
3624                                struct skin* tmpskin = found;
3625                                for(i = 0; i < status.moveblockcount; i++)
3626                                {
3627                                        tmpskin = tmpskin->next;
3628                                        if(tmpskin != NULL)
3629                                                tmpskin->bordercol = found->fontcol;
3630                                        else
3631                                                break;
3632                                }
3633                        }
3634                        if(status.markmodus > 0)
3635                        {
3636                                found->fontcol = status.markcol;
3637                                int i = 0;
3638                                struct skin* tmpskin = found;
3639                                for(i = 0; i < status.moveblockcount; i++)
3640                                {
3641                                        tmpskin = tmpskin->next;
3642                                        if(tmpskin != NULL)
3643                                                tmpskin->fontcol = status.markcol;
3644                                        else
3645                                                break;
3646                                }
3647                        }
3648                        else
3649                                found->fontcol = selcol;
3650                }
3651                else if(status.listboxselecttype == 3)
3652                {
3653                        if(status.markmodus > 0)
3654                        {
3655                                found->bordersize = 1;
3656                                found->bordercol = status.markcol;
3657                                int i = 0;
3658                                struct skin* tmpskin = found;
3659                                for(i = 0; i < status.moveblockcount; i++)
3660                                {
3661                                        tmpskin = tmpskin->next;
3662                                        if(tmpskin != NULL)
3663                                        {
3664                                                tmpskin->bordersize = 1;
3665                                                tmpskin->bordercol = status.markcol;
3666                                        }
3667                                        else
3668                                                break;
3669                                }
3670                        }
3671                        else
3672                                changeselectpic(found, status.selectpic);
3673                }
3674
3675                if(node->aktpage == -1)
3676                        node->aktpage = found->pagecount;
3677                node->select = found;
3678        }
3679
3680        if(node->aktpage == -1) node->aktpage = 0;
3681        if(node->aktpage > node->pagecount)
3682        {
3683                if(node->pagecount == 0) node->aktpage = 0;
3684                else node->aktpage = 1;
3685        }
3686        node->poscount = 0;
3687        return 0;
3688}
3689
3690int calcrwidth(struct skin* node, struct skin* parent)
3691{
3692        int scrollbarwidth = 0;
3693
3694        if(node->prozwidth == 1)
3695                node->rwidth = (((parent->iwidth * 100) / 100) * node->width) / 100;
3696        else
3697                node->rwidth = node->width;
3698
3699        if(node->scrollbar == YES || node->scrollbar == AUTOYES || node->scrollbar == AUTONO) scrollbarwidth = SCROLLBARWIDTH;
3700
3701        if(node->rwidth < (node->bordersize << 1) + scrollbarwidth) node->rwidth = (node->bordersize << 1) + scrollbarwidth;
3702
3703        return 0;
3704}
3705
3706int calcrheight(struct skin* node, struct skin* parent)
3707{
3708        if(node->prozheight == 1)
3709                node->rheight = (((parent->iheight * 100) / 100) * node->height) / 100;
3710        else
3711        {
3712                node->rheight = node->height;
3713                if(node->fontsize == 0) node->fontsize = parent->fontsize;
3714                if(node->fontsize == 0) node->fontsize = 1;
3715                if(node->rheight == 0) node->rheight = node->fontsize + 2;
3716        }
3717
3718        if(node->rheight < (node->bordersize << 1) + node->titlesize) node->rheight = (node->bordersize << 1) + node->titlesize;
3719
3720        return 0;
3721}
3722
3723int calcrposx(struct skin* node, struct skin* parent)
3724{
3725        if(node->prozposx == 1)
3726                node->rposx = (((parent->iwidth * 100) / 100) * node->posx) / 100;
3727        else
3728                node->rposx = node->posx;
3729
3730        if(node->posx == CENTER || (node->posx == 0 && parent->halign == CENTER))
3731                node->rposx = parent->iposx + (parent->iwidth >> 1) - (node->rwidth >> 1);
3732        else if(node->posx == LEFT)
3733                node->rposx = parent->iposx;
3734        else if(node->posx == RIGHT || (node->posx == 0 && parent->halign == RIGHT))
3735                node->rposx = parent->iposx + parent->iwidth - node->rwidth;
3736        else
3737                node->rposx = parent->iposx + node->rposx;
3738
3739        if(node->rposx > parent->iposx + parent->iwidth)
3740                node->rposx = parent->iposx + parent->iwidth;
3741
3742        return 0;
3743}
3744
3745int calcrposy(struct skin* node, struct skin* parent)
3746{
3747        if(node->prozposy == 1)
3748                node->rposy = (((parent->iheight * 100) / 100) * node->posy) / 100;
3749        else
3750                node->rposy = node->posy;
3751
3752        if(node->posy == MIDDLE || (node->posy == 0 && parent->valign == MIDDLE))
3753                node->rposy = parent->iposy + (parent->iheight >> 1) - (node->rheight >> 1);
3754        else if(node->posy == TOP)
3755                node->rposy = parent->iposy;
3756        else if(node->posy == BOTTOM || (node->posy ==0 && parent->valign == BOTTOM))
3757                node->rposy = parent->iposy + parent->iheight - node->rheight;
3758        else
3759                node->rposy = parent->iposy + node->rposy;
3760
3761        if(node->rposy > parent->iposy + parent->iheight)
3762                node->rposy = parent->iposy + parent->iheight;
3763
3764        return 0;
3765}
3766
3767int setnodeattr(struct skin* node, struct skin* parent, int screencalc)
3768{
3769        if(node != skin) node->flag = clearbit(node->flag, 0);
3770        if((parent->type & LISTBOX) || (parent->type & FILELIST) || (parent->type & GRID))
3771                if(node->pagecount != parent->aktpage) return 1;
3772
3773        int shadowlx = 0, shadowrx = 0, shadowoy = 0, shadowuy = 0;
3774        unsigned int linecount = 0, pagecount = 0, poscount = 0;
3775        char* tmpstr = NULL;
3776
3777        if(node->child != NULL && status.picbordersize > 0)
3778                node->bordersize = status.picbordersize;
3779       
3780        if(node->nodestyle != 0)
3781        {
3782                if(node->nodestyle == 2 && getconfigint("skinblinkoff", NULL) == 0)
3783                        node->nodestyle = 1;
3784                else if(node->nodestyle == 1 && getconfigint("skinblinkoff", NULL) == 1)
3785                        node->nodestyle = 2;
3786                if(node->nodestyle == 1)
3787                        setblink(node);
3788        }
3789       
3790        if(node->skinfunc != NULL)
3791        {
3792                if(node->funcrettype == FUNCPIC)
3793                {
3794                        tmpstr = node->skinfunc(node, node->param1, node->param2);
3795                        changepic(node, tmpstr);
3796                }
3797                else if(node->funcrettype == FUNCPICOLED)
3798                {
3799                        tmpstr = node->skinfunc(node, node->param1, node->param2);
3800                        if(tmpstr != NULL)
3801                                changepic(node, tmpstr);       
3802                }
3803                else if(node->funcrettype == FUNCPROGRESS)
3804                {
3805                        tmpstr = node->skinfunc(node, node->param1, node->param2);
3806                        if(tmpstr != NULL)
3807                        {
3808                                node->hidden = NO;
3809                                node->progresssize = atoi(tmpstr);
3810                        }
3811                        else
3812                                node->hidden = YES;
3813                }
3814                else
3815                {
3816                        tmpstr = node->skinfunc(node, node->param1, node->param2);
3817                        changetext(node, _(tmpstr));
3818                }
3819                free(tmpstr);
3820        }
3821
3822        if(screencalc != 2)
3823        {
3824                if(node->hidden == YES || parent->hidden == YES || node->locked == YES || parent->locked == YES) return 1;
3825                if(checkbit(parent->flag, 0) == 0) return 1;
3826        }
3827
3828        calcrwidth(node, parent);
3829        if(!(parent->type & LISTBOX) && !(parent->type & FILELIST) && !(parent->type & GRID))
3830                calcrheight(node, parent);
3831        calcrposx(node, parent);
3832        calcrposy(node, parent);
3833
3834        if(node->height < 0)
3835                node->rheight = parent->iheight + node->height - (node->rposy - parent->iposy);
3836        if(node->width < 0)
3837                node->rwidth = parent->iwidth + node->width - (node->rposx - parent->iposx);
3838
3839        node->iposx = node->rposx + node->bordersize + node->hspace;
3840        node->iposy = node->rposy + node->bordersize + node->titlesize + node->vspace;
3841        node->iwidth = node->rwidth - (node->bordersize << 1) - (node->hspace << 1);
3842        node->iheight = node->rheight - (node->bordersize << 1) - node->titlesize - (node->vspace << 1);
3843
3844        switch(node->shadowpos)
3845        {
3846                case BOTTOMLEFT: shadowlx = shadowuy = node->shadowsize; break;
3847                case BOTTOMRIGHT: shadowrx = shadowuy = node->shadowsize; break;
3848                case TOPLEFT: shadowlx = shadowoy = node->shadowsize; break;
3849                default: shadowrx = shadowoy = node->shadowsize; break;
3850        }
3851
3852        if((parent->type & LISTBOX) || (parent->type & FILELIST) || (parent->type & GRID))
3853                calclistboxchild(node, parent);
3854
3855        if(node->picprozwidth == 1)
3856                node->rpicwidth = (((node->iwidth * 100) / 100) * node->picwidth) / 100;
3857        else
3858                node->rpicwidth = node->picwidth;
3859        if(node->picprozheight == 1)
3860                node->rpicheight = (((node->iheight * 100) / 100) * node->picheight) / 100;
3861        else
3862                node->rpicheight = node->picheight;
3863
3864        if(node->rposx - shadowlx < parent->iposx)
3865        {
3866                if(screencalc == 0) err("node (%s posx=%d) out of parent (%s posx=%d)", node->name, node->rposx - shadowlx, parent->name, parent->iposx);
3867                node->rposx = parent->iposx + shadowlx;
3868                //return 1;
3869        }
3870        if(node->rposy - shadowoy < parent->iposy)
3871        {
3872                if(screencalc == 0) err("node (%s posy=%d) out of parent (%s posy=%d)", node->name, node->rposy - shadowoy, parent->name, parent->iposy);
3873                node->rposy = parent->iposy + shadowoy;
3874                //return 1;
3875        }
3876        if(node->rposx + node->rwidth + shadowrx > parent->iposx + parent->iwidth)
3877        {
3878                if(screencalc == 0) err("node (%s posxx=%d) out of parent (%s posxx=%d)", node->name, node->rposx + node->rwidth + shadowrx, parent->name, parent->iposx + parent->iwidth);
3879                node->rwidth = parent->iwidth - node->rposx - shadowrx;
3880                //return 1;
3881        }
3882        if(node->rposy + node->rheight + shadowuy > parent->iposy + parent->iheight)
3883        {
3884                if(screencalc == 0) err("node (%s posyy=%d) out of parent (%s posyy=%d)", node->name, node->rposy + node->rheight + shadowuy, parent->name, parent->iposy + parent->iheight);
3885                node->rheight = parent->iheight - node->rposy - shadowuy;
3886                //return 1;
3887        }
3888
3889        if(node->font == NULL && parent->font != NULL)
3890        {
3891                changefont(node, parent->font);
3892                if(node->font == NULL)
3893                {
3894                        err("no memory");
3895                }
3896        }
3897
3898        if(node->fontsize == 0) node->fontsize = parent->fontsize;
3899        if(node->fontsize == 0) node->fontsize = 1;
3900        if(node->fontsize2 == 0) node->fontsize2 = parent->fontsize2;
3901        if(node->fontsize2 == 0) node->fontsize2 = 1;
3902        if(node->fontcol == 0) node->fontcol = parent->fontcol;
3903        if(node->fontcol2 == 0) node->fontcol2 = parent->fontcol2;
3904
3905        if((node->type & INPUTBOX) || (node->type & INPUTBOXNUM))
3906        {
3907                if(node->aktpage < 1) node->aktpage = 1;
3908                checkinputboxnumright(node);
3909                changeret(node, node->input);
3910        }
3911
3912        if((node->type & LISTBOX) || (node->type & FILELIST) || (node->type & GRID))
3913        {
3914                if(node->aktpage == 0) node->aktpage = 1;
3915                calclistbox(node);
3916                if(node->scrollbar != NO)
3917                        calcscrollbar(node);
3918        }
3919        if(node->type & TEXTBOX)
3920        {
3921                if(node->aktpage < 1) node->aktpage = 1;
3922                if(node->text == NULL && node->text2 == NULL)
3923                        node->pagecount = 0;
3924                else
3925                {
3926                        if(node->wrap == YES)
3927                        {
3928                                wrapstr(node->text, node->font, node->fontsize, node->iwidth, node->charspace);
3929                                wrapstr(node->text2, node->font, node->fontsize2, node->iwidth, node->charspace);
3930                        }
3931                        calctext(node->text, node->text2, &node->linecount, &node->pagecount, &node->poscount, node->iheight / node->fontsize, node->aktpage);
3932                }
3933                if(node->text2 != NULL) node->scrollbar = NO;
3934                if(node->scrollbar != NO)
3935                        calcscrollbar(node);
3936        }
3937
3938        if((node->type & CHOICEBOX) && node->input != NULL)
3939        {
3940                char* pos = NULL;
3941                calctext(node->input, NULL, &node->linecount, &node->pagecount, &node->poscount, 1, node->aktpage);
3942
3943                free(node->ret);
3944                node->ret = NULL;
3945
3946                if(node->choiceboxvalue != NULL)
3947                {
3948                        calctext(node->choiceboxvalue, NULL, &linecount, &pagecount, &poscount, 1, node->aktpage);
3949                        pos = strchr(node->choiceboxvalue + poscount, '\n');
3950                        if(pos == NULL)
3951                                changeret(node, node->choiceboxvalue + poscount);
3952                        else
3953                                node->ret = strndup(node->choiceboxvalue + poscount, pos - (node->choiceboxvalue + poscount));
3954                }
3955                else if(node->input != NULL)
3956                {
3957                        pos = strchr(node->input + node->poscount, '\n');
3958                        if(pos == NULL)
3959                                changeret(node, node->input + node->poscount);
3960                        else
3961                                node->ret = strndup(node->input + node->poscount, pos - (node->input + node->poscount));
3962                }
3963        }
3964
3965        //set parent transparent to child
3966        //if(node->transparent == 0 && parent != skin)
3967                //node->transparent = parent->transparent;
3968
3969        return 0;
3970}
3971
3972int clearscreenalways()
3973{
3974        int i, ret = 0;
3975        int tmp = sizeof(status.drawallways) / sizeof(skin);
3976
3977        for(i = 0; i < tmp; i++)
3978        {
3979                if(status.drawallways[i] != NULL)
3980                {
3981                        clearrect(status.drawallways[i]->rposx, status.drawallways[i]->rposy, status.drawallways[i]->rwidth, status.drawallways[i]->rheight);
3982                }
3983        }
3984
3985        return ret;
3986}
3987
3988int drawscreenalways(struct skin* node, int screencalc)
3989{
3990        int i, ret = 0;
3991        int tmp = sizeof(status.drawallways) / sizeof(skin);
3992       
3993        m_lock(&status.oledmutex, 25);
3994        for(i = 0; i < tmp; i++)
3995        {
3996                if(status.drawallways[i] != NULL)
3997                {
3998                        if(node != status.drawallways[i])
3999                        {
4000                                if(status.drawallwaysbg[i] != NULL)
4001                                        free(status.drawallwaysbg[i]);
4002                                status.drawallwaysbg[i] = savescreen(status.drawallways[i]);
4003                                ret = drawscreen(status.drawallways[i], screencalc, 1);
4004                        }
4005                }
4006        }
4007        m_unlock(&status.oledmutex, 25);
4008       
4009        return ret;
4010}
4011
4012int drawscreennode(struct skin *node, char* nodename, int screencalc)
4013{
4014        node = getscreennode(node, nodename);
4015
4016        m_lock(&status.drawingmutex, 0);
4017        if(node != status.skinerr)
4018                drawnode(node, 1);
4019        drawscreenalways(node, screencalc);
4020        blitfb(0);
4021        m_unlock(&status.drawingmutex, 0);
4022
4023        return 0;
4024}
4025
4026int drawscreennodebyname(char* screenname, char* nodename, int screencalc)
4027{
4028        struct skin *node;
4029
4030        node = getscreennodebyname(screenname, nodename);
4031        m_lock(&status.drawingmutex, 0);
4032        if(node != status.skinerr)
4033                drawnode(node, 1);
4034
4035        drawscreenalways(node, screencalc);
4036        blitfb(0);
4037        m_unlock(&status.drawingmutex, 0);
4038
4039        return 0;
4040}
4041
4042//flag 0: draw normal with allways
4043//flag 1: draw without allways
4044//flag 2: from thread (mutex is set in thread)
4045//flag 3: unused
4046//flag 4: same as 0 but animate
4047//screencalc 0: calculate and draw
4048//screencalc 1: only calculate without hidden nodes
4049//screencalc 2: only calculate hidden nodes
4050int drawscreen(struct skin* node, int screencalc, int flag)
4051{
4052        struct fb* merkskinfb = NULL;
4053        int ret;
4054        struct skin *child = NULL, *parent = NULL, *oldparent = NULL;
4055
4056        if(node == NULL)
4057        {
4058                err("node = NULL");
4059                return 1;
4060        }
4061
4062        if(status.skinblink == 0)
4063                status.skinblink = 1;
4064        else
4065                status.skinblink = 0;
4066
4067        if(flag == 0 || flag == 4)
4068                m_lock(&status.drawingmutex, 0);
4069
4070        parent = skin;
4071
4072        ret = setnodeattr(node, parent, screencalc);
4073        if(ret == 1)
4074        {
4075                if(flag == 0 || flag == 4)
4076                        m_unlock(&status.drawingmutex, 0);
4077                err("setnodeattr ret = 1");
4078                return 1;
4079        }
4080        debug(100, "start drawscreen with screenname=%s", node->name);
4081        if(node->name != NULL && ostrstr(node->name, "LCD_") != NULL)
4082        {
4083                m_lock(&status.oledmutex, 25);
4084                if(lcdskinfb == NULL) {
4085#ifndef MIPSEL                 
4086                        if(node->name != NULL && ostrstr(node->name, "LCD_spf87") != NULL) {
4087                                unsigned char *newskinfb = calloc(1, 4 * 800 * 480);
4088                                if(newskinfb == NULL)
4089                                {
4090                                        if(flag == 0 || flag == 4)
4091                                                m_unlock(&status.drawingmutex, 0);
4092                                        m_unlock(&status.oledmutex, 25);
4093                                        return -2;
4094                                }
4095                                lcdskinfb = addfb("lcdskinfb", 999, 800, 480, 4, -1, newskinfb, 4 * 800 * 480, 0);
4096                        }
4097                        else if(node->name != NULL && ostrstr(node->name, "LCD_spf72") != NULL) {
4098                                unsigned char *newskinfb = calloc(1, 4 * 800 * 480);
4099                                if(newskinfb == NULL)
4100                                {
4101                                        if(flag == 0 || flag == 4)
4102                                                m_unlock(&status.drawingmutex, 0);
4103                                        m_unlock(&status.oledmutex, 25);
4104                                        return -2;
4105                                }
4106                                lcdskinfb = addfb("lcdskinfb", 999, 800, 480, 4, -1, newskinfb, 4 * 800 * 480, 0);
4107                        }
4108                        else if(node->name != NULL && ostrstr(node->name, "LCD_spf83") != NULL) {
4109                                unsigned char *newskinfb = calloc(1, 4 * 800 * 600);
4110                                if(newskinfb == NULL)
4111                                {
4112                                        if(flag == 0 || flag == 4)
4113                                                m_unlock(&status.drawingmutex, 0);
4114                                        m_unlock(&status.oledmutex, 25);
4115                                        return -2;
4116                                }
4117                                lcdskinfb = addfb("lcdskinfb", 999, 800, 600, 4, -1, newskinfb, 4 * 800 * 600, 0);
4118                        }
4119                        else if(node->name != NULL && ostrstr(node->name, "LCD_spf85") != NULL) {
4120                                unsigned char *newskinfb = calloc(1, 4 * 800 * 600);
4121                                if(newskinfb == NULL)
4122                                {
4123                                        if(flag == 0 || flag == 4)
4124                                                m_unlock(&status.drawingmutex, 0);
4125                                        m_unlock(&status.oledmutex, 25);
4126                                        return -2;
4127                                }
4128                                lcdskinfb = addfb("lcdskinfb", 999, 800, 600, 4, -1, newskinfb, 4 * 800 * 600, 0);
4129                        }
4130                        else if(node->name != NULL && ostrstr(node->name, "LCD_spf75") != NULL) {
4131                                unsigned char *newskinfb = calloc(1, 4 * 800 * 480);
4132                                if(newskinfb == NULL)
4133                                {
4134                                        if(flag == 0 || flag == 4)
4135                                                m_unlock(&status.drawingmutex, 0);
4136                                        m_unlock(&status.oledmutex, 25);
4137                                        return -2;
4138                                }
4139                                lcdskinfb = addfb("lcdskinfb", 999, 800, 480, 4, -1, newskinfb, 4 * 800 * 480, 0);
4140                        }
4141                        else if(node->name != NULL && ostrstr(node->name, "LCD_spf107") != NULL) {
4142                                unsigned char *newskinfb = calloc(1, 4 * 1024 * 600);
4143                                if(newskinfb == NULL)
4144                                {
4145                                        if(flag == 0 || flag == 4)
4146                                                m_unlock(&status.drawingmutex, 0);
4147                                        m_unlock(&status.oledmutex, 25);
4148                                        return -2;
4149                                }
4150                                lcdskinfb = addfb("lcdskinfb", 999, 1024, 600, 4, -1, newskinfb, 4 * 1024 * 600, 0);
4151                        }
4152                        else if(node->name != NULL && ostrstr(node->name, "LCD_spf105") != NULL) {
4153                                unsigned char *newskinfb = calloc(1, 4 * 1024 * 600);
4154                                if(newskinfb == NULL)
4155                                {
4156                                        if(flag == 0 || flag == 4)
4157                                                m_unlock(&status.drawingmutex, 0);
4158                                        m_unlock(&status.oledmutex, 25);
4159                                        return -2;
4160                                }
4161                                lcdskinfb = addfb("lcdskinfb", 999, 1024, 600, 4, -1, newskinfb, 4 * 1024 * 600, 0);
4162                        }
4163                        else {
4164                                unsigned char *newskinfb = calloc(1, 4 * 320 * 240);
4165                                if(newskinfb == NULL)
4166                                {
4167                                        if(flag == 0 || flag == 4)
4168                                                m_unlock(&status.drawingmutex, 0);
4169                                        m_unlock(&status.oledmutex, 25);
4170                                        return -2;
4171                                }
4172                                lcdskinfb = addfb("lcdskinfb", 999, 320, 240, 4, -1, newskinfb, 4 * 320 * 240, 0);
4173                        }
4174#else   
4175                        if(node->name != NULL && ostrstr(node->name, "LCD_spf87") != NULL)
4176                                lcdskinfb = oledaddfb(800, 480);
4177                        else if(node->name != NULL && ostrstr(node->name, "LCD_spf72") != NULL)
4178                                lcdskinfb = oledaddfb(800, 480);
4179                        else if(node->name != NULL && ostrstr(node->name, "LCD_spf83") != NULL)
4180                                lcdskinfb = oledaddfb(800, 600);
4181                        else if(node->name != NULL && ostrstr(node->name, "LCD_spf85") != NULL)
4182                                lcdskinfb = oledaddfb(800, 600);
4183                        else if(node->name != NULL && ostrstr(node->name, "LCD_spf75") != NULL)
4184                                lcdskinfb = oledaddfb(800, 480);
4185                        else if(node->name != NULL && ostrstr(node->name, "LCD_spf107") != NULL)
4186                                lcdskinfb = oledaddfb(1024, 600);
4187                        else if(node->name != NULL && ostrstr(node->name, "LCD_spf105") != NULL)
4188                                lcdskinfb = oledaddfb(1024, 600);
4189                        else
4190                                lcdskinfb = oledaddfb(320, 240);
4191                        if(lcdskinfb == NULL)
4192                        {
4193                                if(flag == 0 || flag == 4)
4194                                        m_unlock(&status.drawingmutex, 0);
4195                                m_unlock(&status.oledmutex, 25);
4196                                return -2;
4197                        }
4198#endif
4199                }
4200                merkskinfb = skinfb;
4201                //memset(lcdskinfb->fb, 0, lcdskinfb->varfbsize);
4202                skinfb = lcdskinfb;
4203        }
4204        else if(node->name != NULL && ostrstr(node->name, "OLED_") != NULL)
4205        {
4206                m_lock(&status.oledmutex, 25);
4207                if(oledskinfb == NULL) {
4208                        if(node->name != NULL && ostrstr(node->name, "OLED_nemesis") != NULL) {
4209                                debug(100, "alloc OLED_nemesis framebuffer");
4210                                oledskinfb = oledaddfb(256, 64);
4211                                if(oledskinfb == NULL)
4212                                {
4213                                        if(flag == 0 || flag == 4)
4214                                                m_unlock(&status.drawingmutex, 0);
4215                                        return -2;
4216                                }
4217                        }
4218                        else if(node->name != NULL && ostrstr(node->name, "OLED_dream1") != NULL) {
4219                                debug(100, "alloc OLED_dream1 framebuffer");
4220                                oledskinfb = oledaddfb(128, 64);
4221                                if(oledskinfb == NULL)
4222                                {
4223                                        if(flag == 0 || flag == 4)
4224                                                m_unlock(&status.drawingmutex, 0);
4225                                        return -2;
4226                                }
4227                        }
4228                }
4229                merkskinfb = skinfb;
4230                skinfb = oledskinfb;
4231        }
4232
4233        if(screencalc == 0 || flag == 4)
4234        {
4235                if(flag == 0 || flag == 2 || flag == 4) clearscreenalways();
4236                drawnode(node, 0);
4237        }
4238        parent = node;
4239        oldparent = node;
4240        child = node->child;
4241
4242        while(child != NULL)
4243        {
4244                if(child->parentpointer != NULL)
4245                        parent = child->parentpointer;
4246                else if(child->parent != NULL)
4247                {
4248                        parent = getscreennode(node, child->parent);
4249                        if(parent == status.skinerr) parent = oldparent;
4250                }
4251                else
4252                        parent = oldparent;
4253
4254                if(setnodeattr(child, parent, screencalc) == 0 && screencalc == 0)
4255                        drawnode(child, 1);
4256                child = child->next;
4257        }
4258
4259        if(flag == 0 || flag == 2 || flag == 4)
4260        {
4261                if(screencalc == 0)
4262                {
4263                        if(merkskinfb != NULL)
4264                        {       
4265                                if(node->name != NULL && ostrstr(node->name, "LCD_spf") != NULL)
4266                                        write_FB_to_JPEG_file(skinfb->fb, skinfb->width, skinfb->height, "/tmp/titanlcd.jpg", 75);
4267                                else if(node->name != NULL && ostrstr(node->name, "OLED_") != NULL)
4268                                        write2oled(skinfb->fb, skinfb->width, skinfb->height);
4269                                else                   
4270                                        pngforlcd(skinfb->fb, skinfb->width, skinfb->height);
4271                        }
4272                        else   
4273                        {
4274                                status.drawscreencount++;
4275                                drawscreenalways(node, screencalc);
4276                                if(flag == 4)
4277                                        blitfb(1);
4278                                else
4279                                        blitfb(0);
4280                        }
4281                }
4282        }
4283
4284        if(merkskinfb != NULL)
4285        {
4286                debug(100, "no framebuffer screenname=%s", node->name);
4287                /*delete temporary FB*/
4288#ifndef MIPSEL
4289                if(skinfb == oledskinfb)
4290#else
4291                if(skinfb == oledskinfb || skinfb == lcdskinfb)
4292#endif
4293                {
4294                        skinfb = merkskinfb;
4295                        merkskinfb = NULL;
4296                }
4297                else
4298                {
4299                        debug(100, "free lcdskinfb");
4300                        free(skinfb->fb); skinfb->fb = NULL; 
4301                        skinfb = merkskinfb;
4302                        merkskinfb = NULL;
4303                        delfb("lcdskinfb");
4304                        lcdskinfb = NULL;
4305                }
4306                debug(100, "no framebuffer end");
4307                m_unlock(&status.oledmutex, 25);
4308        }
4309        //else
4310        //{
4311        //      if(ostrcmp(getconfig("write_fb_to_jpeg", NULL), "yes") == 0)
4312        //              write_FB_to_JPEG_file(skinfb->fb, skinfb->width, skinfb->height, "/tmp/fb.jpg", 3);
4313        //}
4314        if(flag == 0 || flag == 4)
4315                m_unlock(&status.drawingmutex, 0);
4316        debug(100, "ende drawscreen with screenname=%s", node->name);
4317        return 0;
4318}
4319
4320int drawscreenbyname(char* screenname, int screencalc, int flag)
4321{
4322        int ret;
4323        struct skin* node = NULL;
4324
4325        node = getscreen(screenname);
4326        if(node == status.skinerr)
4327        {
4328                err("screen not found (%s)", screenname);
4329                return 1;
4330        }
4331
4332        ret = drawscreen(node, screencalc, flag);
4333        return ret;
4334}
4335
4336int changeinput(struct skin* node, char* text)
4337{
4338        int ret = 1;
4339
4340        if(node != NULL)
4341        {
4342                free(node->input);
4343                if(text != NULL)
4344                {
4345                        if((node->type & INPUTBOXNUM) && node->mask != NULL && strlen(text) == 0)
4346                                node->input = strdup(node->mask);
4347                        else
4348                                node->input = strdup(text);
4349                }
4350                else
4351                {
4352                        if((node->type & INPUTBOXNUM) && node->mask != NULL)
4353                                node->input = strdup(node->mask);
4354                        else
4355                                node->input = text;
4356                }
4357                ret = 0;
4358        }
4359
4360        return ret;
4361}
4362
4363int changetext(struct skin* node, char* text)
4364{
4365        int ret = 1;
4366
4367        if(node != NULL)
4368        {
4369                free(node->text);
4370                if(text != NULL)
4371                        node->text = strdup(text);
4372                else
4373                        node->text = text;
4374                ret = 0;
4375        }
4376
4377        return ret;
4378}
4379
4380int changetext2(struct skin* node, char* text)
4381{
4382        int ret = 1;
4383
4384        if(node != NULL)
4385        {
4386                free(node->text2);
4387                if(text != NULL)
4388                        node->text2 = strdup(text);
4389                else
4390                        node->text2 = text;
4391                ret = 0;
4392        }
4393
4394        return ret;
4395}
4396
4397
4398int changename(struct skin* node, char* text)
4399{
4400        int ret = 1;
4401
4402        if(node != NULL)
4403        {
4404                free(node->name);
4405                if(text != NULL)
4406                        node->name = strdup(text);
4407                else
4408                        node->name = strdup("unknown");
4409                ret = 0;
4410        }
4411
4412        return ret;
4413}
4414
4415int changepicmem(struct skin* node, char* text, int timeout, int del)
4416{
4417        unsigned long width = 0, height = 0, rowbytes = 0;
4418        int ret = 1, channels = 0, memfd = -1, length = 0;
4419        unsigned char* buf = NULL;
4420
4421        if(node != NULL)
4422        {
4423                free(node->pic);
4424                if(text != NULL)
4425                {
4426                        node->picmem = 1;
4427                        node->pic = changepicpath(text);
4428
4429                        if(getpic(node->pic) == NULL)
4430                        {
4431                                length = strlen(node->pic);
4432                                if(node->pic[length - 1] == 'g' && node->pic[length - 2] == 'n' && node->pic[length - 3] == 'p')
4433                                        buf = readpng(node->pic, &width, &height, &rowbytes, &channels, 0, 0, 0, 0, 0, 0);
4434                                else if(getconfigint("pichwdecode", NULL) == 1)
4435                                        readjpg(node->pic, &width, &height, &rowbytes, &channels, &buf, &memfd);
4436                                else
4437                                        buf = loadjpg(node->pic, &width, &height, &rowbytes, &channels, 1);
4438                                addpic(node->pic, buf, memfd, width, height, rowbytes, channels, timeout, del, NULL);
4439                        }
4440                }
4441                else
4442                        node->pic = text;
4443                ret = 0;
4444        }
4445
4446        return ret;
4447}
4448
4449int changepic(struct skin* node, char* text)
4450{
4451        int ret = 1;
4452
4453        if(node != NULL)
4454        {
4455                node->picmem = 0;
4456                free(node->pic);
4457                if(text != NULL)
4458                        node->pic = changepicpath(text);
4459                else
4460                        node->pic = text;
4461                ret = 0;
4462        }
4463
4464        return ret;
4465}
4466
4467int changeselectpic(struct skin* node, char* text)
4468{
4469        int ret = 1;
4470
4471        if(node != NULL)
4472        {
4473                free(node->selectpic);
4474                if(text != NULL)
4475                        node->selectpic = changepicpath(text);
4476                else
4477                        node->selectpic = text;
4478                ret = 0;
4479        }
4480
4481        return ret;
4482}
4483
4484int changetitle(struct skin* node, char* text)
4485{
4486        int ret = 1;
4487
4488        struct skin* titletext = getscreennode(node, "titletext");
4489        if( (text != NULL) && (titletext != status.skinerr) )
4490                changetext(titletext, text);
4491        else
4492                debug(10, "failed titletext=%s", text);
4493
4494        if(node != NULL)
4495        {
4496                free(node->title);
4497                if( (text != NULL) && (node->fontsize > 1) )
4498                {
4499                        node->title = strdup(text);
4500                        node->titlesize = node->fontsize + 6;
4501                }
4502                else
4503                {
4504                        node->title = NULL;
4505                        node->titlesize = 0;
4506                }
4507                ret = 0;
4508        }
4509
4510        return ret;
4511}
4512
4513int changemask(struct skin* node, char* text)
4514{
4515        int ret = 1;
4516
4517        if(node != NULL)
4518        {
4519                free(node->mask);
4520                if(text != NULL)
4521                {
4522                        if((node->type & INPUTBOXNUM) && (node->input == NULL || strlen(node->input) == 0))
4523                        {
4524                                node->mask = strdup(text);
4525                                free(node->input);
4526                                node->input = strdup(text);
4527                        }
4528                        else
4529                                node->mask = strdup(text);
4530                }
4531                else
4532                        node->mask = text;
4533                ret = 0;
4534        }
4535
4536        return ret;
4537}
4538
4539int changeret(struct skin* node, char* text)
4540{
4541        int ret = 1;
4542
4543        if(node != NULL)
4544        {
4545                free(node->ret);
4546                if(text != NULL)
4547                        node->ret = strdup(text);
4548                else
4549                        node->ret = text;
4550                ret = 0;
4551        }
4552
4553        return ret;
4554}
4555
4556int changeparent(struct skin* node, char* text)
4557{
4558        int ret = 1;
4559
4560        if(node != NULL)
4561        {
4562                free(node->parent);
4563                if(text != NULL)
4564                        node->parent = strdup(text);
4565                else
4566                        node->parent = text;
4567                ret = 0;
4568        }
4569
4570        return ret;
4571}
4572
4573int changefont(struct skin* node, char* text)
4574{
4575        int ret = 1;
4576
4577        if(node != NULL)
4578        {
4579                free(node->font);
4580                if(text != NULL)
4581                        node->font = strdup(text);
4582                else
4583                        node->font = text;
4584                ret = 0;
4585        }
4586
4587        return ret;
4588}
4589
4590int changeparam1(struct skin* node, char* text)
4591{
4592        int ret = 1;
4593
4594        if(node != NULL)
4595        {
4596                free(node->param1);
4597                if(text != NULL)
4598                        node->param1 = strdup(text);
4599                else
4600                        node->param1 = text;
4601                ret = 0;
4602        }
4603
4604        return ret;
4605}
4606
4607int changeparam2(struct skin* node, char* text)
4608{
4609        int ret = 1;
4610
4611        if(node != NULL)
4612        {
4613                free(node->param2);
4614                if(text != NULL)
4615                        node->param2 = strdup(text);
4616                else
4617                        node->param2 = text;
4618                ret = 0;
4619        }
4620
4621        return ret;
4622}
4623
4624int changechoiceboxvalue(struct skin* node, char* text)
4625{
4626        int ret = 1;
4627
4628        if(node != NULL)
4629        {
4630                free(node->choiceboxvalue);
4631                if(text != NULL)
4632                        node->choiceboxvalue = strdup(text);
4633                else
4634                        node->choiceboxvalue = text;
4635                ret = 0;
4636        }
4637
4638        return ret;
4639}
4640
4641unsigned char * resize(unsigned char *origin, int ox, int oy, int dx, int dy, int type, unsigned char * dst, int flag)
4642{
4643        unsigned char * cr;
4644
4645        if(dst == NULL)
4646        {
4647                cr = (unsigned char*) malloc(dx*dy*3);
4648
4649                if(cr == NULL)
4650                {
4651                        printf("Error: malloc\n");
4652                        return(origin);
4653                }
4654        }
4655        else
4656                cr = dst;
4657
4658        if(type == 1)
4659        {
4660                unsigned char *p,*l;
4661                int i,j,k,ip;
4662                l = cr;
4663
4664                for(j=0; j<dy; j++, l += dx*3)
4665                {
4666                        p = origin + (j*oy/dy*ox*3);
4667                        for(i=0, k=0; i<dx; i++, k+=3)
4668                        {
4669                                ip=i*ox/dx*3;
4670                                memmove(l+k, p+ip, 3);
4671                        }
4672                }
4673        }
4674        else
4675        {
4676                unsigned char *p,*q;
4677                int i,j,k,l,ya,yb;
4678                int sq,r,g,b;
4679
4680                p=cr;
4681
4682                int xa_v[dx];
4683                for(i=0;i<dx;i++)
4684                        xa_v[i] = i*ox/dx;
4685                int xb_v[dx+1];
4686               
4687                for(i=0;i<dx;i++)
4688                {
4689                        xb_v[i]= (i+1)*ox/dx;
4690                        if(xb_v[i]>=ox)
4691                                xb_v[i]=ox-1;
4692                }
4693               
4694                for(j=0;j<dy;j++)
4695                {
4696                        ya= j*oy/dy;
4697                        yb= (j+1)*oy/dy; if(yb>=oy) yb=oy-1;
4698                        for(i=0;i<dx;i++,p+=3)
4699                        {
4700                                for(l=ya,r=0,g=0,b=0,sq=0;l<=yb;l++)
4701                                {
4702                                        q=origin+((l*ox+xa_v[i])*3);
4703                                        for(k=xa_v[i];k<=xb_v[i];k++,q+=3,sq++)
4704                                        {
4705                                                r+=q[0]; g+=q[1]; b+=q[2];
4706                                        }
4707                                }
4708                                p[0]=r/sq; p[1]=g/sq; p[2]=b/sq;
4709                        }
4710                }
4711        }
4712       
4713        if(flag == 1)
4714                free(origin);
4715       
4716        return(cr);
4717}
4718
4719#endif
Note: See TracBrowser for help on using the repository browser.