Initial revision
diff --git a/contiki-cpc/apps/configedit.c b/contiki-cpc/apps/configedit.c
new file mode 100644
index 0000000..5d43f72
--- /dev/null
+++ b/contiki-cpc/apps/configedit.c
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2002, Adam Dunkels.
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution. 
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.  
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+ *
+ * This file is part of the Contiki desktop environment
+ *
+ * $Id: configedit.c,v 1.1 2006/04/17 15:18:16 kthacker Exp $
+ *
+ */
+
+#include "contiki.h"
+
+#include "ctk-draw-service.h"
+#include "packet-service.h"
+
+#include "uip.h"
+#include "uip_arp.h"
+#include "resolv.h"
+#include "ctk.h"
+#include "ctk-draw.h"
+
+#include "program-handler.h"
+
+#include "cfs.h"
+
+//#include "cfs-init.h"
+#include "cfs-cpc.h"
+
+#include "loader.h"
+
+#include "log.h"
+
+
+#include <stdio.h>
+
+#include <string.h>
+
+/* TCP/IP configuration window. */
+static struct ctk_window window;
+
+#define LABELMAXWIDTH 12
+
+const static struct ctk_label cfslabel =
+  {CTK_LABEL(0, 1, LABELMAXWIDTH, 1, "Disk driver")};
+static char cfs[25];
+static struct ctk_textentry cfstextentry =
+  {CTK_TEXTENTRY(LABELMAXWIDTH + 1, 1, 16, 1, cfs, 24)};
+
+const static struct ctk_label themelabel =
+  {CTK_LABEL(0, 3, LABELMAXWIDTH, 1, "CTK theme")};
+static char theme[25];
+static struct ctk_textentry themetextentry =
+  {CTK_TEXTENTRY(LABELMAXWIDTH + 1, 3, 16, 1, theme, 24)};
+
+const static struct ctk_label driverlabel =
+  {CTK_LABEL(0, 5, LABELMAXWIDTH, 1, "Net driver")};
+static char driver[25];
+static struct ctk_textentry drivertextentry =
+  {CTK_TEXTENTRY(LABELMAXWIDTH + 1, 5, 16, 1, driver, 24)};
+
+const static struct ctk_label screensaverlabel =
+  {CTK_LABEL(0, 7, LABELMAXWIDTH, 1, "Screensaver")};
+static char screensaver[25];
+struct ctk_textentry screensavertextentry =
+  {CTK_TEXTENTRY(LABELMAXWIDTH + 1, 7, 16, 1, screensaver, 24)};
+
+
+const static struct ctk_label ipaddrlabel =
+  {CTK_LABEL(0, 9, LABELMAXWIDTH, 1, "IP address")};
+static char ipaddr[25];
+struct ctk_textentry ipaddrtextentry =
+  {CTK_TEXTENTRY(LABELMAXWIDTH + 1, 9, 16, 1, ipaddr, 24)};
+const static struct ctk_label netmasklabel =
+  {CTK_LABEL(0, 11, LABELMAXWIDTH, 1, "Netmask")};
+static char netmask[25];
+static struct ctk_textentry netmasktextentry =
+  {CTK_TEXTENTRY(LABELMAXWIDTH + 1, 11, 16, 1, netmask, 24)};
+const static struct ctk_label gatewaylabel =
+  {CTK_LABEL(0, 13, LABELMAXWIDTH, 1, "Gateway")};
+static char gateway[25];
+static struct ctk_textentry gatewaytextentry =
+  {CTK_TEXTENTRY(LABELMAXWIDTH + 1, 13, 16, 1, gateway, 24)};
+const static struct ctk_label dnsserverlabel =
+  {CTK_LABEL(0, 15, LABELMAXWIDTH, 1, "DNS server")};
+static char dnsserver[25];
+static struct ctk_textentry dnsservertextentry =
+  {CTK_TEXTENTRY(LABELMAXWIDTH + 1, 15, 16, 1, dnsserver, 24)};
+
+const static struct ctk_button savebutton =
+  {CTK_BUTTON(0, 17, 12, "Save & close")};
+const static struct ctk_button cancelbutton =
+  {CTK_BUTTON(24, 17, 6, "Cancel")};
+
+/*static DISPATCHER_SIGHANDLER(configedit_sighandler, s, data);
+static struct dispatcher_proc p =
+  {DISPATCHER_PROC("Config editor", NULL, configedit_sighandler, NULL)};
+  static ek_id_t id;*/
+
+EK_EVENTHANDLER(configedit_eventhandler, ev, data);
+EK_PROCESS(p, "Config editor", EK_PRIO_NORMAL,
+	   configedit_eventhandler, NULL, NULL);
+static ek_id_t id = EK_ID_NONE;
+
+
+/*-----------------------------------------------------------------------------------*/
+struct ptentry {
+  char c;
+  char * (* pfunc)(char *str);
+};
+
+/*-----------------------------------------------------------------------------------*/
+static char *
+parse(char *str, struct ptentry *t)
+{
+  struct ptentry *p;
+
+  /* Loop over the parse table entries in t in order to find one that
+     matches the first character in str. */
+  for(p = t; p->c != 0; ++p) {
+    if(*str == p->c) {
+      /* Skip rest of the characters up to the first space. */
+      while(*str != ' ') {
+	++str;
+      }
+
+      /* Skip all spaces.*/
+      while(*str == ' ') {
+	++str;
+      }
+
+      /* Call parse table entry function and return. */
+      return p->pfunc(str);
+    }
+  }
+
+  /* Did not find matching entry in parse table. We just call the
+     default handler supplied by the caller and return. */
+  return p->pfunc(str);
+}
+/*-----------------------------------------------------------------------------------*/
+static char *
+skipnewline(char *str)
+{
+  /* Skip all characters until the newline. */
+  while(*str != '\n') {
+    ++str;
+  }
+
+  /* Return a pointer to the first character after the newline. */
+  return str + 1;
+}
+/*-----------------------------------------------------------------------------------*/
+static char *
+nullterminate(char *str)
+{
+  char *nt;
+
+  /* Nullterminate string. Start with finding newline character. */
+  for(nt = str; *nt != '\r' &&
+	*nt != '\n'; ++nt);
+
+  /* Replace newline with a null char. */
+  *nt = 0;
+
+  /* Remove trailing spaces. */
+  while(nt > str && *(nt - 1) == ' ') {
+    *(nt - 1) = 0;
+    --nt;
+  }
+    
+  /* Return pointer to null char. */
+  return nt;
+}
+/*-----------------------------------------------------------------------------------*/
+static char * __fastcall__
+copystr(char *dst, char *src, int len)
+{
+  char *nt = nullterminate(src);
+  strncpy(dst, src, len);
+  return nt + 1;
+}
+/*-----------------------------------------------------------------------------------*/
+static char *
+loaddriver(char *str)
+{
+  return copystr(driver, str, sizeof(driver));
+}
+/*-----------------------------------------------------------------------------------*/
+static char *
+loadtheme(char *str)
+{
+  return copystr(theme, str, sizeof(theme));
+}
+/*-----------------------------------------------------------------------------------*/
+static char *
+loadcfs(char *str)
+{
+  return copystr(cfs, str, sizeof(cfs));
+}
+/*-----------------------------------------------------------------------------------*/
+static char *
+loadscreensaver(char *str)
+{
+  return copystr(screensaver, str, sizeof(screensaver));
+}
+/*-----------------------------------------------------------------------------------*/
+static char *
+ipaddrconf(char *str)
+{
+  return copystr(ipaddr, str, sizeof(ipaddr));
+}
+/*-----------------------------------------------------------------------------------*/
+static char *
+netmaskconf(char *str)
+{
+  return copystr(netmask, str, sizeof(netmask));
+}
+/*-----------------------------------------------------------------------------------*/
+static char *
+drconf(char *str)
+{
+  return copystr(gateway, str, sizeof(gateway));
+}
+/*-----------------------------------------------------------------------------------*/
+static char *
+dnsconf(char *str)
+{
+  return copystr(dnsserver, str, sizeof(dnsserver));
+}
+/*-----------------------------------------------------------------------------------*/
+const static struct ptentry initparsetab[] =
+  {{'n', loaddriver},
+   {'t', loadtheme},
+   {'c', loadcfs},
+   {'s', loadscreensaver},
+   {'i', ipaddrconf},
+   {'m', netmaskconf},
+   {'r', drconf},
+   {'d', dnsconf},
+   {'#', skipnewline},
+
+   /* Default action */
+   {0, skipnewline}};
+static void
+initscript(void)
+{
+  char line[40], *lineptr;
+  /*  struct c64_fs_file f;*/
+  int f;
+
+  if((f = cfs_open("config.cfg", 0)) == -1) {
+    return;
+  }
+  line[0] = ' ';
+  while(line[0] != '.' &&
+	line[0] != 0) {
+    lineptr = line;
+    do {
+      if(cfs_read(f, lineptr, 1) != 1) {
+	cfs_close(f);
+	return;
+      }
+      ++lineptr;
+    } while(*(lineptr - 1) != '\n' &&
+	    *(lineptr - 1) != '\r');
+
+    *lineptr = 0;
+
+    if(line[0] != '.' &&
+       line[0] != 0) {
+      parse(line, initparsetab);
+    }
+    
+  }
+  cfs_close(f);
+  return;
+}
+/*-----------------------------------------------------------------------------------*/
+static int makeline(char *line, char c, char *str)
+{
+  int len;
+
+  len = strlen(str);
+  
+  line[0] = c;
+  line[1] = ' ';
+  strcpy(&line[2], str);
+  line[2 + len] = '\n';
+  line[3 + len] = 0;
+  return len + 3;
+}
+
+#if 0
+struct scriptvar
+{
+ const char *var;
+ char chr;
+};
+
+cstatic struct scriptvar scriptvars[]=
+{
+{cfs,'c'},
+
+
+};
+#endif
+
+
+/*-----------------------------------------------------------------------------------*/
+static void
+savescript(void)
+{
+  char line[40];
+  /*  struct c64_fs_file f;*/
+  int f;
+  
+  f = cfs_open("@:config.cfg", CFS_WRITE);
+  if(f == -1) {
+    log_message("Could not open config.cfg", "");
+    return;
+  }
+  if(cfs[0] != 0) {
+	int len = makeline(line, 'c',cfs);
+	cfs_write(f, line, len);
+//    cfs_write(f, line, makeline(line, 'c', cfs));
+  }
+  if(theme[0] != 0) {
+	int len = makeline(line, 't',theme);
+	cfs_write(f, line, len);
+//    cfs_write(f, line, makeline(line, 't', theme));
+  }
+  if(driver[0] != 0) {
+	int len = makeline(line, 'n',driver);
+	cfs_write(f, line, len);
+//    cfs_write(f, line, makeline(line, 'n', driver));
+  }
+  if(ipaddr[0] != 0) {
+	int len = makeline(line, 'i',ipaddr);
+	cfs_write(f, line, len);
+//    cfs_write(f, line, makeline(line, 'i', ipaddr));
+  }
+  if(netmask[0] != 0) {
+	int len = makeline(line, 'm',netmask);
+	cfs_write(f, line, len);
+//    cfs_write(f, line, makeline(line, 'm', netmask));
+  }
+  if(gateway[0] != 0) {
+	int len = makeline(line, 'r',gateway);
+	cfs_write(f, line, len);
+//    cfs_write(f, line, makeline(line, 'r', gateway));
+  }
+  if(dnsserver[0] != 0) {
+	int len = makeline(line, 'd',dnsserver);
+	cfs_write(f, line, len);
+//    cfs_write(f, line, makeline(line, 'd', dnsserver));
+  }
+  
+  if(screensaver[0] != 0) {
+	int len = makeline(line, 's',screensaver);
+	cfs_write(f, line, len);
+//    cfs_write(f, line, makeline(line, 's', screensaver));
+  }
+  
+  strcpy(line, ".\n\0\n\n\n");
+  cfs_write(f, line, strlen(line));
+  
+  cfs_close(f);
+  
+}
+/*-----------------------------------------------------------------------------------*/
+LOADER_INIT_FUNC(configedit_init, arg)
+{
+  arg_free(arg);
+  
+  if(id == EK_ID_NONE) {
+    id = ek_start(&p);
+  }    
+}
+/*-----------------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------------*/
+static void
+configedit_quit(void)
+{
+  ek_exit();
+  id = EK_ID_NONE;
+  LOADER_UNLOAD();
+}
+/*-----------------------------------------------------------------------------------*/
+static void
+quit_services(void)
+{
+  cfs_cpc_init(NULL);
+  ctk_draw_quit();  
+}
+/*-----------------------------------------------------------------------------------*/
+EK_EVENTHANDLER(configedit_eventhandler, ev, data)
+{
+  EK_EVENTHANDLER_ARGS(ev, data);
+
+  if(ev == EK_EVENT_INIT) {
+    /* Create window. */
+    ctk_window_new(&window, 32, 18, "Config editor");
+
+    CTK_WIDGET_ADD(&window, &cfslabel);  
+    CTK_WIDGET_ADD(&window, &cfstextentry);
+    CTK_TEXTENTRY_CLEAR(&cfstextentry);
+
+    CTK_WIDGET_ADD(&window, &themelabel);  
+    CTK_WIDGET_ADD(&window, &themetextentry);
+    CTK_TEXTENTRY_CLEAR(&themetextentry);
+    
+    CTK_WIDGET_ADD(&window, &driverlabel);  
+    CTK_WIDGET_ADD(&window, &drivertextentry);
+    CTK_TEXTENTRY_CLEAR(&drivertextentry);
+
+    CTK_WIDGET_ADD(&window, &screensaverlabel);
+    CTK_WIDGET_ADD(&window, &screensavertextentry);
+    CTK_TEXTENTRY_CLEAR(&screensavertextentry);
+
+    CTK_WIDGET_ADD(&window, &ipaddrlabel);  
+    CTK_WIDGET_ADD(&window, &ipaddrtextentry);
+    CTK_TEXTENTRY_CLEAR(&ipaddrtextentry);
+
+    CTK_WIDGET_ADD(&window, &netmasklabel);
+    CTK_WIDGET_ADD(&window, &netmasktextentry);
+    CTK_TEXTENTRY_CLEAR(&netmasktextentry);
+
+    CTK_WIDGET_ADD(&window, &gatewaylabel);
+    CTK_WIDGET_ADD(&window, &gatewaytextentry);
+    CTK_TEXTENTRY_CLEAR(&gatewaytextentry);
+
+    CTK_WIDGET_ADD(&window, &dnsserverlabel);
+    CTK_WIDGET_ADD(&window, &dnsservertextentry);
+    CTK_TEXTENTRY_CLEAR(&dnsservertextentry);
+
+
+    CTK_WIDGET_ADD(&window, &savebutton);
+    CTK_WIDGET_ADD(&window, &cancelbutton);    
+    
+    CTK_WIDGET_FOCUS(&window, &cfstextentry);  
+
+    /* Fill the configuration strings with values from the current
+       configuration */
+    initscript();
+    
+    ctk_window_open(&window);
+
+  } else if(ev == ctk_signal_button_activate) {   
+    if(data == (ek_data_t)&savebutton) {
+      savescript();
+      quit_services();
+      ctk_window_close(&window);
+      configedit_quit();
+      program_handler_load("config.prg", NULL);
+    } else if(data == (ek_data_t)&cancelbutton) {
+      ctk_window_close(&window);
+      configedit_quit();
+    }
+  } else if(ev == ctk_signal_window_close ||
+	    ev == EK_EVENT_REQUEST_EXIT) {
+    ctk_window_close(&window);
+    configedit_quit();
+  }
+}
+/*-----------------------------------------------------------------------------------*/