/* Silky - A GTK+ client for SILC. Copyright (C) 2003, 2004, 2005 Toni Willberg - Command history management functions 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 http://silky.sourceforge.net/ */ #include #ifdef HAVE_CONFIG_H # include #endif #include "cmdhistory.h" #include "log.h" /* this points to first (newest) cmd_history entry. ->next == NULL, ->prev == previous (older) entry */ SilkyCmdHistoryItem *cmd_history = NULL; /* this points to currently displayed cmd_history entry, when browsing. SHOULD BE NULL WHEN NOT BROWSING! */ SilkyCmdHistoryItem *current_cmd_history_entry = NULL; char *cmd_history_prev(void) { if( !cmd_history ) { debug("no command history yet"); return(NULL); } if( !current_cmd_history_entry ) { debug("setting current_cmd_history_entry to newest history entry"); current_cmd_history_entry = cmd_history; return(current_cmd_history_entry->text); } if( !current_cmd_history_entry->prev ) { debug("already at oldest command history entry, ignoring..."); return(""); } current_cmd_history_entry = current_cmd_history_entry->prev; return(current_cmd_history_entry->text); } char *cmd_history_next(void) { if( !cmd_history ) { debug("no command history yet"); return(""); } if( !current_cmd_history_entry ) { debug("not browsing command history, ignoring"); return(""); } if( !current_cmd_history_entry->next ) { debug("already at newest command history entry, setting current_cmd_history_entry to NULL"); current_cmd_history_entry = NULL; return(""); } current_cmd_history_entry = current_cmd_history_entry->next; return(current_cmd_history_entry->text); } void cmd_history_push(char *text) { SilkyCmdHistoryItem *c = NULL, *oldc = NULL; int count; int length=0; if( !g_utf8_validate(text, g_utf8_strlen(text, -1), NULL) ) { debug("non-utf8 string passed as argument"); return; } /* first, let's test if entered command is the same as last entry in history. no point in having it added twice */ if( cmd_history && !strcmp(text, cmd_history->text) ) { debug("Entered command equals last command in history, will not duplicate it"); return; } /* now let's add newest entry to the beginning, so cmd_history points to it */ debug("adding new command cmd_history entry: '%s'", text); if( !(c = malloc( sizeof( SilkyCmdHistoryItem ) )) ) { debug_error("can not allocate memory for new command history entry!!!"); } c->next = NULL; /* cut */ length = g_utf8_strlen(text,-1); if( length > 256 ) length = 256; g_utf8_strncpy(c->text, text, length); /* populate it */ if(cmd_history) { /* if some command cmd_history already exists... */ c->prev = cmd_history; /* link it to current newest entry */ cmd_history->next = c; /* link current newest entry to it */ } else c->prev = NULL; cmd_history = c; /* and finally make it the newest entry */ /* if addition was succesful, let's expire oldest entry */ debug("expiring oldest command cmd_history entry"); for( count = 0,oldc = cmd_history;oldc && oldc->prev && count < CMD_HISTORY_DEPTH;oldc=oldc->prev,count++ ) {} /* iterate to oldest entry */ if( count < CMD_HISTORY_DEPTH ) return; if( c != oldc ) { /* only expire if it's not currently added entry (happens when there's only one) */ oldc->next->prev = NULL; /* unlink it */ free(oldc); /* and release it from memory */ } }