📄 hotlist.c
字号:
target = strdup (l_hotlist->current->text);
break;
}
hotlist_done ();
return target;
}
void load_group (struct hotlist *grp)
{
void *profile_keys;
char *key, *value;
char *group_section;
struct hotlist *current = 0;
group_section = find_group_section (grp);
profile_keys = profile_init_iterator (group_section, profile_name);
current_group = grp;
while (profile_keys){
profile_keys = profile_iterator_next (profile_keys, &key, &value);
add2hotlist (strdup (value), strdup (key), HL_TYPE_GROUP, 0);
}
free (group_section);
profile_keys = profile_init_iterator (grp->directory, profile_name);
while (profile_keys){
profile_keys = profile_iterator_next (profile_keys, &key, &value);
add2hotlist (strdup (value), strdup (key), HL_TYPE_ENTRY, 0);
}
for (current = grp->head; current; current = current->next)
load_group (current);
}
#define TKN_GROUP 0
#define TKN_ENTRY 1
#define TKN_STRING 2
#define TKN_URL 3
#define TKN_ENDGROUP 4
#define TKN_COMMENT 5
#define TKN_EOL 125
#define TKN_EOF 126
#define TKN_UNKNOWN 127
static char *tkn_buf;
static int tkn_buf_length;
static int tkn_length;
static char *hotlist_file_name;
static FILE *hotlist_file;
static time_t hotlist_file_mtime;
static int hot_skip_blanks ()
{
int c;
while ((c = getc (hotlist_file)) != EOF && c != '\n' && isspace (c))
;
return c;
}
static int hot_next_token ()
{
int c;
#define CHECK_BUF() \
do { \
if (tkn_length == tkn_buf_length) \
tkn_buf = tkn_buf ? (realloc (tkn_buf, tkn_buf_length += 1024)) \
: (malloc (tkn_buf_length = 1024)); \
} while (0)
tkn_length = 0;
again:
c = hot_skip_blanks ();
switch (c) {
case EOF:
return TKN_EOF;
break;
case '\n':
return TKN_EOL;
break;
case '#':
while ((c = getc (hotlist_file)) != EOF && c != '\n') {
if (c == EOF)
return TKN_EOF;
if (c != '\n') {
CHECK_BUF();
tkn_buf[tkn_length++] = c == '\n' ? ' ' : c;
}
}
CHECK_BUF();
tkn_buf[tkn_length] = '\0';
return TKN_COMMENT;
break;
case '"':
while ((c = getc (hotlist_file)) != EOF && c != '"') {
if (c == '\\')
if ((c = getc (hotlist_file)) == EOF)
return TKN_EOF;
CHECK_BUF();
tkn_buf[tkn_length++] = c == '\n' ? ' ' : c;
}
if (c == EOF)
return TKN_EOF;
CHECK_BUF();
tkn_buf[tkn_length] = '\0';
return TKN_STRING;
break;
case '\\':
if ((c = getc (hotlist_file)) == EOF)
return TKN_EOF;
if (c == '\n')
goto again;
/* fall through; it is taken as normal character */
default:
do {
CHECK_BUF();
tkn_buf[tkn_length++] = toupper(c);
} while ((c = fgetc (hotlist_file)) != EOF && isalnum (c));
if (c != EOF)
ungetc (c, hotlist_file);
CHECK_BUF();
tkn_buf[tkn_length] = '\0';
if (strncmp (tkn_buf, "GROUP", tkn_length) == 0)
return TKN_GROUP;
else if (strncmp (tkn_buf, "ENTRY", tkn_length) == 0)
return TKN_ENTRY;
else if (strncmp (tkn_buf, "ENDGROUP", tkn_length) == 0)
return TKN_ENDGROUP;
else if (strncmp (tkn_buf, "URL", tkn_length) == 0)
return TKN_URL;
else
return TKN_UNKNOWN;
break;
}
}
#define SKIP_TO_EOL { \
int _tkn; \
while ((_tkn = hot_next_token ()) != TKN_EOF && _tkn != TKN_EOL) ; \
}
#define CHECK_TOKEN(_TKN_) \
if ((tkn = hot_next_token ()) != _TKN_) { \
hotlist_state.readonly = 1; \
hotlist_state.file_error = 1; \
while (tkn != TKN_EOL && tkn != TKN_EOF) \
tkn = hot_next_token (); \
break; \
}
static void
hot_load_group (struct hotlist * grp)
{
int tkn;
struct hotlist *new_grp;
char *label, *url;
current_group = grp;
while ((tkn = hot_next_token()) != TKN_ENDGROUP)
switch (tkn) {
case TKN_GROUP:
CHECK_TOKEN(TKN_STRING);
new_grp = add2hotlist (strdup (tkn_buf), 0, HL_TYPE_GROUP, 0);
SKIP_TO_EOL;
hot_load_group (new_grp);
current_group = grp;
break;
case TKN_ENTRY:
CHECK_TOKEN(TKN_STRING);
label = strdup (tkn_buf);
CHECK_TOKEN(TKN_URL);
CHECK_TOKEN(TKN_STRING);
url = strdup (tkn_buf);
add2hotlist (label, url, HL_TYPE_ENTRY, 0);
SKIP_TO_EOL;
break;
case TKN_COMMENT:
label = strdup (tkn_buf);
add2hotlist (label, 0, HL_TYPE_COMMENT, 0);
break;
case TKN_EOF:
hotlist_state.readonly = 1;
hotlist_state.file_error = 1;
return;
break;
case TKN_EOL:
/* skip empty lines */
break;
default:
hotlist_state.readonly = 1;
hotlist_state.file_error = 1;
SKIP_TO_EOL;
break;
}
SKIP_TO_EOL;
}
static void
hot_load_file (struct hotlist * grp)
{
int tkn;
struct hotlist *new_grp;
char *label, *url;
current_group = grp;
while ((tkn = hot_next_token())!= TKN_EOF)
switch (tkn) {
case TKN_GROUP:
CHECK_TOKEN(TKN_STRING);
new_grp = add2hotlist (strdup (tkn_buf), 0, HL_TYPE_GROUP, 0);
SKIP_TO_EOL;
hot_load_group (new_grp);
current_group = grp;
break;
case TKN_ENTRY:
CHECK_TOKEN(TKN_STRING);
label = strdup (tkn_buf);
CHECK_TOKEN(TKN_URL);
CHECK_TOKEN(TKN_STRING);
url = strdup (tkn_buf);
add2hotlist (label, url, HL_TYPE_ENTRY, 0);
SKIP_TO_EOL;
break;
case TKN_COMMENT:
label = strdup (tkn_buf);
add2hotlist (label, 0, HL_TYPE_COMMENT, 0);
break;
case TKN_EOL:
/* skip empty lines */
break;
default:
hotlist_state.readonly = 1;
hotlist_state.file_error = 1;
SKIP_TO_EOL;
break;
}
}
void
clean_up_hotlist_groups (char *section)
{
char *grp_section;
void *profile_keys;
char *key, *value;
grp_section = copy_strings (section, ".Group", (char *)0);
if (profile_has_section (section, profile_name))
profile_clean_section (section, profile_name);
if (profile_has_section (grp_section, profile_name)) {
profile_keys = profile_init_iterator (grp_section, profile_name);
while (profile_keys) {
profile_keys = profile_iterator_next (profile_keys, &key, &value);
clean_up_hotlist_groups (key);
}
profile_clean_section (grp_section, profile_name);
}
free (grp_section);
}
void load_hotlist (void)
{
char *grp_section;
int has_old_list = 0;
int remove_old_list = 0;
struct stat stat_buf;
if (hotlist_state.loaded) {
stat (hotlist_file_name, &stat_buf);
if (hotlist_file_mtime < stat_buf.st_mtime)
done_hotlist ();
else
return;
}
if (!hotlist_file_name)
hotlist_file_name = concat_dir_and_file (home_dir, HOTLIST_FILENAME);
hotlist = new_hotlist ();
hotlist->type = HL_TYPE_GROUP;
hotlist->label = strdup (_(" Top level group "));
hotlist->up = hotlist;
/*
* compatibility :-(
*/
hotlist->directory = strdup ("Hotlist");
grp_section = copy_strings ("Hotlist", ".Group", (char *)0);
has_old_list = profile_has_section ("Hotlist", profile_name) ||
profile_has_section (grp_section, profile_name);
free (grp_section);
if ((hotlist_file = fopen (hotlist_file_name, "r")) == 0) {
int result;
char *msg;
msg = copy_strings (_("Hotlist is now kept in file ~/"), HOTLIST_FILENAME,
_("MC will load hotlist from ~/"), PROFILE_NAME,
_(" and then delete [Hotlist] section there"), NULL);
message (0, _(" Hotlist Load "), msg);
free (msg);
load_group (hotlist);
hotlist_state.loaded = 1;
/*
* just to be shure we got copy
*/
hotlist_state.modified = 1;
result = save_hotlist ();
hotlist_state.modified = 0;
if (result) {
remove_old_list = 1;
} else {
char *msg;
msg = copy_strings (_("MC was unable to write ~/"), HOTLIST_FILENAME,
_(" file, your old hotlist entries were not deleted"), NULL);
message (D_ERROR, _(" Hotlist Load "), msg);
free (msg);
}
} else {
hot_load_file (hotlist);
fclose (hotlist_file);
hotlist_state.loaded = 1;
if (has_old_list) {
int result;
char *msg;
msg = copy_strings (
_("You have ~/"), HOTLIST_FILENAME, _(" file and [Hotlist] section in ~/"), PROFILE_NAME, "\n",
_("Your ~/"), HOTLIST_FILENAME, _(" most probably was created\n"),
_("by an earlier development version of MC\nand is more actual than ~/"),
PROFILE_NAME, _(" entries\n\n"),
_("You can choose between\n\n"
" Remove - remove old hotlist entries from ~/"), PROFILE_NAME, "\n",
_(" Keep - keep your old entries; you will be asked\n"
" the same question next time\n"
" Merge - add old entries to hotlist as group \"Entries from ~/"),
PROFILE_NAME, "\"\n\n", NULL);
result = query_dialog (_(" Hotlist Load "),
msg, D_ERROR, 3, _("&Remove"), _("&Keep"), _("&Merge"));
if (result == 0)
remove_old_list = 1;
else if (result == 2) {
struct hotlist *grp = hotlist->head;
struct hotlist *old;
hotlist->head = 0;
load_group (hotlist);
old = new_hotlist ();
old->type = HL_TYPE_GROUP;
old->label = copy_strings (_(" Entries from ~/"), PROFILE_NAME, NULL);
old->up = hotlist;
old->head = hotlist->head;
old->next = grp;
hotlist->head = old;
hotlist_state.modified = 1;
if (!save_hotlist ()){
char *str;
str = copy_strings (_("MC was unable to write ~/"), HOTLIST_FILENAME,
_(" file your old hotlist entries were not deleted"), NULL);
message (D_ERROR, _(" Hotlist Load "), str);
free (str);
} else
remove_old_list = 1;
hotlist_state.modified = 0;
}
}
}
if (remove_old_list) {
clean_up_hotlist_groups ("Hotlist");
sync_profiles ();
}
stat (hotlist_file_name, &stat_buf);
hotlist_file_mtime = stat_buf.st_mtime;
current_group = hotlist;
}
void save_group (struct hotlist *grp)
{
struct hotlist *current = grp->head;
char *group_section;
group_section = find_group_section (grp);
profile_clean_section (group_section, profile_name);
for (;current && current->type == HL_TYPE_GROUP; current = current->next){
WritePrivateProfileString (group_section,
current->directory,
current->label,
profile_name);
}
free (group_section);
for (current = grp->head;
current && current->type == HL_TYPE_GROUP;
current = current->next)
save_group (current);
profile_clean_section (grp->directory, profile_name);
for (;current; current = current->next){
WritePrivateProfileString (grp->directory,
current->directory,
current->label,
profile_name);
}
}
static int list_level = 0;
void hot_save_group (struct hotlist *grp)
{
struct hotlist *current = grp->head;
int i;
char *s;
#define INDENT(n) \
do { \
for (i = 0; i < n; i++) \
putc (' ', hotlist_file); \
} while (0)
for (;current; current = current->next)
switch (current->type) {
case HL_TYPE_GROUP:
INDENT (list_level);
fputs ("GROUP \"", hotlist_file);
for (s = current->label; *s; s++) {
if (*s == '"')
putc ('\\', hotlist_file);
else if (*s == '\\')
putc ('\\', hotlist_file);
putc (*s, hotlist_file);
}
fputs ("\"\n", hotlist_file);
list_level += 2;
hot_save_group (current);
list_level -= 2;
INDENT (list_level);
fputs ("ENDGROUP\n", hotlist_file);
break;
case HL_TYPE_ENTRY:
INDENT(list_level);
fputs ("ENTRY \"", hotlist_file);
for (s = current->label; *s; s++) {
if (*s == '"')
putc ('\\', hotlist_file);
else if (*s == '\\')
putc ('\\', hotlist_file);
putc (*s, hotlist_file);
}
fputs ("\" URL \"", hotlist_file);
for (s = current->directory; *s; s++) {
if (*s == '"')
putc ('\\', hotlist_file);
else if (*s == '\\')
putc ('\\', hotlist_file);
putc (*s, hotlist_file);
}
fputs ("\"\n", hotlist_file);
break;
case HL_TYPE_COMMENT:
fprintf (hotlist_file, "#%s\n", current->label);
break;
}
}
int save_hotlist (void)
{
int saved = 0;
struct stat stat_buf;
if (!hotlist_state.readonly && hotlist_state.modified && hotlist_file_name) {
char *fbak = copy_strings (hotlist_file_name, ".bak", 0);
rename (hotlist_file_name, fbak);
if ((hotlist_file = fopen (hotlist_file_name, "w")) != 0) {
if (stat (fbak, &stat_buf) == 0)
chmod (hotlist_file_name, stat_buf.st_mode);
else
chmod (hotlist_file_name, S_IRUSR | S_IWUSR);
hot_save_group (hotlist);
fflush (hotlist_file);
fclose (hotlist_file);
stat (hotlist_file_name, &stat_buf);
hotlist_file_mtime = stat_buf.st_mtime;
saved = 1;
hotlist_state.modified = 0;
} else
rename (fbak, hotlist_file_name);
free (fbak);
}
return saved;
}
void done_hotlist (void)
{
remove_group (hotlist);
hotlist_state.loaded = 0;
if (hotlist->label)
free (hotlist->label);
if (hotlist->directory)
free (hotlist->directory);
free (hotlist);
if (hotlist_file_name)
free (hotlist_file_name);
hotlist_file_name = 0;
hotlist = current_group = 0;
l_hotlist = 0;
current_group = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -