/*
* MapInfo.c -- MapInfo interface.
*
* Authors : Patrick Lecoanet.
* Creation date :
*
* $Id: MapInfo.c,v 1.28 2005/04/27 07:32:03 lecoanet Exp $
*/
/*
* Copyright (c) 1993 - 2005 CENA, Patrick Lecoanet --
*
* See the file "Copyright" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
#ifndef _WIN32
#include <sys/param.h>
#include <netinet/in.h>
#else
#include <winsock2.h>
#endif
#include "MapInfo.h"
#include "tkZinc.h"
#include <memory.h>
#include <math.h>
static const char rcsid[] = "$Id: MapInfo.c,v 1.28 2005/04/27 07:32:03 lecoanet Exp $";
static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " $";
/*
*-----------------------------------------------------------------------
*
* New types
*
*-----------------------------------------------------------------------
*/
typedef struct {
ZnPtr tag;
ZnMapInfoLineStyle style;
int width;
ZnPoint center;
unsigned int radius;
int start_angle;
int extend;
} ZnMapInfoArcStruct, *ZnMapInfoArc;
typedef struct {
ZnPtr tag;
ZnMapInfoLineStyle style;
int width;
ZnPoint from;
ZnPoint to;
unsigned int num_marks;
ZnPoint *marks;
} ZnMapInfoLineStruct, *ZnMapInfoLine;
typedef struct {
ZnPtr tag;
ZnPoint at;
char symbol[2];
} ZnMapInfoSymbolStruct, *ZnMapInfoSymbol;
typedef struct {
ZnPtr tag;
ZnMapInfoTextStyle text_style;
ZnMapInfoLineStyle line_style;
ZnPoint at;
char *text;
} ZnMapInfoTextStruct, *ZnMapInfoText;
typedef struct {
char *name;
ZnList lines;
ZnList symbols;
ZnList texts;
ZnList arcs;
} ZnMapInfoStruct, *ZnMapInfo;
#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) == ZnMapInfoLineMarked ? ZnMapInfoLineSimple : (style));
/*
*-----------------------------------------------------------------------
*
* ComputeLineMarks --
* Add marks to a line in the marks substructure.
*
*-----------------------------------------------------------------------
*/
static void
ComputeLineMarks(ZnMapInfoLine marked_line)
{
ZnDim length;
ZnPos x_from = marked_line->from.x;
ZnPos y_from = marked_line->from.y;
ZnPos x_to = marked_line->to.x;
ZnPos y_to = marked_line->to.y;
ZnPos delta_x = x_from - x_to;
ZnPos delta_y = y_from - y_to;
ZnPos step_x, step_y;
unsigned int j;
length = sqrt(delta_x * delta_x + delta_y * delta_y);
step_x = (x_to - x_from) * MARKERS_SPACING / length;
step_y = (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 = ZnMalloc(marked_line->num_marks * sizeof(ZnPoint));
}
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 ZnMapInfoId
ZnMapInfoCreate(char *name)
{
ZnMapInfo new_map;
new_map = ZnMalloc(sizeof(ZnMapInfoStruct));
memset((char *) new_map, 0, sizeof(ZnMapInfoStruct));
if (!name) {
name = "";
}
new_map->name = (char *) ZnMalloc(strlen(name)+1);
/*printf("Nouvelle MapInfo: %s\n", name);*/
strcpy(new_map->name, name);
return((ZnMapInfoId) new_map);
}
static char *
ZnMapInfoName(ZnMapInfoId map_info)
{
if (!map_info) {
return "";
}
return ((ZnMapInfo) map_info)->name;
}
static ZnMapInfoId
ZnMapInfoDuplicate(ZnMapInfoId map_info)
{
ZnMapInfo cur_map = map_info;
ZnMapInfo new_map;
unsigned int i, num_lines, num_texts;
ZnMapInfoText new_texts, cur_texts;
ZnMapInfoLine new_lines, cur_lines;
if (!cur_map) {
return ((ZnMapInfoId) NULL);
}
new_map = ZnMapInfoCreate(cur_map->name);
if (cur_map->lines) {
new_map->lines = ZnListDuplicate(cur_map->lines);
cur_lines = ZnListArray(cur_map->lines);
new_lines = ZnListArray(new_map->lines);
num_lines = ZnListSize(cur_map->lines);
for (i = 0; i < num_lines; i++) {
if (new_lines[i].style == ZnMapInfoLineMarked) {
new_lines[i].marks = ZnMalloc(new_lines[i].num_marks * sizeof(ZnPoint));
memcpy((char *) new_lines[i].marks,
(char *) cur_lines[i].marks,
new_lines[i].num_marks * sizeof(ZnPoint));
}
}
}
if (cur_map->symbols) {
new_map->symbols = ZnListDuplicate(cur_map->symbols);
}
if (cur_map->texts) {
new_map->texts = ZnListDuplicate(cur_map->texts);
cur_texts = ZnListArray(cur_map->texts);
new_texts = ZnListArray(new_map->texts);
num_texts = ZnListSize(cur_map->texts);
for (i = 0; i < num_texts; i++) {
new_texts[i].text = 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((ZnMapInfoId) new_map);
}
static void
ZnMapInfoDelete(ZnMapInfoId map_info)
{
ZnMapInfo cur_map = map_info;
unsigned int i, num_texts, num_lines;
ZnMapInfoText cur_texts;
ZnMapInfoLine cur_lines;
if (cur_map) {
if (cur_map->texts) {
num_texts = ZnListSize(cur_map->texts);
cur_texts = ZnListArray(cur_map->texts);
for (i = 0; i < num_texts; i++) {
ZnFree(cur_texts[i].text);
}
ZnListFree(cur_map->texts);
}
if (cur_map->lines) {
num_lines = ZnListSize(cur_map->lines);
cur_lines = ZnListArray(cur_map->lines);
for (i = 0; i < num_lines; i++) {
if (cur_lines[i].style == ZnMapInfoLineMarked) {
ZnFree(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
ZnMapInfoEmpty(ZnMapInfoId map_info)
{
ZnMapInfo cur_map = 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
ZnMapInfoAddLine(ZnMapInfoId map_info,
unsigned int index,
ZnPtr tag,
ZnMapInfoLineStyle line_style,
ZnDim line_width,
ZnPos x_from,
ZnPos y_from,
ZnPos x_to,
ZnPos y_to)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoLineStruct line_struct;
if (cur_map) {
if (!cur_map->lines) {
cur_map->lines = ZnListNew(16, sizeof(ZnMapInfoLineStruct));
}
line_struct.style = line_style;
if (line_width == 1.0) {
line_struct.width = 0;
}
else {
line_struct.width = (int) 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;
/*printf("Ajout de la ligne: %d %d %d %d\n", x_from, y_from, x_to, y_to);*/
if (line_style == ZnMapInfoLineMarked) {
ComputeLineMarks(&line_struct);
}
ZnListAdd(cur_map->lines, &line_struct, index);
}
}
static void
ZnMapInfoReplaceLine(ZnMapInfoId map_info,
unsigned int index,
ZnPtr tag,
ZnMapInfoLineStyle line_style,
ZnDim line_width,
ZnPos x_from,
ZnPos y_from,
ZnPos x_to,
ZnPos y_to)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoLine line_ptr;
if (cur_map && cur_map->lines) {
line_ptr = ZnListAt(cur_map->lines, index);
if (line_ptr) {
if (line_ptr->style == ZnMapInfoLineMarked) {
ZnFree(line_ptr->marks);
}
line_ptr->style = line_style;
if (line_width == 1.0) {
line_ptr->width = 0;
}
else {
line_ptr->width = (int) 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 == ZnMapInfoLineMarked) {
ComputeLineMarks(line_ptr);
}
}
}
}
static void
ZnMapInfoRemoveLine(ZnMapInfoId map_info,
unsigned int index)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoLine line_ptr;
if (cur_map && cur_map->lines) {
line_ptr = ZnListAt(cur_map->lines, index);
if (line_ptr) {
if (line_ptr->style == ZnMapInfoLineMarked) {
ZnFree(line_ptr->marks);
}
ZnListDelete(cur_map->lines, index);
}
}
}
void
ZnMapInfoGetLine(ZnMapInfoId map_info,
unsigned int index,
ZnPtr *tag,
ZnMapInfoLineStyle *line_style,
ZnDim *line_width,
ZnPos *x_from,
ZnPos *y_from,
ZnPos *x_to,
ZnPos *y_to)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoLine line_ptr;
if (cur_map && cur_map->lines) {
line_ptr = 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.0) {
*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
ZnMapInfoGetMarks(ZnMapInfoId map_info,
unsigned int index,
ZnPoint **marks,
unsigned int *num_marks)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoLine line_ptr;
if (cur_map && cur_map->lines) {
line_ptr = ZnListAt(cur_map->lines, index);
if (line_ptr && line_ptr->style == ZnMapInfoLineMarked) {
if (marks) {
*marks = line_ptr->marks;
}
if (num_marks) {
*num_marks = line_ptr->num_marks;
}
}
}
}
unsigned int
ZnMapInfoNumLines(ZnMapInfoId map_info)
{
ZnMapInfo cur_map = map_info;
if (cur_map && cur_map->lines) {
return ZnListSize(cur_map->lines);
}
else {
return 0;
}
}
static void
ZnMapInfoAddSymbol(ZnMapInfoId map_info,
unsigned int index,
ZnPtr tag,
ZnPos x,
ZnPos y,
int symbol)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoSymbolStruct symbol_struct;
if (cur_map) {
if (!cur_map->symbols) {
cur_map->symbols = ZnListNew(16, sizeof(ZnMapInfoSymbolStruct));
}
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
ZnMapInfoReplaceSymbol(ZnMapInfoId map_info,
unsigned int index,
ZnPtr tag,
ZnPos x,
ZnPos y,
int symbol)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoSymbolStruct 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
ZnMapInfoRemoveSymbol(ZnMapInfoId map_info,
unsigned int index)
{
ZnMapInfo cur_map = map_info;
if (cur_map && cur_map->symbols) {
ZnListDelete(cur_map->symbols, index);
}
}
void
ZnMapInfoGetSymbol(ZnMapInfoId map_info,
unsigned int index,
ZnPtr *tag,
ZnPos *x,
ZnPos *y,
char *symbol)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoSymbol symbol_ptr;
if (cur_map && cur_map->symbols) {
symbol_ptr = 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
ZnMapInfoNumSymbols(ZnMapInfoId map_info)
{
ZnMapInfo cur_map = map_info;
if (cur_map && cur_map->symbols) {
return ZnListSize(cur_map->symbols);
}
else {
return 0;
}
}
static void
ZnMapInfoAddText(ZnMapInfoId map_info,
unsigned int index,
ZnPtr tag,
ZnMapInfoTextStyle text_style,
ZnMapInfoLineStyle line_style,
ZnPos x,
ZnPos y,
char *text)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoTextStruct text_struct;
if (cur_map) {
if (!cur_map->texts) {
cur_map->texts = ZnListNew(16, sizeof(ZnMapInfoTextStruct));
}
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 = ZnMalloc(strlen(text) + 1);
strcpy(text_struct.text, text);
ZnListAdd(cur_map->texts, &text_struct, index);
}
}
static void
ZnMapInfoReplaceText(ZnMapInfoId map_info,
unsigned int index,
ZnPtr tag,
ZnMapInfoTextStyle text_style,
ZnMapInfoLineStyle line_style,
ZnPos x,
ZnPos y,
char *text)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoText text_ptr;
if (cur_map && cur_map->texts) {
text_ptr = 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 = ZnMalloc(strlen(text) + 1);
strcpy(text_ptr->text, text);
}
}
}
static void
ZnMapInfoRemoveText(ZnMapInfoId map_info,
unsigned int index)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoText text_ptr;
if (cur_map && cur_map->texts) {
text_ptr = ZnListAt(cur_map->texts, index);
if (text_ptr) {
ZnFree(text_ptr->text);
ZnListDelete(cur_map->texts, index);
}
}
}
void
ZnMapInfoGetText(ZnMapInfoId map_info,
unsigned int index,
ZnPtr *tag,
ZnMapInfoTextStyle *text_style,
ZnMapInfoLineStyle *line_style,
ZnPos *x,
ZnPos *y,
char **text)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoText text_ptr;
if (cur_map && cur_map->texts) {
text_ptr = 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
ZnMapInfoNumTexts(ZnMapInfoId map_info)
{
ZnMapInfo cur_map = map_info;
if (cur_map && cur_map->texts) {
return ZnListSize(cur_map->texts);
}
else {
return 0;
}
}
static void
ZnMapInfoAddArc(ZnMapInfoId map_info,
unsigned int index,
ZnPtr tag,
ZnMapInfoLineStyle line_style,
ZnDim line_width,
ZnPos center_x,
ZnPos center_y,
ZnDim radius,
ZnReal start_angle,
ZnReal extend)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoArcStruct arc_struct;
if (cur_map) {
if (!cur_map->arcs) {
cur_map->arcs = ZnListNew(16, sizeof(ZnMapInfoArcStruct));
}
arc_struct.style = NOT_MARKED_STYLE(line_style);
if (line_width == 1.0) {
arc_struct.width = 0;
}
else {
arc_struct.width = (int) line_width;
}
arc_struct.tag = tag;
arc_struct.center.x = center_x;
arc_struct.center.y = center_y;
arc_struct.radius = (int) radius;
arc_struct.start_angle = (int) start_angle;
arc_struct.extend = (int) extend;
ZnListAdd(cur_map->arcs, &arc_struct, index);
}
}
static void
ZnMapInfoReplaceArc(ZnMapInfoId map_info,
unsigned int index,
ZnPtr tag,
ZnMapInfoLineStyle line_style,
ZnDim line_width,
ZnPos center_x,
ZnPos center_y,
ZnDim radius,
ZnReal start_angle,
ZnReal extend)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoArc arc_ptr;
if (cur_map && cur_map->arcs) {
arc_ptr = ZnListAt(cur_map->arcs, index);
if (arc_ptr) {
arc_ptr->style = NOT_MARKED_STYLE(line_style);
if (line_width == 1.0) {
arc_ptr->width = 0;
}
else {
arc_ptr->width = (int) line_width;
}
arc_ptr->tag = tag;
arc_ptr->center.x = center_x;
arc_ptr->center.y = center_y;
arc_ptr->radius = (int) radius;
arc_ptr->start_angle = (int) start_angle;
arc_ptr->extend = (int) extend;
}
}
}
static void
ZnMapInfoRemoveArc(ZnMapInfoId map_info,
unsigned int index)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoArc arc_ptr;
if (cur_map && cur_map->arcs) {
arc_ptr = ZnListAt(cur_map->arcs, index);
if (arc_ptr) {
ZnListDelete(cur_map->arcs, index);
}
}
}
void
ZnMapInfoGetArc(ZnMapInfoId map_info,
unsigned int index,
ZnPtr *tag,
ZnMapInfoLineStyle *line_style,
ZnDim *line_width,
ZnPos *center_x,
ZnPos *center_y,
ZnDim *radius,
ZnReal *start_angle,
ZnReal *extend)
{
ZnMapInfo cur_map = map_info;
ZnMapInfoArc arc_ptr;
if (cur_map && cur_map->arcs) {
arc_ptr = 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.0) {
*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
ZnMapInfoNumArcs(ZnMapInfoId map_info)
{
ZnMapInfo cur_map = map_info;
if (cur_map && cur_map->arcs) {
return ZnListSize(cur_map->arcs);
}
else {
return 0;
}
}
static void
ZnMapInfoScale(ZnMapInfoId map_info,
ZnReal factor)
{
ZnMapInfo mp = map_info;
int i, num;
ZnMapInfoLine line_ptr;
ZnMapInfoSymbol sym_ptr;
ZnMapInfoText text_ptr;
ZnMapInfoArc arc_ptr;
if (mp && mp->lines) {
num = ZnListSize(mp->lines);
line_ptr = 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 = 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 = 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 = ZnListArray(mp->arcs);
for (i = 0; i < num; i++, arc_ptr++) {
arc_ptr->center.x *= factor;
arc_ptr->center.y *= factor;
arc_ptr->radius = (unsigned int) (arc_ptr->radius * factor);
}
}
}
static void
ZnMapInfoTranslate(ZnMapInfoId map_info,
ZnPos x,
ZnPos y)
{
ZnMapInfo mp = map_info;
int i, num;
ZnMapInfoLine line_ptr;
ZnMapInfoSymbol sym_ptr;
ZnMapInfoText text_ptr;
ZnMapInfoArc arc_ptr;
if (mp && mp->lines) {
num = ZnListSize(mp->lines);
line_ptr = 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 = 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 = 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 = 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((unsigned int) vm->id);
vm->dashed = ntohi((unsigned int) vm->dashed);
vm->expanded = ntohi((unsigned int) vm->expanded);
vm->marked = ntohi((unsigned int) vm->marked);
vm->color = ntohi((unsigned int) vm->color);
for (loop = 0; loop < 50; loop++) {
vm->elements[loop] = ntohi((unsigned int) vm->elements[loop]);
vm->x[loop] = ntohi((unsigned int) vm->x[loop]);
vm->y[loop] = ntohi((unsigned int) vm->y[loop]);
vm->symbol[loop] = ntohi((unsigned int) vm->symbol[loop]);
vm->text[loop] = ntohi((unsigned int) vm->text[loop]);
}
vm->num_elements = ntohi((unsigned int) vm->num_elements);
}
/*
*-----------------------------------------------------------------------
*
* FillMap - Fill map with data in Videomap record vm.
*
*-----------------------------------------------------------------------
*/
static void
FillMap(ZnMapInfoId map,
VideoMap *vm)
{
int i;
ZnBool has_start_pos = False;
ZnPos x_cur=0, y_cur=0;
char ch;
ZnPos 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;
ZnMapInfoAddText(map, ZnMapInfoNumTexts(map), NULL, ZnMapInfoNormalText,
ZnMapInfoLineSimple, 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]) {
ZnMapInfoAddSymbol(map, ZnMapInfoNumSymbols(map), NULL, x_cur, y_cur,
(char) 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;
ZnMapInfoAddText(map, ZnMapInfoNumTexts(map), NULL, ZnMapInfoNormalText,
ZnMapInfoLineSimple, text_x, text_y, text);
}
if (vm->dashed) {
ZnMapInfoAddLine(map, ZnMapInfoNumLines(map), NULL, ZnMapInfoLineDashed,
0, x_cur, y_cur,
(int) (short) vm->x[i], (int) (short) vm->y[i]);
}
else if (vm->marked) {
ZnMapInfoAddLine(map, ZnMapInfoNumLines(map), NULL, ZnMapInfoLineMarked,
0, x_cur, y_cur,
(int) (short) vm->x[i], (int) (short) vm->y[i]);
}
else {
ZnMapInfoAddLine(map, ZnMapInfoNumLines(map), NULL, ZnMapInfoLineSimple,
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]) {
ZnMapInfoAddSymbol(map, ZnMapInfoNumSymbols(map), NULL, x_cur, y_cur,
(char) 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;
ZnMapInfoAddText(map, ZnMapInfoNumTexts(map), NULL, ZnMapInfoNormalText,
ZnMapInfoLineSimple, text_x, text_y, text);
}
}
/*
*-----------------------------------------------------------------------
*
* ZnMapInfoGetVideomap - 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
ZnMapInfoGetVideomap(ZnMapInfoId map,
char *filename,
unsigned int index)
{
VideoMap current_vm;
Tcl_Channel chan;
unsigned int cur_index, cur_id;
/* Open the specified map file. */
chan = Tcl_OpenFileChannel(NULL, filename, "r", 0);
if (chan == NULL) {
return TCL_ERROR;
}
if (Tcl_SetChannelOption(NULL, chan,
"-translation", "binary") == TCL_ERROR) {
return TCL_ERROR;
}
/* Load the map */
/* First skip the leading maps up to index. */
cur_index = 0;
if (Tcl_Read(chan, (char *) ¤t_vm,
sizeof(VideoMap)) != sizeof(VideoMap)) {
goto error;
}
cur_id = ntohi((unsigned int) current_vm.id);
while (cur_index != index) {
if (Tcl_Read(chan, (char *) ¤t_vm,
sizeof(VideoMap)) != sizeof(VideoMap)) {
goto error;
}
if (cur_id != ntohi((unsigned int) current_vm.id)) {
cur_index++;
cur_id = ntohi((unsigned int) current_vm.id);
}
};
/* Then load all the map modules. */
do {
ReorderVidomap(¤t_vm);
FillMap(map, ¤t_vm);
if ((Tcl_Read(chan, (char *) ¤t_vm,
sizeof(VideoMap)) != sizeof(VideoMap)) &&
!Tcl_Eof(chan)) {
goto error;
}
}
while ((cur_id == ntohi((unsigned int) current_vm.id)) &&
!Tcl_Eof(chan));
Tcl_Close(NULL, chan);
return TCL_OK;
error:
Tcl_Close(NULL, chan);
return TCL_ERROR;
}
/*
*-----------------------------------------------------------------------
*
* ZnMapInfoVideomapIds - 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
ZnMapInfoVideomapIds(char *filename)
{
Tcl_Channel chan;
VideoMap current_vm;
unsigned int cur_id;
ZnList ids;
/* Open the specified map file. */
chan = Tcl_OpenFileChannel(NULL, filename, "r", 0);
if (chan == NULL) {
return NULL;
}
if (Tcl_SetChannelOption(NULL, chan,
"-translation", "binary") == TCL_ERROR) {
return NULL;
}
if (Tcl_Read(chan, (char *) ¤t_vm,
sizeof(VideoMap)) != sizeof(VideoMap)) {
error:
Tcl_Close(NULL, chan);
return NULL;
}
cur_id = ntohi((unsigned int) current_vm.id);
ids = ZnListNew(16, sizeof(int));
/*printf("id %d\n", cur_id);*/
ZnListAdd(ids, &cur_id, ZnListTail);
do {
if (Tcl_Read(chan, (char *) ¤t_vm,
sizeof(VideoMap)) != sizeof(VideoMap)) {
ZnListFree(ids);
goto error;
}
if (cur_id != ntohi((unsigned int) current_vm.id)) {
cur_id = ntohi((unsigned int) current_vm.id);
/*printf("id %d\n", cur_id);*/
ZnListAdd(ids, &cur_id, ZnListTail);
}
}
while (!Tcl_Eof(chan));
Tcl_Close(NULL, chan);
return ids;
}
/*
*--------------------------------------------------------------------------
*
* ZnMapInfo 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;
ZnMapInfoChangeProc proc;
} ZnMapInfoClient;
typedef struct {
ZnMapInfoId map_info;
ZnBool deleted;
ZnList clients;
} ZnMapInfoMaster;
static void
ZnMapInfoInit()
{
Tcl_InitHashTable(&mapInfoTable, TCL_ONE_WORD_KEYS);
map_info_inited = True;
}
static void
UpdateMapInfoClients(ZnMapInfoMaster *master)
{
int i, num;
ZnMapInfoClient *client;
num = ZnListSize(master->clients);
client = 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,
ZnMapInfoId *map_info)
{
Tk_Uid uid = Tk_GetUid(name);
Tcl_HashEntry *entry;
int new;
ZnMapInfoMaster *master;
if (!map_info_inited) {
ZnMapInfoInit();
}
entry = Tcl_CreateHashEntry(&mapInfoTable, uid, &new);
if (!new) {
/*
* Empty the map info if it is not.
*/
master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
if (master->deleted) {
master->deleted = False;
}
else {
ZnMapInfoEmpty(master->map_info);
UpdateMapInfoClients(master);
}
}
else {
master = (ZnMapInfoMaster *) ZnMalloc(sizeof(ZnMapInfoMaster));
master->map_info = ZnMapInfoCreate(name);
master->deleted = False;
master->clients = ZnListNew(1, sizeof(ZnMapInfoClient));
Tcl_SetHashValue(entry, master);
}
if (map_info) {
*map_info = master->map_info;
}
return TCL_OK;
}
static int
ZnDuplicateZnMapInfo(Tcl_Interp *interp,
char *name,
ZnMapInfoId map_info)
{
Tk_Uid uid = Tk_GetUid(name);
Tcl_HashEntry *entry;
int new;
ZnMapInfoMaster *master;
if (!map_info_inited) {
ZnMapInfoInit();
}
entry = Tcl_CreateHashEntry(&mapInfoTable, uid, &new);
if (!new) {
Tcl_AppendResult(interp, "duplicate mapinfo \"", name, "\" already exists", NULL);
return TCL_ERROR;
}
master = (ZnMapInfoMaster *) ZnMalloc(sizeof(ZnMapInfoMaster));
master->map_info = ZnMapInfoDuplicate(map_info);
master->deleted = False;
master->clients = ZnListNew(1, sizeof(ZnMapInfoClient));
Tcl_SetHashValue(entry, master);
return TCL_OK;
}
static ZnMapInfoMaster *
LookupMapInfoMaster(Tcl_Interp *interp,
char *name)
{
Tk_Uid uid = Tk_GetUid(name);
Tcl_HashEntry *entry;
ZnMapInfoMaster *master;
if (!map_info_inited) {
ZnMapInfoInit();
}
entry = Tcl_FindHashEntry(&mapInfoTable, uid);
if (entry == NULL) {
mp_error:
Tcl_AppendResult(interp, "mapinfo \"", name, "\" doesn't exist", NULL);
return NULL;
}
master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
if (master->deleted) {
goto mp_error;
}
return master;
}
static int
ZnDeleteMapInfo(Tcl_Interp *interp,
char *name)
{
ZnMapInfoMaster *master;
Tk_Uid uid = Tk_GetUid(name);
Tcl_HashEntry *entry;
if (!map_info_inited) {
ZnMapInfoInit();
}
entry = Tcl_FindHashEntry(&mapInfoTable, uid);
if (entry == NULL) {
return TCL_ERROR;
}
master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
if (ZnListSize(master->clients) != 0) {
master->deleted = True;
ZnMapInfoEmpty(master->map_info);
UpdateMapInfoClients(master);
}
else {
ZnMapInfoDelete(master->map_info);
ZnListFree(master->clients);
Tcl_DeleteHashEntry(entry);
ZnFree(master);
}
return TCL_OK;
}
ZnMapInfoId
ZnGetMapInfo(Tcl_Interp *interp,
char *name,
ZnMapInfoChangeProc proc,
ClientData client_data)
{
ZnMapInfoMaster *master;
ZnMapInfoClient 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(ZnMapInfoId map_info,
ZnMapInfoChangeProc proc,
ClientData client_data)
{
Tk_Uid uid = Tk_GetUid(ZnMapInfoName(map_info));
Tcl_HashEntry *entry;
ZnMapInfoMaster *master;
ZnMapInfoClient *client;
unsigned int num, i;
if (!map_info_inited) {
ZnMapInfoInit();
}
entry = Tcl_FindHashEntry(&mapInfoTable, uid);
if (entry == NULL) {
return;
}
master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
client = 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(ZnMapInfoId map_info)
{
Tk_Uid uid = Tk_GetUid(ZnMapInfoName(map_info));
Tcl_HashEntry *entry;
ZnMapInfoMaster *master;
if (!map_info_inited) {
ZnMapInfoInit();
}
entry = Tcl_FindHashEntry(&mapInfoTable, uid);
if (entry == NULL) {
return;
}
master = (ZnMapInfoMaster *) Tcl_GetHashValue(entry);
UpdateMapInfoClients(master);
}
/*
* These arrays must be kept in sync with the ZnMapInfoLineStyle
* and ZnMapInfoTextStyle enums.
*/
static char *line_style_strings[] = {
"simple",
"dashed",
"dotted",
"mixed",
"marked",
};
static char *text_style_strings[] = {
"normal",
"underlined"
};
static char *
ZnMapInfoLineStyleToString(ZnMapInfoLineStyle line_style)
{
return line_style_strings[line_style];
}
static int
ZnMapInfoLineStyleFromString(Tcl_Interp *interp,
char *str,
ZnMapInfoLineStyle *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 TCL_ERROR;
}
static char *
ZnMapInfoTextStyleToString(ZnMapInfoTextStyle text_style)
{
return text_style_strings[text_style];
}
static int
ZnMapInfoTextStyleFromString(Tcl_Interp *interp,
char *str,
ZnMapInfoTextStyle *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 TCL_ERROR;
}
int
ZnMapInfoObjCmd(ClientData client_data,
Tcl_Interp *interp, /* Current interpreter. */
int argc, /* Number of arguments. */
Tcl_Obj *CONST args[])
{
ZnPos x, y;
int index, index2, result;
ZnMapInfoMaster *master;
Tcl_Obj *l;
#ifdef PTK_800
static char *sub_cmd_strings[] =
#else
static CONST char *sub_cmd_strings[] =
#endif
{
"add", "count", "create", "delete", "duplicate",
"get", "remove", "replace", "scale", "translate", NULL
};
#ifdef PTK_800
static char *e_type_strings[] =
#else
static CONST char *e_type_strings[] =
#endif
{
"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 TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, args[2], sub_cmd_strings,
"subCmd", 0, &index) != TCL_OK) {
return TCL_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 TCL_ERROR;
}
if (ZnCreateMapInfo(interp, Tcl_GetString(args[1]), NULL) == TCL_ERROR) {
return TCL_ERROR;
}
}
break;
/*
* delete
*/
case ZN_MI_DELETE:
{
if (argc != 3) {
Tcl_WrongNumArgs(interp, 1, args, "mapInfo delete");
return TCL_ERROR;
}
if (ZnDeleteMapInfo(interp, Tcl_GetString(args[1])) == TCL_ERROR) {
return TCL_ERROR;
}
}
break;
/*
* duplicate
*/
case ZN_MI_DUPLICATE:
{
if (argc != 4) {
Tcl_WrongNumArgs(interp, 1, args, "mapInfo duplicate name");
return TCL_ERROR;
}
master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
if (master == NULL) {
return TCL_ERROR;
}
if (ZnDuplicateZnMapInfo(interp, Tcl_GetString(args[3]),
master->map_info) == TCL_ERROR) {
return TCL_ERROR;
}
}
break;
/*
* add/replace
*/
case ZN_MI_ADD:
case ZN_MI_REPLACE:
{
ZnMapInfoLineStyle line_style;
ZnMapInfoTextStyle text_style;
int i, insert, val;
ZnPos 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 TCL_ERROR;
}
master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
if (master == NULL) {
return TCL_ERROR;
}
if (!add_cmd) {
if (Tcl_GetIntFromObj(interp, args[4], &insert) == TCL_ERROR) {
return TCL_ERROR;
}
}
if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
"elementType", 0, &index2) != TCL_OK) {
return TCL_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 TCL_ERROR;
}
if (ZnMapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param]),
&line_style) == TCL_ERROR) {
return TCL_ERROR;
}
for (i = 0; i < 5; i++) {
if (Tcl_GetDoubleFromObj(interp, args[num_param+i+1], &coords[i]) == TCL_ERROR) {
return TCL_ERROR;
}
}
if (coords[0] < 0) {
coords[0] = 0;
}
if (add_cmd) {
ZnMapInfoAddLine(master->map_info, ZnListTail, NULL, line_style,
coords[0], coords[1], coords[2], coords[3], coords[4]);
}
else {
ZnMapInfoReplaceLine(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 TCL_ERROR;
}
for (i = 0; i < 2; i++) {
if (Tcl_GetDoubleFromObj(interp, args[num_param+i], &coords[i]) == TCL_ERROR) {
return TCL_ERROR;
}
}
if (Tcl_GetIntFromObj(interp, args[num_param+2], &val) == TCL_ERROR) {
return TCL_ERROR;
}
if (val < 0) {
val = 0;
}
if (add_cmd) {
ZnMapInfoAddSymbol(master->map_info, ZnListTail, NULL, coords[0],
coords[1], (char) val);
}
else {
ZnMapInfoReplaceSymbol(master->map_info, insert, NULL, coords[0],
coords[1], (char) val);
}
}
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 TCL_ERROR;
}
if (ZnMapInfoTextStyleFromString(interp, Tcl_GetString(args[num_param]),
&text_style) == TCL_ERROR) {
return TCL_ERROR;
}
if (ZnMapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param+1]),
&line_style) == TCL_ERROR) {
return TCL_ERROR;
}
for (i = 0; i < 2; i++) {
if (Tcl_GetDoubleFromObj(interp, args[num_param+i+2], &coords[i]) == TCL_ERROR) {
return TCL_ERROR;
}
}
if (add_cmd) {
ZnMapInfoAddText(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 %g %g %s\n", text_style,
line_style, coords[0], coords[1], Tcl_GetString(args[num_param+4]));*/
ZnMapInfoReplaceText(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 TCL_ERROR;
}
if (ZnMapInfoLineStyleFromString(interp, Tcl_GetString(args[num_param]),
&line_style) == TCL_ERROR) {
return TCL_ERROR;
}
for (i = 0; i < 6; i++) {
if (Tcl_GetDoubleFromObj(interp, args[num_param+i+1], &coords[i]) == TCL_ERROR) {
return TCL_ERROR;
}
}
if (coords[0] < 0) {
coords[0] = 0;
}
if (coords[3] < 0) {
coords[3] = 0;
}
if (add_cmd) {
ZnMapInfoAddArc(master->map_info, ZnListTail, NULL, line_style, coords[0],
coords[1], coords[2], coords[3], coords[4], coords[5]);
}
else {
ZnMapInfoReplaceArc(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 TCL_ERROR;
}
master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
if (master == NULL) {
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
"elementType", 0, &index2) != TCL_OK) {
return TCL_ERROR;
}
switch ((enum e_types) index2) {
case ZN_E_LINE:
count = ZnMapInfoNumLines(master->map_info);
break;
case ZN_E_SYMBOL:
count = ZnMapInfoNumSymbols(master->map_info);
break;
case ZN_E_TEXT:
count = ZnMapInfoNumTexts(master->map_info);
break;
case ZN_E_ARC:
count = ZnMapInfoNumArcs(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 TCL_ERROR;
}
master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
if (master == NULL) {
return TCL_ERROR;
}
if (Tcl_GetIntFromObj(interp, args[4], &insert) == TCL_ERROR) {
return TCL_ERROR;
}
if (insert < 0) {
insert = 0;
}
if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
"elementType", 0, &index2) != TCL_OK) {
return TCL_ERROR;
}
switch ((enum e_types) index2) {
case ZN_E_LINE:
{
ZnMapInfoLineStyle line_style;
ZnDim line_width;
ZnPos x_to, y_to;
ZnMapInfoGetLine(master->map_info, insert, NULL, &line_style,
&line_width, &x, &y, &x_to, &y_to);
l = Tcl_GetObjResult(interp);
Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(ZnMapInfoLineStyleToString(line_style), -1));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(line_width));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x_to));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y_to));
}
break;
case ZN_E_SYMBOL:
{
char symbol;
ZnMapInfoGetSymbol(master->map_info, insert, NULL, &x, &y, &symbol);
l = Tcl_GetObjResult(interp);
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y));
Tcl_ListObjAppendElement(interp, l, Tcl_NewIntObj(symbol));
}
break;
case ZN_E_TEXT:
{
char *text;
ZnMapInfoTextStyle text_style;
ZnMapInfoLineStyle line_style;
ZnMapInfoGetText(master->map_info, insert, NULL, &text_style, &line_style,
&x, &y, &text);
l = Tcl_GetObjResult(interp);
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y));
Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(ZnMapInfoTextStyleToString(text_style), -1));
Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(ZnMapInfoLineStyleToString(line_style), -1));
Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(text, -1));
}
break;
case ZN_E_ARC:
{
ZnMapInfoLineStyle line_style;
ZnDim line_width, radius;
ZnPos start, extent;
ZnMapInfoGetArc(master->map_info, insert, NULL, &line_style, &line_width,
&x, &y, &radius, &start, &extent);
l = Tcl_GetObjResult(interp);
Tcl_ListObjAppendElement(interp, l, Tcl_NewStringObj(ZnMapInfoLineStyleToString(line_style), -1));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(line_width));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(x));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(y));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(radius));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(start));
Tcl_ListObjAppendElement(interp, l, Tcl_NewDoubleObj(extent));
}
break;
}
}
break;
/*
* remove
*/
case ZN_MI_REMOVE:
{
int insert;
if (argc != 5) {
Tcl_WrongNumArgs(interp, 1, args, "mapInfo remove type index");
return TCL_ERROR;
}
master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
if (master == NULL) {
return TCL_ERROR;
}
if (Tcl_GetIntFromObj(interp, args[4], &insert) == TCL_ERROR) {
return TCL_ERROR;
}
if (insert < 0) {
insert = 0;
}
if (Tcl_GetIndexFromObj(interp, args[3], e_type_strings,
"elementType", 0, &index2) != TCL_OK) {
return TCL_ERROR;
}
switch ((enum e_types) index2) {
case ZN_E_LINE:
ZnMapInfoRemoveLine(master->map_info, insert);
break;
case ZN_E_SYMBOL:
ZnMapInfoRemoveSymbol(master->map_info, insert);
break;
case ZN_E_TEXT:
ZnMapInfoRemoveText(master->map_info, insert);
break;
case ZN_E_ARC:
ZnMapInfoRemoveArc(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 TCL_ERROR;
}
master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
if (master == NULL) {
return TCL_ERROR;
}
if (Tcl_GetDoubleFromObj(interp, args[3], &factor) == TCL_ERROR) {
return TCL_ERROR;
}
ZnMapInfoScale(master->map_info, factor);
UpdateMapInfoClients(master);
}
break;
/*
* translate
*/
case ZN_MI_TRANSLATE:
{
if (argc != 5) {
Tcl_WrongNumArgs(interp, 1, args, "mapInfo translate xAmount yAmount");
return TCL_ERROR;
}
master = LookupMapInfoMaster(interp, Tcl_GetString(args[1]));
if (master == NULL) {
return TCL_ERROR;
}
if (Tcl_GetDoubleFromObj(interp, args[3], &x) == TCL_ERROR) {
return TCL_ERROR;
}
if (Tcl_GetDoubleFromObj(interp, args[4], &y) == TCL_ERROR) {
return TCL_ERROR;
}
ZnMapInfoTranslate(master->map_info, x, y);
UpdateMapInfoClients(master);
}
break;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* VideomapObjCmd --
*
*
*----------------------------------------------------------------------
*/
int
ZnVideomapObjCmd(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;
#ifdef PTK_800
static char *sub_cmd_strings[] =
#else
static CONST char *sub_cmd_strings[] =
#endif
{
"ids", "load", NULL
};
enum sub_cmds {
ZN_V_IDS, ZN_V_LOAD
};
if (argc < 2) {
Tcl_WrongNumArgs(interp, 1, args, "?subCmd? filename $args?");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, args[1], sub_cmd_strings,
"subCmd", 0, &index) != TCL_OK) {
return TCL_ERROR;
}
switch((enum sub_cmds) index) {
/*
* ids
*/
case ZN_V_IDS:
{
if (argc != 3) {
Tcl_WrongNumArgs(interp, 1, args,"ids filename");
return TCL_ERROR;
}
ids = ZnMapInfoVideomapIds(Tcl_GetString(args[2]));
if (ids == NULL) {
Tcl_AppendResult(interp, "unable to look at videomap file \"",
Tcl_GetString(args[2]), "\"", NULL);
return TCL_ERROR;
}
id_array = 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:
{
ZnMapInfoId map_info;
int insert;
if (argc != 5) {
Tcl_WrongNumArgs(interp, 1, args, "load filename index mapInfo");
return TCL_ERROR;
}
if (Tcl_GetIntFromObj(interp, args[3], &insert) == TCL_ERROR) {
return TCL_ERROR;
}
if (insert < 0) {
insert = 0;
}
if (ZnCreateMapInfo(interp, Tcl_GetString(args[4]), &map_info) == TCL_ERROR) {
return TCL_ERROR;
}
if (ZnMapInfoGetVideomap(map_info, Tcl_GetString(args[2]), insert) == TCL_ERROR) {
Tcl_AppendResult(interp, "unable to load videomap file \"",
Tcl_GetString(args[2]), ":",
Tcl_GetString(args[3]), "\"", NULL);
return TCL_ERROR;
}
ZnUpdateMapInfoClients(map_info);
}
break;
}
return TCL_OK;
}