--- plrdlg.c.old	Tue Jan 30 13:59:52 2001
+++ plrdlg.c	Sun Jun 10 17:43:53 2001
@@ -35,6 +35,7 @@
 #include "gui_stuff.h"
 #include "inteldlg.h"
 #include "spaceshipdlg.h"
+#include "colors.h"
 
 #include "plrdlg.h"
 
@@ -47,7 +48,9 @@
 static GtkWidget *players_vision_command;
 static GtkWidget *players_sship_command;
 
-static int list_index_to_player_index[MAX_NUM_PLAYERS];
+static int listindex_to_playerindex[MAX_NUM_PLAYERS];
+static int playerindex_to_listindex[MAX_NUM_PLAYERS];
+#define LI_2_PI(num) *(int*)(gtk_clist_get_row_data(GTK_CLIST(players_list), num))
 
 static void create_players_dialog(void);
 static void players_button_callback(GtkWidget *w, gpointer data);
@@ -59,7 +62,8 @@
 static void players_list_ucallback(GtkWidget *w, gint row, gint column);
 static void players_sship_callback(GtkWidget *w, gpointer data);
 
-#define NUM_COLOUMS 9
+#define NUM_COLOUMS 10
+#define DEF_SORT_COLUMN 1 /* default sort column (1 = nation) */
 
 static int delay_plrdlg_update=0;
 
@@ -94,19 +98,52 @@
 }
 
 
+/*
+ * Sort plrs by column...
+ */
+static void sort_players_callback(GtkButton *button, gpointer *data)
+{
+  int sort_column = GPOINTER_TO_INT(data);
+  int i;
+
+  /* first - sort the clist */
+  if (sort_column == GTK_CLIST(players_list)->sort_column) {
+    if (GTK_CLIST(players_list)->sort_type == GTK_SORT_ASCENDING) {
+      gtk_clist_set_sort_type(GTK_CLIST(players_list), GTK_SORT_DESCENDING);
+    } else {
+      gtk_clist_set_sort_type(GTK_CLIST(players_list), GTK_SORT_ASCENDING);
+    }
+  } else {
+    gtk_clist_set_sort_type(GTK_CLIST(players_list), GTK_SORT_ASCENDING);
+    gtk_clist_set_sort_column(GTK_CLIST(players_list), sort_column);
+  }
+  gtk_clist_sort( GTK_CLIST(players_list));
+
+  /* second - update the index */
+  for (i=0; i<GTK_CLIST(players_list)->rows; i++) {
+     playerindex_to_listindex[LI_2_PI(i)]=i;
+  }  
+}
+
+
 /****************************************************************
 ...
 *****************************************************************/
 void create_players_dialog(void)
 {
-  static gchar *titles_[NUM_COLOUMS] = { N_("Name"), N_("Nation"), N_("Embassy"),
-					 N_("Dipl.State"), N_("Vision"),
-					 N_("Reputation"), N_("State"),
-					 N_("Host"), N_("Idle") };
+  static gchar *titles_[NUM_COLOUMS] = { N_("Name"), N_("Nation"), N_("Ai"),
+      N_("Embassy"), N_("Dipl.State"), N_("Vision"), N_("Reputation"),
+      N_("State"), N_("Host"), N_("Idle") };
   static gchar **titles;
-  int    i;
+  int i;
   GtkAccelGroup *accel=gtk_accel_group_new();
 
+  /* initialises the indexes, necessary for update_players_dialog */
+  for (i=0; i<MAX_NUM_PLAYERS; i++) {
+    playerindex_to_listindex[i]=-1;
+    listindex_to_playerindex[i]=-1;
+  }
+
   if (!titles) titles = intl_slist(NUM_COLOUMS, titles_);
 
   players_dialog_shell = gtk_dialog_new();
@@ -117,7 +154,6 @@
   gtk_window_set_title(GTK_WINDOW(players_dialog_shell), _("Players"));
 
   players_list=gtk_clist_new_with_titles(NUM_COLOUMS, titles);
-  gtk_clist_column_titles_passive(GTK_CLIST(players_list));
 
   for(i=0; i<NUM_COLOUMS; i++)
     gtk_clist_set_column_auto_resize (GTK_CLIST (players_list), i, TRUE);
@@ -191,7 +227,86 @@
   gtk_widget_add_accelerator(players_close_command, "clicked",
 	accel, GDK_Escape, 0, 0);
 
+  /* default sort column is nation name */
+  gtk_clist_set_sort_column(GTK_CLIST(players_list), DEF_SORT_COLUMN);
+
+  for (i=0;i < NUM_COLOUMS; i++ )
+    gtk_signal_connect(GTK_OBJECT(GTK_CLIST(players_list)->column[i].button),
+      "clicked", GTK_SIGNAL_FUNC(sort_players_callback), GINT_TO_POINTER(i) );
+
+  gtk_clist_clear(GTK_CLIST(players_list));
   update_players_dialog();
+  gtk_clist_set_column_auto_resize (GTK_CLIST (players_list), 7, FALSE);
+}
+
+
+/* builds the text for the cells of a row in the player report */
+void build_row(char **row, int i) {
+   static char idlebuf[32], statebuf[32], namebuf[32], dsbuf[32], repbuf[32],
+      aibuff[2];      
+   const struct player_diplstate *pds;
+   
+   /* text for idleness */
+   if(game.players[i].nturns_idle>3) {
+     my_snprintf(idlebuf, sizeof(idlebuf), _("(idle %d turns)"),
+		 game.players[i].nturns_idle-1);
+   } else {
+     idlebuf[0]='\0';
+   }
+
+   /* text for state */
+   if(game.players[i].is_alive) {
+     if(game.players[i].is_connected) {
+       if(game.players[i].turn_done)
+	 sz_strlcpy(statebuf, _("done"));
+       else
+	 sz_strlcpy(statebuf, _("moving"));
+     }
+     else
+       statebuf[0]='\0';
+   }
+   else
+     sz_strlcpy(statebuf, _("R.I.P"));
+
+   /* text for name, plus AI marker */ 
+   if (game.players[i].ai.control) {
+      aibuff[0]='*';
+   } else {
+      aibuff[0]=' ';
+   }
+   aibuff[1]=0;
+
+   my_snprintf(namebuf, sizeof(namebuf), "%-16s", game.players[i].name);
+
+   /* text for diplstate type and turns -- not applicable if this is me */
+   if (i == game.player_idx) {
+     strcpy(dsbuf, "-");
+   } else {
+     pds = player_get_diplstate(game.player_idx, i);
+     if (pds->type == DS_CEASEFIRE) {
+       my_snprintf(dsbuf, sizeof(dsbuf), "%s (%d)",
+		   diplstate_text(pds->type), pds->turns_left);
+     } else {
+       my_snprintf(dsbuf, sizeof(dsbuf), "%s",
+		   diplstate_text(pds->type));
+     }
+   }
+
+   /* text for reputation */
+   my_snprintf(repbuf, sizeof(repbuf),
+	       reputation_text(game.players[i].reputation));
+
+   /* assemble the whole lot */
+   row[0] = namebuf;
+   row[1] = get_nation_name(game.players[i].nation);
+   row[2] = aibuff;
+   row[3] = get_embassy_status(game.player_ptr, &game.players[i]);
+   row[4] = dsbuf;
+   row[5] = get_vision_status(game.player_ptr, &game.players[i]);
+   row[6] = repbuf;
+   row[7] = statebuf;
+   row[8] = (char*)player_addr_hack(&game.players[i]);  /* Fixme */
+   row[9] = idlebuf;
 }
 
 
@@ -200,83 +315,57 @@
 **************************************************************************/
 void update_players_dialog(void)
 {
-   if(players_dialog_shell && !delay_plrdlg_update) {
-    int i,j;
-    char *row[NUM_COLOUMS];
-    const struct player_diplstate *pds;
-
+  if(players_dialog_shell && !delay_plrdlg_update) {
+    GdkColor *state_col;
+    char *row_texts[NUM_COLOUMS];
+    int i, j, row, sort_needed=0;
+        
     gtk_clist_freeze(GTK_CLIST(players_list));
-    gtk_clist_clear(GTK_CLIST(players_list));
-
-    for(i=0,j=0; i<game.nplayers; i++) {
-      char idlebuf[32], statebuf[32], namebuf[32], dsbuf[32], repbuf[32];      
 
+    for(i=0; i<game.nplayers; i++) {
       /* skip barbarians */
-      if(is_barbarian(&game.players[i]))
+      if(is_barbarian(&game.players[i])) {
         continue;
-      /* text for idleness */
-      if(game.players[i].nturns_idle>3) {
-	my_snprintf(idlebuf, sizeof(idlebuf), _("(idle %d turns)"),
-		    game.players[i].nturns_idle-1);
-      } else {
-	idlebuf[0]='\0';
-      }
-
-      /* text for state */
-      if(game.players[i].is_alive) {
-	if(game.players[i].is_connected) {
-	  if(game.players[i].turn_done)
-	    sz_strlcpy(statebuf, _("done"));
-	  else
-	    sz_strlcpy(statebuf, _("moving"));
-	}
-	else
-	  statebuf[0]='\0';
       }
-      else
-	sz_strlcpy(statebuf, _("R.I.P"));
-
-      /* text for name, plus AI marker */ 
-      if(game.players[i].ai.control)
-	my_snprintf(namebuf, sizeof(namebuf), "*%-15s", game.players[i].name);
-      else
-	my_snprintf(namebuf, sizeof(namebuf), "%-16s", game.players[i].name);
-
-      /* text for diplstate type and turns -- not applicable if this is me */
-      if (i == game.player_idx) {
-	strcpy(dsbuf, "-");
+      row=playerindex_to_listindex[i];
+      build_row(row_texts, i);
+      if (row==-1) {
+        /* a nation is not in the player report yet. this happens when */
+        /* the report is just opened and after a split. */
+      	row=GTK_CLIST(players_list)->rows;
+        gtk_clist_append(GTK_CLIST(players_list), row_texts);
+        gtk_clist_set_row_data(GTK_CLIST(players_list), row,
+      	                       &(listindex_to_playerindex[row]));
+        listindex_to_playerindex[row] = i;
+        playerindex_to_listindex[i] = row;
+        sort_needed=1;
       } else {
-	pds = player_get_diplstate(game.player_idx, i);
-	if (pds->type == DS_CEASEFIRE) {
-	  my_snprintf(dsbuf, sizeof(dsbuf), "%s (%d)",
-		      diplstate_text(pds->type), pds->turns_left);
-	} else {
-	  my_snprintf(dsbuf, sizeof(dsbuf), "%s",
-		      diplstate_text(pds->type));
+        /* the nation already had a row in the player report. in that case */
+        /* we just update the row. */
+	for(j=0; j<NUM_COLOUMS; j++) {
+          gtk_clist_set_text(GTK_CLIST(players_list), row, j, row_texts[j]);
 	}
       }
 
-      /* text for reputation */
-      my_snprintf(repbuf, sizeof(repbuf),
-		  reputation_text(game.players[i].reputation));
-
-      /* assemble the whole lot */
-      row[0] = namebuf;
-      row[1] = get_nation_name(game.players[i].nation);
-      row[2] = get_embassy_status(game.player_ptr, &game.players[i]);
-      row[3] = dsbuf;
-      row[4] = get_vision_status(game.player_ptr, &game.players[i]);
-      row[5] = repbuf;
-      row[6] = statebuf;
-      row[7] = (char*)player_addr_hack(&game.players[i]);  /* Fixme */
-      row[8] = idlebuf;
-
-      gtk_clist_append(GTK_CLIST(players_list), row);
+      /* now add some eye candy ... */
+      switch(player_get_diplstate(game.player_idx, i)->type) {
+      case DS_WAR:
+	state_col=colors_standard[COLOR_STD_RED];
+	break;
+      case DS_ALLIANCE:
+	state_col=colors_standard[COLOR_STD_GROUND];
+	break;
+      default:
+	state_col=colors_standard[COLOR_STD_BLACK];
+      }
+      gtk_clist_set_foreground(GTK_CLIST(players_list), row, state_col);
+    }
 
-      list_index_to_player_index[j] = i;
-      j++;
+    if (sort_needed) {
+      /* when new nations appear in the report, we have to sort it */
+      gtk_clist_sort(GTK_CLIST(players_list));
     }
-    
+
     gtk_clist_thaw(GTK_CLIST(players_list));
     gtk_widget_show_all(players_list);
   }
@@ -287,7 +376,7 @@
 **************************************************************************/
 void players_list_callback(GtkWidget *w, gint row, gint column)
 {
-  int player_index = list_index_to_player_index[row];
+  int player_index = LI_2_PI(row);
   struct player *pplayer = &game.players[player_index];
 
   if(pplayer->spaceship.state != SSHIP_NONE)
@@ -349,7 +438,7 @@
     return;
 
   row=(gint)selection->data;
-  player_index = list_index_to_player_index[row];
+  player_index = LI_2_PI(row);
 
   if(player_has_embassy(game.player_ptr, &game.players[player_index])) {
     struct packet_diplomacy_info pa;
@@ -379,7 +468,7 @@
     struct packet_generic_integer pa;    
 
     row = (gint)selection->data;
-    player_index = list_index_to_player_index[row];
+    player_index = LI_2_PI(row);
 
     pa.value = player_index;
     send_packet_generic_integer(&aconnection, PACKET_PLAYER_CANCEL_PACT,
@@ -402,7 +491,7 @@
     struct packet_generic_integer pa;    
 
     row = (gint)selection->data;
-    player_index = list_index_to_player_index[row];
+    player_index = LI_2_PI(row);
 
     pa.value = player_index;
     send_packet_generic_integer(&aconnection, PACKET_PLAYER_REMOVE_VISION,
@@ -423,7 +512,7 @@
       return;
 
   row=(gint)selection->data;
-  player_index = list_index_to_player_index[row];
+  player_index = LI_2_PI(row);
 
   if(player_has_embassy(game.player_ptr, &game.players[player_index]))
     popup_intel_dialog(&game.players[player_index]);
@@ -442,7 +531,7 @@
       return;
 
   row=(gint)selection->data;
-  player_index = list_index_to_player_index[row];
+  player_index = LI_2_PI(row);
 
   popup_spaceship_dialog(&game.players[player_index]);
 }