/*
    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 <glib.h>

#ifdef HAVE_CONFIG_H
#  include <config.h>
#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 */
    }
}



syntax highlighted by Code2HTML, v. 0.9.1