home *** CD-ROM | disk | FTP | other *** search
- /*
- * This is a plug-in for the GIMP.
- *
- * Generates clickable image maps.
- *
- * Copyright (C) 1998-1999 Maurits Rijk lpeek.mrijk@consunet.nl
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
- #include <stdio.h>
- #include "imap_command.h"
-
- #define INFINITE_UNDO_LEVELS -1
-
- static void command_destruct(Command_t *command);
-
- static CommandList_t _command_list = {NULL, DEFAULT_UNDO_LEVELS};
- static CommandList_t *_current_command_list = &_command_list;
-
- static void
- command_list_callback_add(CommandListCallback_t *list,
- CommandListCallbackFunc_t func, gpointer data)
- {
- CommandListCB_t *cb = g_new(CommandListCB_t, 1);
- cb->func = func;
- cb->data = data;
- list->list = g_list_append(list->list, cb);
- }
-
- static void
- command_list_callback_call(CommandListCallback_t *list, Command_t *command)
- {
- GList *p;
- for (p = list->list; p; p = p->next) {
- CommandListCB_t *cb = (CommandListCB_t*) p->data;
- cb->func(command, cb->data);
- }
- }
-
- CommandList_t*
- command_list_new(gint undo_levels)
- {
- CommandList_t *list = g_new(CommandList_t, 1);
- list->parent = NULL;
- list->undo_levels = undo_levels;
- list->list = NULL;
- list->undo = NULL;
- list->redo = NULL;
- list->update_cb.list = NULL;
- return list;
- }
-
- static void
- command_list_clear(CommandList_t *list)
- {
- GList *p;
- for (p = list->list; p; p = p->next)
- command_destruct((Command_t*) p->data);
- g_list_free(list->list);
- list->list = NULL;
- list->undo = NULL;
- list->redo = NULL;
- command_list_callback_call(&list->update_cb, NULL);
- }
-
- void
- command_list_destruct(CommandList_t *list)
- {
- command_list_clear(list);
- g_free(list);
- }
-
- void
- command_list_remove_all(void)
- {
- command_list_clear(&_command_list);
- }
-
- static void
- _command_list_add(CommandList_t *list, Command_t *command)
- {
- GList *p, *q;
-
- /* Remove rest */
- for (p = list->redo; p; p = q) {
- Command_t *curr = (Command_t*) p->data;
- q = p->next;
- command_destruct(curr);
- list->list = g_list_remove_link(list->list, p);
- }
-
- if (g_list_length(list->list) == list->undo_levels) {
- GList *first = g_list_first(list->list);
- Command_t *curr = (Command_t*) first->data;
- command_destruct(curr);
- list->list = g_list_remove_link(list->list, first);
- }
- list->list = g_list_append(list->list, (gpointer) command);
- list->undo = g_list_last(list->list);
- list->redo = NULL;
-
- command_list_callback_call(&list->update_cb, command);
- }
-
- void
- command_list_add(Command_t *command)
- {
- _command_list_add(_current_command_list, command);
- }
-
- /* Fix me! */
- void
- subcommand_list_add(CommandList_t *list, Command_t *command)
- {
- _command_list_add(list, command);
- }
-
- static CommandClass_t parent_command_class = {
- NULL, /* parent_command_destruct */
- NULL, /* parent_command_execute */
- NULL, /* parent_command_undo */
- NULL /* parent_command_redo */
- };
-
- static Command_t*
- command_list_start(CommandList_t *list, const gchar *name)
- {
- Command_t *command = g_new(Command_t, 1);
- command_init(command, name, &parent_command_class);
- command->sub_commands = command_list_new(INFINITE_UNDO_LEVELS);
-
- command_list_add(command);
- command->sub_commands->parent = _current_command_list;
- _current_command_list = command->sub_commands;
-
- return command;
- }
-
- static void
- command_list_end(CommandList_t *list)
- {
- _current_command_list = list->parent;
- }
-
- Command_t*
- subcommand_start(const gchar *name)
- {
- return command_list_start(_current_command_list, name);
- }
-
- void
- subcommand_end(void)
- {
- command_list_end(_current_command_list);
- }
-
- static void
- _command_list_set_undo_level(CommandList_t *list, gint level)
- {
- gint diff = g_list_length(list->list) - level;
- if (diff > 0) {
- GList *p, *q;
- /* first remove data at the front */
- for (p = list->list; diff && p != list->undo; p = q, diff--) {
- Command_t *curr = (Command_t*) p->data;
- q = p->next;
- command_destruct(curr);
- list->list = g_list_remove_link(list->list, p);
- }
-
- /* If still to long start removing redo levels at the end */
- for (p = g_list_last(list->list); diff && p != list->undo; p = q,
- diff--) {
- Command_t *curr = (Command_t*) p->data;
- q = p->prev;
- command_destruct(curr);
- list->list = g_list_remove_link(list->list, p);
- }
- command_list_callback_call(&list->update_cb,
- (Command_t*) list->undo->data);
- }
- list->undo_levels = level;
- }
-
- void
- command_list_set_undo_level(gint level)
- {
- _command_list_set_undo_level(&_command_list, level);
- }
-
- Command_t*
- command_list_get_redo_command(void)
- {
- return (_command_list.redo) ? (Command_t*) _command_list.redo->data :
- NULL;
- }
-
- void
- command_list_add_update_cb(CommandListCallbackFunc_t func, gpointer data)
- {
- command_list_callback_add(&_command_list.update_cb, func, data);
- }
-
- static void
- command_destruct(Command_t *command)
- {
- if (command->sub_commands)
- command_list_destruct(command->sub_commands);
- if (command->class->destruct)
- command->class->destruct(command);
- }
-
- static void
- command_list_execute(CommandList_t *list)
- {
- GList *p;
- for (p = list->list; p; p = p->next) {
- Command_t *command = (Command_t*) p->data;
- if (command->sub_commands)
- command_list_execute(command->sub_commands);
- if (command->class->execute)
- (void) command->class->execute(command);
- }
- }
-
- void
- command_execute(Command_t *command)
- {
- if (command->locked) {
- command->locked = FALSE;
- } else {
- if (command->sub_commands)
- command_list_execute(command->sub_commands);
- if (command->class->execute) {
- CmdExecuteValue_t value = command->class->execute(command);
- if (value == CMD_APPEND)
- command_list_add(command);
- else if (value == CMD_DESTRUCT)
- command_destruct(command);
- }
- }
- }
-
- void
- command_redo(Command_t *command)
- {
- if (command->sub_commands)
- command_list_redo_all(command->sub_commands);
- if (command->class->redo)
- command->class->redo(command);
- else if (command->class->execute)
- (void) command->class->execute(command);
- }
-
- void
- command_undo(Command_t *command)
- {
- if (command->sub_commands)
- command_list_undo_all(command->sub_commands);
- if (command->class->undo)
- command->class->undo(command);
- }
-
- void
- command_set_name(Command_t *command, const gchar *name)
- {
- command->name = name;
- command_list_callback_call(&_command_list.update_cb, command);
- }
-
- void
- command_list_undo(CommandList_t *list)
- {
- Command_t *command = (Command_t*) list->undo->data;
- command_undo(command);
-
- list->redo = list->undo;
- list->undo = list->undo->prev;
- if (list->undo)
- command = (Command_t*) list->undo->data;
- else
- command = NULL;
- command_list_callback_call(&list->update_cb, command);
- }
-
- void
- command_list_undo_all(CommandList_t *list)
- {
- while (list->undo)
- command_list_undo(list);
- }
-
- void
- last_command_undo(void)
- {
- command_list_undo(&_command_list);
- }
-
- void
- command_list_redo(CommandList_t *list)
- {
- Command_t *command = (Command_t*) list->redo->data;
- command_redo(command);
-
- list->undo = list->redo;
- list->redo = list->redo->next;
- command_list_callback_call(&list->update_cb, command);
- }
-
- void
- command_list_redo_all(CommandList_t *list)
- {
- while (list->redo)
- command_list_redo(list);
- }
-
- void
- last_command_redo(void)
- {
- command_list_redo(&_command_list);
- }
-
- Command_t*
- command_init(Command_t *command, const gchar *name, CommandClass_t *class)
- {
- command->sub_commands = NULL;
- command->name = name;
- command->class = class;
- command->locked = FALSE;
- return command;
- }
-
- void
- command_add_subcommand(Command_t *command, Command_t *sub_command)
- {
- if (!command->sub_commands)
- command->sub_commands = command_list_new(INFINITE_UNDO_LEVELS);
- subcommand_list_add(command->sub_commands, sub_command);
- }
-
- static CmdExecuteValue_t basic_command_execute(Command_t *command);
-
- static CommandClass_t basic_command_class = {
- NULL, /* basic_command_destruct */
- basic_command_execute,
- NULL,
- NULL /* basic_command_redo */
- };
-
- typedef struct {
- Command_t parent;
- void (*func)(void);
- } BasicCommand_t;
-
- Command_t*
- command_new(void (*func)(void))
- {
- BasicCommand_t *command = g_new(BasicCommand_t, 1);
- command->func = func;
- return command_init(&command->parent, "Unknown", &basic_command_class);
- }
-
- static CmdExecuteValue_t
- basic_command_execute(Command_t *command)
- {
- ((BasicCommand_t*) command)->func();
- return CMD_DESTRUCT;
- }
-