Base: LCDproc 0.5.2
[lcdproc-de200c.git] / docs / lcdproc-dev / driver-api.docbook
blobf32a0d00bba3849a270e669b0c3a98a9dbac47a8
1 <chapter id="driver-api">
2   <title>The LCDproc driver API</title>
4 <para>
5   This chapter describes the driver API of v0.5 of LCDproc.
6   At time of this writing, this version is not released and some things might
7   be changed.
8 </para>
10 <para>
11   The API consists of several functions to tell the driver that
12   certains actions should be performed, some data, and several functions
13   to retrieve configuration data from the server.
14 </para>
16 <sect1 id="api-overview">
17   <title>OVERVIEW OF OPERATION</title>
19 <para>
20   The API is best descibed by starting with the struct lcd_logical_driver
21   which is defined in server/drivers/lcd.h.
22 </para>
24 <para>
25   The use of the API has changed from v0.4 to v0.5. The default functions that
26   the server put in the pointers in v0.4 do no longer exist. Instead empty
27   functions are the default. If a driver implements a function, the function
28   will be detected by the server. The driver should at least implement all
29   basic functions like driver_chr and driver_str itself, and should also have
30   defined a number of other symbols for the server.
31 </para>
33 <para>
34   I will walk through the driver struct here.
35 </para>
37 <screen>
39 typedef struct lcd_logical_driver {
41         //////// Variables to be provided by the driver module
42         // The driver loader will look for symbols with these names !
44         // pointer to a string describing the API version
45         char *api_version;
47         // Does this driver require to be in foreground ?
48         int *stay_in_foreground;// Does this driver require to be in foreground ?
50         / Does this driver support multiple instances ?
51         int *supports_multiple;
53         // What should alternatively be prepended to the function names ?
54         char **symbol_prefix;
57 The programmer should define the following symbols:
58 char * api_version = API_VERSION;       // &lt;-- this symbol is defined by make
59 int stay_in_foreground = 0;             // This driver does not need to be in foreground
60 int supports_multiple = 0;              // This driver does not c$support multiple instances
61 char *symbol_prefix = "MyDriver_";      // Driver functions start with MyDriver_
62 And fill these values with the correct values. Upon loading the driver module,
63 the server will locate these symbols and store pointers to them in the
64 driver struct.
66 Because the drivers are loadable, some kind of version checking should be
67 done. Therefor the server expects the correct version number to be found in
68 the api_version symbol (a string). For the v0.5 version this should be "0.5".
69 If the version is incompatible, the driver will not be loaded. The current
70 API version can always be determined by inserting the compiler define
71 API_VERSION in the code.
74         //////// Functions to be provided by the driver module
76         //// Mandatory functions (necessary for all drivers)
78         // initialize driver: returns &gt;= 0 on success
79         int (*init)             (Driver *drvthis);
81         // close driver
82         void (*close)           (Driver *drvthis);
85         //// Essential output functions (necessary for output drivers)
87         // get display width / height (in characters; 1-based)
88         int (*width)            (Driver *drvthis);
89         int (*height)           (Driver *drvthis);
91         // clear screen
92         void (*clear)           (Driver *drvthis);
94         // flush screen contents to LCD
95         void (*flush)           (Driver *drvthis);
97         // write string s at position (x,y)
98         void (*string)          (Driver *drvthis, int x, int y, char *str);
100         // write char c at position (x,y)
101         void (*chr)             (Driver *drvthis, int x, int y, char c);
104         //// essential input functions (necessary for input drivers)
106         // get key from driver: returns a string denoting the key pressed
107         const char *(*get_key)  (Driver *drvthis);
110         //// Extended output functions (optional; core provides alternatives)
112         // draw a bar from pos (x,y) upward / to the right filling promille of len chars
113         void (*vbar)            (Driver *drvthis, int x, int y, int len, int promille, int options);
114         void (*hbar)            (Driver *drvthis, int x, int y, int len, int promille, int options);
116         // display (big) number num at horizontal position x
117         void (*num)             (Driver *drvthis, int x, int num);
119         // set heartbeat state; animate heartbeat
120         void (*heartbeat)       (Driver *drvthis, int state);
122         // draw named icon at position (x,y)
123         void (*icon)            (Driver *drvthis, int x, int y, int icon);
125         // set cursor type and move it to position (x,y)
126         void (*cursor)          (Driver *drvthis, int x, int y, int type);
129         //// User-defined character functions
131         // set special character / get free characters
132         // - It is currently unclear how this system should work exactly
133         // - The set_char function expects a simple block of data with 1 byte for each pixel-line.
134         //   (So that is 8 bytes for a 5x8 char)
135         void (*set_char)        (Driver *drvthis, char ch, unsigned char *dat);
136         int (*get_free_chars)   (Driver *drvthis);
138         // get width / height of a character cell (in pixels)
139         // - necessary to provide info about cell size to clients
140         // - if not defined, the core will provide alternatives returning default values
141         int (*cellwidth)        (Driver *drvthis);
142         int (*cellheight)       (Driver *drvthis);
145         //// Hardware functions
147         // get / set the display's contrast
148         int (*get_contrast)     (Driver *drvthis);
149         int (*set_contrast)     (Driver *drvthis, int promille);
151         // get / set brightness for given backlight state
152         int (*get_brightness)   (Driver *drvthis, int state);
153         int (*set_brightness)   (Driver *drvthis, int state, int promille);
155         // set backlight state
156         void (*backlight)       (Driver *drvthis, int state);
158         // set output
159         void (*output)          (Driver *drvthis, int state);
162         //// Informational functions
163         // get a string describing the driver and it's features
164         const char * (*get_info) (Driver *drvthis);
168         //////// Variables in server core, available for drivers
170         // name of the driver instance (name of the config file section)
171         // - do not change from the driver; consider it read-only
172         // - to be used to access the driver's own section in the config file
173         char * name;    
175         // pointer to the driver instance's private data
176         // - filled by the server by calling store_private_ptr()
177         // - the driver should cast this to it's own private structure pointer
178         void * private_data;
181         //////// Functions in server core, available for drivers
183         // store a pointer to the driver instance's private data
184         int (*store_private_ptr) (struct lcd_logical_driver * driver, void * private_data);
186         // Config file functions, cwprovided by the server
187         // - see configfile.h on how to use these functions
188         // - as sectionname, always use the driver name: drvthis->name
189         char (*config_get_bool) (char * sectionname, char * keyname,
190                                 int skip, char default_value);
191         int (*config_get_int)   (char * sectionname, char * keyname,
192                                 int skip, int default_value);
193         double (*config_get_float) (char * sectionname, char * keyname,
194                                 int skip, double default_value);
195         char *(*config_get_string) (char * sectionname, char * keyname,
196                                 int skip, char * default_value);
197                                 // Returns a string in server memory space.
198                                 // Copy this string.
199         int config_has_section  (char *sectionname);
200         int config_has_key      (char *sectionname, char *keyname);
202         // error reporting function
203         // - see drivers/report.h for details
204         void (*report)                  ( const int level, const char *format, .../*args*/ );
206         // Display properties functions (for drivers that adapt to other loaded drivers)
207         // - the return the size of another already loaded driver
208         // - if no driver is loaded yet, the return values will be 0
209         int (*get_display_width) ();
210         int (*get_display_height) ();
211 } Driver;
213 </screen>
215 </sect1>
217 <sect1 id="private-data">
218   <title>PRIVATE DATA</title>
220 <para>
221   With the introduction of loadable modules it is necesary to stop using global
222   variables to store a driver's data in. Instead, you should store it in a
223   structure, that you allocate abd store on driver's init. If you don't use
224   this system, but use globals, you get queer results if you run two LCDd
225   daemons on one machine. They will then use the same variables !
226 </para>
228 <para>
229   In the driver's private structure will probably at least be something like:
230 </para>
232 <screen>
233 typedef struct my_driver_private {
234         int fd;                         // file descriptor for the LCD device
235         int width, height;              // dimension of the LCD (in characters, 1-based
236         int cellwidth, cellheight;      // Size of each LCD cell, in pixels
237         unsigned char *framebuf;        // Frame buffer...
238 } PrivateData;
239 </screen>
241 <para>
242   You allocate and store this structure like this:
243 </para>
245 <screen>
246         PrivateData *p;
248         // Allocate and store private data
249         p = (PrivateData *) malloc(sizeof(PrivateData));
250         if (p == NULL)
251                 return -1;
252         if (drvthis->store_private_ptr( drvthis, p ) &lt; 0)
253                 return -1;
255         // initialize private data
256         p->fd = -1;
257         p->cellheight = 8;
258         p->cellwidth = 6;
260         (... continue with the rest of your init routine)
261 </screen>
263 <para>
264   You retrieve this private data pointer by adding the following code to the
265   beginning of your functions:
266 </para>
268 <screen>
269         PrivateData *p = (PrivateData *) drvthis->private_data;
270 </screen>
272 <para>
273   Then you can access your data like:
274 </para>
275 <screen>
276         p->framebuf
277 </screen>
279 </sect1>
281 <sect1 id="function-details">
282   <title>FUNCTIONS IN DETAIL</title>
284 <funcsynopsis>
285   <funcprototype>
286         <funcdef>int <function>(*init)</function></funcdef>
287         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
288   </funcprototype>
289 </funcsynopsis>
290 <para>
291   The init() function.
292   It starts up the LCD, initializes all variables, allocates private data space
293   and stores the pointer by calling store_private_ptr();
294 </para>
296 <funcsynopsis>
297   <funcprototype>
298         <funcdef>void <function>(*close)</function></funcdef>
299         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
300   </funcprototype>
301 </funcsynopsis>
302 <para>
303   Shut down the connection with the LCD.
304   Called just before unloading the driver.
305 </para>
307 <funcsynopsis>
308   <funcprototype>
309         <funcdef>int <function>(*width)</function></funcdef>
310         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
311   </funcprototype>
312 </funcsynopsis>
313 <para>
314   Get the screen width in characters.
315   The result is 1-based.
316 </para>
318 <funcsynopsis>
319   <funcprototype>
320         <funcdef>int <function>(*height)</function></funcdef>
321         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
322   </funcprototype>
323 </funcsynopsis>
324 <para>
325   Get the screen height in character lines.
326   The result is 1-based.
327 </para>
329 <funcsynopsis>
330   <funcprototype>
331         <funcdef>void <function>(*clear)</function></funcdef>
332         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
333   </funcprototype>
334 </funcsynopsis>
335 <para>
336   Clear the framebuffer.
337 </para>
339 <funcsynopsis>
340   <funcprototype>
341         <funcdef>void <function>(*flush)</function></funcdef>
342         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
343   </funcprototype>
344 </funcsynopsis>
345 <para>
346   Flush the framebuffer to the LCD.
347 </para>
349 <funcsynopsis>
350   <funcprototype>
351         <funcdef>void <function>(*string)</function></funcdef>
352         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
353         <paramdef>int <parameter>x</parameter></paramdef>
354         <paramdef>int <parameter>y</parameter></paramdef>
355         <paramdef>char *<parameter>str</parameter></paramdef>
356   </funcprototype>
357 </funcsynopsis>
358 <para>
359   Place string <replaceable>str</replaceable> into position
360   (<replaceable>x</replaceable>,<replaceable>y</replaceable>) in the framebuffer.
361   All coordinates are 1-based, i.e. (1,1) is top left.
362   The driver should check for overflows, i.e. that the positional parameters
363   are within the screen's boundaries and cut off the part of the string
364   that is out of bounds.
365 </para>
367 <funcsynopsis>
368   <funcprototype>
369         <funcdef>void <function>(*chr)</function></funcdef>
370         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
371         <paramdef>int <parameter>x</parameter></paramdef>
372         <paramdef>int <parameter>y</parameter></paramdef>
373         <paramdef>char <parameter>c</parameter></paramdef>
374   </funcprototype>
375 </funcsynopsis>
376 <para>
377   Place a single character <replaceable>c</replaceable> into position
378   (<replaceable>x</replaceable>,<replaceable>y</replaceable>) in the framebuffer.
379   The driver should check for overflows, i.e. that the positional parameters
380   are within the screen's boundaries and ignore the request if 
381   the character is out of bounds.
382 </para>
384 <funcsynopsis>
385   <funcprototype>
386         <funcdef>void <function>(*vbar)</function></funcdef>
387         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
388         <paramdef>int <parameter>x</parameter></paramdef>
389         <paramdef>int <parameter>y</parameter></paramdef>
390         <paramdef>int <parameter>len</parameter></paramdef>
391         <paramdef>int <parameter>promille</parameter></paramdef>
392         <paramdef>int <parameter>options</parameter></paramdef>
393   </funcprototype>
394 </funcsynopsis>
395 <para>
396   Draw a vertical bar at position (<replaceable>x</replaceable>,<replaceable>y</replaceable>)
397   that has maximal length <replaceable>len</replaceable>, where a fraction of
398   (<replaceable>promille</replaceable> / 1000) is filled.
399 </para>
401 <funcsynopsis>
402   <funcprototype>
403         <funcdef>void <function>(*hbar)</function></funcdef>
404         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
405         <paramdef>int <parameter>x</parameter></paramdef>
406         <paramdef>int <parameter>y</parameter></paramdef>
407         <paramdef>int <parameter>len</parameter></paramdef>
408         <paramdef>int <parameter>promille</parameter></paramdef>
409         <paramdef>int <parameter>options</parameter></paramdef>
410   </funcprototype>
411 </funcsynopsis>
412 <para>
413   Draw a horizontal bar at position (<replaceable>x</replaceable>,<replaceable>y</replaceable>)
414   that has maximal length <replaceable>len</replaceable>, where a fraction of
415   (<replaceable>promille</replaceable> / 1000) is filled.
416 </para>
418 <funcsynopsis>
419   <funcprototype>
420         <funcdef>void <function>(*num)</function></funcdef>
421         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
422         <paramdef>int <parameter>x</parameter></paramdef>
423         <paramdef>int <parameter>num</parameter></paramdef>
424   </funcprototype>
425 </funcsynopsis>
426 <para>
427   Display big number <replaceable>num</replaceable> at horizontal position <replaceable>x</replaceable>.
428 </para>
430 <funcsynopsis>
431   <funcprototype>
432         <funcdef>void <function>(*heartbeat)</function></funcdef>
433         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
434         <paramdef>int <parameter>state</parameter></paramdef>
435   </funcprototype>
436 </funcsynopsis>
437 <para>
438   Sets the heartbeat to the indicated state: 0=off 1=graph1 2=graph2
439   HEARTBEAT_ON to say that we want to display/refresh the heartbeat.
440   The driver choose how to do it. See MtxOrb.c
441 </para>
443 <funcsynopsis>
444   <funcprototype>
445         <funcdef>void <function>(*icon)</function></funcdef>
446         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
447         <paramdef>int <parameter>x</parameter></paramdef>
448         <paramdef>int <parameter>y</parameter></paramdef>
449         <paramdef>int <parameter>icon</parameter></paramdef>
450   </funcprototype>
451 </funcsynopsis>
452 <para>
453   Draw named icon <replaceable>icon</replaceable> at position
454   (<replaceable>x</replaceable>,<replaceable>y</replaceable>).
455 </para>
457 <funcsynopsis>
458   <funcprototype>
459         <funcdef>void <function>(*cursor)</function></funcdef>
460         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
461         <paramdef>int <parameter>x</parameter></paramdef>
462         <paramdef>int <parameter>y</parameter></paramdef>
463         <paramdef>int <parameter>type</parameter></paramdef>
464   </funcprototype>
465 </funcsynopsis>
466 <para>
467   Move cursor to position (<replaceable>x</replaceable>,<replaceable>y</replaceable>),
468   setting its type to <replaceable>type</replaceable>.
469 </para>
471 <funcsynopsis>
472   <funcprototype>
473         <funcdef>void <function>(*set_char)</function></funcdef>
474         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
475         <paramdef>char <parameter>ch</parameter></paramdef>
476         <paramdef>unsigned char *<parameter>dat</parameter></paramdef>
477   </funcprototype>
478 </funcsynopsis>
479 <para>
480 The set_char function expects a simple block of data with 1 byte for each pixel-line.
481 (So that is 8 bytes for a 5x8 char)
482 </para>
484 <funcsynopsis>
485   <funcprototype>
486         <funcdef>int <function>(*get_free_chars)</function></funcdef>
487         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
488   </funcprototype>
489 </funcsynopsis>
490 <para>
491 </para>
493 <funcsynopsis>
494   <funcprototype>
495         <funcdef>int <function>(*cellwidth)</function></funcdef>
496         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
497   </funcprototype>
498 </funcsynopsis>
499 <para>
500   Return the width of a character cell in pixels.
501   The result is 1-based.
502 </para>
504 <funcsynopsis>
505   <funcprototype>
506         <funcdef>int <function>(*cellheight)</function></funcdef>
507         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
508   </funcprototype>
509 </funcsynopsis>
510 <para>
511   Return the height of a character cell in pixels.
512   The result is 1-based.
513 </para>
515 <funcsynopsis>
516   <funcprototype>
517         <funcdef>int <function>(*get_contrast)</function></funcdef>
518         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
519   </funcprototype>
520 </funcsynopsis>
521 <para>
522   Get the contrast value from the driver.
523   The return value is an integer in the range from 0 to 1000.
524   Many displays do not support getting or setting contrast using software.
525 </para>
527 <funcsynopsis>
528   <funcprototype>
529         <funcdef>int <function>(*set_contrast)</function></funcdef>
530         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
531         <paramdef>int <parameter>promille</parameter></paramdef>
532   </funcprototype>
533 </funcsynopsis>
534 <para>
535   Sets the contrast to the given value, which is an integer in the range from 0 to 1000.
536   It is up to the driver to map the logical interval [0, 1000] into the
537   interval that the hardware supports.
538   Many displays do not support software setting of contrast.
539 </para>
541 <funcsynopsis>
542   <funcprototype>
543         <funcdef>int <function>(*get_brightness)</function></funcdef>
544         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
545         <paramdef>int <parameter>state</parameter></paramdef>
546   </funcprototype>
547 </funcsynopsis>
548 <para>
549   Get the brightness value from the driver for the given backlight state.
550   The parameter <parameter>state</parameter> determnies which one
551   is returned.
552   The return value is an integer in the range from 0 to 1000.
553   Many displays do not support getting or setting brightness using software.
554 </para>
556 <funcsynopsis>
557   <funcprototype>
558         <funcdef>int <function>(*set_brightness)</function></funcdef>
559         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
560         <paramdef>int <parameter>state</parameter></paramdef>
561         <paramdef>int <parameter>promille</parameter></paramdef>
562   </funcprototype>
563 </funcsynopsis>
564 <para>
565   Set the brightness for the given backlight state to the value given.
566   Value must be an integer in the range from 0 to 1000.
567   It is up to the driver to map the logical interval [0, 1000] into the
568   interval that the hardware supports.
569   Many displays do not support software setting of brightness.
570 </para>
572 <funcsynopsis>
573   <funcprototype>
574         <funcdef>void <function>(*backlight)</function></funcdef>
575         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
576         <paramdef>int <parameter>state</parameter></paramdef>
577   </funcprototype>
578 </funcsynopsis>
579 <para>
580   Sets the backlight to the given brightness state.
581   Often hardware can only support two values for the backlight:
582   on and off.
583   In that case any value of state &gt; 0 will switch the backlight on.
584 </para>
586 <funcsynopsis>
587   <funcprototype>
588         <funcdef>void <function>(*output)</function></funcdef>
589         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
590         <paramdef>int <parameter>state</parameter></paramdef>
591   </funcprototype>
592 </funcsynopsis>
593 <para>
594   Sets the output value. Some displays/wirings have a general purpose
595   output, which can be controlled by calling this function. See the
596   'output' command in the 'widget language'.
597 </para>
599 <funcsynopsis>
600   <funcprototype>
601         <funcdef>const char *<function>(*get_key)</function></funcdef>
602         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
603   </funcprototype>
604 </funcsynopsis>
605 <para>
606   Checks if a key has been pressed on the device.
607   Returns NULL for "no key pressed", or a string describing the pressd key.
608   These characters should match the keypad-layout.
609 </para>
611 <funcsynopsis>
612   <funcprototype>
613         <funcdef>const char *<function>(*get_info)</function></funcdef>
614         <paramdef>Driver *<parameter>drvthis</parameter></paramdef>
615   </funcprototype>
616 </funcsynopsis>
617 <para>
618   Returns a string describing the driver and its features.
619 </para>
621 <funcsynopsis>
622   <funcprototype>
623         <funcdef>char <function>(*config_get_bool)</function></funcdef>
624         <paramdef>char *<parameter>sectionname</parameter></paramdef>
625         <paramdef>char *<parameter>keyname</parameter></paramdef>
626         <paramdef>int <parameter>skip</parameter></paramdef>
627         <paramdef>char <parameter>default_value</parameter></paramdef>
628   </funcprototype>
629 </funcsynopsis>
630 <para>
631   Call to server. Retrieve a bool from the config file.
632   Sectionname should be the name of the driver (as in the struct).
633   If the key cannot be found, the default value will be returned.
634   skip should be 0 usually, but if you want to retrieve multiple
635   identical keys, then increase skip to get every next value.
636 </para>
638 <funcsynopsis>
639   <funcprototype>
640         <funcdef>int <function>(*config_get_int)</function></funcdef>
641         <paramdef>char *<parameter>sectionname</parameter></paramdef>
642         <paramdef>char *<parameter>keyname</parameter></paramdef>
643         <paramdef>int <parameter>skip</parameter></paramdef>
644         <paramdef>int <parameter>default_value</parameter></paramdef>
645   </funcprototype>
646 </funcsynopsis>
647 <para>
648   Call to server. Retrieve an integer from the config file.
649 </para>
651 <funcsynopsis>
652   <funcprototype>
653         <funcdef>double <function>(*config_get_float)</function></funcdef>
654         <paramdef>char *<parameter>sectionname</parameter></paramdef>
655         <paramdef>char *<parameter>keyname</parameter></paramdef>
656         <paramdef>int <parameter>skip</parameter></paramdef>
657         <paramdef>double <parameter>default_value</parameter></paramdef>
658   </funcprototype>
659 </funcsynopsis>
660 <para>
661   Call to server. Retrieve a float from the config file.
662 </para>
664 <funcsynopsis>
665   <funcprototype>
666         <funcdef>char *<function>(*config_get_string)</function></funcdef>
667         <paramdef>char *<parameter>sectionname</parameter></paramdef>
668         <paramdef>char *<parameter>keyname</parameter></paramdef>
669         <paramdef>int <parameter>skip</parameter></paramdef>
670         <paramdef>char *<parameter>default</parameter></paramdef>
671   </funcprototype>
672 </funcsynopsis>
673 <para>
674   Call to server. Retrieve a string from the config file.
675   Fill result with a pointer to some available space. You can fill it
676   with a default value. If the key is found, it will be overwritten
677   with the value from the key.
678   Note that you should always first copy the the returned string.
679   It is in the address space of the server, and will be freed at the
680   next call.
681 </para>
683 <funcsynopsis>
684   <funcprototype>
685         <funcdef>int <function>config_has_section</function></funcdef>
686         <paramdef>char *<parameter>sectionname</parameter></paramdef>
687   </funcprototype>
688 </funcsynopsis>
689 <para>
690   Returns wether a section exists. Does not need to be called prior
691   to a call to a config_get_* function.
692 </para>
694 <funcsynopsis>
695   <funcprototype>
696         <funcdef>int <function>config_has_key</function></funcdef>
697         <paramdef>char *<parameter>sectionname</parameter></paramdef>
698         <paramdef>char *<parameter>keyname</parameter></paramdef>
699   </funcprototype>
700 </funcsynopsis>
701 <para>
702   Returns the number of times a key exists. Does not need to be called
703   prior to a call to a config_get_* function.
704 </para>
707 <screen>
708 First version, Joris Robijn, 20011016
709 </screen>
711 </sect1>
713 </chapter>