1 /*
2  * $LynxId: LYMap.c,v 1.50 2018/03/05 22:32:14 tom Exp $
3  *			Lynx Client-side Image MAP Support	       LYMap.c
4  *			==================================
5  *
6  *	Author: FM	Foteos Macrides (macrides@sci.wfbr.edu)
7  *
8  */
9 
10 #include <HTUtils.h>
11 #include <HTTP.h>
12 #include <HTAnchor.h>
13 #include <HTAccess.h>
14 #include <HTFormat.h>
15 #include <HTParse.h>
16 #include <HTAlert.h>
17 #include <LYUtils.h>
18 #include <LYMap.h>
19 #include <GridText.h>
20 #include <LYGlobalDefs.h>
21 #include <LYKeymap.h>
22 #include <LYCharUtils.h>
23 #include <LYCharSets.h>
24 #include <LYStrings.h>
25 
26 #ifdef DIRED_SUPPORT
27 #include <LYUpload.h>
28 #include <LYLocal.h>
29 #endif
30 
31 #include <LYexit.h>
32 #include <LYLeaks.h>
33 
34 #define NO_MAP_TITLE "[USEMAP]"
35 
36 typedef struct _LYMapElement {
37     char *address;
38     char *title;
39     BOOLEAN intern_flag;
40 } LYMapElement;
41 
42 typedef struct _LYImageMap {
43     char *address;
44     char *title;
45     HTList *elements;
46 } LYImageMap;
47 
48 static HTList *LynxMaps = NULL;
49 
50 BOOL LYMapsOnly = FALSE;
51 
52 /*
53  * Utility for freeing a list of MAPs.
54  */
ImageMapList_free(HTList * theList)55 void ImageMapList_free(HTList *theList)
56 {
57     LYImageMap *map;
58     LYMapElement *element;
59     HTList *cur = theList;
60     HTList *current;
61 
62     if (!cur)
63 	return;
64 
65     while (NULL != (map = (LYImageMap *) HTList_nextObject(cur))) {
66 	FREE(map->address);
67 	FREE(map->title);
68 	if (map->elements) {
69 	    current = map->elements;
70 	    while (NULL !=
71 		   (element = (LYMapElement *) HTList_nextObject(current))) {
72 		FREE(element->address);
73 		FREE(element->title);
74 		FREE(element);
75 	    }
76 	    HTList_delete(map->elements);
77 	    map->elements = NULL;
78 	}
79 	FREE(map);
80     }
81     HTList_delete(theList);
82     return;
83 }
84 
85 #ifdef LY_FIND_LEAKS
86 /*
87  * Utility for freeing the global list of MAPs.  - kw
88  */
LYLynxMaps_free(void)89 static void LYLynxMaps_free(void)
90 {
91     ImageMapList_free(LynxMaps);
92     LynxMaps = NULL;
93     return;
94 }
95 #endif /* LY_FIND_LEAKS */
96 
97 /*
98  * We keep two kinds of lists:
99  * - A global list (LynxMaps) shared by MAPs from all documents that
100  *   do not have POST data.
101  * - For each response to a POST which contains MAPs, a list specific
102  *   to this combination of URL and post_data.  It is kept in the
103  *   HTParentAnchor structure and is freed when the document is removed
104  *   from memory, in the course of normal removal of anchors.
105  *   MAPs from POST responses can only be accessed via internal links,
106  *   i.e., from within the same document (with the same post_data).
107  *   The notion of "same document" is extended, so that LYNXIMGMAP:
108  *   and List Page screens are logically part of the document on which
109  *   they are based. - kw
110  *
111  * If track_internal_links is false, only the global list will be used
112  * for all MAPs.
113  *
114  */
115 
116 /*
117  * Utility for creating an LYImageMap list, if it doesn't exist already, adding
118  * LYImageMap entry structures if needed, and removing any LYMapElements in a
119  * pre-existing LYImageMap entry so that it will have only those from AREA tags
120  * for the current analysis of MAP element content.  - FM
121  */
LYAddImageMap(char * address,char * title,HTParentAnchor * node_anchor)122 BOOL LYAddImageMap(char *address,
123 		   char *title,
124 		   HTParentAnchor *node_anchor)
125 {
126     LYImageMap *tmp = NULL;
127     LYImageMap *old = NULL;
128     HTList *cur = NULL;
129     HTList *theList = NULL;
130     HTList *curele = NULL;
131     LYMapElement *ele = NULL;
132 
133     if (isEmpty(address))
134 	return FALSE;
135     if (!(node_anchor && node_anchor->address))
136 	return FALSE;
137 
138     /*
139      * Set theList to either the global LynxMaps list or, if we are associated
140      * with post data, the specific list.  The list is created if it doesn't
141      * already exist.  - kw
142      */
143     if (track_internal_links && node_anchor->post_data) {
144 	/*
145 	 * We are handling a MAP element found while parsing node_anchor's
146 	 * stream of data, and node_anchor has post_data associated and should
147 	 * therefore represent a POST response, so use the specific list.  - kw
148 	 */
149 	theList = node_anchor->imaps;
150 	if (!theList) {
151 	    theList = node_anchor->imaps = HTList_new();
152 	}
153     } else {
154 	if (!LynxMaps) {
155 	    LynxMaps = HTList_new();
156 #ifdef LY_FIND_LEAKS
157 	    atexit(LYLynxMaps_free);
158 #endif
159 	}
160 	theList = LynxMaps;
161     }
162 
163     if (theList) {
164 	cur = theList;
165 	while (NULL != (old = (LYImageMap *) HTList_nextObject(cur))) {
166 	    if (old->address == 0)	/* shouldn't happen */
167 		continue;
168 	    if (!strcmp(old->address, address)) {
169 		FREE(old->address);
170 		FREE(old->title);
171 		if (old->elements) {
172 		    curele = old->elements;
173 		    while (NULL !=
174 			   (ele = (LYMapElement *) HTList_nextObject(curele))) {
175 			FREE(ele->address);
176 			FREE(ele->title);
177 			FREE(ele);
178 		    }
179 		    HTList_delete(old->elements);
180 		    old->elements = NULL;
181 		}
182 		break;
183 	    }
184 	}
185     }
186 
187     tmp = (old != NULL) ?
188 	old : typecalloc(LYImageMap);
189     if (tmp == NULL) {
190 	outofmem(__FILE__, "LYAddImageMap");
191 	return FALSE;
192     }
193     StrAllocCopy(tmp->address, address);
194     if (non_empty(title))
195 	StrAllocCopy(tmp->title, title);
196     if (tmp != old)
197 	HTList_addObject(theList, tmp);
198     return TRUE;
199 }
200 
201 /*
202  * Utility for adding LYMapElement's to LYImageMap's
203  * in the appropriate list. - FM
204  */
LYAddMapElement(char * map,char * address,char * title,HTParentAnchor * node_anchor,int intern_flag GCC_UNUSED)205 BOOL LYAddMapElement(char *map,
206 		     char *address,
207 		     char *title,
208 		     HTParentAnchor *node_anchor,
209 		     int intern_flag GCC_UNUSED)
210 {
211     LYMapElement *tmp = NULL;
212     LYImageMap *theMap = NULL;
213     HTList *theList = NULL;
214     HTList *cur = NULL;
215 
216     if (isEmpty(map) || isEmpty(address))
217 	return FALSE;
218     if (!(node_anchor && node_anchor->address))
219 	return FALSE;
220 
221     /*
222      * Set theList to either the global LynxMaps list or, if we are associated
223      * with post data, the specific list.  The list should already exist, since
224      * this function is only called if the AREA tag we are handling was within
225      * a MAP element in node_anchor's stream of data, so that LYAddImageMap has
226      * been called.  - kw
227      */
228     if (track_internal_links && node_anchor->post_data) {
229 	/*
230 	 * We are handling an AREA tag found while parsing node_anchor's stream
231 	 * of data, and node_anchor has post_data associated and should
232 	 * therefore represent a POST response, so use the specific list.  - kw
233 	 */
234 	theList = node_anchor->imaps;
235 	if (!theList) {
236 	    return FALSE;
237 	}
238     } else {
239 	if (!LynxMaps)
240 	    LYAddImageMap(map, NULL, node_anchor);
241 	theList = LynxMaps;
242     }
243 
244     cur = theList;
245     while (NULL != (theMap = (LYImageMap *) HTList_nextObject(cur))) {
246 	if (!strcmp(theMap->address, map)) {
247 	    break;
248 	}
249     }
250     if (!theMap)
251 	return FALSE;
252     if (!theMap->elements)
253 	theMap->elements = HTList_new();
254     cur = theMap->elements;
255     while (NULL != (tmp = (LYMapElement *) HTList_nextObject(cur))) {
256 	if (!strcmp(tmp->address, address)) {
257 	    FREE(tmp->address);
258 	    FREE(tmp->title);
259 	    HTList_removeObject(theMap->elements, tmp);
260 	    FREE(tmp);
261 	    break;
262 	}
263     }
264 
265     tmp = typecalloc(LYMapElement);
266     if (tmp == NULL) {
267 	perror("Out of memory in LYAddMapElement");
268 	return FALSE;
269     }
270     StrAllocCopy(tmp->address, address);
271     if (non_empty(title))
272 	StrAllocCopy(tmp->title, title);
273     else
274 	StrAllocCopy(tmp->title, address);
275     if (track_internal_links)
276 	tmp->intern_flag = (BOOLEAN) intern_flag;
277     HTList_appendObject(theMap->elements, tmp);
278 
279     CTRACE((tfp,
280 	    "LYAddMapElement\n\tmap     %s\n\taddress %s\n\ttitle   %s)\n",
281 	    NonNull(map), NonNull(address), NonNull(title)));
282 
283     return TRUE;
284 }
285 
286 /*
287  * Utility for checking whether an LYImageMap entry with a given address
288  * already exists in the LynxMaps structure.  - FM
289  */
LYHaveImageMap(char * address)290 BOOL LYHaveImageMap(char *address)
291 {
292     LYImageMap *Map;
293     HTList *cur = LynxMaps;
294 
295     if (!(cur && non_empty(address)))
296 	return FALSE;
297 
298     while (NULL != (Map = (LYImageMap *) HTList_nextObject(cur))) {
299 	if (!strcmp(Map->address, address)) {
300 	    return TRUE;
301 	}
302     }
303 
304     return FALSE;
305 }
306 
307 /*
308  * Fills in a DocAddress structure for getting the HTParentAnchor of the
309  * underlying resource.  ALso returns a pointer to that anchor in
310  * *punderlying if we are dealing with POST data.  - kw
311  *
312  * address  is the address of the underlying resource, i.e., the one
313  *	    containing the MAP element, the MAP's name appended as
314  *	    fragment is ignored.
315  * anAnchor is the LYNXIMGMAP: anchor; if it is associated with POST
316  *	    data, we want the specific list, otherwise the global list.
317  */
fill_DocAddress(DocAddress * wwwdoc,const char * address,HTParentAnchor * anAnchor,HTParentAnchor ** punderlying)318 static void fill_DocAddress(DocAddress *wwwdoc,
319 			    const char *address,
320 			    HTParentAnchor *anAnchor,
321 			    HTParentAnchor **punderlying)
322 {
323     char *doc_address = NULL;
324     HTParentAnchor *underlying;
325 
326     StrAllocCopy(doc_address, address);
327     if (anAnchor && anAnchor->post_data) {
328 	wwwdoc->address = doc_address;
329 	wwwdoc->post_data = anAnchor->post_data;
330 	wwwdoc->post_content_type = anAnchor->post_content_type;
331 	wwwdoc->bookmark = NULL;
332 	wwwdoc->isHEAD = FALSE;
333 	wwwdoc->safe = FALSE;
334 	underlying = HTAnchor_findAddress(wwwdoc);
335 	if (underlying->safe)
336 	    wwwdoc->safe = TRUE;
337 	if (punderlying)
338 	    *punderlying = underlying;
339     } else {
340 	wwwdoc->address = doc_address;
341 	wwwdoc->post_data = NULL;
342 	wwwdoc->post_content_type = NULL;
343 	wwwdoc->bookmark = NULL;
344 	wwwdoc->isHEAD = FALSE;
345 	wwwdoc->safe = FALSE;
346 	if (punderlying)
347 	    *punderlying = NULL;
348     }
349 }
350 
351 /*
352  * Get the appropriate list for creating a LYNXIMGMAP:  pseudo- document:
353  * either the global list (LynxMaps), or the specific list if a List Page for a
354  * POST response is requested.  Also fill in the DocAddress structure etc.  by
355  * calling fill_DocAddress().
356  *
357  * address is the address of the underlying resource, i.e., the one
358  *	   containing the MAP element, the MAP's name appended as
359  *	   fragment is ignored.
360  * anchor  is the LYNXIMGMAP: anchor for which LYLoadIMGmap() is
361  *	   requested; if it is associated with POST data, we want the
362  *	   specific list for this combination of address+post_data.
363  *
364  * if track_internal_links is false, the Anchor passed to
365  * LYLoadIMGmap() will never have post_data, so that the global list
366  * will be used. - kw
367  */
get_the_list(DocAddress * wwwdoc,const char * address,HTParentAnchor * anchor,HTParentAnchor ** punderlying)368 static HTList *get_the_list(DocAddress *wwwdoc,
369 			    const char *address,
370 			    HTParentAnchor *anchor,
371 			    HTParentAnchor **punderlying)
372 {
373     HTList *result;
374 
375     if (anchor->post_data) {
376 	fill_DocAddress(wwwdoc, address, anchor, punderlying);
377 	if (non_empty(punderlying)) {
378 	    result = (*punderlying)->imaps;
379 	} else {
380 	    result = anchor->imaps;
381 	}
382     } else {
383 	fill_DocAddress(wwwdoc, address, NULL, punderlying);
384 	result = LynxMaps;
385     }
386     return result;
387 }
388 
389 /*	LYLoadIMGmap - F.Macrides (macrides@sci.wfeb.edu)
390  *	------------
391  *	Create a text/html stream with a list of links
392  *	for HyperText References in AREAs of a MAP.
393  */
394 
LYLoadIMGmap(const char * arg,HTParentAnchor * anAnchor,HTFormat format_out,HTStream * sink)395 static int LYLoadIMGmap(const char *arg,
396 			HTParentAnchor *anAnchor,
397 			HTFormat format_out,
398 			HTStream *sink)
399 {
400     HTFormat format_in = WWW_HTML;
401     HTStream *target = NULL;
402     char *buf = NULL;
403     LYMapElement *tmp = NULL;
404     LYImageMap *theMap = NULL;
405     char *MapTitle = NULL;
406     char *MapAddress = NULL;
407     HTList *theList;
408     HTList *cur = NULL;
409     const char *address = NULL;
410     char *cp = NULL;
411     DocAddress WWWDoc;
412     HTParentAnchor *underlying;
413     BOOL old_cache_setting = LYforce_no_cache;
414     BOOL old_reloading = reloading;
415     HTFormat old_format_out = HTOutputFormat;
416 
417     if (isLYNXIMGMAP(arg)) {
418 	address = (arg + LEN_LYNXIMGMAP);
419     }
420     if (!(address && StrChr(address, ':'))) {
421 	HTAlert(MISDIRECTED_MAP_REQUEST);
422 	return (HT_NOT_LOADED);
423     }
424 
425     theList = get_the_list(&WWWDoc, address, anAnchor, &underlying);
426     if (WWWDoc.safe)
427 	anAnchor->safe = TRUE;
428 
429     if (!theList) {
430 	if (anAnchor->post_data && !WWWDoc.safe &&
431 	    ((underlying && underlying->document && !LYforce_no_cache) ||
432 	     HTConfirm(CONFIRM_POST_RESUBMISSION) != TRUE)) {
433 	    HTAlert(FAILED_MAP_POST_REQUEST);
434 	    return (HT_NOT_LOADED);
435 	}
436 	LYforce_no_cache = TRUE;
437 	reloading = TRUE;
438 	HTOutputFormat = WWW_PRESENT;
439 	LYMapsOnly = TRUE;
440 	if (!HTLoadAbsolute(&WWWDoc)) {
441 	    LYforce_no_cache = old_cache_setting;
442 	    reloading = old_reloading;
443 	    HTOutputFormat = old_format_out;
444 	    LYMapsOnly = FALSE;
445 	    HTAlert(MAP_NOT_ACCESSIBLE);
446 	    return (HT_NOT_LOADED);
447 	}
448 	LYforce_no_cache = old_cache_setting;
449 	reloading = old_reloading;
450 	HTOutputFormat = old_format_out;
451 	LYMapsOnly = FALSE;
452 	theList = get_the_list(&WWWDoc, address, anAnchor, &underlying);
453     }
454 
455     if (!theList) {
456 	HTAlert(MAPS_NOT_AVAILABLE);
457 	return (HT_NOT_LOADED);
458     }
459 
460     cur = theList;
461     while (NULL != (theMap = (LYImageMap *) HTList_nextObject(cur))) {
462 	if (!strcmp(theMap->address, address)) {
463 	    break;
464 	}
465     }
466     if (theMap && HTList_count(theMap->elements) == 0) {
467 	/*
468 	 * We found a MAP without any usable AREA.  Fake a redirection to the
469 	 * address with fragment.  We do this even for post data (internal link
470 	 * within a document with post data) if it will not result in an
471 	 * unwanted network request.  - kw
472 	 */
473 	if (!anAnchor->post_data) {
474 	    StrAllocCopy(redirecting_url, address);
475 	    return (HT_REDIRECTING);
476 	} else if (WWWDoc.safe ||
477 		   (underlying->document && !anAnchor->document &&
478 		    (LYinternal_flag || LYoverride_no_cache))) {
479 	    StrAllocCopy(redirecting_url, address);
480 	    redirect_post_content = TRUE;
481 	    return (HT_REDIRECTING);
482 	}
483     }
484     if (!(theMap && theMap->elements)) {
485 	if (anAnchor->post_data && !WWWDoc.safe &&
486 	    ((underlying && underlying->document && !LYforce_no_cache) ||
487 	     HTConfirm(CONFIRM_POST_RESUBMISSION) != TRUE)) {
488 	    HTAlert(FAILED_MAP_POST_REQUEST);
489 	    return (HT_NOT_LOADED);
490 	}
491 	LYforce_no_cache = TRUE;
492 	reloading = TRUE;
493 	HTOutputFormat = WWW_PRESENT;
494 	LYMapsOnly = TRUE;
495 	if (!HTLoadAbsolute(&WWWDoc)) {
496 	    LYforce_no_cache = old_cache_setting;
497 	    reloading = old_reloading;
498 	    HTOutputFormat = old_format_out;
499 	    LYMapsOnly = FALSE;
500 	    HTAlert(MAP_NOT_ACCESSIBLE);
501 	    return (HT_NOT_LOADED);
502 	}
503 	LYforce_no_cache = old_cache_setting;
504 	reloading = old_reloading;
505 	HTOutputFormat = old_format_out;
506 	LYMapsOnly = FALSE;
507 	cur = get_the_list(&WWWDoc, address, anAnchor, &underlying);
508 	while (NULL != (theMap = (LYImageMap *) HTList_nextObject(cur))) {
509 	    if (!strcmp(theMap->address, address)) {
510 		break;
511 	    }
512 	}
513 	if (!(theMap && theMap->elements)) {
514 	    HTAlert(MAP_NOT_AVAILABLE);
515 	    return (HT_NOT_LOADED);
516 	}
517     }
518     if (track_internal_links)
519 	anAnchor->no_cache = TRUE;
520 
521     target = HTStreamStack(format_in,
522 			   format_out,
523 			   sink, anAnchor);
524 
525     if (target == NULL) {
526 	HTSprintf0(&buf, CANNOT_CONVERT_I_TO_O,
527 		   HTAtom_name(format_in), HTAtom_name(format_out));
528 	HTAlert(buf);
529 	FREE(buf);
530 	return (HT_NOT_LOADED);
531     }
532 
533     if (non_empty(theMap->title)) {
534 	StrAllocCopy(MapTitle, theMap->title);
535     } else if (non_empty(anAnchor->title)) {
536 	StrAllocCopy(MapTitle, anAnchor->title);
537     } else if (non_empty(LYRequestTitle) &&
538 	       strcasecomp(LYRequestTitle, NO_MAP_TITLE)) {
539 	StrAllocCopy(MapTitle, LYRequestTitle);
540     } else if ((cp = StrChr(address, '#')) != NULL) {
541 	StrAllocCopy(MapTitle, (cp + 1));
542     }
543     if (isEmpty(MapTitle)) {
544 	StrAllocCopy(MapTitle, NO_MAP_TITLE);
545     } else {
546 	LYEntify(&MapTitle, TRUE);
547     }
548 
549 #define PUTS(buf)    (*target->isa->put_block)(target, buf, (int) strlen(buf))
550 
551     HTSprintf0(&buf, "<html>\n<head>\n");
552     PUTS(buf);
553     HTSprintf0(&buf, "<META %s content=\"" STR_HTML ";charset=%s\">\n",
554 	       "http-equiv=\"content-type\"",
555 	       LYCharSet_UC[current_char_set].MIMEname);
556     PUTS(buf);
557     /*
558      * This page is a list of titles and anchors for them.  Since titles
559      * already passed SGML/HTML stage they are converted to current_char_set.
560      * That is why we insist on META charset for this page.
561      */
562     HTSprintf0(&buf, "<title>%s</title>\n", MapTitle);
563     PUTS(buf);
564     HTSprintf0(&buf, "</head>\n<body>\n");
565     PUTS(buf);
566 
567     HTSprintf0(&buf, "<h1><em>%s</em></h1>\n", MapTitle);
568     PUTS(buf);
569 
570     StrAllocCopy(MapAddress, address);
571     LYEntify(&MapAddress, FALSE);
572     HTSprintf0(&buf, "<h2><em>MAP:</em>&nbsp;%s</h2>\n", MapAddress);
573     PUTS(buf);
574 
575     HTSprintf0(&buf, "<%s compact>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ?
576 					"ol" : "ul"));
577     PUTS(buf);
578     cur = theMap->elements;
579     while (NULL != (tmp = (LYMapElement *) HTList_nextObject(cur))) {
580 	StrAllocCopy(MapAddress, tmp->address);
581 	LYEntify(&MapAddress, FALSE);
582 	PUTS("<li><a href=\"");
583 	PUTS(MapAddress);
584 	PUTS("\"");
585 	if (track_internal_links && tmp->intern_flag) {
586 	    PUTS(" TYPE=\"internal link\"");
587 	}
588 	PUTS("\n>");
589 	LYformTitle(&MapTitle, tmp->title);
590 	LYEntify(&MapTitle, TRUE);
591 	PUTS(MapTitle);
592 	PUTS("</a>\n");
593     }
594     HTSprintf0(&buf, "</%s>\n</body>\n</html>\n",
595 	       ((keypad_mode == NUMBERS_AS_ARROWS)
596 		? "ol"
597 		: "ul"));
598     PUTS(buf);
599 
600     (*target->isa->_free) (target);
601     FREE(MapAddress);
602     FREE(MapTitle);
603     FREE(buf);
604     return (HT_LOADED);
605 }
606 
LYPrintImgMaps(FILE * fp)607 void LYPrintImgMaps(FILE *fp)
608 {
609     const char *only = HTLoadedDocumentURL();
610     size_t only_len = strlen(only);
611     HTList *outer = LynxMaps;
612     HTList *inner;
613     LYImageMap *map;
614     LYMapElement *elt;
615     int count;
616 
617     if (HTList_count(outer) > 0) {
618 	while (NULL != (map = (LYImageMap *) HTList_nextObject(outer))) {
619 	    if (only_len != 0) {
620 		if (StrNCmp(only, map->address, only_len)
621 		    || (map->address[only_len] != '\0'
622 			&& map->address[only_len] != '#')) {
623 		    continue;
624 		}
625 	    }
626 	    fprintf(fp, "\n%s\n", isEmpty(map->title) ? NO_MAP_TITLE : map->title);
627 	    fprintf(fp, "%s\n", map->address);
628 	    inner = map->elements;
629 	    count = 0;
630 	    while (NULL != (elt = (LYMapElement *) HTList_nextObject(inner))) {
631 		fprintf(fp, "%4d. %s", ++count, elt->address);
632 		if (track_internal_links && elt->intern_flag)
633 		    fprintf(fp, " TYPE=\"internal link\"");
634 		fprintf(fp, "\n");
635 	    }
636 	}
637     }
638 }
639 
640 #ifdef GLOBALDEF_IS_MACRO
641 #define _LYIMGMAP_C_GLOBALDEF_1_INIT { "LYNXIMGMAP", LYLoadIMGmap, 0}
642 GLOBALDEF(HTProtocol, LYLynxIMGmap, _LYIMGMAP_C_GLOBALDEF_1_INIT);
643 #else
644 GLOBALDEF HTProtocol LYLynxIMGmap =
645 {"LYNXIMGMAP", LYLoadIMGmap, 0};
646 #endif /* GLOBALDEF_IS_MACRO */
647