PXML support for file associations, and spitting out extra .desktop files for them...
[pandora-libraries.git] / lib / pnd_pxml.c
1
2 #include <stdio.h> /* for FILE */
3 #include <stdlib.h> /* for malloc */
4 #include <string.h> /* for string ops */
5
6 #include <sys/types.h> /* for stat */
7 #include <sys/stat.h> /* for stat */
8 #include <unistd.h> /* for stat */
9
10 #include "pnd_pxml.h"
11 #include "pnd_pathiter.h"
12 #include "pnd_tinyxml.h"
13 #include "pnd_logger.h"
14
15 pnd_pxml_handle *pnd_pxml_fetch ( char *fullpath ) {
16   FILE *f;
17   char *b;
18   unsigned int len;
19   pnd_pxml_handle *h;
20
21   f = fopen ( fullpath, "r" );
22
23   if ( ! f ) {
24     return ( 0 );
25   }
26
27   fseek ( f, 0, SEEK_END );
28
29   len = ftell ( f );
30
31   fseek ( f, 0, SEEK_SET );
32
33   if ( ! len ) {
34     return ( NULL );
35   }
36
37   b = (char*) malloc ( len + 1 );
38
39   if ( ! b ) {
40     fclose ( f );
41     return ( 0 );
42   }
43
44   fread ( b, 1, len, f );
45
46   fclose ( f );
47
48   h = pnd_pxml_fetch_buffer ( fullpath, b );
49   free ( b );
50
51   return ( h );
52 }
53
54 pnd_pxml_handle *pnd_pxml_fetch_buffer ( char *filename, char *buffer ) {
55
56   pnd_pxml_t **p = malloc ( sizeof(pnd_pxml_t*) * PXML_MAXAPPS );
57   memset ( p, '\0', sizeof(pnd_pxml_t*) * PXML_MAXAPPS );
58
59   if ( ! pnd_pxml_parse ( filename, buffer, strlen ( buffer ), p ) ) {
60     return ( 0 );
61   }
62
63   return ( (pnd_pxml_handle*) p );
64 }
65
66 void pnd_pxml_delete ( pnd_pxml_handle h ) {
67   pnd_pxml_t *p = (pnd_pxml_t*) h;
68
69   int i;
70   if (p->titles) {
71     for (i = 0; i < p->titles_c; i++)
72     {
73       free(p->titles[i].language);
74       free(p->titles[i].string);
75     }
76     free(p->titles);
77   }
78
79   if (p->descriptions) {
80     for (i = 0; i < p->descriptions_c; i++)
81     {
82       free(p->descriptions[i].language);
83       free(p->descriptions[i].string);
84     }
85     free(p->descriptions);
86   }
87
88   if ( p -> unique_id ) {
89      free ( p -> unique_id );
90   }
91   if ( p -> package_id ) {
92      free ( p -> package_id );
93   }
94   if ( p -> standalone ) {
95     free ( p -> standalone );
96   }
97   if ( p -> icon ) {
98     free ( p -> icon );
99   }
100   if ( p -> previewpic1 ) {
101     free ( p -> previewpic1 );
102   }
103   if ( p -> previewpic2 ) {
104     free ( p -> previewpic2 );
105   }
106   if ( p -> author_name ) {
107     free ( p -> author_name );
108   }
109   if ( p -> author_website ) {
110     free ( p -> author_website );
111   }
112   if ( p -> version_major ) {
113     free ( p -> version_major );
114   }
115   if ( p -> version_minor ) {
116     free ( p -> version_minor );
117   }
118   if ( p -> version_release ) {
119     free ( p -> version_release );
120   }
121   if ( p -> version_build ) {
122     free ( p -> version_build );
123   }
124   if ( p -> exec ) {
125     free ( p -> exec );
126   }
127   if ( p -> main_category ) {
128     free ( p -> main_category );
129   }
130   if ( p -> subcategory1 ) {
131     free ( p -> subcategory1 );
132   }
133   if ( p -> subcategory2 ) {
134     free ( p -> subcategory2 );
135   }
136   if ( p -> altcategory ) {
137     free ( p -> altcategory );
138   }
139   if ( p -> altsubcategory1 ) {
140     free ( p -> altsubcategory1 );
141   }
142   if ( p -> altsubcategory2 ) {
143     free ( p -> altsubcategory2 );
144   }
145   if ( p -> osversion_major ) {
146     free ( p -> osversion_major );
147   }
148   if ( p -> osversion_minor ) {
149     free ( p -> osversion_minor );
150   }
151   if ( p -> osversion_release ) {
152     free ( p -> osversion_release );
153   }
154   if ( p -> osversion_build ) {
155     free ( p -> osversion_build );
156   }
157   if ( p -> associationitem1_name ) {
158     free ( p -> associationitem1_name );
159   }
160   if ( p -> associationitem1_filetype ) {
161     free ( p -> associationitem1_filetype );
162   }
163   if ( p -> associationitem1_command ) {
164     free ( p -> associationitem1_command );
165   }
166   if ( p -> associationitem1_args ) {
167     free ( p -> associationitem1_args );
168   }
169   if ( p -> associationitem2_name ) {
170     free ( p -> associationitem2_name );
171   }
172   if ( p -> associationitem2_filetype ) {
173     free ( p -> associationitem2_filetype );
174   }
175   if ( p -> associationitem2_command ) {
176     free ( p -> associationitem2_command );
177   }
178   if ( p -> associationitem2_args ) {
179     free ( p -> associationitem2_args );
180   }
181   if ( p -> associationitem3_name ) {
182     free ( p -> associationitem3_name );
183   }
184   if ( p -> associationitem1_filetype ) {
185     free ( p -> associationitem3_filetype );
186   }
187   if ( p -> associationitem1_command ) {
188     free ( p -> associationitem3_command );
189   }
190   if ( p -> associationitem1_args ) {
191     free ( p -> associationitem3_args );
192   }
193   if ( p -> clockspeed ) {
194     free ( p -> clockspeed );
195   }
196   if ( p -> background ) {
197     free ( p -> background );
198   }
199   if ( p -> startdir ) {
200     free ( p -> startdir );
201   }
202   if ( p -> appdata_dirname ) {
203     free ( p -> appdata_dirname );
204   }
205   if ( p -> info_name ) {
206     free ( p -> info_name );
207   }
208   if ( p -> info_filename ) {
209     free ( p -> info_filename );
210   }
211   if ( p -> info_type ) {
212     free ( p -> info_type );
213   }
214   if ( p -> exec_no_x11 ) {
215     free ( p -> exec_no_x11 );
216   }
217   if ( p -> execargs ) {
218     free ( p -> execargs );
219   }
220   if ( p -> mkdir_sp ) {
221     free ( p -> mkdir_sp );
222   }
223   if ( p -> package_version_major ) {
224     free ( p -> package_version_major );
225   }
226   if ( p -> package_version_minor ) {
227     free ( p -> package_version_minor );
228   }
229   if ( p -> package_version_release ) {
230     free ( p -> package_version_release );
231   }
232   if ( p -> package_version_build ) {
233     free ( p -> package_version_build );
234   }
235
236   free(p); /*very important!*/
237
238   return;
239 }
240
241 void pnd_pxml_set_app_name ( pnd_pxml_handle h, char *v ) {
242   /*
243    * Please do not use this function if it can be avoided; it is only here for compatibility.
244    * The function might fail on low memory, and there's no way for the user to know when this happens.
245    */
246   pnd_pxml_t *p = (pnd_pxml_t*) h;
247   char has_en_field = 0;
248   int i;
249
250   if (!v) return; /*TODO: add error information? Make it possible to set the string to NULL?*/
251
252   for (i = 0; i < p->titles_c; i++)
253   {
254     if (strncmp("en", p->titles[i].language, 2) == 0) /*strict comparison; match "en_US", "en_GB" etc... All these are set.*/
255     {
256       free(p->titles[i].string);
257       p->titles[i].string = strdup(v);
258       has_en_field = 1;
259     }
260   }
261
262   if (!has_en_field)
263   {
264     p->titles_c++;
265     if (p->titles_c > p->titles_alloc_c) //we don't have enough strings allocated
266     {
267       p->titles_alloc_c <<= 1;
268       p->titles = (pnd_localized_string_t *)realloc((void*)p->titles, p->titles_alloc_c);
269       if (!p->titles) return; //errno = ENOMEM
270     }
271     p->titles[p->titles_c - 1].language = "en_US";
272     p->titles[p->titles_c - 1].string = strdup(v);
273   }
274
275   return;
276 }
277
278 unsigned char pnd_is_pxml_valid_app ( pnd_pxml_handle h ) {
279   //pnd_pxml_t *p = (pnd_pxml_t*) h; //unused atm
280
281   // for now, lets just verify the exec-path is valid
282
283   //printf ( "exec is '%s'\n", p -> exec );
284
285   return ( 1 );
286
287   // even this is complicated by pnd_run.sh semantics .. can't check if it exists
288   // during discovery, since it is not mounted yet..
289 #if 0
290   struct stat buf;
291   if ( stat ( p -> exec, &buf ) == 0 ) {
292     return ( 1 ); // path is present
293   }
294 #endif
295
296   return ( 0 );
297 }
298
299 signed char pnd_pxml_merge_override ( pnd_pxml_handle h, char *searchpath ) {
300   // the pxml includes a unique-id; use this value to attempt to find an
301   // override in the given searchpath
302   signed char retval = 0;
303
304 #if 0 // TODO: Unfinished entirely now
305   pnd_pxml_handle mergeh;
306
307   if ( ! pnd_pxml_get_unique_id ( h ) ) {
308     return ( -1 ); // no unique-id present, so can't use it to name potential override files
309   }
310
311   SEARCHPATH_PRE
312   {
313
314     // do it
315     strncat ( buffer, "/", FILENAME_MAX );
316     strncat ( buffer, pnd_pxml_get_unique_id ( h ), FILENAME_MAX );
317     strncat ( buffer, ".xml", FILENAME_MAX );
318     //printf ( "  Path to seek merges: '%s'\n", buffer );
319
320     // TODO: handle multiple subapps!
321     mergeh = pnd_pxml_fetch ( buffer );
322
323     if ( mergeh ) {
324
325       // TODO: handle all the various data bits
326       if ( pnd_pxml_get_app_name_en ( mergeh ) ) {
327         pnd_pxml_set_app_name ( h, pnd_pxml_get_app_name_en ( mergeh ) );
328       }
329
330       pnd_pxml_delete ( mergeh );
331     }
332
333   }
334   SEARCHPATH_POST
335 #endif
336
337   return ( retval );
338 }
339
340 char *pnd_pxml_get_best_localized_string(pnd_localized_string_t strings[], int strings_c, char *iso_lang)
341 {
342   int i;
343   int similarity_weight = 0xffff; /*Set to something Really Bad in the beginning*/
344   char *best_match = NULL;
345
346   for(i = 0; i < strings_c; i++)
347   {
348     // factor in the length -- if we're given 'en' and have a string 'en_US', thats better than 'de_something'; if we don't
349     // use length, then en_US and de_FO are same to 'en'.
350     int maxcount = strlen ( strings[i].language ) < strlen ( iso_lang ) ? strlen ( strings[i].language ) : strlen ( iso_lang );
351     int new_weight = abs(strncmp(strings[i].language, iso_lang, maxcount));
352     //pnd_log ( PND_LOG_DEFAULT, "looking for lang %s, looking at lang %s (weight %d, old %d): %s\n",
353     //          iso_lang, strings [ i ].language, new_weight, similarity_weight, strings [ i ].string );
354     if (new_weight < similarity_weight)
355     {
356       similarity_weight = new_weight;
357       best_match = strings[i].string;
358     }
359   }
360
361   if ( best_match ) {
362     //pnd_log ( PND_LOG_DEFAULT, "best match: %s\n", best_match );
363     return strdup(best_match);
364   }
365
366   //pnd_log ( PND_LOG_DEFAULT, "best match: FAIL\n" );
367
368   return ( NULL );
369 }
370
371 char *pnd_pxml_get_package_id ( pnd_pxml_handle h ) {
372   pnd_pxml_t *p = (pnd_pxml_t*) h;
373   return ( p -> package_id );
374 }
375
376 char *pnd_pxml_get_app_name ( pnd_pxml_handle h, char *iso_lang ) {
377   pnd_pxml_t *p = (pnd_pxml_t *) h;
378   return pnd_pxml_get_best_localized_string(p->titles, p->titles_c, iso_lang);
379 }
380
381 char *pnd_pxml_get_app_name_en ( pnd_pxml_handle h ) {
382   return pnd_pxml_get_app_name(h, "en");
383 }
384
385 char *pnd_pxml_get_app_name_de ( pnd_pxml_handle h ) {
386   return pnd_pxml_get_app_name(h, "de");
387 }
388
389 char *pnd_pxml_get_app_name_it ( pnd_pxml_handle h ) {
390   return pnd_pxml_get_app_name(h, "it");
391 }
392
393 char *pnd_pxml_get_app_name_fr ( pnd_pxml_handle h ) {
394   return pnd_pxml_get_app_name(h, "fr");
395 }
396 char *pnd_pxml_get_unique_id ( pnd_pxml_handle h ) {
397   pnd_pxml_t *p = (pnd_pxml_t*) h;
398   return ( p -> unique_id );
399 }
400
401 char *pnd_pxml_get_appdata_dirname ( pnd_pxml_handle h ) {
402   pnd_pxml_t *p = (pnd_pxml_t*) h;
403   return ( p -> appdata_dirname );
404 }
405
406 char *pnd_pxml_get_standalone ( pnd_pxml_handle h ) {
407   pnd_pxml_t *p = (pnd_pxml_t*) h;
408   return ( p -> standalone );
409 }
410
411 char *pnd_pxml_get_icon ( pnd_pxml_handle h ) {
412   pnd_pxml_t *p = (pnd_pxml_t*) h;
413   return ( p -> icon );
414 }
415
416 // this guy's func name is 'out of sync' with the family of functions below; but since it
417 // exists, rather than just remove it and break someones code, will add in the appropriate
418 // function wrapper; the header only specifies the other guy (always did), so the header
419 // was already on the right path.
420 char *pnd_pxml_get_app_description ( pnd_pxml_handle h, char *iso_lang ) {
421   pnd_pxml_t *p = (pnd_pxml_t *) h;
422   return pnd_pxml_get_best_localized_string(p->descriptions, p->descriptions_c, iso_lang);
423 }
424
425 char *pnd_pxml_get_description_en ( pnd_pxml_handle h ) {
426   return pnd_pxml_get_app_description(h, "en");
427 }
428
429 char *pnd_pxml_get_description_de ( pnd_pxml_handle h ) {
430   return pnd_pxml_get_app_description(h, "de");
431 }
432
433 char *pnd_pxml_get_description_it ( pnd_pxml_handle h ) {
434   return pnd_pxml_get_app_description(h, "it");
435 }
436
437 char *pnd_pxml_get_description_fr ( pnd_pxml_handle h ) {
438   return pnd_pxml_get_app_description(h, "fr");
439 }
440
441 // wrapper added so family of function names is consistent; see comment for pnd_pxml_get_app_description() above
442 char *pnd_pxml_get_description ( pnd_pxml_handle h, char *iso_lang) {
443   return ( pnd_pxml_get_app_description ( h, iso_lang ) );
444 }
445
446 char *pnd_pxml_get_previewpic1 ( pnd_pxml_handle h ) {
447   pnd_pxml_t *p = (pnd_pxml_t*) h;
448   return ( p -> previewpic1 );
449 }
450
451 char *pnd_pxml_get_previewpic2 ( pnd_pxml_handle h ) {
452   pnd_pxml_t *p = (pnd_pxml_t*) h;
453   return ( p -> previewpic2 );
454 }
455
456 char *pnd_pxml_get_author_name ( pnd_pxml_handle h ) {
457   pnd_pxml_t *p = (pnd_pxml_t*) h;
458   return ( p -> author_name );
459 }
460
461 char *pnd_pxml_get_author_website ( pnd_pxml_handle h ) {
462   pnd_pxml_t *p = (pnd_pxml_t*) h;
463   return ( p -> author_website );
464 }
465
466 char *pnd_pxml_get_version_major ( pnd_pxml_handle h ) {
467   pnd_pxml_t *p = (pnd_pxml_t*) h;
468   return ( p -> version_major );
469 }
470
471 char *pnd_pxml_get_version_minor ( pnd_pxml_handle h ) {
472   pnd_pxml_t *p = (pnd_pxml_t*) h;
473   return ( p -> version_minor );
474 }
475
476 char *pnd_pxml_get_version_release ( pnd_pxml_handle h ) {
477   pnd_pxml_t *p = (pnd_pxml_t*) h;
478   return ( p -> version_release );
479 }
480
481 char *pnd_pxml_get_version_build ( pnd_pxml_handle h ) {
482   pnd_pxml_t *p = (pnd_pxml_t*) h;
483   return ( p -> version_build );
484 }
485
486 char *pnd_pxml_get_exec ( pnd_pxml_handle h ) {
487   pnd_pxml_t *p = (pnd_pxml_t*) h;
488   return ( p -> exec );
489 }
490
491 char *pnd_pxml_get_execargs ( pnd_pxml_handle h ) {
492   pnd_pxml_t *p = (pnd_pxml_t*) h;
493   return ( p -> execargs );
494 }
495
496 char *pnd_pxml_get_exec_option_no_x11 ( pnd_pxml_handle h ) {
497   pnd_pxml_t *p = (pnd_pxml_t*) h;
498   return ( p -> exec_no_x11 );
499 }
500
501 char *pnd_pxml_get_main_category ( pnd_pxml_handle h ) {
502   pnd_pxml_t *p = (pnd_pxml_t*) h;
503   return ( p -> main_category );
504 }
505
506 char *pnd_pxml_get_subcategory1 ( pnd_pxml_handle h ) {
507   pnd_pxml_t *p = (pnd_pxml_t*) h;
508   return ( p -> subcategory1 );
509 }
510
511 char *pnd_pxml_get_subcategory2 ( pnd_pxml_handle h ) {
512   pnd_pxml_t *p = (pnd_pxml_t*) h;
513   return ( p -> subcategory2 );
514 }
515
516 char *pnd_pxml_get_altcategory ( pnd_pxml_handle h ) {
517   pnd_pxml_t *p = (pnd_pxml_t*) h;
518   return ( p -> altcategory );
519 }
520
521 char *pnd_pxml_get_altsubcategory1 ( pnd_pxml_handle h ) {
522   pnd_pxml_t *p = (pnd_pxml_t*) h;
523   return ( p -> altsubcategory1 );
524 }
525
526 char *pnd_pxml_get_altsubcategory2 ( pnd_pxml_handle h ) {
527   pnd_pxml_t *p = (pnd_pxml_t*) h;
528   return ( p -> altsubcategory2 );
529 }
530
531 char *pnd_pxml_get_osversion_major ( pnd_pxml_handle h ) {
532   pnd_pxml_t *p = (pnd_pxml_t*) h;
533   return ( p -> osversion_major );
534 }
535
536 char *pnd_pxml_get_osversion_minor ( pnd_pxml_handle h ) {
537   pnd_pxml_t *p = (pnd_pxml_t*) h;
538   return ( p -> osversion_minor );
539 }
540
541 char *pnd_pxml_get_osversion_release ( pnd_pxml_handle h ) {
542   pnd_pxml_t *p = (pnd_pxml_t*) h;
543   return ( p -> osversion_release );
544 }
545
546 char *pnd_pxml_get_osversion_build ( pnd_pxml_handle h ) {
547   pnd_pxml_t *p = (pnd_pxml_t*) h;
548   return ( p -> osversion_build );
549 }
550
551 char *pnd_pxml_get_associationitem1_name ( pnd_pxml_handle h ) {
552   pnd_pxml_t *p = (pnd_pxml_t*) h;
553   return ( p -> associationitem1_name );
554 }
555
556 char *pnd_pxml_get_associationitem1_filetype ( pnd_pxml_handle h ) {
557   pnd_pxml_t *p = (pnd_pxml_t*) h;
558   return ( p -> associationitem1_filetype );
559 }
560
561 char *pnd_pxml_get_associationitem1_command ( pnd_pxml_handle h ) {
562   pnd_pxml_t *p = (pnd_pxml_t*) h;
563   return ( p -> associationitem1_command );
564 }
565
566 char *pnd_pxml_get_associationitem1_args ( pnd_pxml_handle h ) {
567   pnd_pxml_t *p = (pnd_pxml_t*) h;
568   return ( p -> associationitem1_args );
569 }
570
571 char *pnd_pxml_get_associationitem2_name ( pnd_pxml_handle h ) {
572   pnd_pxml_t *p = (pnd_pxml_t*) h;
573   return ( p -> associationitem2_name );
574 }
575
576 char *pnd_pxml_get_associationitem2_filetype ( pnd_pxml_handle h ) {
577   pnd_pxml_t *p = (pnd_pxml_t*) h;
578   return ( p -> associationitem2_filetype );
579 }
580
581 char *pnd_pxml_get_associationitem2_command ( pnd_pxml_handle h ) {
582   pnd_pxml_t *p = (pnd_pxml_t*) h;
583   return ( p -> associationitem2_command );
584 }
585
586 char *pnd_pxml_get_associationitem2_args ( pnd_pxml_handle h ) {
587   pnd_pxml_t *p = (pnd_pxml_t*) h;
588   return ( p -> associationitem2_args );
589 }
590
591 char *pnd_pxml_get_associationitem3_name ( pnd_pxml_handle h ) {
592   pnd_pxml_t *p = (pnd_pxml_t*) h;
593   return ( p -> associationitem3_name );
594 }
595
596 char *pnd_pxml_get_associationitem3_filetype ( pnd_pxml_handle h ) {
597   pnd_pxml_t *p = (pnd_pxml_t*) h;
598   return ( p -> associationitem3_filetype );
599 }
600
601 char *pnd_pxml_get_associationitem3_command ( pnd_pxml_handle h ) {
602   pnd_pxml_t *p = (pnd_pxml_t*) h;
603   return ( p -> associationitem3_command );
604 }
605
606 char *pnd_pxml_get_associationitem3_args ( pnd_pxml_handle h ) {
607   pnd_pxml_t *p = (pnd_pxml_t*) h;
608   return ( p -> associationitem3_args );
609 }
610
611 char *pnd_pxml_get_clockspeed ( pnd_pxml_handle h ) {
612   pnd_pxml_t *p = (pnd_pxml_t*) h;
613   return ( p -> clockspeed );
614 }
615
616 char *pnd_pxml_get_background ( pnd_pxml_handle h ) {
617   pnd_pxml_t *p = (pnd_pxml_t*) h;
618   return ( p -> background );
619 }
620
621 char *pnd_pxml_get_startdir ( pnd_pxml_handle h ) {
622   pnd_pxml_t *p = (pnd_pxml_t*) h;
623   return ( p -> startdir );
624 }
625
626 char *pnd_pxml_get_mkdir ( pnd_pxml_handle h ) {
627   pnd_pxml_t *p = (pnd_pxml_t*) h;
628   return ( p -> mkdir_sp );
629 }
630
631 char *pnd_pxml_get_package_version_major ( pnd_pxml_handle h ) {
632    pnd_pxml_t *p = (pnd_pxml_t*) h;
633    return ( p -> package_version_major );
634 }
635
636 char *pnd_pxml_get_package_version_minor ( pnd_pxml_handle h ) {
637    pnd_pxml_t *p = (pnd_pxml_t*) h;
638    return ( p -> package_version_minor );
639 }
640
641 char *pnd_pxml_get_package_version_release ( pnd_pxml_handle h ) {
642    pnd_pxml_t *p = (pnd_pxml_t*) h;
643    return ( p -> package_version_release );
644 }
645
646 char *pnd_pxml_get_package_version_build ( pnd_pxml_handle h ) {
647    pnd_pxml_t *p = (pnd_pxml_t*) h;
648    return ( p -> package_version_build );
649 }
650
651 unsigned char pnd_pxml_is_affirmative ( char *v ) {
652
653   if ( ! v ) {
654     return ( 0 );
655   }
656
657   if ( ( v [ 0 ] == 'Y' ) ||
658        ( v [ 0 ] == 'y' ) ||
659        ( v [ 0 ] == '1' ) )
660   {
661     return ( 0 );
662   }
663
664   return ( 0 );
665 }
666
667 pnd_pxml_x11_req_e pnd_pxml_get_x11 ( char *pxmlvalue ) {
668
669   if ( ! pxmlvalue ) {
670     return ( pnd_pxml_x11_ignored );
671   } else if ( strcasecmp ( pxmlvalue, "req" ) == 0 ) {
672     return ( pnd_pxml_x11_required );
673   } else if ( strcasecmp ( pxmlvalue, "stop" ) == 0 ) {
674     return ( pnd_pxml_x11_stop );
675   } else if ( strcasecmp ( pxmlvalue, "ignore" ) == 0 ) {
676     return ( pnd_pxml_x11_ignored );
677   }
678
679   return ( pnd_pxml_x11_ignored ); // default
680 }
681
682 char *pnd_pxml_get_info_name ( pnd_pxml_handle h ) {
683   pnd_pxml_t *p = (pnd_pxml_t*) h;
684   return ( p -> info_name );
685 }
686
687 char *pnd_pxml_get_info_type ( pnd_pxml_handle h ) {
688   pnd_pxml_t *p = (pnd_pxml_t*) h;
689   return ( p -> info_type );
690 }
691
692 char *pnd_pxml_get_info_src ( pnd_pxml_handle h ) {
693   pnd_pxml_t *p = (pnd_pxml_t*) h;
694   return ( p -> info_filename );
695 }