source: titan/titan/skin.h @ 15271

Last change on this file since 15271 was 15271, checked in by nit, 12 years ago

[titan] add bgpic= to skinconfig, a background picture for all screens

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