2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include <glade/glade.h>
24 #include <libgnomevfs/gnome-vfs.h>
25 #include <gconf/gconf-client.h>
27 #include <libanjuta/anjuta-utils.h>
28 #include <libanjuta/anjuta-debug.h>
32 //#include "text_editor.h"
33 #include "indent-util.h"
34 #include "indent-dialog.h"
37 #define INDENT_FILE_INPUT PACKAGE_DATA_DIR"/indent_test.c"
38 #define INDENT_FILE_OUTPUT TMPDIR"/indent_test.c"
40 #define AUTOFORMAT_DISABLE "autoformat.disable"
41 #define AUTOFORMAT_STYLE "autoformat.style"
42 #define AUTOFORMAT_LIST_STYLE "autoformat.list.style"
43 #define AUTOFORMAT_OPTS "autoformat.opts"
45 static IndentOption indent_option
[] = {
46 {"bl", FALSE
, "bl_checkbutton", NULL
},
47 {"bli", FALSE
, "bli_checkbutton", "bli_spinbutton"},
48 {"br", FALSE
, "br_checkbutton", NULL
},
49 {"ci", FALSE
, "ci_checkbutton", "ci_spinbutton"},
50 {"cli", FALSE
, "cli_checkbutton", "cli_spinbutton"},
51 {"cs", FALSE
, "cs_checkbutton", NULL
},
52 {"pcs", TRUE
, "pcs_checkbutton", NULL
},
53 {"saf", TRUE
, "saf_checkbutton", NULL
},
54 {"sai", TRUE
, "sai_checkbutton", NULL
},
55 {"saw", TRUE
, "saw_checkbutton", NULL
},
56 {"bad", TRUE
, "bad_checkbutton", NULL
},
57 {"bap", TRUE
, "bap_checkbutton", NULL
},
58 {"sob", TRUE
, "sob_checkbutton", NULL
},
59 {"cdb", TRUE
, "cdb_checkbutton", NULL
},
60 {"bbb", FALSE
, "bbb_checkbutton", NULL
},
61 {"cd", FALSE
, "cd_checkbutton", "cd_spinbutton"},
62 {"ce", TRUE
, "ce_checkbutton", NULL
},
63 {"c", FALSE
, "c_checkbutton", "c_spinbutton"},
64 {"cp", FALSE
, "cp_checkbutton", "cp_spinbutton"},
65 {"d", FALSE
, "d_checkbutton", "d_spinbutton"},
66 {"fc1", TRUE
, "fc1_checkbutton", NULL
},
67 {"fca", TRUE
, "fca_checkbutton", NULL
},
68 {"sc", TRUE
, "sc_checkbutton", NULL
},
69 {"bc", TRUE
, "bc_checkbutton", NULL
},
70 {"bls", FALSE
, "bls_checkbutton", NULL
},
71 {"brs", FALSE
, "brs_checkbutton", NULL
},
72 {"di", FALSE
, "di_checkbutton", "di_spinbutton"},
73 {"psl", TRUE
, "psl_checkbutton", NULL
},
74 {"i", FALSE
, "i_checkbutton", "i_spinbutton"},
75 {"ip", FALSE
, "ip_checkbutton", "ip_spinbutton"},
76 {"lp", TRUE
, "lp_checkbutton", NULL
},
77 {"ts", FALSE
, "ts_checkbutton", "ts_spinbutton"},
78 {"bbo", TRUE
, "bbo_checkbutton", NULL
},
79 {"hnl", TRUE
, "hnl_checkbutton", NULL
},
80 {"l", FALSE
, "l_checkbutton", "l_spinbutton"},
81 {NULL
, FALSE
, NULL
, NULL
}
85 static IndentStyle standard_indent_style
[] = {
86 {"GNU coding style", "-nbad -bap -bbo -nbc -bl -bli2 -bls -ncdb -nce -cp1 "
87 "-cs -di2 -nfc1 -nfca -hnl -i2 -ip5 -lp -pcs -nprs -psl -saf -sai -saw "
89 {"Kernighan and Ritchie style", "-nbad -bap -nbc -bbo -br -brs -c33 -cd33 "
90 "-ncdb -ce -ci4 -cli0 -cp33 -cs -d0 -di1 -nfc1 -nfca -hnl -i4 -ip0 -l75 "
91 "-lp -npcs -nprs -npsl -saf -sai -saw -nsc -nsob -nss" , FALSE
},
92 {"Original Berkeley style", "-nbad -nbap -bbo -bc -br -brs -c33 -cd33 -cdb "
93 "-ce -ci4 -cli0 -cp33 -di16 -fc1 -fca -hnl -i4 -ip4 -l75 -lp -npcs "
95 {"Anjuta coding style", "-l80 -lc80 -ts4 -i4 -sc -bli0 -bl0 -cbi0 -ss", FALSE
},
96 {"Style of Kangleipak", "-i8 -sc -bli0 -bl0 -cbi0 -ss", FALSE
},
97 {"Hello World style", "-gnu -i0 -bli0 -cbi0 -cdb -sc -bl0 -ss", FALSE
},
101 /******************************************************************************/
102 void indent_init_hash(IndentData
*idt
);
104 void indent_destroy_hash_data(gpointer key
, gpointer data
, gpointer user_data
);
105 void indent_free_data(IndentData
*idt
);
106 void indent_free_style(IndentData
*idt
);
108 void indent_init_indent_style(IndentData
*idt
);
109 gint
indent_load_all_style(IndentData
*idt
);
111 gchar
*indent_alpha_string(gchar
*option
);
112 gboolean
indent_option_is_numeric(gchar
*option
);
113 void indent_anal_option(gchar
*option
, IndentData
*idt
);
114 gint
indent_compare_options(gchar
*opt1
, gchar
*opt2
);
115 gchar
*indent_sort_options(gchar
*line
);
116 gint
indent_compare_style(IndentStyle
*style
, gchar
*name_style
);
118 void indent_save_list_style(GList
*list
, IndentData
*idt
);
120 /*****************************************************************************/
123 indent_init(AnjutaPreferences
*prefs
)
127 idt
= g_new(IndentData
, 1);
128 indent_init_hash(idt
);
130 idt
->style_list
= NULL
;
131 idt
->checkbutton_blocked
= FALSE
;
136 indent_init_hash(IndentData
*idt
)
139 OptionData
*ptroption
;
142 idt
->option_hash
= g_hash_table_new_full ((GHashFunc
) g_str_hash
,
143 (GEqualFunc
) g_str_equal
,
144 (GDestroyNotify
) g_free
,
145 (GDestroyNotify
) g_free
);
146 idt
->check_hash
= g_hash_table_new_full ((GHashFunc
) g_str_hash
,
147 (GEqualFunc
) g_str_equal
,
148 (GDestroyNotify
) g_free
,
149 (GDestroyNotify
) g_free
);
150 idt
->spin_hash
= g_hash_table_new_full ((GHashFunc
) g_str_hash
,
151 (GEqualFunc
) g_str_equal
,
152 (GDestroyNotify
) g_free
,
153 (GDestroyNotify
) g_free
);
154 for (i
=0; indent_option
[i
].option
!= NULL
; i
++)
156 ptroption
= g_new(OptionData
, 1);
157 ptroption
->not_option
= indent_option
[i
].not_option
;
158 ptroption
->checkbutton
= indent_option
[i
].checkbutton
;
159 ptroption
->spinbutton
= indent_option
[i
].spinbutton
;
160 g_hash_table_insert (idt
->option_hash
, indent_option
[i
].option
, ptroption
);
161 ptrcheck
= g_new(CheckData
, 1);
162 ptrcheck
->option
= indent_option
[i
].option
;
163 ptrcheck
->not_option
= indent_option
[i
].not_option
;
164 ptrcheck
->spinbutton
= indent_option
[i
].spinbutton
;
165 g_hash_table_insert (idt
->check_hash
, indent_option
[i
].checkbutton
, ptrcheck
);
166 if (indent_option
[i
].spinbutton
)
167 g_hash_table_insert (idt
->spin_hash
, indent_option
[i
].spinbutton
,
168 indent_option
[i
].option
);
175 indent_destroy_hash_data(gpointer key
, gpointer data
, gpointer user_data
)
181 indent_free_data(IndentData
*idt
)
183 g_hash_table_foreach(idt
->option_hash
, indent_destroy_hash_data
, NULL
);
184 g_hash_table_foreach(idt
->check_hash
, indent_destroy_hash_data
, NULL
);
188 indent_free_style(IndentData
*idt
)
192 list
= idt
->style_list
;
196 list
= g_list_next(list
);
198 g_list_free(idt
->style_list
);
202 indent_free(IndentData
*idt
)
204 indent_free_style(idt
);
205 indent_free_data(idt
);
209 indent_init_indent_style(IndentData
*idt
)
211 IndentStyle
*indent_style
;
214 for (i
=0; standard_indent_style
[i
].name
!= NULL
; i
++)
216 indent_style
= g_new(IndentStyle
, 1);
217 indent_style
->name
= standard_indent_style
[i
].name
;
218 indent_style
->options
= standard_indent_style
[i
].options
;
219 indent_style
->modifiable
= standard_indent_style
[i
].modifiable
;
220 idt
->style_list
= g_list_append(idt
->style_list
, indent_style
);
225 indent_init_load_style(IndentData
*idt
)
227 indent_init_indent_style(idt
);
228 idt
->style_active
= indent_load_all_style(idt
);
233 indent_load_all_style(IndentData
*idt
)
235 GSList
*list2
= NULL
;
237 gchar
*style_name
= NULL
;
238 gchar
*options
= NULL
;
239 IndentStyle
*indent_style
;
241 list2
= anjuta_preferences_get_list (idt
->prefs
, AUTOFORMAT_LIST_STYLE
,
247 indent_style
= g_new(IndentStyle
, 1);
248 indent_style
->name
= g_strdup((gchar
*)list2
->data
);
249 key
= g_strdup((gchar
*)list2
->data
);
250 key
= g_strconcat(AUTOFORMAT_OPTS
, "/", g_strdelimit(key
, " ", '_'), NULL
);
251 options
= anjuta_preferences_get (idt
->prefs
, key
);
252 indent_style
->options
= g_strdup(options
);
253 indent_style
->modifiable
= TRUE
;
254 idt
->style_list
=g_list_append(idt
->style_list
, indent_style
);
257 list2
= g_slist_next(list2
);
260 if (!anjuta_preferences_get_pair (idt
->prefs
, AUTOFORMAT_STYLE
,
261 GCONF_VALUE_STRING
, GCONF_VALUE_STRING
,
262 &style_name
, &options
))
265 return indent_find_index(style_name
, idt
);
269 indent_alpha_string(gchar
*option
)
273 while(g_ascii_isalpha(*(ptr
)) )
277 return g_strndup(option
, ptr
- option
);
281 indent_option_is_numeric(gchar
*option
)
283 gboolean numeric
= FALSE
;
286 if (! g_ascii_isdigit(*(option
++)) )
295 indent_anal_option(gchar
*option
, IndentData
*idt
)
297 gboolean flag_n
= FALSE
;
302 if (*(option
++) != '-') return;
308 if (*option
== 0) return;
310 if ((ptrdata
= g_hash_table_lookup(idt
->option_hash
, option
)) == NULL
311 || ptrdata
->spinbutton
)
313 if ( (alpha_option
= indent_alpha_string(option
)) == NULL
)
315 if ((ptrdata
= g_hash_table_lookup(idt
->option_hash
, alpha_option
)) == NULL
)
317 if ( flag_n
&& ptrdata
->not_option
)
319 g_free(alpha_option
);
322 if ( !flag_n
&& (ptrdata
->spinbutton
!= NULL
))
324 num
= g_strdup(option
+ strlen(alpha_option
));
325 if (!indent_option_is_numeric(num
))
330 indent_toggle_button_set_active(ptrdata
->checkbutton
, !flag_n
, idt
);
331 indent_widget_set_sensitive(ptrdata
->spinbutton
, TRUE
, idt
);
332 indent_spinbutton_set_value(ptrdata
->spinbutton
, num
, idt
);
335 g_free(alpha_option
);
340 indent_toggle_button_set_active(ptrdata
->checkbutton
, TRUE
, idt
);
342 if (ptrdata
->not_option
)
343 indent_toggle_button_set_active(ptrdata
->checkbutton
, FALSE
, idt
);
349 indent_anal_line_option(gchar
*line
, IndentData
*idt
)
354 split
= g_strsplit(line
, " ", -1);
357 if (strlen(split
[i
]) > 0)
358 indent_anal_option(split
[i
], idt
);
366 indent_delete_option(gchar
*line
, gchar
*short_option
, gboolean num
)
371 gchar
*ptr_start
= NULL
;
372 gchar
*ptr_end
= NULL
;
375 result
= g_strdup("");
376 split
= g_strsplit(line
, " ", -1);
379 if (strlen(split
[i
]) != 0)
381 ptr_start
= split
[i
];
382 if (*(ptr_start
++) == '-')
384 if (*(ptr_start
) == 'n')
389 while(g_ascii_isalpha(*ptr_end
))
391 opt
= g_strndup(ptr_start
, ptr_end
- ptr_start
);
395 while(g_ascii_isalnum(*ptr_end
))
397 opt
= g_strndup(ptr_start
, ptr_end
- ptr_start
);
399 if (strlen(opt
) > 0 && g_ascii_strcasecmp(opt
, short_option
) != 0)
400 result
= g_strconcat(result
, split
[i
], " ", NULL
);
411 indent_compare_options(gchar
*opt1
, gchar
*opt2
)
416 if (*(opt1
) == 'n') opt1
++;
421 if (*(opt2
) == 'n') opt2
++;
423 return g_ascii_strcasecmp(opt1
, opt2
);
427 indent_sort_options(gchar
*line
)
432 gboolean exch
= TRUE
;
435 split
= g_strsplit(line
, " ", -1);
436 /* Remove empty items or not beginning by '-' */
439 if ((strlen(split
[i
]) != 0) && (*(split
[i
]) == '-'))
440 split
[j
++] = split
[i
];
442 } /* j = number of items */
448 for (i
=0; i
<j
-1; i
++)
450 if (indent_compare_options(split
[i
], split
[i
+1]) > 0)
452 tmp
= split
[i
]; split
[i
] = split
[i
+1]; split
[i
+1] = tmp
;
459 result
= g_strconcat(result
, split
[i
], " ", NULL
);
466 indent_insert_option(gchar
*line
, gchar
*option
)
468 line
= g_strconcat(option
, " ", line
, NULL
);
469 line
= indent_sort_options(line
);
474 indent_execute(gchar
*line_option
, IndentData
*idt
)
481 options
= g_strconcat(line_option
, " ",INDENT_FILE_INPUT
, NULL
);
482 cmd
= g_strconcat ("indent ", options
, " -o ", INDENT_FILE_OUTPUT
, NULL
);
485 pid
= anjuta_util_execute_shell (PACKAGE_DATA_DIR
, cmd
);
487 waitpid (pid
, &status
, 0);
493 indent_get_buffer(void)
495 GnomeVFSResult result
;
496 GnomeVFSHandle
*handle
;
497 GnomeVFSFileInfo info
;
498 gchar
*read_buf
= NULL
;
501 text_uri
= gnome_vfs_get_uri_from_local_path(INDENT_FILE_OUTPUT
);
502 result
= gnome_vfs_get_file_info(text_uri
, &info
,
503 GNOME_VFS_FILE_INFO_DEFAULT
|
504 GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS
);
505 if(result
!= GNOME_VFS_OK
)
507 DEBUG_PRINT("Cannot get info: %s\n", text_uri
);
510 if((result
= gnome_vfs_open (&handle
, text_uri
,
511 GNOME_VFS_OPEN_READ
)) != GNOME_VFS_OK
)
513 DEBUG_PRINT("Cannot open: %s\n", text_uri
);
516 read_buf
= g_new0(char, info
.size
+ 1);
518 result
= gnome_vfs_read (handle
, read_buf
, info
.size
, NULL
);
519 if(!(result
== GNOME_VFS_OK
|| result
== GNOME_VFS_ERROR_EOF
))
522 DEBUG_PRINT("No file: %s\n", text_uri
);
525 gnome_vfs_close (handle
);
531 indent_save_list_style(GList
*list
, IndentData
*idt
)
533 GSList
*list2
= NULL
;
539 if (idtst
->modifiable
)
540 list2
= g_slist_append(list2
, idtst
->name
);
541 list
= g_list_next(list
);
543 anjuta_preferences_set_list (idt
->prefs
, AUTOFORMAT_LIST_STYLE
,
544 GCONF_VALUE_STRING
, list2
);
549 indent_save_style(gchar
*style_name
, gchar
*options
, IndentData
*idt
)
553 if (!anjuta_preferences_dir_exists (idt
->prefs
, AUTOFORMAT_OPTS
))
554 anjuta_preferences_add_dir (idt
->prefs
, AUTOFORMAT_OPTS
,
555 GCONF_CLIENT_PRELOAD_NONE
);
557 key
= g_strdup(style_name
);
558 key
= g_strconcat(AUTOFORMAT_OPTS
, "/", g_strdelimit(key
, " ", '_'), NULL
);
560 anjuta_preferences_set(idt
->prefs
, key
, options
); //**//
565 indent_save_all_style(IndentData
*idt
)
570 if (anjuta_preferences_dir_exists (idt
->prefs
, AUTOFORMAT_OPTS
) )
571 anjuta_preferences_remove_dir (idt
->prefs
, AUTOFORMAT_OPTS
);
572 anjuta_preferences_add_dir (idt
->prefs
, AUTOFORMAT_OPTS
,
573 GCONF_CLIENT_PRELOAD_NONE
);
575 list1
= idt
->style_list
;
576 indent_save_list_style(list1
, idt
);
578 list1
= idt
->style_list
;
582 if (idtst
->modifiable
)
583 indent_save_style(idtst
->name
, idtst
->options
, idt
);
584 list1
= g_list_next(list1
);
589 indent_compare_style(IndentStyle
*style
, gchar
*name_style
)
591 return g_ascii_strcasecmp(style
->name
, name_style
);
595 indent_find_style(gchar
*style_name
, IndentData
*idt
)
599 list
= g_list_find_custom(idt
->style_list
, style_name
,
600 (GCompareFunc
) indent_compare_style
);
602 return ((IndentStyle
*)list
->data
)->options
;
608 indent_find_index(gchar
*style_name
, IndentData
*idt
)
613 if (style_name
== NULL
)
615 list
= g_list_find_custom(idt
->style_list
, style_name
,
616 (GCompareFunc
) indent_compare_style
);
617 index
= g_list_index(idt
->style_list
, list
->data
);
622 indent_remove_style(gchar
*style_name
, IndentData
*idt
)
626 list
= g_list_find_custom(idt
->style_list
, style_name
,
627 (GCompareFunc
) indent_compare_style
);
628 if ( list
&& ((IndentStyle
*)list
->data
)->modifiable
)
630 list
= g_list_remove(list
, list
->data
);
637 indent_update_style(gchar
*style_name
, gchar
*options
, IndentData
*idt
)
641 list
= g_list_find_custom(idt
->style_list
, style_name
,
642 (GCompareFunc
) indent_compare_style
);
643 if ( list
&& ((IndentStyle
*)list
->data
)->modifiable
)
645 ((IndentStyle
*)list
->data
)->name
= style_name
;
646 ((IndentStyle
*)list
->data
)->options
= options
;
654 indent_save_active_style(gchar
*style_name
, gchar
*options
, IndentData
*idt
)
656 anjuta_preferences_set_pair (idt
->prefs
, AUTOFORMAT_STYLE
,
657 GCONF_VALUE_STRING
, GCONF_VALUE_STRING
,
658 &style_name
, &options
);
662 indent_add_style(gchar
*style_name
, IndentData
*idt
)
665 IndentStyle
*indent_style
;
667 list
= g_list_find_custom(idt
->style_list
, style_name
,
668 (GCompareFunc
) indent_compare_style
);
673 indent_style
= g_new(IndentStyle
, 1);
674 indent_style
->name
= style_name
;
675 indent_style
->options
= standard_indent_style
[0].options
;
676 indent_style
->modifiable
= TRUE
;
677 idt
->style_list
=g_list_append(idt
->style_list
, indent_style
);