source: titan/titan/skin.h @ 32105

Last change on this file since 32105 was 32105, checked in by Stephan, 9 years ago

[webif] led bar gray when mute
[oled] symbols only for nemesis

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