source: titan/titan/skin.h @ 38562

Last change on this file since 38562 was 38562, checked in by obi, 7 years ago

fix

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