source: titan/titan/skin.h @ 32089

Last change on this file since 32089 was 32089, checked in by Stephan, 8 years ago

[oled] symbol for streaming

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