作図ソフト dia の改良版
Revisão | 65c5b65f088f639bcb8c2a7314c4f8d3efffc2c5 (tree) |
---|---|
Hora | 2004-04-02 21:43:43 |
Autor | Lars Clausen <lclausen@src....> |
Commiter | Lars Clausen |
Arrow persistence, xfig fixes, abs dirs.
@@ -1,4 +1,29 @@ | ||
1 | -2004-04-01 Lars Clausen <lc@pc770.sb.statsbiblioteket.dk> | |
1 | +2004-04-02 Lars Clausen <lc@pc770.sb.statsbiblioteket.dk> | |
2 | + | |
3 | + * app/recent_files.c: Use absolute name for recent files list. | |
4 | + | |
5 | + * lib/attributes.c: Set start and end arrow types, correctly. | |
6 | + | |
7 | + * lib/widgets.c (dia_arrow_selector_set_arrow): Use new function | |
8 | + to get arrow index. | |
9 | + | |
10 | + * lib/diaarrowchooser.[ch]: Support for setting arrow info. | |
11 | + | |
12 | + * app/interface.c (create_lineprops_area): Set persistently stored | |
13 | + arrow info. | |
14 | + | |
15 | + * lib/arrows.[ch]: New function to get arrow index (in arrow_types) | |
16 | + from arrow type. | |
17 | + | |
18 | + * lib/dia_dirs.c: dia_get_absolute_path now creates a canonical | |
19 | + path (i.e. without '.' or '..'). Not tuned for Win32 yet. | |
20 | + | |
21 | + * plug-ins/xfig/xfig-import.c: Redone ordering of import to comply | |
22 | + with what xfig does. Text now converted from latin-1 to utf-8 | |
23 | + (latin-1, since that's what xfig seems to use. Would like to see | |
24 | + examples of non-latin-1 figs). String case problems fixed. | |
25 | + | |
26 | +2004-04-01 Lars Clausen <lars@raeder.dk> | |
2 | 27 | |
3 | 28 | * lib/attributes.c: |
4 | 29 | * app/interface.c: Default arrows now stored persistently, too. |
@@ -1117,7 +1117,7 @@ create_lineprops_area(GtkWidget *parent) | ||
1117 | 1117 | arrow.width = persistence_register_real("start-arrow-width", DEFAULT_ARROW_WIDTH); |
1118 | 1118 | arrow.length = persistence_register_real("start-arrow-length", DEFAULT_ARROW_LENGTH); |
1119 | 1119 | arrow.type = arrow_type_from_name(persistence_register_string("start-arrow-type", "None")); |
1120 | - dia_arrow_chooser_set_arrow_type(DIA_ARROW_CHOOSER(chooser), arrow.type); | |
1120 | + dia_arrow_chooser_set_arrow(DIA_ARROW_CHOOSER(chooser), &arrow); | |
1121 | 1121 | attributes_set_default_start_arrow(arrow); |
1122 | 1122 | gtk_tooltips_set_tip(tool_tips, chooser, _("Arrow style at the beginning of new lines. Click to pick an arrow, or set arrow parameters with Details..."), NULL); |
1123 | 1123 | gtk_widget_show(chooser); |
@@ -1131,7 +1131,7 @@ create_lineprops_area(GtkWidget *parent) | ||
1131 | 1131 | arrow.width = persistence_register_real("end-arrow-width", DEFAULT_ARROW_WIDTH); |
1132 | 1132 | arrow.length = persistence_register_real("end-arrow-length", DEFAULT_ARROW_LENGTH); |
1133 | 1133 | arrow.type = arrow_type_from_name(persistence_register_string("end-arrow-type", "Filled Concave")); |
1134 | - dia_arrow_chooser_set_arrow_type(DIA_ARROW_CHOOSER(chooser), arrow.type); | |
1134 | + dia_arrow_chooser_set_arrow(DIA_ARROW_CHOOSER(chooser), &arrow); | |
1135 | 1135 | attributes_set_default_end_arrow(arrow); |
1136 | 1136 | |
1137 | 1137 | gtk_wrap_box_pack(GTK_WRAP_BOX(parent), chooser, FALSE, TRUE, FALSE, TRUE); |
@@ -167,8 +167,10 @@ recent_file_history_make_menu() | ||
167 | 167 | void |
168 | 168 | recent_file_history_add(const char *fname) |
169 | 169 | { |
170 | + gchar *absname = dia_get_absolute_filename(fname); | |
170 | 171 | recent_file_history_clear_menu(); |
171 | - persistent_list_add("recent-files", fname); | |
172 | + persistent_list_add("recent-files", absname); | |
173 | + g_free(absname); | |
172 | 174 | |
173 | 175 | recent_file_history_make_menu(); |
174 | 176 | } |
@@ -193,9 +195,11 @@ recent_file_history_init() { | ||
193 | 195 | void |
194 | 196 | recent_file_history_remove (const char *fname) |
195 | 197 | { |
198 | + gchar *absname = dia_get_absolute_filename(fname); | |
196 | 199 | recent_file_history_clear_menu(); |
197 | 200 | |
198 | - persistent_list_remove("recent-files", fname); | |
201 | + persistent_list_remove("recent-files", absname); | |
202 | + g_free(absname); | |
199 | 203 | |
200 | 204 | recent_file_history_make_menu(); |
201 | 205 | } |
@@ -1407,8 +1407,24 @@ arrow_type_from_name(gchar *name) | ||
1407 | 1407 | { |
1408 | 1408 | int i; |
1409 | 1409 | for (i = 0; arrow_types[i].name != NULL; i++) { |
1410 | - if (!strcmp(arrow_types[i].name, name)) return arrow_types[i].enum_value; | |
1410 | + if (!strcmp(arrow_types[i].name, name)) { | |
1411 | + return arrow_types[i].enum_value; | |
1412 | + } | |
1411 | 1413 | } |
1412 | 1414 | printf("Unknown arrow type %s\n", name); |
1413 | 1415 | return 0; |
1414 | 1416 | } |
1417 | + | |
1418 | +gint | |
1419 | +arrow_index_from_type(ArrowType atype) | |
1420 | +{ | |
1421 | + int i = 0; | |
1422 | + | |
1423 | + for (i = 0; arrow_types[i].name != NULL; i++) { | |
1424 | + if (arrow_types[i].enum_value == atype) { | |
1425 | + return i; | |
1426 | + } | |
1427 | + } | |
1428 | + printf("Can't find arrow index for type %d\n", atype); | |
1429 | + return 0; | |
1430 | +} |
@@ -65,7 +65,7 @@ typedef enum { | ||
65 | 65 | |
66 | 66 | struct menudesc { |
67 | 67 | char *name; |
68 | - int enum_value; | |
68 | + ArrowType enum_value; | |
69 | 69 | }; |
70 | 70 | |
71 | 71 | /** The number of centimeters long and wide an arrow starts with by default. |
@@ -103,5 +103,7 @@ void arrow_transform_points(Arrow *arrow, Point *start, Point *to, | ||
103 | 103 | |
104 | 104 | /** Returns the ArrowType for a given name of an arrow, or 0 if not found. */ |
105 | 105 | ArrowType arrow_type_from_name(gchar *name); |
106 | +/** Returns the index in arrow_types of the given arrow type. */ | |
107 | +gint arrow_index_from_type(ArrowType type); | |
106 | 108 | |
107 | 109 | #endif /* ARROWS_H */ |
@@ -101,7 +101,8 @@ void | ||
101 | 101 | attributes_set_default_start_arrow(Arrow arrow) |
102 | 102 | { |
103 | 103 | attributes_start_arrow = arrow; |
104 | - persistence_set_string("start-arrow-type", arrow_types[arrow.type].name); | |
104 | + persistence_set_string("start-arrow-type", | |
105 | + arrow_types[arrow_index_from_type(arrow.type)].name); | |
105 | 106 | persistence_set_real("start-arrow-width", arrow.width); |
106 | 107 | persistence_set_real("start-arrow-length", arrow.length); |
107 | 108 | } |
@@ -115,6 +116,10 @@ void | ||
115 | 116 | attributes_set_default_end_arrow(Arrow arrow) |
116 | 117 | { |
117 | 118 | attributes_end_arrow = arrow; |
119 | + persistence_set_string("end-arrow-type", | |
120 | + arrow_types[arrow_index_from_type(arrow.type)].name); | |
121 | + persistence_set_real("end-arrow-width", arrow.width); | |
122 | + persistence_set_real("end-arrow-length", arrow.length); | |
118 | 123 | } |
119 | 124 | |
120 | 125 | void |
@@ -126,6 +126,54 @@ dia_config_ensure_dir(const gchar *filename) | ||
126 | 126 | return exists; |
127 | 127 | } |
128 | 128 | |
129 | +/** Remove all instances of . and .. from an absolute path. | |
130 | + * This is not a cheap function. | |
131 | + * Returns a newly allocated string, or NULL if too many ..'s were found */ | |
132 | +static gchar * | |
133 | +dia_get_canonical_path (gchar *path) { | |
134 | + if (g_str_has_suffix(path, "/..")) { | |
135 | + gchar *prev = g_path_get_dirname(path); | |
136 | + path = prev; | |
137 | + prev = dia_get_canonical_path(path); | |
138 | + g_free(path); | |
139 | + if (prev == NULL) return NULL; | |
140 | + path = prev; | |
141 | + /* Snip! */ | |
142 | + prev = g_path_get_dirname(prev); | |
143 | + if (!strcmp(path, prev)) { | |
144 | + /* .. ran over / */ | |
145 | + return NULL; | |
146 | + } | |
147 | + g_free(path); | |
148 | + return prev; | |
149 | + } else if (g_str_has_suffix(path, "/.")) { | |
150 | + gchar *prev = g_path_get_dirname(path); | |
151 | + path = prev; | |
152 | + prev = dia_get_canonical_path(path); | |
153 | + g_free(path); | |
154 | + return prev; | |
155 | + } else { | |
156 | + gchar *end = g_path_get_basename(path); | |
157 | + gchar *prev = g_path_get_dirname(path); | |
158 | + gchar *tmp; | |
159 | + if (strcmp(path, prev)) { /* Something got removed */ | |
160 | + tmp = prev; | |
161 | + prev = dia_get_canonical_path(tmp); | |
162 | + if (prev == NULL) return NULL; | |
163 | + g_free(tmp); | |
164 | + tmp = prev; | |
165 | + prev = g_build_filename(tmp, end, NULL); | |
166 | + g_free(tmp); | |
167 | + g_free(end); | |
168 | + return prev; | |
169 | + } else { | |
170 | + g_free(end); | |
171 | + g_free(prev); | |
172 | + return g_strdup(path); | |
173 | + } | |
174 | + } | |
175 | +} | |
176 | + | |
129 | 177 | /** Return an absolute filename from an absolute or relative filename. |
130 | 178 | * The value returned is newly allocated. |
131 | 179 | */ |
@@ -134,10 +182,18 @@ dia_get_absolute_filename (const gchar *filename) | ||
134 | 182 | { |
135 | 183 | gchar *current_dir; |
136 | 184 | gchar *fullname; |
185 | + gchar *canonical; | |
137 | 186 | if (filename == NULL) return NULL; |
138 | 187 | if (g_path_is_absolute(filename)) return g_strdup(filename); |
139 | 188 | current_dir = g_get_current_dir(); |
140 | 189 | fullname = g_build_filename(current_dir, filename, NULL); |
141 | 190 | g_free(current_dir); |
142 | - return fullname; | |
191 | + if (strchr(fullname, '.') == NULL) return fullname; | |
192 | + canonical = dia_get_canonical_path(fullname); | |
193 | + if (canonical == NULL) { | |
194 | + message_warning("Too many ..'s in filename %s\n", filename); | |
195 | + return filename; | |
196 | + } | |
197 | + free(fullname); | |
198 | + return canonical; | |
143 | 199 | } |
@@ -363,25 +363,31 @@ dia_arrow_chooser_dialog_destroy (DiaArrowChooser *chooser) | ||
363 | 363 | } |
364 | 364 | |
365 | 365 | static void |
366 | -dia_arrow_chooser_change_arrow_type(GtkMenuItem *mi, DiaArrowChooser *arrow) | |
366 | +dia_arrow_chooser_change_arrow_type(GtkMenuItem *mi, DiaArrowChooser *chooser) | |
367 | 367 | { |
368 | 368 | ArrowType atype = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(mi), |
369 | 369 | menuitem_enum_key)); |
370 | - dia_arrow_chooser_set_arrow_type(arrow, atype); | |
370 | + Arrow arrow; | |
371 | + arrow.width = chooser->arrow.width; | |
372 | + arrow.length = chooser->arrow.length; | |
373 | + arrow.type = atype; | |
374 | + dia_arrow_chooser_set_arrow(chooser, &arrow); | |
371 | 375 | } |
372 | 376 | |
373 | 377 | /** Set the type of arrow shown by the arrow chooser. |
374 | 378 | */ |
375 | 379 | void |
376 | -dia_arrow_chooser_set_arrow_type(DiaArrowChooser *arrow, ArrowType atype) { | |
377 | - if (arrow->arrow.type != atype) { | |
378 | - dia_arrow_preview_set(arrow->preview, atype, arrow->left); | |
379 | - arrow->arrow.type = atype; | |
380 | - if (arrow->dialog != NULL) | |
381 | - dia_arrow_selector_set_arrow(arrow->selector, arrow->arrow); | |
382 | - if (arrow->callback) | |
383 | - (* arrow->callback)(arrow->arrow, arrow->user_data); | |
380 | +dia_arrow_chooser_set_arrow(DiaArrowChooser *chooser, Arrow *arrow) { | |
381 | + if (chooser->arrow.type != arrow->type) { | |
382 | + dia_arrow_preview_set(chooser->preview, arrow->type, chooser->left); | |
383 | + chooser->arrow.type = arrow->type; | |
384 | + if (chooser->dialog != NULL) | |
385 | + dia_arrow_selector_set_arrow(chooser->selector, chooser->arrow); | |
386 | + if (chooser->callback) | |
387 | + (* chooser->callback)(chooser->arrow, chooser->user_data); | |
384 | 388 | } |
389 | + chooser->arrow.width = arrow->width; | |
390 | + chooser->arrow.length = arrow->length; | |
385 | 391 | } |
386 | 392 | |
387 | 393 | ArrowType dia_arrow_chooser_get_arrow_type(DiaArrowChooser *arrow) { |
@@ -85,7 +85,7 @@ struct _DiaArrowChooserClass | ||
85 | 85 | GtkWidget *dia_arrow_chooser_new (gboolean left, |
86 | 86 | DiaChangeArrowCallback callback, |
87 | 87 | gpointer user_data, GtkTooltips *tool_tips); |
88 | -void dia_arrow_chooser_set_arrow_type(DiaArrowChooser *arrow, ArrowType atype); | |
89 | -ArrowType dia_arrow_chooser_get_arrow_type(DiaArrowChooser *arrow); | |
88 | +void dia_arrow_chooser_set_arrow(DiaArrowChooser *chooser, Arrow *arrow); | |
89 | +ArrowType dia_arrow_chooser_get_arrow_type(DiaArrowChooser *chooser); | |
90 | 90 | |
91 | 91 | #endif |
@@ -750,7 +750,6 @@ persistent_list_add(const gchar *role, const gchar *item) | ||
750 | 750 | PersistentList *plist = persistent_list_get(role); |
751 | 751 | if(plist == NULL) printf("Can't find list for %s when adding %s\n", |
752 | 752 | role, item); |
753 | - printf("Adding item %s to %s, first is %s\n", item, role, (plist->glist!=NULL?plist->glist->data:"")); | |
754 | 753 | if (plist->sorted) { |
755 | 754 | /* Sorting not implemented yet. */ |
756 | 755 | } else { |
@@ -1402,16 +1402,8 @@ void | ||
1402 | 1402 | dia_arrow_selector_set_arrow (DiaArrowSelector *as, |
1403 | 1403 | Arrow arrow) |
1404 | 1404 | { |
1405 | - int arrow_type_index = 0,i = 0; | |
1406 | - const struct menudesc *md = arrow_types; | |
1407 | - | |
1408 | - while (md->name) { | |
1409 | - if (md->enum_value == arrow.type) { | |
1410 | - arrow_type_index = i; | |
1411 | - break; | |
1412 | - } | |
1413 | - md++; i++; | |
1414 | - } | |
1405 | + int arrow_type_index = arrow_index_from_type(arrow.type); | |
1406 | + | |
1415 | 1407 | gtk_menu_set_active(GTK_MENU (as->arrow_type_menu), arrow_type_index); |
1416 | 1408 | gtk_option_menu_set_history (GTK_OPTION_MENU(as->omenu), arrow_type_index); |
1417 | 1409 | /* TODO: restore CheckMenu version of menu */ |
@@ -622,16 +622,20 @@ fig_read_arrow(FILE *file) { | ||
622 | 622 | return arrow; |
623 | 623 | } |
624 | 624 | |
625 | -static void | |
626 | -fig_fix_text(char *text) { | |
625 | +static gchar * | |
626 | +fig_fix_text(gchar *text) { | |
627 | 627 | int i, j; |
628 | 628 | int asciival; |
629 | + GError *err = NULL; | |
630 | + gchar *converted; | |
631 | + gboolean needs_conversion = FALSE; | |
629 | 632 | |
630 | 633 | for (i = 0, j = 0; text[i] != 0; i++, j++) { |
631 | 634 | if (text[i] == '\\') { |
632 | 635 | sscanf(text+i+1, "%3o", &asciival); |
633 | 636 | text[j] = asciival; |
634 | 637 | i+=3; |
638 | + needs_conversion = TRUE; | |
635 | 639 | } else { |
636 | 640 | text[j] = text[i]; |
637 | 641 | } |
@@ -641,6 +645,21 @@ fig_fix_text(char *text) { | ||
641 | 645 | if (text[j-2] == '\001') { |
642 | 646 | text[j-2] = 0; |
643 | 647 | } |
648 | + if (needs_conversion) { | |
649 | + /* Crudely assuming that fig uses Latin-1 */ | |
650 | + converted = g_convert(text, strlen(text), "UTF-8", "ISO-8859-1", | |
651 | + NULL, NULL, &err); | |
652 | + if (err != NULL) { | |
653 | + printf("Error converting %s: %s\n", text, err->message); | |
654 | + return text; | |
655 | + } | |
656 | + if (!g_utf8_validate(converted, -1, NULL)) { | |
657 | + printf("Fails to validate %s\n", converted); | |
658 | + return text; | |
659 | + } | |
660 | + if (text != converted) g_free(text); | |
661 | + return converted; | |
662 | + } else return text; | |
644 | 663 | } |
645 | 664 | |
646 | 665 | static char * |
@@ -659,7 +678,7 @@ fig_read_text_line(FILE *file) { | ||
659 | 678 | text_buf = (char *)g_realloc(text_buf, text_alloc*sizeof(char)); |
660 | 679 | } |
661 | 680 | |
662 | - fig_fix_text(text_buf); | |
681 | + text_buf = fig_fix_text(text_buf); | |
663 | 682 | |
664 | 683 | return text_buf; |
665 | 684 | } |
@@ -1379,8 +1398,9 @@ fig_read_line_choice(FILE *file, char *choice1, char *choice2) { | ||
1379 | 1398 | } |
1380 | 1399 | |
1381 | 1400 | buf[strlen(buf)-1] = 0; /* Remove trailing newline */ |
1382 | - if (!strcmp(buf, choice1)) return 0; | |
1383 | - if (!strcmp(buf, choice2)) return 1; | |
1401 | + g_strstrip(buf); /* And any other whitespace */ | |
1402 | + if (!g_strcasecmp(buf, choice1)) return 0; | |
1403 | + if (!g_strcasecmp(buf, choice2)) return 1; | |
1384 | 1404 | message_warning(_("`%s' is not one of `%s' or `%s'\n"), buf, choice1, choice2); |
1385 | 1405 | return 0; |
1386 | 1406 | } |
@@ -1396,6 +1416,7 @@ fig_read_paper_size(FILE *file, DiagramData *dia) { | ||
1396 | 1416 | } |
1397 | 1417 | |
1398 | 1418 | buf[strlen(buf)-1] = 0; /* Remove trailing newline */ |
1419 | + g_strstrip(buf); /* And any other whitespace */ | |
1399 | 1420 | if ((paper = find_paper(buf)) != -1) { |
1400 | 1421 | get_paper_info(&dia->paper, paper, NULL); |
1401 | 1422 | return TRUE; |
@@ -1563,7 +1584,7 @@ import_fig(const gchar *filename, DiagramData *dia, void* user_data) { | ||
1563 | 1584 | } while (TRUE); |
1564 | 1585 | |
1565 | 1586 | /* Now we can reorder for the depth fields */ |
1566 | - for (i = 999; i >= 0; i--) { | |
1587 | + for (i = 0; i < 1000; i++) { | |
1567 | 1588 | if (depths[i] != NULL) |
1568 | 1589 | layer_add_objects_first(dia->active_layer, depths[i]); |
1569 | 1590 | } |