1 /*
2 
3     Geogrid-Viewer overlay file  Version 0.9.3
4 
5     A detail description of the ASCII-overlay-fomat you can find in the
6     helpfile of Geogrid-Viewer.
7 
8     Latest changes at 11.01.2005 by Fredie Kern
9 
10     Copyright (C) 2005 Fredie Kern, f.kern@xdesy.de
11 
12 
13     This program is free software; you can redistribute it and/or modify
14     it under the terms of the GNU General Public License as published by
15     the Free Software Foundation; either version 2 of the License, or
16     (at your option) any later version.
17 
18     This program is distributed in the hope that it will be useful,
19     but WITHOUT ANY WARRANTY; without even the implied warranty of
20     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21     GNU General Public License for more details.
22 
23     You should have received a copy of the GNU General Public License
24     along with this program; if not, write to the Free Software
25     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
26 
27  */
28 #include "defs.h"
29 #include "grtcirc.h"
30 
31 static short_handle mkshort_handle;
32 
33 #define MYNAME         "overlay"
34 #define PARAMETER_FILE "overlay.def"
35 
36 #undef  MAPNAME
37 #define MAPNAME "Bundesrepublik 1:1 Mio"
38 #undef  MAPNAME
39 #define MAPNAME "Top. Karte 1:50.000 Nieders."
40 
41 static gbfile* fpout;
42 static gbfile* fpin;
43 static int govl_cnt;
44 static double govl_sum_e=0.0;
45 static double govl_sum_n=0.0;
46 static double govl_sumcnt=0.0;
47 static int    govl_symbol_cnt=0;
48 static int    govl_group_cnt=0;
49 /*
50 static double govl_last_east=0.0;
51 static double govl_last_north=0.0;
52 */
53 
54 static int     govl_col=1;
55 static char*   govl_col_s = NULL;
56 static int     govl_size=101;
57 static char*   govl_size_s = NULL;
58 static double  govl_dir=0.0;
59 
60 static char* govl_mapname = NULL;
61 static int   govl_zoomfc = 100;
62 static char* govl_zoomfc_s = NULL;
63 static int   govl_dimmfc = 100;
64 static char* govl_dimmfc_s = NULL;
65 
66 
67 static int     govl_txtcol=1;
68 static int     govl_txtsize=120;
69 static int     govl_font=1;
70 static int     govl_txttrans=0;
71 
72 static char* govl_txtcol_s = NULL;
73 static char* govl_txtsize_s = NULL;
74 static char* govl_font_s = NULL;
75 static char* govl_txttrans_s = NULL;
76 
77 static char* govl_file_s = NULL;
78 
79 static arglist_t ovl_args[] = {
80   {
81     "col", &govl_col_s, "color index [1-9] for routes",
82     NULL, ARGTYPE_INT, "1", "9"
83   },
84   {
85     "size", &govl_size_s, "size index [101-] for routes",
86     NULL, ARGTYPE_INT, "101", NULL
87   },
88   {
89     "mapname", &govl_mapname, "name of map",
90     NULL, ARGTYPE_STRING, ARG_NOMINMAX
91   },
92   {
93     "zoomfc", &govl_zoomfc_s, "zoom factor of map in %",
94     NULL, ARGTYPE_INT, ARG_NOMINMAX
95   },
96   {
97     "dimmfc", &govl_dimmfc_s, "dimmer factor of map in %",
98     NULL, ARGTYPE_INT, ARG_NOMINMAX
99   },
100   {
101     "txtcol", &govl_txtcol_s, "color index [1-9] for waypoint names",
102     NULL, ARGTYPE_INT, "1", "9"
103   },
104   {
105     "txtsize", &govl_txtsize_s, "text size [101-] for waypoint names",
106     NULL, ARGTYPE_INT, "101", NULL
107   },
108   {
109     "font", &govl_font_s, "font index [1-] for waypoint names",
110     NULL, ARGTYPE_INT, "1", NULL
111   },
112   {
113     "txttrans", &govl_txttrans_s, "set text background to transparent",
114     NULL, ARGTYPE_BOOL, ARG_NOMINMAX
115   },
116   {
117     "file", &govl_file_s, "use file of parameters (parameters on command line overwrites file parameters)",
118     NULL, ARGTYPE_STRING, ARG_NOMINMAX
119   },
120   ARG_TERMINATOR
121 };
122 
123 
124 static char* Keywords[]= {
125   "Typ",
126   "Group",
127   "Col",
128   "Zoom",
129   "Size",
130   "Art",
131   "Punkte",
132   "Path",
133   "Dir",
134   "Font",
135   "Area",
136   "Text",
137   "Width",
138   "Height",
139   "Trans",
140   "TransByte",
141   NULL
142 };
143 
144 #define KEY_TYP        0
145 #define KEY_GROUP      1
146 #define KEY_COL        2
147 #define KEY_ZOOM       3
148 #define KEY_SIZE       4
149 #define KEY_ART        5
150 #define KEY_PUNKTE     6
151 #define KEY_PATH       7
152 #define KEY_DIR        8
153 #define KEY_FONT       9
154 #define KEY_AREA      10
155 #define KEY_TEXT      11
156 #define KEY_WIDTH     12
157 #define KEY_HEIGHT    13
158 #define KEY_TRANS     14
159 #define KEY_TRANSBYTE 15
160 
isKeyword(char * str,char ** keys)161 static int isKeyword(char* str,char** keys)
162 {
163   int i;
164 
165   i = 0;
166   while (keys[i]!=NULL && strcmp(str,keys[i])) {
167     i++;
168   }
169   return(keys[i]==NULL ? -1 : i);
170 }
171 
172 /*----------------------------------------------*/
173 
174 static
ovl_rd_init(char const * fname)175 void ovl_rd_init(char const* fname)
176 {
177   fpin = gbfopen(fname, "r", MYNAME);
178 }
179 
180 #define SECTION_NONE    0
181 #define SECTION_SYMBOL  1
182 #define SECTION_PUNKTE  2
183 #define SECTION_OVERLAY 3
184 
185 #define MAXLINE 512
186 
187 static  struct _group {
188   int  group;
189   char* name;
190 }* groups;
191 static  int    groups_cnt;
192 
ovl_add_group(int aktgrp,char * akttxt)193 static void ovl_add_group(int aktgrp,char* akttxt)
194 {
195   int i;
196 
197   i = 0;
198   while (i<groups_cnt && groups[i].group!=aktgrp) {
199     i++;
200   }
201   if (i==groups_cnt) {
202     groups = (struct _group*) xrealloc(groups,(groups_cnt+1)*sizeof(struct _group));
203     groups[i].group = aktgrp;
204     groups[i].name = NULL;
205     groups_cnt++;
206   }
207   groups[i].name = (char*) xrealloc(groups[i].name,(strlen(akttxt)+1)*sizeof(char));
208   strcpy(groups[i].name,akttxt);
209 }
210 
211 /*
212   The name of route is stored in a 'Text'-symbol with identical 'Group'-number.
213 */
route_add_name(const route_head * hd)214 static void route_add_name(const route_head* hd)
215 {
216   int grp;
217   int i;
218   char name[MAXLINE];
219   route_head* route;
220 
221   route = (route_head*) hd;
222   grp = atoi(route->rte_name);
223   i = 0;
224   while (i<groups_cnt && groups[i].group!=grp) {
225     i++;
226   }
227   if (i==groups_cnt) { // not found
228     sprintf(name,"undef(%d)",grp); /* pseudo name*/
229     sprintf(name,"?%d",grp);
230   } else {
231     strcpy(name,groups[i].name);
232   }
233   route->rte_name = (char*) xrealloc(route->rte_name,(strlen(name)+1)*sizeof(char));
234   strcpy(route->rte_name,name);
235 }
236 
ovl_read(void)237 static void ovl_read(void)
238 {
239   char*    line;
240   int     isSection;
241   int     aktTyp,aktCol,aktSize,aktArt,aktGroup;
242   int     aktArea,aktWidth,aktHeight,aktTrans,aktTransByte,aktDir;
243   double  aktX,aktY;
244   char*   aktPath;
245   char*   aktText;
246   char*   pstr;
247   int     keyw,i;
248   double  rwert;
249   route_head* route_head = NULL;
250   waypoint*   wpt;
251   int      sym_cnt;
252   int lineno = 0;
253 
254   groups = NULL;
255   groups_cnt = 0;
256   aktTyp = aktCol = aktSize = aktArt = aktGroup = -1;
257   aktArea = aktWidth = aktHeight = aktTrans = aktTransByte = aktDir = -1;
258   aktX = aktY = 0.0;
259   aktText = NULL;
260   aktPath = NULL;
261   sym_cnt = 0;
262   isSection = SECTION_NONE;
263   while ((line = gbfgetstr(fpin))) {
264     if ((lineno == 0) && fpin->unicode) {
265       cet_convert_init(CET_CHARSET_UTF8, 1);
266     }
267     lineno++;
268     line = lrtrim(line);
269     if ((pstr = strstr(line,"[Symbol "))!= NULL) {
270       sym_cnt++;
271       isSection = SECTION_SYMBOL;
272     } else if ((pstr = strstr(line,"[Overlay]"))!= NULL) {
273       isSection = SECTION_OVERLAY;
274     } else if (isSection==SECTION_SYMBOL) {
275       pstr = strtok(line,"=");
276       if (pstr!=NULL) {
277         keyw = isKeyword(pstr,Keywords);
278         pstr = strtok(NULL,"\n");
279         if (pstr!=NULL) {
280           switch (keyw) {
281           case KEY_TYP     :
282             aktTyp = atoi(pstr);
283             break;
284           case KEY_GROUP   :
285             aktGroup = atoi(pstr);
286             ovl_add_group(aktGroup,"?"); /* 'Group' without relation to 'Text'-Symbol */
287             switch (aktTyp) {
288             case 3: // Linie
289               route_head = route_head_alloc();
290               route_head->rte_num = sym_cnt;
291               route_head->rte_name = xstrdup(pstr); /* use group-number for the moment */
292               route_add_head(route_head);
293               break;
294             }
295             break;
296           case KEY_COL     :
297             aktCol = atoi(pstr);
298             break;
299           case KEY_ZOOM    :
300             break;
301           case KEY_SIZE    :
302             aktSize = atoi(pstr);
303             break;
304           case KEY_ART     :
305             aktArt = atoi(pstr);
306             break;
307           case KEY_AREA     :
308             aktArea = atoi(pstr);
309             if (aktTyp==5 || aktTyp==5 || aktTyp==7) {
310               isSection = SECTION_PUNKTE;  // Rechteck, Kreis, Dreieck
311             }
312             break;
313           case KEY_PUNKTE  :
314             isSection = SECTION_PUNKTE; // Linie, Fl�che
315             break;
316 #ifdef WITH_BITMAP
317           case KEY_PATH     :
318             aktPath = xstrdup(pstr);
319             isSection = SECTION_PUNKTE; // Bitmap
320             break;
321           case KEY_TRANS     :
322             aktTrans = atoi(pstr);
323             break;
324           case KEY_TRANSBYTE     :
325             aktTransByte = atoi(pstr);
326             break;
327 #endif
328           case KEY_TEXT     :
329             aktText = xstrdup(pstr);
330             /* The last 'Text'-symbol wins as a information block for
331                waypoint/route description.
332                Infos from previous symbols get overwrited.
333             */
334             ovl_add_group(aktGroup,aktText);
335             break;
336           case KEY_WIDTH     :
337             aktWidth = atoi(pstr);
338             break;
339           case KEY_HEIGHT     :
340             aktHeight = atoi(pstr);
341             break;
342           case KEY_DIR     :
343             aktDir = atoi(pstr);
344             if (aktTyp==2) {
345               isSection = SECTION_PUNKTE;  // Text
346             }
347             break;
348           }
349         }
350       }
351     } else if (isSection==SECTION_PUNKTE) {
352       pstr = strtok(line,"=");
353       if (strstr(pstr,"XKoord")!=NULL || strstr(pstr,"YKoord")!=NULL) {
354         if ((pstr = strtok(NULL,"\n"))!=NULL) {
355           rwert = atof(pstr);
356           if (line[0]=='X') {
357             aktX = rwert;
358           } else if (line[0]=='Y') {
359             aktY = rwert;
360             switch (aktTyp) {
361 #ifdef WITH_BITMAP
362             case 1: // Bitmap
363               wpt = waypt_new();
364               wpt->latitude = aktY;
365               wpt->longitude = aktX;
366               wpt->altitude = 0.0;
367               wpt->shortname = strdup(aktPath);
368               waypt_add(wpt);
369               break;
370 #endif
371             case 2: // Text
372               isSection = SECTION_SYMBOL;
373               break;
374             case 3: // Linie
375               wpt = waypt_new();
376               wpt->latitude = aktY;
377               wpt->longitude = aktX;
378               wpt->altitude = 0.0;
379               route_add_wpt(route_head, wpt);
380               break;
381             case 4: // Fl�che
382               break;
383             case 5: // Rechteck
384               break;
385             case 6: // Kreis
386               break;
387             case 7: // Dreieck
388               break;
389             }
390           }
391         }
392       }
393     } else if (isSection==SECTION_OVERLAY) {
394       isSection = SECTION_NONE;
395     }
396   }
397   route_disp_all(route_add_name,NULL,NULL);
398   if (aktText!=NULL) {
399     xfree(aktText);
400   }
401   if (aktPath!=NULL) {
402     xfree(aktPath);
403   }
404   for (i=0; i<groups_cnt; i++) {
405     if (groups[i].name!=NULL) {
406       xfree(groups[i].name);
407     }
408   }
409   xfree(groups);
410 }
411 
ovl_rd_deinit(void)412 static void ovl_rd_deinit(void)
413 {
414   gbfclose(fpin);
415 }
416 
417 /*------------------------------------------*/
ovl_read_parameter(const char * fname)418 void ovl_read_parameter(const char* fname)
419 {
420   gbfile*    fpin;
421   arglist_t* p;
422   char*      str;
423   char*      pstr;
424 
425   fpin = gbfopen(fname, "r", MYNAME);
426   if (fpin!=NULL) {
427     while ((str = gbfgetstr(fpin))) {
428       str = lrtrim(str); // trim
429       if (str[0]!=';') {
430         p = ovl_args;
431         pstr = strtok(str,"=");
432         if (pstr!=NULL) {
433           while (p->argstring!=NULL) {
434             if (strcmp(pstr,p->argstring)==0) {
435               pstr = strtok(NULL,"\n");
436               if (p->argtype==ARGTYPE_BOOL) {
437                 *(p->argval) = atoi(pstr) ? xstrdup(pstr) : NULL;
438               } else {
439                 *(p->argval) = xstrdup(pstr);
440               }
441               break;
442             }
443             p++;
444           }
445         }
446       }
447     }
448     gbfclose(fpin);
449   }
450 }
451 
ovl_wr_init(const char * fname)452 static void ovl_wr_init(const char* fname)
453 {
454   fpout = gbfopen(fname, "w", MYNAME);
455   govl_sum_n = 0.0;
456   govl_sum_e = 0.0;
457   govl_sumcnt = 0.0;
458   govl_symbol_cnt = 0;
459 
460 
461   ovl_read_parameter(govl_file_s!=NULL ? govl_file_s : PARAMETER_FILE);
462 
463   if (govl_col_s!=NULL) {
464     govl_col = atoi(govl_col_s);
465   }
466   if (govl_size_s!=NULL) {
467     govl_size = atoi(govl_size_s);
468   }
469   if (govl_mapname==NULL) {
470     govl_mapname = xstrdup(MAPNAME);
471   }
472   if (govl_zoomfc_s!=NULL) {
473     govl_zoomfc = atoi(govl_zoomfc_s);
474   }
475   if (govl_dimmfc_s!=NULL) {
476     govl_dimmfc = atoi(govl_dimmfc_s);
477   }
478   if (govl_txtcol_s!=NULL) {
479     govl_txtcol = atoi(govl_txtcol_s);
480   }
481   if (govl_txtsize_s!=NULL) {
482     govl_txtsize = atoi(govl_txtsize_s);
483   }
484   if (govl_font_s!=NULL) {
485     govl_font = atoi(govl_font_s);
486   }
487   if (govl_txttrans_s!=NULL) {
488     govl_txttrans = 1;
489   }
490 }
491 
ovl_wr_deinit(void)492 static void ovl_wr_deinit(void)
493 {
494   gbfprintf(fpout,"[Overlay]\n");
495   gbfprintf(fpout,"Symbols=%d\n",govl_symbol_cnt);
496   gbfprintf(fpout,"[MapLage]\n");
497   gbfprintf(fpout,"MapName=%s\n",govl_mapname);
498   gbfprintf(fpout,"DimmFc=%d\n",govl_dimmfc);
499   gbfprintf(fpout,"ZoomFc=%d\n",govl_zoomfc);
500   if (govl_symbol_cnt) {
501     gbfprintf(fpout,"CenterLat=%.8lf\n",govl_sum_n/govl_sumcnt); // precision 8 = better than 1mm
502     gbfprintf(fpout,"CenterLong=%.8lf\n",govl_sum_e/govl_sumcnt);
503   } else {
504     gbfprintf(fpout,"CenterLong=10.52374295\n"); // Braunschweiger L�we, Mittelpunkt der Welt :-)
505     gbfprintf(fpout,"CenterLat=52.26474445\n");
506   }
507   gbfprintf(fpout,"RefOn=0\n");
508 
509   gbfclose(fpout);
510 }
511 
symbol_init(const route_head * hd)512 static void symbol_init(const route_head* hd)
513 {
514   gbfprintf(fpout,"[Symbol %d]\n",govl_symbol_cnt+1);
515   gbfprintf(fpout,"Typ=3\n");                            // Linie
516   gbfprintf(fpout,"Group=%d\n"   ,govl_group_cnt+1+1);   // group==1 : not a group
517   gbfprintf(fpout,"Col=%d\n"     ,govl_col);
518   gbfprintf(fpout,"Zoom=2\n");
519   gbfprintf(fpout,"Size=%d\n"    ,govl_size);
520   gbfprintf(fpout,"Art=1\n");
521   gbfprintf(fpout,"Punkte=%d\n"  ,hd->rte_waypt_ct);
522   govl_cnt = 0;
523   govl_symbol_cnt++;
524   govl_group_cnt++;
525 }
526 
symbol_text(double east,double north,char * text,int group)527 static void symbol_text(double east,double north,char* text,int group)
528 {
529   gbfprintf(fpout,"[Symbol %d]\n",govl_symbol_cnt+1);
530   gbfprintf(fpout,"Typ=2\n");                           // Text
531   gbfprintf(fpout,"Group=%d\n",group+1);  // group==1 : not a group
532   gbfprintf(fpout,"Col=%d\n",govl_txtcol);
533   gbfprintf(fpout,"Area=%d\n",govl_txttrans ? 1 : 2); // =2 opak =1 transparent
534   gbfprintf(fpout,"Zoom=%d\n",2);
535   gbfprintf(fpout,"Size=%d\n",govl_txtsize);
536   gbfprintf(fpout,"Font=%d\n",govl_font);
537   gbfprintf(fpout,"Dir=%d\n",100+((int) govl_dir));
538   gbfprintf(fpout,"XKoord=%.8lf\n",east);  // precision 8 = better than 1mm
539   gbfprintf(fpout,"YKoord=%.8lf\n",north);
540   gbfprintf(fpout,"Text=%s\n",text);
541   govl_symbol_cnt++;
542 }
543 
symbol_point(const waypoint * wpt)544 static void symbol_point(const waypoint* wpt)
545 {
546   double east,north;
547 
548   east  = wpt->longitude;
549   north = wpt->latitude;
550   gbfprintf(fpout,"XKoord%d=%.8lf\n",govl_cnt,east);    // precision 8 = better than 1mm
551   gbfprintf(fpout,"YKoord%d=%.8lf\n",govl_cnt,north);
552   govl_cnt++;
553   govl_sum_e += east;
554   govl_sum_n += north;
555   govl_sumcnt += 1.0;
556   /*
557     govl_last_east  = east;
558     govl_last_north = north;
559   */
560 }
561 
562 
symbol_deinit(const route_head * hd)563 static void symbol_deinit(const route_head* hd)
564 {
565   queue* elem, *tmp;
566   waypoint* waypointp;
567   int i;
568   double lat1,lon1,lat2,lon2;
569   double lats,lons,late,lone;
570   double dist,d,dd;
571 
572   lat1 = lon1 = lat2 = lon2 = 0.0;
573   lats = lons = late = lone = 0.0;
574   dist = 0.0;
575   i = 0;
576   QUEUE_FOR_EACH(&(hd->waypoint_list), elem, tmp) {
577     waypointp = (waypoint*) elem;
578     lat2 = RAD(waypointp->latitude);
579     lon2 = RAD(waypointp->longitude);
580     if (i) {
581       d   = gcdist(lat1, lon1, lat2, lon2);
582       dist += d;
583     } else {
584       lats = lat2; // start point
585       lons = lon2;
586     }
587     lat1 = lat2;
588     lon1 = lon2;
589     i++;
590   }
591   late = lat2;  // end point
592   lone = lon2;
593   dd = 0;
594   i = 0;
595   elem = QUEUE_FIRST(&(hd->waypoint_list));
596   while (elem!=&(hd->waypoint_list) && dd<dist/2.0) {
597     waypointp = (waypoint*) elem;
598     lat2 = RAD(waypointp->latitude);
599     lon2 = RAD(waypointp->longitude);
600     if (i) {
601       d   = gcdist(lat1, lon1, lat2, lon2);
602       dd += d;
603     }
604     lat1 = lat2;
605     lon1 = lon2;
606     elem = QUEUE_NEXT(elem);
607     i++;
608   }
609 
610   d = gcdist(lats,lons,late,lone);
611 //  d = acos( sin(lats)*sin(late)+cos(lats)*cos(late)*cos(lone-lons) );
612   dd = acos((sin(late) - sin(lats)*cos(d))/(cos(lats)*sin(d)));
613   if (lone<lons) {
614     dd = -dd;  // correction because the ambiguity of acos function
615   }
616   dd = DEG(dd);              // azimuth
617   dd = 360.0 - (dd + 270.0); // make it anticlockwise and start counting on x-axis
618   dd = dd <   0.0 ? dd + 360.0 : dd; // normalizing
619   dd = dd > 360.0 ? dd - 360.0 : dd; // normalizing
620 
621   /* name of route */
622   /* plot text at the last point of route */
623   govl_dir = dd;  // approximated text rotation, correct value must be the azimuth in UTM
624   symbol_text(DEG(lon1),DEG(lat1),hd->rte_name,govl_group_cnt);
625   govl_dir = 0.0; // restore
626 }
627 
overlay_waypt_pr(const waypoint * waypointp)628 static void overlay_waypt_pr(const waypoint* waypointp)
629 {
630   const char* oname;
631   char* odesc;
632 
633   /*
634    * Desparation time, try very hard to get a good shortname
635   */
636   odesc = waypointp->notes;
637   if (!odesc) {
638     odesc = waypointp->description;
639   }
640   if (!odesc) {
641     odesc = waypointp->shortname;
642   }
643   oname = global_opts.synthesize_shortnames ?
644           mkshort(mkshort_handle, odesc) :
645           waypointp->shortname;
646 
647   gbfprintf(fpout,"[Symbol %d]\n",govl_symbol_cnt+1);
648   gbfprintf(fpout,"Typ=1\n");
649   gbfprintf(fpout,"Group=1\n");
650   gbfprintf(fpout,"Width=100\n");
651   gbfprintf(fpout,"Height=100\n");
652   gbfprintf(fpout,"Dir=%d\n",100+((int) govl_dir));
653   gbfprintf(fpout,"Zoom=2\n");
654   gbfprintf(fpout,"Trans=2\n");
655   gbfprintf(fpout,"TransByte=5\n");
656   gbfprintf(fpout,"Path=%s\n","waypoint.bmp");
657   gbfprintf(fpout,"XKoord=%.8lf\n",waypointp->longitude);
658   gbfprintf(fpout,"YKoord=%.8lf\n",waypointp->latitude);
659   govl_symbol_cnt++;
660   govl_sum_e += waypointp->longitude;
661   govl_sum_n += waypointp->latitude;
662   govl_sumcnt += 1.0;
663 
664 }
665 
ovl_write(void)666 static void ovl_write(void)
667 {
668   waypt_disp_all(overlay_waypt_pr);
669   track_disp_all(symbol_init, symbol_deinit, symbol_point);
670   route_disp_all(symbol_init, symbol_deinit, symbol_point);
671   /*
672     switch(global_opts.objective)
673     {
674       case wptdata:
675         break;
676       case trkdata:
677         break;
678     }
679   */
680 }
681 
682 
683 ff_vecs_t overlay_vecs = {
684   ff_type_internal,
685   FF_CAP_RW_ALL,
686   ovl_rd_init,
687   ovl_wr_init,
688   ovl_rd_deinit,
689   ovl_wr_deinit,
690   ovl_read,
691   ovl_write,
692   NULL,
693   ovl_args,
694   CET_CHARSET_ASCII, 0	/* CET-REVIEW */
695 };
696