Index: CHANGES
===================================================================
RCS file: /cvs/cvsroot/loki_setup/CHANGES,v
retrieving revision 1.77
diff -u -r1.77 CHANGES
--- CHANGES	2003/02/27 06:16:01	1.77
+++ CHANGES	2003/03/29 10:46:13
@@ -2,6 +2,10 @@
 Stephane Peter (Codehost) - Tue Feb 11 20:33:32 PST 2003
  * Added the 'environment' tag to store the values of
    environment variables.
+TTimo (qeradiant.com) - Mon Feb 10 12:17:08 CET 2003
+ * Added SETUP_COMPONENT_PATH env to run scripts
+TTimo (qeradiant.com) - Sun Jan 26 23:36:06 CET 2003
+ * Ported over our subcomponent code
 Stephane Peter (Codehost) - Fri Dec  6 16:31:27 PST 2002
  * Do not display the main GTK dialog until we're done with the EULAs.
  * Various fixes for menu items
Index: Makefile.in
===================================================================
RCS file: /cvs/cvsroot/loki_setup/Makefile.in,v
retrieving revision 1.18
diff -u -r1.18 Makefile.in
--- Makefile.in	2003/03/26 05:45:10	1.18
+++ Makefile.in	2003/03/29 10:46:13
@@ -126,7 +126,7 @@
 	    strip image/setup.data/bin/$(os)/$(arch)/$(libc)/setup.gtk; \
 	    $(BRANDELF) -t $(os) image/setup.data/bin/$(os)/$(arch)/$(libc)/setup.gtk; \
 	else \
-		echo No directory to copy the binary files to.; \
+		echo image/setup.data/bin/$(os)/$(arch)/$(libc): No directory to copy the binary files to.; \
 	fi
 
 install-image: all
@@ -151,7 +151,7 @@
 	    cp setup.gtk $(IMAGE)/setup.data/bin/$(os)/$(arch)/$(libc); \
 	    strip $(IMAGE)/setup.data/bin/$(os)/$(arch)/$(libc)/setup.gtk; \
 	else \
-		echo No directory to copy the binary files to.; \
+		echo $(IMAGE)/setup.data/bin/$(os)/$(arch)/$(libc): No directory to copy the binary files to.; \
 	fi
 
 # Pretty LPP-specific
@@ -161,7 +161,7 @@
 	    strip $(IMAGE)/bin/$(os)/$(arch)/check; \
 	    cp check.glade $(IMAGE)/misc/; \
 	else \
-		echo No directory to copy the binary files to.; \
+		echo $(IMAGE)/bin/$(os)/$(arch): No directory to copy the binary files to.; \
 	fi
 
 # Copy loki_uninstall and the required files
@@ -176,7 +176,7 @@
 	        cp $$file $$path; \
 	    done; \
 	else \
-		echo No directory to copy the binary files to.; \
+		echo $(IMAGE)/bin/$(os)/$(arch): No directory to copy the binary files to.; \
 	fi
 
 install-loki_uninstall: loki_uninstall
@@ -191,7 +191,7 @@
 	        cp $$file $$path; \
 	    done; \
 	else \
-		echo No directory to copy the binary files to.; \
+		echo $(IMAGE)/loki_uninstall/bin/$(arch)/$(libc): No directory to copy the binary files to.; \
 	fi
 	@if [ -d $(UPDATES) ]; then \
 	    rm -rf $(UPDATES)/bin-$(arch)-$(UNINSTALL_VERSION)/; \
Index: copy.c
===================================================================
RCS file: /cvs/cvsroot/loki_setup/copy.c,v
retrieving revision 1.65
diff -u -r1.65 copy.c
--- copy.c	2003/02/27 06:16:01	1.65
+++ copy.c	2003/03/29 10:46:16
@@ -343,7 +343,7 @@
 				*slash = '\0';
 			}
 			push_curdir(dir);
-			if ( run_script(info, buf, 0) == 0 ) {
+			if ( run_script(info, buf, NULL, 0) == 0 ) {
 				const char *target = xmlGetProp(node, "target");
 				if ( target ) {
 					char targetpath[PATH_MAX];
@@ -677,7 +677,7 @@
 		if ( ! update(info, _("Running script"), 0, 0, current_option_txt) )
 			return 0;
 	}
-    return(run_script(info, script, -1));
+    return(run_script(info, script, dest, -1));
 }
 
 ssize_t copy_node(install_info *info, xmlNodePtr node, const char *dest,
@@ -766,6 +766,7 @@
 {
     ssize_t size, copied;
     char tmppath[PATH_MAX];
+	const char *component_dest;
 
     size = 0;
     while ( node ) {
@@ -828,6 +829,58 @@
                 }
 				current_component = NULL; /* Out of the component */
             }
+        }
+		/* Parse subcomponents */
+		else if (!strcmp(node->name, "subcomponent")) {
+			const char *name, *version;        
+			xmlNodePtr child;
+        	name = xmlGetProp(node, "name");
+        	if (!name)
+				log_fatal(_("SubComponent element must have a name"));
+        	version = xmlGetProp(node, "version");
+        	if (!version)
+        	{
+        		log_warning(_("SubComponent doesn't have a version"));
+          		version = strdup("noversion");
+        	}
+        	child = node->childs;
+        	while(child)
+        	{
+          		if(!strcmp(child->name, "option"))
+          		{
+            		/* only run if it has been actually selected for install */
+            		const char *install;
+            		install = xmlGetProp(child, "install");
+            		if (install && !strcmp(install,"true"))
+            		{
+              			/* add this subcomponent as a standard component */
+              			current_component = add_component_entry(info, name, version, 
+                		(strcmp(xmlGetProp(child, "install"), "true") != 0) ? 0 : 1);
+              			if(xmlGetProp(child, "path"))
+              			{
+                			/* if the path's been changed, use the path it was changed to */
+                			component_dest = xmlGetProp(child, "path");
+              			}
+              			else
+              			{
+                			/* if the path hasn't been changed, install to the default path */
+                			component_dest = xmlGetProp(child, "default_path");
+              			}
+              			// TODO: verify the install location ?
+              			copied = copy_node(info, child, component_dest, update);
+              			if ( copied > 0 ) 
+              			{
+                			size += copied;
+              			}
+              			copied = copy_tree(info, child->childs, component_dest, update);
+              			if(copied > 0)
+              			{
+                			size += copied;
+              			}
+            		}
+          		}
+          		child = child->next;
+        	}
         } else if ( ! strcmp(node->name, "environment") ) {
 			const char *prop = xmlGetProp(node, "var");
 			if ( prop ) {
Index: gtk_ui.c
===================================================================
RCS file: /cvs/cvsroot/loki_setup/gtk_ui.c,v
retrieving revision 1.78
diff -u -r1.78 gtk_ui.c
--- gtk_ui.c	2003/03/24 00:47:16	1.78
+++ gtk_ui.c	2003/03/29 10:46:20
@@ -143,6 +143,7 @@
 static GladeXML *setup_glade = NULL;
 static GladeXML *setup_glade_readme = NULL;
 static GladeXML *setup_glade_license = NULL;
+static GladeXML *setup_glade_subcomponent = NULL;
 static int cur_state;
 static install_info *cur_info;
 static int diskspace;
@@ -159,6 +160,7 @@
 void setup_destroy_view_readme_slot(GtkWidget*, gpointer);
 static yesno_answer gtkui_prompt(const char*, yesno_answer);
 static void gtkui_abort(install_info *info);
+static int gtkui_dir_prompt (install_info *info, const char *message, char *path);
 
 static int iterate_for_state(void)
 {
@@ -1189,6 +1191,189 @@
     }
 }
 
+/*************** subcomponent *********************/
+
+void setup_button_subcomponent_browse(GtkWidget *widget, gpointer func_data)
+{
+  GtkWidget *entry = (GtkWidget *)func_data;
+  xmlNodePtr node = gtk_object_get_data(GTK_OBJECT(widget), "node");
+  char *widget_data = gtk_object_get_data(GTK_OBJECT(widget), "data");
+  char path[PATH_MAX];
+  strncpy(path, gtk_entry_get_text(GTK_ENTRY(entry)), PATH_MAX);
+    
+  gtkui_dir_prompt(cur_info, widget_data, path);
+  
+  if(path[strlen(path)-1] != '/')
+    strcat(path, "/");
+  
+  gtk_entry_set_text(GTK_ENTRY(entry), path);
+  
+  xmlSetProp(node, "path", path);
+}
+
+void setup_subcomponent_toggle(GtkWidget *widget, gpointer func_data)
+{
+  int state = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  GtkWidget *entry = gtk_object_get_data(GTK_OBJECT(widget), "entry");
+  GtkWidget *button = gtk_object_get_data(GTK_OBJECT(widget), "button");
+  xmlNodePtr node = gtk_object_get_data(GTK_OBJECT(widget), "node");
+
+  if(state)
+  {
+    gtk_widget_set_sensitive(GTK_WIDGET(entry), TRUE);
+    gtk_widget_set_sensitive(GTK_WIDGET(button), TRUE);
+    xmlSetProp(node, "install", "true");
+    xmlSetProp(node, "path", gtk_entry_get_text(GTK_ENTRY(entry)));
+  }
+  else
+  {
+    gtk_widget_set_sensitive(GTK_WIDGET(entry), FALSE);
+    gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
+    xmlSetProp(node, "install", "false");
+    xmlSetProp(node, "path", "");
+  }
+}
+
+void subcomponent_update_entry(GtkWidget *widget, gpointer func_data)
+{
+  xmlNodePtr node = gtk_object_get_data(GTK_OBJECT(widget), "node");
+  char *path = malloc(strlen(gtk_entry_get_text(GTK_ENTRY(widget)))+2);
+  strcpy(path, gtk_entry_get_text(GTK_ENTRY(widget)));
+  
+  if (path[strlen(path)-1] != '/')
+	  strcat(path, "/");
+  
+  if(path)
+    xmlSetProp(node, "path", path);
+}
+
+void setup_button_subcomponent(GtkWidget *widget, gpointer func_data)
+{
+  xmlNodePtr node;
+  xmlNodePtr child;
+  GtkWidget *window, *frame, *w, *vbox, *hbox,
+            *check, *entry, *button, *sep;
+  const char *text;
+  char name[256];
+  int count=0;
+  int install=0;
+  
+  install_info *info = (install_info *)func_data;
+
+  setup_glade_subcomponent = glade_xml_new(SETUP_GLADE, "subcomponent_dialog");
+  glade_xml_signal_autoconnect(setup_glade_subcomponent);
+  window = glade_xml_get_widget(setup_glade_subcomponent, "subcomponent_dialog");
+  frame  = glade_xml_get_widget(setup_glade_subcomponent, "subcomponent_frame");
+  
+  w = glade_xml_get_widget(setup_glade_subcomponent, "subcomponent_button_cancel");
+  gtk_widget_hide(w);
+  
+  gtk_widget_realize(window);
+  gtk_widget_realize(frame);
+  gtk_container_foreach(GTK_CONTAINER(frame), empty_container, frame);
+  
+  w = gtk_vbox_new(TRUE, 2);
+  gtk_container_add(GTK_CONTAINER(frame), w);
+  gtk_widget_show(w);
+  
+  gtk_object_set_data(GTK_OBJECT(window), "data", w);
+  
+  node = info->config->root->childs;
+  while(node != NULL && strcmp(node->name, "subcomponent"))
+	  node = node->next;
+  if (!node)
+	  log_fatal(_("subcomponent element not found"));
+  child = node->childs;
+  // subcomponent options
+  while(child != NULL)
+  {
+    if(!strcmp(child->name, "option"))
+    {
+      if(!strcmp(xmlGetProp(child, "install"), "true"))
+        install=1;
+      else
+        install=0;
+      
+      vbox = gtk_vbox_new(FALSE, 2);
+      gtk_box_pack_start(GTK_BOX(w), vbox, TRUE, FALSE, 0);
+      gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
+      gtk_widget_show(vbox);
+
+      if(count)
+      {
+        sep = gtk_hseparator_new();
+        gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0);
+        gtk_widget_show(sep);
+      }
+      
+      text = xmlNodeListGetString(info->config, child->childs, 1);
+      parse_line(&text, name, sizeof(name));
+
+      check = gtk_check_button_new_with_label(name);
+      gtk_box_pack_start(GTK_BOX(vbox), check, FALSE, FALSE, 0);
+      if(install)
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
+      gtk_signal_connect(GTK_OBJECT(check), "toggled", GTK_SIGNAL_FUNC(setup_subcomponent_toggle), NULL);
+      gtk_object_set_data(GTK_OBJECT(check), "name", name);
+      gtk_object_set_data(GTK_OBJECT(check), "node", child);
+      gtk_widget_show(check);
+      
+      hbox = gtk_hbox_new(FALSE, 2);
+      gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, FALSE, 0);
+      gtk_widget_show(hbox);
+      
+      entry = gtk_entry_new();
+      //gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, FALSE, 0);
+      gtk_container_add(GTK_CONTAINER(hbox), entry);
+      if(!install)
+        gtk_widget_set_sensitive(GTK_WIDGET(entry), FALSE);
+      gtk_signal_connect(GTK_OBJECT(entry), "focus_out_event", GTK_SIGNAL_FUNC(subcomponent_update_entry), NULL);
+      gtk_object_set_data(GTK_OBJECT(entry), "name", name);
+      gtk_object_set_data(GTK_OBJECT(entry), "node", child);
+      gtk_widget_show(entry);
+      
+      if(xmlGetProp(child, "path"))
+      {
+        gtk_entry_set_text(GTK_ENTRY(entry), xmlGetProp(child, "path"));
+      }
+      else if (xmlGetProp(child, "default_path"))
+      {
+        gtk_entry_set_text(GTK_ENTRY(entry), xmlGetProp(child, "default_path"));
+      }
+        
+      
+      button = gtk_button_new_with_label("...");
+      gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+      gtk_object_set_data(GTK_OBJECT(button), "data", gtk_entry_get_text(GTK_ENTRY(entry)));
+      gtk_object_set_data(GTK_OBJECT(button), "node", child);
+      gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(setup_button_subcomponent_browse), entry);
+      if(!install)
+        gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
+      gtk_widget_show(button);
+      
+      gtk_object_set_data(GTK_OBJECT(check), "entry", entry);
+      gtk_object_set_data(GTK_OBJECT(check), "button", button);
+      
+      count++;
+    }
+    child = child->next;
+  }
+  gtk_widget_show(window);
+  //gtk_window_set_modal(GTK_WINDOW(window), TRUE);
+}
+
+void setup_button_subcomponent_cancel(GtkWidget *widget, gpointer func_data)
+{
+  GtkWidget *window = glade_xml_get_widget(setup_glade_subcomponent, "subcomponent_dialog");
+  gtk_widget_hide(window);
+}
+
+void setup_button_subcomponent_ok(GtkWidget *widget, gpointer func_data)
+{
+  GtkWidget *window = glade_xml_get_widget(setup_glade_subcomponent, "subcomponent_dialog");
+  gtk_widget_hide(window);
+}
+
 /********** UI functions *************/
 
 static install_state gtkui_init(install_info *info, int argc, char **argv, int noninteractive)
@@ -1496,7 +1681,13 @@
                     parse_option(info, xmlGetProp(node, "name"), child, window, options, 0, NULL, 0, NULL);
                 }
             }
-        }
+	} else if ( ! strcmp(node->name, "subcomponent") ) {
+		GtkWidget *widget = gtk_button_new_with_label(xmlGetProp(node, "name"));
+		gtk_box_pack_start(GTK_BOX(options), GTK_WIDGET(widget), FALSE, FALSE, 5);
+		gtk_object_set_data(GTK_OBJECT(widget), "data", (gpointer)xmlGetProp(node, "name"));
+		gtk_signal_connect(GTK_OBJECT(widget), "clicked", GTK_SIGNAL_FUNC(setup_button_subcomponent), (gpointer)info);
+		gtk_widget_show(widget);	
+	}
 	node = node->next;
     }
     init_install_path();
@@ -1681,6 +1872,63 @@
     gtkui_idle(info);
 }
 
+static int dirname_loop;
+static int prompt_ret;
+
+void store_dirname_slot(GtkFileSelection *selector, gpointer user_data) {
+  char *aux;
+  char *selected_dirname = (char *)user_data;
+  GtkWidget *parent;
+
+  parent = gtk_widget_get_toplevel (GTK_WIDGET(selector));
+  aux = gtk_file_selection_get_filename (GTK_FILE_SELECTION (parent));
+  if (strlen(aux))
+    strcpy(selected_dirname, aux);
+
+  dirname_loop = 0;
+}
+
+void abort_slot(GtkFileSelection *selector, gpointer user_data) {
+  dirname_loop = 0;
+  prompt_ret = 0;
+}
+
+static int gtkui_dir_prompt (install_info *info, const char *message, char *path)
+{
+  GtkWidget *selector;
+  char *aux;
+
+  /* Create the selector */   
+  selector = gtk_file_selection_new(message);
+
+  gtk_file_selection_set_filename(GTK_FILE_SELECTION(selector), path);
+  gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION(selector));
+   
+  gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(selector)->ok_button),
+    "clicked", GTK_SIGNAL_FUNC (store_dirname_slot), path);
+
+  gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(selector)->cancel_button),
+    "clicked", GTK_SIGNAL_FUNC (abort_slot), path);
+   
+  /* Display that dialog */
+   
+  gtk_grab_add(selector);
+  gtk_widget_show (selector);
+  gtk_grab_remove(selector);
+
+  dirname_loop = 1;
+  prompt_ret = 1;
+
+  while (dirname_loop==1)
+    gtk_main_iteration();
+
+  aux = gtk_file_selection_get_filename (GTK_FILE_SELECTION(selector));
+
+  gtk_widget_destroy(selector);
+  
+  return prompt_ret;
+}
+
 int gtkui_okay(Install_UI *UI, int *argc, char ***argv)
 {
     extern int force_console;
@@ -1730,7 +1978,3 @@
 #endif
 
 #endif
-
-
-
-
Index: install.c
===================================================================
RCS file: /cvs/cvsroot/loki_setup/install.c,v
retrieving revision 1.102
diff -u -r1.102 install.c
--- install.c	2003/03/27 04:16:26	1.102
+++ install.c	2003/03/29 10:46:24
@@ -999,7 +999,7 @@
 				log_fatal(_("XML: 'require' tag doesn't have a mandatory 'command' attribute"));
 			} else {
 				/* Launch the command */
-				if ( run_script(info, prop, 0) != 0 ) {
+				if ( run_script(info, prop, NULL, 0) != 0 ) {
 					/* We failed: print out error message */
 					text = xmlNodeListGetString(info->config, node->childs, 1);
 					if(text) {
@@ -1139,7 +1139,7 @@
 		return 0;
 
 	    /* Launch the command */
-	    return run_script(info, txt, 0) == 0;
+	    return run_script(info, txt, NULL, 0) == 0;
 	}
     }
     return 1;
@@ -1321,7 +1321,7 @@
 
     if (GetPreUnInstall(info) && info->installed_bytes>0) {
 		snprintf(path, sizeof(path), "sh %s", GetPreUnInstall(info));
-        run_script(info, path, 0);
+        run_script(info, path, NULL, 0);
     }
 
     if ( file_exists(info->install_path) ) {
@@ -1338,7 +1338,7 @@
 			/* Do not run scripts if nothing was installed */
 			if ( info->installed_bytes>0 ) {
 				for ( selem = opt->pre_script_list; selem; selem = selem->next ) { /* RPM pre-uninstall */
-					run_script(info, selem->script, 0);
+					run_script(info, selem->script, NULL, 0);
 				}
 			}
 
@@ -1355,7 +1355,7 @@
             }
 			if ( info->installed_bytes>0 ) {
 				for ( selem = opt->post_script_list; selem; selem = selem->next ) { /* RPM post-uninstall */
-					run_script(info, selem->script, 0);
+					run_script(info, selem->script, NULL, 0);
 				}
 			}
 
@@ -1373,7 +1373,7 @@
     }
     if (GetPostUnInstall(info) && info->installed_bytes>0) {
 		snprintf(path, sizeof(path), "sh %s", GetPostUnInstall(info));
-        run_script(info, path, 0);
+        run_script(info, path, NULL, 0);
     }
 
     if ( uninstall_generated ) {
@@ -1753,7 +1753,7 @@
 	if ( ! restoring_corrupt() ) {
 		script = GetPreInstall(info);
 		if ( script ) {
-			exitval = run_script(info, script, -1);
+			exitval = run_script(info, script, NULL, -1);
 		}
 	}
     return exitval;
@@ -1766,7 +1766,7 @@
 	if ( ! restoring_corrupt() ) {
 		script = GetPostInstall(info);
 		if ( script ) {
-			exitval = run_script(info, script, -1);
+			exitval = run_script(info, script, NULL, -1);
 		}
 	}
     return exitval;
@@ -1787,7 +1787,7 @@
 					/* Run the command and set it to "true" if the return value is ok */
 					str = xmlGetProp(child, "command");
 					if ( str ) {
-						cmd = run_script(info, str, 0);
+						cmd = run_script(info, str, NULL, 0);
 						xmlSetProp(child, "install", cmd ? "false" : "true");
 					} else {
 						log_fatal(_("Missing 'command' attribute for an option"));
@@ -2213,12 +2213,15 @@
 }
 
 /* Run some shell script commands */
-int run_script(install_info *info, const char *script, int arg)
+int run_script(install_info *info, const char *script, const char *dest, int arg)
 {
     char script_file[PATH_MAX];
     int fd;
     int exitval;
     char working_dir[PATH_MAX];
+	
+	if (!dest)
+		dest = "";
     
     /* We need to append the working directory onto the script name so
        it can always be found. Do this only if the script file exists
@@ -2255,7 +2258,8 @@
 					"SETUP_CDROMPATH=\"%s\"\n"
 					"SETUP_DISTRO=\"%s\"\n"
 					"SETUP_OPTIONTAGS=\"%s\"\n"
-					"export SETUP_PRODUCTNAME SETUP_PRODUCTVER SETUP_INSTALLPATH SETUP_SYMLINKSPATH SETUP_CDROMPATH SETUP_DISTRO SETUP_OPTIONTAGS\n"
+					"SETUP_COMPONENT_PATH=\"%s\"\n"
+					"export SETUP_PRODUCTNAME SETUP_PRODUCTVER SETUP_INSTALLPATH SETUP_SYMLINKSPATH SETUP_CDROMPATH SETUP_DISTRO SETUP_OPTIONTAGS SETUP_COMPONENT_PATH\n"
 					"%s%s\n",
 					info->name, info->version,
 					info->install_path,
@@ -2263,6 +2267,7 @@
 					info->cdroms_list ? info->cdroms_list->mounted : "",
 					info->distro ? distribution_symbol[info->distro] : "",
 					get_optiontags_string(info),
+					dest,
 					working_dir, script);     
             fchmod(fileno(fp),0755); /* Turn on executable bit */
             fclose(fp);
Index: install.h
===================================================================
RCS file: /cvs/cvsroot/loki_setup/install.h,v
retrieving revision 1.65
diff -u -r1.65 install.h
--- install.h	2003/02/27 06:16:01	1.65
+++ install.h	2003/03/29 10:46:25
@@ -353,7 +353,7 @@
    If 'arg' is >= 0, it is passed to the script as a numeric argument,
    otherwise the install path is passed as a command line argument.
  */
-extern int run_script(install_info *info, const char *script, int arg);
+extern int run_script(install_info *info, const char *script, const char *dest, int arg);
 
 /* returns true if any deviant paths are not writable */
 char check_deviant_paths(xmlNodePtr node, install_info *info);
@@ -383,4 +383,3 @@
 
 
 #endif /* _install_h */
-
