source: titan/titan/skin.h @ 30881

Last change on this file since 30881 was 30881, checked in by obi, 8 years ago

add debug for #233

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