/* * MapInfo.c -- MapInfo interface. * * Authors : Patrick Lecoanet. * Creation date : * * $Id$ */ /* * Copyright (c) 1993 - 1999 CENA, Patrick Lecoanet -- * * This code is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this code; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include "MapInfo.h" #include "tkZinc.h" #include #include #include static const char rcsid[] = "$Id$"; static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $"; /* *----------------------------------------------------------------------- * * New types * *----------------------------------------------------------------------- */ typedef struct { ZnPtr tag; MapInfoLineStyle style; int width; MapInfoPointStruct center; unsigned int radius; int start_angle; int extend; } MapInfoArcStruct, *MapInfoArc; typedef struct { ZnPtr tag; MapInfoLineStyle style; int width; MapInfoPointStruct from; MapInfoPointStruct to; unsigned int num_marks; MapInfoPoint marks; } MapInfoLineStruct, *MapInfoLine; typedef struct { ZnPtr tag; MapInfoPointStruct at; char symbol[2]; } MapInfoSymbolStruct, *MapInfoSymbol; typedef struct { ZnPtr tag; MapInfoTextStyle text_style; MapInfoLineStyle line_style; MapInfoPointStruct at; char *text; } MapInfoTextStruct, *MapInfoText; typedef struct { char *name; ZnList lines; ZnList symbols; ZnList texts; ZnList arcs; } MapInfoStruct, *MapInfo; #define MARKERS_SPACING 80.0 /* 10 nautic miles in 1/8 of a mile */ #define BASE_ALLOC_SIZE 8 /* *----------------------------------------------------------------------- * * Macros. * *----------------------------------------------------------------------- */ #define NOT_MARKED_STYLE(style) \ ((style) == MapInfoLineMarked ? MapInfoLineSimple : (style)); /* *----------------------------------------------------------------------- * * ComputeLineMarks -- * Add marks to a line in the marks substructure. * *----------------------------------------------------------------------- */ static void ComputeLineMarks(MapInfoLine marked_line) { double length; unsigned int j; int x_from = marked_line->from.x; int y_from = marked_line->from.y; int x_to = marked_line->to.x; int y_to = marked_line->to.y; int delta_x = x_from - x_to; int delta_y = y_from - y_to; int step_x, step_y; length = sqrt((double)((delta_x) * (delta_x) + (delta_y) * (delta_y))); step_x = (int) ((x_to - x_from) * MARKERS_SPACING / length); step_y = (int) ((y_to - y_from) * MARKERS_SPACING / length); marked_line->num_marks = (int) length / MARKERS_SPACING; /* We don't want markers at ends, so we get rid of the last one if it is at an end */ if (fmod(length, MARKERS_SPACING) == 0.0) { (marked_line->num_marks)--; } if (marked_line->num_marks) { marked_line->marks = (MapInfoPoint) ZnMalloc(marked_line->num_marks * sizeof(MapInfoPointStruct)); } for (j = 0; j < marked_line->num_marks; j++) { marked_line->marks[j].x = x_from + ((j + 1) * step_x); marked_line->marks[j].y = y_from + ((j + 1) * step_y); } } static MapInfoId MapInfoCreate(char *name) { MapInfo new_map; new_map = (MapInfo) ZnMalloc(sizeof(MapInfoStruct)); memset((char *) new_map, 0, sizeof(MapInfoStruct)); if (!name) { name = ""; } new_map->name = (char *) ZnMalloc(strlen(name)+1); strcpy(new_map->name, name); return((MapInfoId) new_map); } static char * MapInfoName(MapInfoId map_info) { if (!map_info) { return ""; } return ((MapInfo) map_info)->name; } static MapInfoId MapInfoDuplicate(MapInfoId map_info) { MapInfo cur_map = (MapInfo) map_info; MapInfo new_map; int i, num_lines, num_texts; MapInfoText new_texts, cur_texts; MapInfoLine new_lines, cur_lines; if (!cur_map) { return ((MapInfoId) NULL); } new_map = (MapInfo) MapInfoCreate(cur_map->name); if (cur_map->lines) { new_map->lines = ZnListDuplicate(cur_map->lines); cur_lines = (MapInfoLine) ZnListArray(cur_map->lines); new_lines = (MapInfoLine) ZnListArray(new_map->lines); num_lines = ZnListSize(cur_map->lines); for (i = 0; i < num_lines; i++) { if (new_lines[i].style == MapInfoLineMarked) { new_lines[i].marks = (MapInfoPoint) ZnMalloc(new_lines[i].num_marks * sizeof(MapInfoPointStruct)); memcpy((char *) new_lines[i].marks, (char *) cur_lines[i].marks, new_lines[i].num_marks * sizeof(MapInfoPointStruct)); } } } if (cur_map->symbols) { new_map->symbols = ZnListDuplicate(cur_map->symbols); } if (cur_map->texts) { new_map->texts = ZnListDuplicate(cur_map->texts); cur_texts = (MapInfoText) ZnListArray(cur_map->texts); new_texts = (MapInfoText) ZnListArray(new_map->texts); num_texts = ZnListSize(cur_map->texts); for (i = 0; i < num_texts; i++) { new_texts[i].text = (char *) ZnMalloc(strlen(cur_texts[i].text) + 1); strcpy(new_texts[i].text, cur_texts[i].text); } } if (cur_map->arcs) { new_map->arcs = ZnListDuplicate(cur_map->arcs); } return((MapInfoId) new_map); } static void MapInfoDelete(MapInfoId map_info) { MapInfo cur_map = (MapInfo) map_info; int i, num_texts, num_lines; MapInfoText cur_texts; MapInfoLine cur_lines; if (cur_map) { if (cur_map->texts) { num_texts = ZnListSize(cur_map->texts); cur_texts = (MapInfoText) ZnListArray(cur_map->texts); for (i = 0; i < num_texts; i++) { ZnFree((char *) cur_texts[i].text); } ZnListFree(cur_map->texts); } if (cur_map->lines) { num_lines = ZnListSize(cur_map->lines); cur_lines = (MapInfoLine) ZnListArray(cur_map->lines); for (i = 0; i < num_lines; i++) { if (cur_lines[i].style == MapInfoLineMarked) { ZnFree((char *) cur_lines[i].marks); } } ZnListFree(cur_map->lines); } if (cur_map->symbols) { ZnListFree(cur_map->symbols); } if (cur_map->arcs) { ZnListFree(cur_map->arcs); } ZnFree(cur_map->name); ZnFree(cur_map); } } static void MapInfoEmpty(MapInfoId map_info) { MapInfo cur_map = (MapInfo) map_info; if (cur_map) { if (cur_map->texts) { ZnListEmpty(cur_map->texts); } if (cur_map->lines) { ZnListEmpty(cur_map->lines); } if (cur_map->symbols) { ZnListEmpty(cur_map->symbols); } if (cur_map->arcs) { ZnListEmpty(cur_map->arcs); } } } static void MapInfoAddLine(MapInfoId map_info, unsigned int index, ZnPtr tag, MapInfoLineStyle line_style, int line_width, int x_from, int y_from, int x_to, int y_to) { MapInfo cur_map = (MapInfo) map_info; MapInfoLineStruct line_struct; if (cur_map) { if (!cur_map->lines) { cur_map->lines = ZnListNew(16, sizeof(MapInfoLineStruct)); } line_struct.style = line_style; if (line_width == 1) { line_struct.width = 0; } else { line_struct.width = line_width; } line_struct.tag = tag; line_struct.from.x = x_from; line_struct.from.y = y_from; line_struct.to.x = x_to; line_struct.to.y = y_to; if (line_style == MapInfoLineMarked) { ComputeLineMarks(&line_struct); } ZnListAdd(cur_map->lines, &line_struct, index); } } static void MapInfoReplaceLine(MapInfoId map_info, unsigned int index, ZnPtr tag, MapInfoLineStyle line_style, int line_width, int x_from, int y_from, int x_to, int y_to) { MapInfo cur_map = (MapInfo) map_info; MapInfoLine line_ptr; if (cur_map && cur_map->lines) { line_ptr = (MapInfoLine) ZnListAt(cur_map->lines, index); if (line_ptr) { if (line_ptr->style == MapInfoLineMarked) { ZnFree((char *) line_ptr->marks); } line_ptr->style = line_style; if (line_width == 1) { line_ptr->width = 0; } else { line_ptr->width = line_width; } line_ptr->tag = tag; line_ptr->from.x = x_from; line_ptr->from.y = y_from; line_ptr->to.x = x_to; line_ptr->to.y = y_to; if (line_ptr->style == MapInfoLineMarked) { ComputeLineMarks(line_ptr); } } } } static void MapInfoRemoveLine(MapInfoId map_info, unsigned int index) { MapInfo cur_map = (MapInfo) map_info; MapInfoLine line_ptr; if (cur_map && cur_map->lines) { line_ptr = (MapInfoLine) ZnListAt(cur_map->lines, index); if (line_ptr) { if (line_ptr->style == MapInfoLineMarked) { ZnFree((char *) line_ptr->marks); } ZnListDelete(cur_map->lines, index); } } } void MapInfoGetLine(MapInfoId map_info, unsigned int index, ZnPtr *tag, MapInfoLineStyle *line_style, int *line_width, int *x_from, int *y_from, int *x_to, int *y_to) { MapInfo cur_map = (MapInfo) map_info; MapInfoLine line_ptr; if (cur_map && cur_map->lines) { line_ptr = (MapInfoLine) ZnListAt(cur_map->lines, index); if (line_ptr) { if (tag) { *tag = line_ptr->tag; } if (line_style) { *line_style = line_ptr->style; } if (line_width) { if (line_ptr->width == 1) { *line_width = 0; } else { *line_width = line_ptr->width; } } if (x_from) { *x_from = line_ptr->from.x; } if (y_from) { *y_from = line_ptr->from.y; } if (x_to) { *x_to = line_ptr->to.x; } if (y_to) { *y_to = line_ptr->to.y; } } } } void MapInfoGetMarks(MapInfoId map_info, unsigned int index, MapInfoPoint *marks, unsigned int *num_marks) { MapInfo cur_map = (MapInfo) map_info; MapInfoLine line_ptr; if (cur_map && cur_map->lines) { line_ptr = (MapInfoLine) ZnListAt(cur_map->lines, index); if (line_ptr && line_ptr->style == MapInfoLineMarked) { if (marks) { *marks = line_ptr->marks; } if (num_marks) { *num_marks = line_ptr->num_marks; } } } } unsigned int MapInfoNumLines(MapInfoId map_info) { MapInfo cur_map = (MapInfo) map_info; if (cur_map && cur_map->lines) { return ZnListSize(cur_map->lines); } else { return 0; } } static void MapInfoAddSymbol(MapInfoId map_info, unsigned int index, ZnPtr tag, int x, int y, char symbol) { MapInfo cur_map = (MapInfo) map_info; MapInfoSymbolStruct symbol_struct; if (cur_map) { if (!cur_map->symbols) { cur_map->symbols = ZnListNew(16, sizeof(MapInfoSymbolStruct)); } symbol_struct.tag = tag; symbol_struct.at.x = x; symbol_struct.at.y = y; symbol_struct.symbol[0] = symbol; symbol_struct.symbol[1] = '\0'; ZnListAdd(cur_map->symbols, &symbol_struct, index); } } static void MapInfoReplaceSymbol(MapInfoId map_info, unsigned int index, ZnPtr tag, int x, int y, char symbol) { MapInfo cur_map = (MapInfo) map_info; MapInfoSymbolStruct symbol_struct; if (cur_map && cur_map->symbols) { symbol_struct.tag = tag; symbol_struct.at.x = x; symbol_struct.at.y = y; symbol_struct.symbol[0] = symbol; symbol_struct.symbol[1] = '\0'; ZnListAtPut(cur_map->symbols, &symbol_struct, index); } } static void MapInfoRemoveSymbol(MapInfoId map_info, unsigned int index) { MapInfo cur_map = (MapInfo) map_info; if (cur_map && cur_map->symbols) { ZnListDelete(cur_map->symbols, index); } } void MapInfoGetSymbol(MapInfoId map_info, unsigned int index, ZnPtr *tag, int *x, int *y, char *symbol) { MapInfo cur_map = (MapInfo) map_info; MapInfoSymbol symbol_ptr; if (cur_map && cur_map->symbols) { symbol_ptr = (MapInfoSymbol) ZnListAt(cur_map->symbols, index); if (symbol_ptr) { if (tag) { *tag = symbol_ptr->tag; } if (x) { *x = symbol_ptr->at.x; } if (y) { *y = symbol_ptr->at.y; } if (symbol) { *symbol = symbol_ptr->symbol[0]; } } } } unsigned int MapInfoNumSymbols(MapInfoId map_info) { MapInfo cur_map = (MapInfo) map_info; if (cur_map && cur_map->symbols) { return ZnListSize(cur_map->symbols); } else { return 0; } } static void MapInfoAddText(MapInfoId map_info, unsigned int index, ZnPtr tag, MapInfoTextStyle text_style, MapInfoLineStyle line_style, int x, int y, char *text) { MapInfo cur_map = (MapInfo) map_info; MapInfoTextStruct text_struct; if (cur_map) { if (!cur_map->texts) { cur_map->texts = ZnListNew(16, sizeof(MapInfoTextStruct)); } text_struct.tag = tag; text_struct.text_style = text_style; text_struct.line_style = NOT_MARKED_STYLE(line_style); text_struct.at.x = x; text_struct.at.y = y; text_struct.text = (char *) ZnMalloc(strlen(text) + 1); strcpy(text_struct.text, text); ZnListAdd(cur_map->texts, &text_struct, index); } } static void MapInfoReplaceText(MapInfoId map_info, unsigned int index, ZnPtr tag, MapInfoTextStyle text_style, MapInfoLineStyle line_style, int x, int y, char *text) { MapInfo cur_map = (MapInfo) map_info; MapInfoText text_ptr; if (cur_map && cur_map->texts) { text_ptr = (MapInfoText) ZnListAt(cur_map->texts, index); if (text_ptr) { ZnFree(text_ptr->text); text_ptr->tag = tag; text_ptr->text_style = text_style; text_ptr->line_style = NOT_MARKED_STYLE(line_style); text_ptr->at.x = x; text_ptr->at.y = y; text_ptr->text = (char *) ZnMalloc(strlen(text) + 1); strcpy(text_ptr->text, text); } } } static void MapInfoRemoveText(MapInfoId map_info, unsigned int index) { MapInfo cur_map = (MapInfo) map_info; MapInfoText text_ptr; if (cur_map && cur_map->texts) { text_ptr = (MapInfoText) ZnListAt(cur_map->texts, index); if (text_ptr) { ZnFree(text_ptr->text); ZnListDelete(cur_map->texts, index); } } } void MapInfoGetText(MapInfoId map_info, unsigned int index, ZnPtr *tag, MapInfoTextStyle *text_style, MapInfoLineStyle *line_style, int *x, int *y, char **text) { MapInfo cur_map = (MapInfo) map_info; MapInfoText text_ptr; if (cur_map && cur_map->texts) { text_ptr = (MapInfoText) ZnListAt(cur_map->texts, index); if (text_ptr) { if (tag) { *tag = text_ptr->tag; } if (text_style) { *text_style = text_ptr->text_style; } if (line_style) { *line_style = text_ptr->line_style; } if (x) { *x = text_ptr->at.x; } if (y) { *y = text_ptr->at.y; } if (text) { *text = text_ptr->text; } } } } unsigned int MapInfoNumTexts(MapInfoId map_info) { MapInfo cur_map = (MapInfo) map_info; if (cur_map && cur_map->texts) { return ZnListSize(cur_map->texts); } else { return 0; } } static void MapInfoAddArc(MapInfoId map_info, unsigned int index, ZnPtr tag, MapInfoLineStyle line_style, int line_width, int center_x, int center_y, unsigned int radius, int start_angle, int extend) { MapInfo cur_map = (MapInfo) map_info; MapInfoArcStruct arc_struct; if (cur_map) { if (!cur_map->arcs) { cur_map->arcs = ZnListNew(16, sizeof(MapInfoArcStruct)); } arc_struct.style = NOT_MARKED_STYLE(line_style); if (line_width == 1) { arc_struct.width = 0; } else { arc_struct.width = line_width; } arc_struct.tag = tag; arc_struct.center.x = center_x; arc_struct.center.y = center_y; arc_struct.radius = radius; arc_struct.start_angle = start_angle; arc_struct.extend = extend; ZnListAdd(cur_map->arcs, &arc_struct, index); } } static void MapInfoReplaceArc(MapInfoId map_info, unsigned int index, ZnPtr tag, MapInfoLineStyle line_style, int line_width, int center_x, int center_y, unsigned int radius, int start_angle, int extend) { MapInfo cur_map = (MapInfo) map_info; MapInfoArc arc_ptr; if (cur_map && cur_map->arcs) { arc_ptr = (MapInfoArc) ZnListAt(cur_map->arcs, index); if (arc_ptr) { arc_ptr->style = NOT_MARKED_STYLE(line_style); if (line_width == 1) { arc_ptr->width = 0; } else { arc_ptr->width = line_width; } arc_ptr->tag = tag; arc_ptr->center.x = center_x; arc_ptr->center.y = center_y; arc_ptr->radius = radius; arc_ptr->start_angle = start_angle; arc_ptr->extend = extend; } } } static void MapInfoRemoveArc(MapInfoId map_info, unsigned int index) { MapInfo cur_map = (MapInfo) map_info; MapInfoArc arc_ptr; if (cur_map && cur_map->arcs) { arc_ptr = (MapInfoArc) ZnListAt(cur_map->arcs, index); if (arc_ptr) { ZnListDelete(cur_map->arcs, index); } } } void MapInfoGetArc(MapInfoId map_info, unsigned int index, ZnPtr *tag, MapInfoLineStyle *line_style, int *line_width, int *center_x, int *center_y, unsigned int *radius, int *start_angle, int *extend) { MapInfo cur_map = (MapInfo) map_info; MapInfoArc arc_ptr; if (cur_map && cur_map->arcs) { arc_ptr = (MapInfoArc) ZnListAt(cur_map->arcs, index); if (arc_ptr) { if (tag) { *tag = arc_ptr->tag; } if (line_style) { *line_style = arc_ptr->style; } if (line_width) { if (arc_ptr->width == 1) { *line_width = 0; } else { *line_width = arc_ptr->width; } } if (center_x) { *center_x = arc_ptr->center.x; } if (center_y) { *center_y = arc_ptr->center.y; } if (radius) { *radius = arc_ptr->radius; } if (start_angle) { *start_angle = arc_ptr->start_angle; } if (extend) { *extend = arc_ptr->extend; } } } } unsigned int MapInfoNumArcs(MapInfoId map_info) { MapInfo cur_map = (MapInfo) map_info; if (cur_map && cur_map->arcs) { return ZnListSize(cur_map->arcs); } else { return 0; } } static void MapInfoScale(MapInfoId map_info, double factor) { MapInfo mp = (MapInfo) map_info; int i, num; MapInfoLine line_ptr; MapInfoSymbol sym_ptr; MapInfoText text_ptr; MapInfoArc arc_ptr; if (mp && mp->lines) { num = ZnListSize(mp->lines); line_ptr = (MapInfoLine) ZnListArray(mp->lines); for (i = 0; i < num; i++, line_ptr++) { line_ptr->from.x *= factor; line_ptr->from.y *= factor; line_ptr->to.x *= factor; line_ptr->to.y *= factor; } } if (mp && mp->symbols) { num = ZnListSize(mp->symbols); sym_ptr = (MapInfoSymbol) ZnListArray(mp->symbols); for (i = 0; i < num; i++, sym_ptr++) { sym_ptr->at.x *= factor; sym_ptr->at.y *= factor; } } if (mp && mp->texts) { num = ZnListSize(mp->texts); text_ptr = (MapInfoText) ZnListArray(mp->texts); for (i = 0; i < num; i++, text_ptr++) { text_ptr->at.x *= factor; text_ptr->at.y *= factor; } } if (mp && mp->arcs) { num = ZnListSize(mp->arcs); arc_ptr = (MapInfoArc) ZnListArray(mp->arcs); for (i = 0; i < num; i++, arc_ptr++) { arc_ptr->center.x *= factor; arc_ptr->center.y *= factor; arc_ptr->radius *= factor; } } } static void MapInfoTranslate(MapInfoId map_info, int x, int y) { MapInfo mp = (MapInfo) map_info; int i, num; MapInfoLine line_ptr; MapInfoSymbol sym_ptr; MapInfoText text_ptr; MapInfoArc arc_ptr; if (mp && mp->lines) { num = ZnListSize(mp->lines); line_ptr = (MapInfoLine) ZnListArray(mp->lines); for (i = 0; i < num; i++, line_ptr++) { line_ptr->from.x += x; line_ptr->from.y += y; line_ptr->to.x += x; line_ptr->to.y += y; } } if (mp && mp->symbols) { num = ZnListSize(mp->symbols); sym_ptr = (MapInfoSymbol) ZnListArray(mp->symbols); for (i = 0; i < num; i++, sym_ptr++) { sym_ptr->at.x += x; sym_ptr->at.y += y; } } if (mp && mp->texts) { num = ZnListSize(mp->texts); text_ptr = (MapInfoText) ZnListArray(mp->texts); for (i = 0; i < num; i++, text_ptr++) { text_ptr->at.x += x; text_ptr->at.y += y; } } if (mp && mp->arcs) { num = ZnListSize(mp->arcs); arc_ptr = (MapInfoArc) ZnListArray(mp->arcs); for (i = 0; i < num; i++, arc_ptr++) { arc_ptr->center.x += x; arc_ptr->center.y += y; } } } #define TEXT_SIZE 256 #define ntohi(n) ntohl((n)) /* *----------------------------------------------------------------------- * * Videomap record definition. Ints are assumed to be 4 bytes. * *----------------------------------------------------------------------- */ typedef struct { int id; /* Map id (internal) */ int dashed; /* Tell if vectors are dashed (exclusive with marked) */ int expanded; /* Device coordinates or world coordinates (ignored now) */ int marked; /* Tell if vectors are marked (exclusive with dashed) */ int color; /* drawing color (ignored now) */ int elements[50]; /* Element type ('P', 'V', 'T') */ int x[50]; /* Coordinates if 'P' or 'V' */ int y[50]; int symbol[50]; /* Filled if 'P' or 'V' */ int text[50]; /* Low order byte is ascii char if 'T' */ int num_elements; /* Number of elements */ } VideoMap; /* *----------------------------------------------------------------------- * * ReorderVidomap - reorder integers according to the endianess * *----------------------------------------------------------------------- */ static void ReorderVidomap(VideoMap *vm) { int loop; vm->id = ntohi(vm->id); vm->dashed = ntohi(vm->dashed); vm->expanded = ntohi(vm->expanded); vm->marked = ntohi(vm->marked); vm->color = ntohi(vm->color); for (loop = 0; loop < 50; loop++) { vm->elements[loop] = ntohi(vm->elements[loop]); vm->x[loop] = ntohi(vm->x[loop]); vm->y[loop] = ntohi(vm->y[loop]); vm->symbol[loop] = ntohi(vm->symbol[loop]); vm->text[loop] = ntohi(vm->text[loop]); } vm->num_elements = ntohi(vm->num_elements); } /* *----------------------------------------------------------------------- * * FillMap - Fill map with data in Videomap record vm. * *----------------------------------------------------------------------- */ static void FillMap(MapInfoId map, VideoMap *vm) { unsigned int i; ZnBool has_start_pos = False; int x_cur=0, y_cur=0; char ch; int text_x=0, text_y=0; char text[TEXT_SIZE]; ZnBool in_text = False; ZnBool in_mod_text = False; unsigned int text_size=0; for (i = 0; i < vm->num_elements; i++) { switch(vm->elements[i] & 0xFF) { case 'p': case 'P': if (in_text) { in_text = in_mod_text = False; while (text[text_size - 1] == ' ') { text_size--; } text[text_size] = (char) 0; MapInfoAddText(map, MapInfoNumTexts(map), NULL, MapInfoNormalText, MapInfoLineSimple, text_x, text_y, text); } x_cur = (int) (short) vm->x[i]; y_cur = (int) (short) vm->y[i]; has_start_pos = True; if (vm->symbol[i]) { MapInfoAddSymbol(map, MapInfoNumSymbols(map), NULL, x_cur, y_cur, vm->symbol[i]); } break; /* We gather consecutive 'T' elements in a text. We skip leading and trailing spaces and mod texts (between '@' and now obsolete) */ case 't': case 'T': if (!has_start_pos) { ZnWarning("Bogus map block, it has been discarded\n"); return; } if (in_text == False) { ch = (char) vm->text[i] & 0xFF; if (ch == '@') { if (in_mod_text == True) { in_mod_text = False; } else { in_mod_text = True; } } else if (in_mod_text == False) { in_text = True; text_size = 0; text_x = x_cur; text_y = y_cur; text[0] = (char) 0; } } if (in_text) { text[text_size] = (char) vm->text[i] & 0xFF; text_size++; } break; case 'v': case 'V': if (!has_start_pos) { ZnWarning("Bogus map block, it has been discarded\n"); return; } if (in_text) { in_text = in_mod_text = False; while (text[text_size - 1] == ' ') { text_size--; } text[text_size] = (char) 0; MapInfoAddText(map, MapInfoNumTexts(map), NULL, MapInfoNormalText, MapInfoLineSimple, text_x, text_y, text); } if (vm->dashed) { MapInfoAddLine(map, MapInfoNumLines(map), NULL, MapInfoLineDashed, 0, x_cur, y_cur, (int) (short) vm->x[i], (int) (short) vm->y[i]); } else if (vm->marked) { MapInfoAddLine(map, MapInfoNumLines(map), NULL, MapInfoLineMarked, 0, x_cur, y_cur, (int) (short) vm->x[i], (int) (short) vm->y[i]); } else { MapInfoAddLine(map, MapInfoNumLines(map), NULL, MapInfoLineSimple, 0, x_cur, y_cur, (int) (short) vm->x[i], (int) (short) vm->y[i]); } x_cur = (int) (short) vm->x[i]; y_cur = (int) (short) vm->y[i]; if (vm->symbol[i]) { MapInfoAddSymbol(map, MapInfoNumSymbols(map), NULL, x_cur, y_cur, vm->symbol[i]); } break; } } if (in_text) { in_text = in_mod_text = False; while (text[text_size - 1] == ' ') { text_size--; } text[text_size] = (char) 0; MapInfoAddText(map, MapInfoNumTexts(map), NULL, MapInfoNormalText, MapInfoLineSimple, text_x, text_y, text); } } /* *----------------------------------------------------------------------- * * MapInfoGetVideomap - Load a mapinfo with the content of a videomap * file named 'filename'. Only the sub map 'index' will be loaded. * If successful a new mapinfo is returned, NULL otherwise. The * index is zero based. * *----------------------------------------------------------------------- */ static int MapInfoGetVideomap(MapInfoId map, char *filename, int index) { VideoMap current_vm; FILE *file; int cur_index, cur_id; /* Open the specified map file. */ file = fopen(filename, "r"); if (file == NULL) { return ZN_ERROR; } /* Load the map */ /* First skip the leading maps up to index. */ cur_index = 0; if (fread(¤t_vm, sizeof(VideoMap), 1, file) < 0) { goto error; } cur_id = ntohi(current_vm.id); while (cur_index != index) { if (fread(¤t_vm, sizeof(VideoMap), 1, file) < 0) { goto error; } if (cur_id != ntohi(current_vm.id)) { cur_index++; cur_id = ntohi(current_vm.id); } }; /* Then load all the map modules. */ do { ReorderVidomap(¤t_vm); FillMap(map, ¤t_vm); if ((fread(¤t_vm, sizeof(VideoMap), 1, file) != 1) && !feof(file)) { goto error; } } while ((cur_id == ntohi(current_vm.id)) && !feof(file)); fclose(file); return ZN_OK; error: fclose(file); return ZN_ERROR; } /* *----------------------------------------------------------------------- * * MapInfoVideomapIds - Return the list of sub map ids contained in a * videomap file. This makes it possible to iterate through such * a file without stumbling on an error, to know how much maps * are there and to sort them according to their ids. * *----------------------------------------------------------------------- */ static ZnList MapInfoVideomapIds(char *filename) { FILE *file; VideoMap current_vm; int cur_id; ZnList ids; /* Open the specified map file. */ file = fopen(filename, "r"); if (file == NULL) { return NULL; } if (fread(¤t_vm, sizeof(VideoMap), 1, file) < 0) { goto error; } cur_id = ntohi(current_vm.id); ids = ZnListNew(16, sizeof(int)); /*printf("id %d\n", cur_id);*/ ZnListAdd(ids, &cur_id, ZnListTail); do { if (fread(¤t_vm, sizeof(VideoMap), 1, file) < 0) { goto error; } if (cur_id != ntohi(current_vm.id)) { cur_id = ntohi(current_vm.id); /*printf("id %d\n", cur_id);*/ ZnListAdd(ids, &cur_id, ZnListTail); } } while (!feof(file)); fclose(file); return ids; error: fclose(file); ZnListFree(ids); return NULL; } /* *-------------------------------------------------------------------------- * * MapInfo and Videomapstuff that should go eventually in its own file. * *-------------------------------------------------------------------------- */ static Tcl_HashTable mapInfoTable; static ZnBool map_info_inited = False; typedef struct { ClientData client_data; MapInfoChangeProc proc; } MapInfoClient; typedef struct { MapInfoId map_info; ZnBool deleted; ZnList clients; } MapInfoMaster; static void MapInfoInit() { Tcl_InitHashTable(&mapInfoTable, TCL_ONE_WORD_KEYS); map_info_inited = True; } static void UpdateMapInfoClients(MapInfoMaster *master) { int i, num; MapInfoClient *client; num = ZnListSize(master->clients); client = (MapInfoClient *) ZnListArray(master->clients); for (i = 0; i < num; i++, client++) { (*client->proc)(client->client_data, master->map_info); } } static int ZnCreateMapInfo(Tcl_Interp *interp, char *name, MapInfoId *map_info) { Tk_Uid uid = Tk_GetUid(name); Tcl_HashEntry *entry; int new; MapInfoMaster *master; if (!map_info_inited) { MapInfoInit(); } entry = Tcl_CreateHashEntry(&mapInfoTable, uid, &new); if (!new) { /* * Empty the map info if it is not. */ master = (MapInfoMaster *) Tcl_GetHashValue(entry); if (master->deleted) { master->deleted = False; } else { MapInfoEmpty(master->map_info); UpdateMapInfoClients(master); } } else { master = (MapInfoMaster *) ZnMalloc(sizeof(MapInfoMaster)); master->map_info = MapInfoCreate(name); master->deleted = False; master->clients = ZnListNew(1, sizeof(MapInfoClient)); Tcl_SetHashValue(entry, master); } if (map_info) { *map_info = master->map_info; } return TCL_OK; } static int ZnDuplicateMapInfo(Tcl_Interp *interp, char *name, MapInfoId map_info) { Tk_Uid uid = Tk_GetUid(name); Tcl_HashEntry *entry; int new; MapInfoMaster *master; if (!map_info_inited) { MapInfoInit(); } entry = Tcl_CreateHashEntry(&mapInfoTable, uid, &new); if (!new) { Tcl_AppendResult(interp, "duplicate mapinfo \"", name, "\" already exists", NULL); return ZN_ERROR; } master = (MapInfoMaster *) ZnMalloc(sizeof(MapInfoMaster)); master->map_info = MapInfoDuplicate(map_info); master->deleted = False; master->clients = ZnListNew(1, sizeof(MapInfoClient)); Tcl_SetHashValue(entry, master); return TCL_OK; } static MapInfoMaster * LookupMapInfoMaster(Tcl_Interp *interp, char *name) { Tk_Uid uid = Tk_GetUid(name); Tcl_HashEntry *entry; MapInfoMaster *master; if (!map_info_inited) { MapInfoInit(); } entry = Tcl_FindHashEntry(&mapInfoTable, uid); if (entry == NULL) { mp_error: Tcl_AppendResult(interp, "mapinfo \"", name, "\" doesn't exist", NULL); return NULL; } master = (MapInfoMaster *) Tcl_GetHashValue(entry); if (master->deleted) { goto mp_error; } return master; } static int ZnDeleteMapInfo(Tcl_Interp *interp, char *name) { MapInfoMaster *master; Tk_Uid uid = Tk_GetUid(name); Tcl_HashEntry *entry; if (!map_info_inited) { MapInfoInit(); } entry = Tcl_FindHashEntry(&mapInfoTable, uid); if (entry == NULL) { return ZN_ERROR; } master = (MapInfoMaster *) Tcl_GetHashValue(entry); if (ZnListSize(master->clients) != 0) { master->deleted = True; MapInfoEmpty(master->map_info); UpdateMapInfoClients(master); } else { MapInfoDelete(master->map_info); ZnListFree(master->clients); Tcl_DeleteHashEntry(entry); ZnFree(master); } return TCL_OK; } MapInfoId ZnGetMapInfo(Tcl_Interp *interp, char *name, MapInfoChangeProc proc, ClientData client_data) { MapInfoMaster *master; MapInfoClient client; master = LookupMapInfoMaster(interp, name); if (master == NULL) { return NULL; } client.proc = proc; client.client_data = client_data; ZnListAdd(master->clients, &client, ZnListTail); return master->map_info; } void ZnFreeMapInfo(MapInfoId map_info, MapInfoChangeProc proc, ClientData client_data) { Tk_Uid uid = Tk_GetUid(MapInfoName(map_info)); Tcl_HashEntry *entry; MapInfoMaster *master; MapInfoClient *client; int num, i; if (!map_info_inited) { MapInfoInit(); } entry = Tcl_FindHashEntry(&mapInfoTable, uid); if (entry == NULL) { return; } master = (MapInfoMaster *) Tcl_GetHashValue(entry); client = (MapInfoClient *) ZnListArray(master->clients); num = ZnListSize(master->clients); for (i = 0; i < num; i++, client++) { if ((client->client_data == client_data) && (client->proc == proc)) { ZnListDelete(master->clients, i); return; } } } static void ZnUpdateMapInfoClients(MapInfoId map_info) { Tk_Uid uid = Tk_GetUid(MapInfoName(map_info)); Tcl_HashEntry *entry; MapInfoMaster *master; if (!map_info_inited) { MapInfoInit(); } entry = Tcl_FindHashEntry(&mapInfoTable, uid); if (entry == NULL) { return; } master = (MapInfoMaster *) Tcl_GetHashValue(entry); UpdateMapInfoClients(master); } /* * These arrays must be kept in sync with the MapInfoLineStyle * and MapInfoTextStyle enums. */ static char *line_style_strings[] = { "simple", "dashed", "dotted", "mixed", "marked", }; static char *text_style_strings[] = { "normal", "underlined" }; static char * MapInfoLineStyleToString(MapInfoLineStyle line_style) { return line_style_strings[line_style]; } static int MapInfoLineStyleFromString(Tcl_Interp *interp, char *str, MapInfoLineStyle *line_style) { int i, num = sizeof(line_style_strings)/sizeof(char *); for (i = 0; i < num; i++) { if (strcmp(str, line_style_strings[i]) == 0) { *line_style = i; return TCL_OK; } } Tcl_AppendResult(interp, " incorrect mapinfo line style \"", str,"\"", NULL); return ZN_ERROR; } static char * MapInfoTextStyleToString(MapInfoTextStyle text_style) { return text_style_strings[text_style]; } static int MapInfoTextStyleFromString(Tcl_Interp *interp, char *str, MapInfoTextStyle *text_style) { int i, num = sizeof(text_style_strings)/sizeof(char *); for (i = 0; i < num; i++) { if (strcmp(str, text_style_strings[i]) == 0) { *text_style = i; return TCL_OK; } } Tcl_AppendResult(interp, " incorrect mapinfo text style \"", str,"\"", NULL); return ZN_ERROR; } int MapInfoObjCmd(ClientData client_data, Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ Tcl_Obj *CONST args[]) { int index, index2, result; MapInfoMaster *master; Tcl_Obj *l; static CONST char *sub_cmd_strings[] = { "add", "count", "create", "delete", "duplicate", "get", "remove", "replace", "scale", "translate", NULL }; static CONST char *e_type_strings[] = { "arc", "line", "symbol", "text", NULL }; enum sub_cmds { ZN_MI_ADD, ZN_MI_COUNT, ZN_MI_CREATE, ZN_MI_DELETE, ZN_MI_DUPLICATE, ZN_MI_GET, ZN_MI_REMOVE, ZN_MI_REPLACE, ZN_MI_SCALE, ZN_MI_TRANSLATE }; enum e_types { ZN_E_ARC, ZN_E_LINE, ZN_E_SYMBOL, ZN_E_TEXT }; if (argc < 3) { Tcl_WrongNumArgs(interp, 1, args, "mapInfo/name subCmd ?args?"); return ZN_ERROR; } if (Tcl_GetIndexFromObj(interp, args[2], sub_cmd_strings, "subCmd", 0, &index) != ZN_OK) { return ZN_ERROR; } result = TCL_OK; /*printf("mapinfo command \"%s\", argc=%d\n", Tcl_GetString(args[2]), argc);*/ switch((enum sub_cmds) index) { /* * create */ case ZN_MI_CREATE: { if (argc != 3) { Tcl_WrongNumArgs(interp, 1, args, "name create"); return ZN_ERROR; } if (ZnCreateMapInfo(interp, Tcl_GetString(args[1]), NULL) == ZN_ERROR) { return ZN_ERROR; } } break; /* * delete */ case ZN_MI_DELETE: { if (argc != 3) { Tcl_WrongNumArgs(interp, 1, args, "mapInfo delete"); return ZN_ERROR; } if (ZnDeleteMapInfo(interp, Tcl_GetString(args[1])) == ZN_ERROR) { return ZN_ERROR; } } break; /* * duplicate */ case ZN_MI_DUPLICATE: { if (argc != 4) { Tcl_WrongNumArgs(interp, 1, args, "mapInfo duplicate name"); return ZN_ERROR; } master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); if (master == NULL) { return ZN_ERROR; } if (ZnDuplicateMapInfo(interp, Tcl_GetString(args[3]), master->map_info) == ZN_ERROR) { return ZN_ERROR; } } break; /* * add/replace */ case ZN_MI_ADD: case ZN_MI_REPLACE: { MapInfoLineStyle line_style; MapInfoTextStyle text_style; int i, insert; int coords[6]; ZnBool add_cmd = (enum sub_cmds) index == ZN_MI_ADD; int num_param = add_cmd ? 4 : 5; if (argc < num_param) { Tcl_WrongNumArgs(interp, 3, args, add_cmd ? "elementType ?args?" : "elementType index ?args?"); return ZN_ERROR; } master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); if (master == NULL) { return ZN_ERROR; } if (!add_cmd) { if (Tcl_GetIntFromObj(interp, args[4], &insert) == ZN_ERROR) { return ZN_ERROR; } if (insert < 0) { insert = 0; } } if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings, "elementType", 0, &index2) != ZN_OK) { return ZN_ERROR; } switch ((enum e_types) index2) { case ZN_E_LINE: { if (argc != (num_param+6)) { Tcl_WrongNumArgs(interp, 4, args, add_cmd ? "style width x1 y1 x2 y2" : "index style width x1 y1 x2 y2"); return ZN_ERROR; } if (MapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param]), &line_style) == ZN_ERROR) { return ZN_ERROR; } for (i = 0; i < 5; i++) { if (Tcl_GetIntFromObj(interp, args[num_param+i+1], &coords[i]) == ZN_ERROR) { return ZN_ERROR; } } if (coords[0] < 0) { coords[0] = 0; } if (add_cmd) { MapInfoAddLine(master->map_info, ZnListTail, NULL, line_style, coords[0], coords[1], coords[2], coords[3], coords[4]); } else { MapInfoReplaceLine(master->map_info, insert, NULL, line_style, coords[0], coords[1], coords[2], coords[3], coords[4]); } } break; case ZN_E_SYMBOL: { if (argc != (num_param+3)) { Tcl_WrongNumArgs(interp, 4, args, add_cmd ? "x y intVal" : "index x y intVal"); return ZN_ERROR; } for (i = 0; i < 3; i++) { if (Tcl_GetIntFromObj(interp, args[num_param+i], &coords[i]) == ZN_ERROR) { return ZN_ERROR; } } if (coords[2] < 0) { coords[2] = 0; } if (add_cmd) { MapInfoAddSymbol(master->map_info, ZnListTail, NULL, coords[0], coords[1], coords[2]); } else { MapInfoReplaceSymbol(master->map_info, insert, NULL, coords[0], coords[1], coords[2]); } } break; case ZN_E_TEXT: { if (argc != (num_param+5)) { Tcl_WrongNumArgs(interp, 4, args, add_cmd ? "textStyle lineStyle x y string" : "index textStyle lineStyle x y string"); return ZN_ERROR; } if (MapInfoTextStyleFromString(interp, Tcl_GetString(args[num_param]), &text_style) == ZN_ERROR) { return ZN_ERROR; } if (MapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param+1]), &line_style) == ZN_ERROR) { return ZN_ERROR; } for (i = 0; i < 2; i++) { if (Tcl_GetIntFromObj(interp, args[num_param+i+2], &coords[i]) == ZN_ERROR) { return ZN_ERROR; } } if (add_cmd) { MapInfoAddText(master->map_info, ZnListTail, NULL, text_style, line_style, coords[0], coords[1], Tcl_GetString(args[num_param+4])); } else { /*printf("replace text ts %d ls %d %d %d %s\n", text_style, line_style, coords[0], coords[1], Tcl_GetString(args[num_param+4]));*/ MapInfoReplaceText(master->map_info, insert, NULL, text_style, line_style, coords[0], coords[1], Tcl_GetString(args[num_param+4])); } } break; case ZN_E_ARC: { if (argc != (num_param+7)) { Tcl_WrongNumArgs(interp, 4, args, add_cmd ? "style width cx cy radius start extent" : "index style width cx cy radius start extent"); return ZN_ERROR; } if (MapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param]), &line_style) == ZN_ERROR) { return ZN_ERROR; } for (i = 0; i < 6; i++) { if (Tcl_GetIntFromObj(interp, args[num_param+i+1], &coords[i]) == ZN_ERROR) { return ZN_ERROR; } } if (coords[0] < 0) { coords[0] = 0; } if (add_cmd) { MapInfoAddArc(master->map_info, ZnListTail, NULL, line_style, coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); } else { MapInfoReplaceArc(master->map_info, insert, NULL, line_style, coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); } } break; } UpdateMapInfoClients(master); } break; /* * count */ case ZN_MI_COUNT: { int count = 0; if (argc != 4) { Tcl_WrongNumArgs(interp, 1, args, "mapInfo count type"); return ZN_ERROR; } master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); if (master == NULL) { return ZN_ERROR; } if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings, "elementType", 0, &index2) != ZN_OK) { return ZN_ERROR; } switch ((enum e_types) index2) { case ZN_E_LINE: count = MapInfoNumLines(master->map_info); break; case ZN_E_SYMBOL: count = MapInfoNumSymbols(master->map_info); break; case ZN_E_TEXT: count = MapInfoNumTexts(master->map_info); break; case ZN_E_ARC: count = MapInfoNumArcs(master->map_info); break; } l = Tcl_NewIntObj(count); Tcl_SetObjResult(interp, l); } break; /* * get */ case ZN_MI_GET: { int insert; if (argc != 5) { Tcl_WrongNumArgs(interp, 1, args, "mapInfo get type index"); return ZN_ERROR; } master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); if (master == NULL) { return ZN_ERROR; } if (Tcl_GetIntFromObj(interp, args[4], &insert) == ZN_ERROR) { return ZN_ERROR; } if (insert < 0) { insert = 0; } if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings, "elementType", 0, &index2) != ZN_OK) { return ZN_ERROR; } switch ((enum e_types) index2) { case ZN_E_LINE: { MapInfoLineStyle line_style; int line_width; int x_from, y_from, x_to, y_to; MapInfoGetLine(master->map_info, insert, NULL, &line_style, &line_width, &x_from, &y_from, &x_to, &y_to); l = Tcl_GetObjResult(interp); Tcl_ListObjAppendElement(interp, l, NewStringObj(MapInfoLineStyleToString(line_style))); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(line_width)); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(x_from)); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(y_from)); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(x_to)); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(y_to)); } break; case ZN_E_SYMBOL: { int x, y; char symbol; MapInfoGetSymbol(master->map_info, insert, NULL, &x, &y, &symbol); l = Tcl_GetObjResult(interp); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(x)); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(y)); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(symbol)); } break; case ZN_E_TEXT: { int x, y; char *text; MapInfoTextStyle text_style; MapInfoLineStyle line_style; MapInfoGetText(master->map_info, insert, NULL, &text_style, &line_style, &x, &y, &text); l = Tcl_GetObjResult(interp); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(x)); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(y)); Tcl_ListObjAppendElement(interp, l, NewStringObj(MapInfoTextStyleToString(text_style))); Tcl_ListObjAppendElement(interp, l, NewStringObj(MapInfoLineStyleToString(line_style))); Tcl_ListObjAppendElement(interp, l, NewStringObj(text)); } break; case ZN_E_ARC: { MapInfoLineStyle line_style; int line_width; int center_x, center_y, start, extent; unsigned int radius; MapInfoGetArc(master->map_info, insert, NULL, &line_style, &line_width, ¢er_x, ¢er_y, &radius, &start, &extent); l = Tcl_GetObjResult(interp); Tcl_ListObjAppendElement(interp, l, NewStringObj(MapInfoLineStyleToString(line_style))); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(line_width)); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(center_x)); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(center_y)); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(radius)); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(start)); Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(extent)); } break; } } break; /* * remove */ case ZN_MI_REMOVE: { int insert; if (argc != 5) { Tcl_WrongNumArgs(interp, 1, args, "mapInfo remove type index"); return ZN_ERROR; } master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); if (master == NULL) { return ZN_ERROR; } if (Tcl_GetIntFromObj(interp, args[4], &insert) == ZN_ERROR) { return ZN_ERROR; } if (insert < 0) { insert = 0; } if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings, "elementType", 0, &index2) != ZN_OK) { return ZN_ERROR; } switch ((enum e_types) index2) { case ZN_E_LINE: MapInfoRemoveLine(master->map_info, insert); break; case ZN_E_SYMBOL: MapInfoRemoveSymbol(master->map_info, insert); break; case ZN_E_TEXT: MapInfoRemoveText(master->map_info, insert); break; case ZN_E_ARC: MapInfoRemoveArc(master->map_info, insert); break; } UpdateMapInfoClients(master); } break; /* * scale */ case ZN_MI_SCALE: { double factor; if (argc != 4) { Tcl_WrongNumArgs(interp, 1, args, "mapInfo scale factor"); return ZN_ERROR; } master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); if (master == NULL) { return ZN_ERROR; } if (Tcl_GetDoubleFromObj(interp, args[3], &factor) == ZN_ERROR) { return ZN_ERROR; } MapInfoScale(master->map_info, factor); UpdateMapInfoClients(master); } break; /* * translate */ case ZN_MI_TRANSLATE: { int x, y; if (argc != 5) { Tcl_WrongNumArgs(interp, 1, args, "mapInfo translate xAmount yAmount"); return ZN_ERROR; } master = LookupMapInfoMaster(interp, Tcl_GetString(args[1])); if (master == NULL) { return ZN_ERROR; } if (Tcl_GetIntFromObj(interp, args[3], &x) == ZN_ERROR) { return ZN_ERROR; } if (Tcl_GetIntFromObj(interp, args[4], &y) == ZN_ERROR) { return ZN_ERROR; } MapInfoTranslate(master->map_info, x, y); UpdateMapInfoClients(master); } break; } return TCL_OK; } /* *---------------------------------------------------------------------- * * VideomapObjCmd -- * * *---------------------------------------------------------------------- */ int VideomapObjCmd(ClientData client_data, Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ Tcl_Obj *CONST args[]) { ZnList ids; int index; int *id_array, id_num, i; Tcl_Obj *l; static CONST char *sub_cmd_strings[] = { "ids", "load", NULL }; enum sub_cmds { ZN_V_IDS, ZN_V_LOAD }; if (argc < 2) { Tcl_WrongNumArgs(interp, 1, args, "?subCmd? filename $args?"); return ZN_ERROR; } if (Tcl_GetIndexFromObj(interp, args[1], sub_cmd_strings, "subCmd", 0, &index) != ZN_OK) { return ZN_ERROR; } switch((enum sub_cmds) index) { /* * ids */ case ZN_V_IDS: { if (argc != 3) { Tcl_WrongNumArgs(interp, 1, args,"ids filename"); return ZN_ERROR; } ids = MapInfoVideomapIds(Tcl_GetString(args[2])); if (ids == NULL) { Tcl_AppendResult(interp, "unable to look at videomap file \"", Tcl_GetString(args[2]), "\"", NULL); return ZN_ERROR; } id_array = (int *) ZnListArray(ids); id_num = ZnListSize(ids); l = Tcl_GetObjResult(interp); for (i = 0; i < id_num; i++) { Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(id_array[i])); } ZnListFree(ids); } break; /* * load */ case ZN_V_LOAD: { MapInfoId map_info; int insert; if (argc != 5) { Tcl_WrongNumArgs(interp, 1, args, "load filename index mapInfo"); return ZN_ERROR; } if (Tcl_GetIntFromObj(interp, args[3], &insert) == ZN_ERROR) { return ZN_ERROR; } if (insert < 0) { insert = 0; } if (ZnCreateMapInfo(interp, Tcl_GetString(args[4]), &map_info) == ZN_ERROR) { return ZN_ERROR; } if (MapInfoGetVideomap(map_info, Tcl_GetString(args[2]), insert) == ZN_ERROR) { Tcl_AppendResult(interp, "unable to load videomap file \"", Tcl_GetString(args[2]), ":", Tcl_GetString(args[3]), "\"", NULL); return ZN_ERROR; } ZnUpdateMapInfoClients(map_info); } break; } return TCL_OK; }