Esempio n. 1
0
static int
TestGUI(void *obj, AG_Window *win)
{
	char path[AG_PATHNAME_MAX];
	AG_TestInstance *ti = obj;
	AG_Box *box;
	AG_Textbox *tb;

	someString[0] = '\0';

	AG_GetString(agConfig, "load-path", path, sizeof(path));
	AG_LabelNew(win, 0, "load-path: %s", path);
	AG_GetString(agConfig, "save-path", path, sizeof(path));
	AG_LabelNew(win, 0, "save-path: %s", path);

	/* Tie some globals to the config settings */
	AG_BindInt(agConfig, "some-int", &someInt);
	AG_BindInt(agConfig, "some-bool", &someBool);
	AG_BindString(agConfig, "some-string", someString, sizeof(someString));
	AG_SetInt(agConfig, "some-int", 2345);

	/* Create some widgets */
	AG_NumericalNewInt(win, 0, NULL, "Some int: ", &someInt);
	AG_CheckboxNewInt(win, 0, "Some bool", &someBool);
	tb = AG_TextboxNew(win, AG_TEXTBOX_HFILL, "Some string: ");
	AG_TextboxBindUTF8(tb, someString, sizeof(someString));

	box = AG_BoxNewHoriz(win, AG_BOX_EXPAND);
	{
		AG_ButtonNewFn(box, 0, "Load configuration", LoadConfig, "%p", ti);
		AG_ButtonNewFn(box, 0, "Save configuration", SaveConfig, "%p", ti);
	}
	return (0);
}
Esempio n. 2
0
/* Create the "save-path" / "tmp-path" directories, if they don't exist. */
int
AG_CreateDataDir(void)
{
	char dataDir[AG_PATHNAME_MAX];
	char tmpDir[AG_PATHNAME_MAX];

	AG_GetString(agConfig, "save-path", dataDir, sizeof(dataDir));
	AG_GetString(agConfig, "tmp-path", tmpDir, sizeof(tmpDir));

	if (AG_FileExists(dataDir) == 0 && AG_MkDir(dataDir) != 0)
		return (-1);
	if (AG_FileExists(tmpDir) == 0 && AG_MkDir(tmpDir) != 0)
		return (-1);
	
	return (0);
}
Esempio n. 3
0
/* Copy the full pathname of a data file to a sized buffer. */
int
AG_ConfigFile(const char *path_key, const char *name, const char *ext,
    char *path, size_t path_len)
{
	char file[AG_PATHNAME_MAX];
	char *dir, *pathp = path;
	int rv;

	AG_GetString(agConfig, path_key, path, path_len);

	for (dir = Strsep(&pathp, AG_PATHSEPMULTI);
	     dir != NULL;
	     dir = Strsep(&pathp, AG_PATHSEPMULTI)) {
		Strlcpy(file, dir, sizeof(file));

		if (name[0] != AG_PATHSEPCHAR) {
			Strlcat(file, AG_PATHSEP, sizeof(file));
		}
		Strlcat(file, name, sizeof(file));
		if (ext != NULL) {
			Strlcat(file, ".", sizeof(file));
			Strlcat(file, ext, sizeof(file));
		}
		if ((rv = AG_FileExists(file)) == 1) {
			if (Strlcpy(path, file, path_len) >= path_len) {
				AG_SetError(_("The search path is too big."));
				return (-1);
			}
			return (0);
		} else if (rv == -1) {
			AG_SetError("%s: %s", file, AG_GetError());
			return (-1);
		}
	}
	AG_GetString(agConfig, path_key, path, path_len);
	AG_SetError(_("Cannot find %s.%s (in <%s>:%s)."), name,
	    (ext != NULL) ? ext : "", path_key, path);
	return (-1);
}
Esempio n. 4
0
File: drv.c Progetto: varialus/agar
/*
 * Dump the display surface(s) to a jpeg in ~/.appname/screenshot/.
 * It is customary to assign a AG_GlobalKeys(3) shortcut for this function.
 */
void
AG_ViewCapture(void)
{
	AG_Surface *s;
	char *pname;
	char dir[AG_PATHNAME_MAX];
	char file[AG_PATHNAME_MAX];
	Uint seq;

	if (agDriverSw == NULL) {
		Verbose("AG_ViewCapture() is not implemented under "
		        "multiple-window drivers\n");
		return;
	}

	AG_LockVFS(&agDrivers);

	if (AGDRIVER_SW_CLASS(agDriverSw)->videoCapture(agDriverSw, &s) == -1) {
		Verbose("Capture failed: %s\n", AG_GetError());
		goto out;
	}

	/* Save to a new file. */
	AG_GetString(agConfig, "save-path", dir, sizeof(dir));
	Strlcat(dir, AG_PATHSEP, sizeof(dir));
	Strlcat(dir, "screenshot", sizeof(dir));
	if (!AG_FileExists(dir) && AG_MkPath(dir) == -1) {
		Verbose("Capture failed: %s\n", AG_GetError());
		goto out;
	}
	pname = (agProgName != NULL) ? agProgName : "agarapp";
	for (seq = 0; ; seq++) {
		Snprintf(file, sizeof(file), "%s%c%s%u.jpg",
		    dir, AG_PATHSEPCHAR, pname, seq++);
		if (!AG_FileExists(file))
			break;			/* XXX race condition */
	}
	if (AG_SurfaceExportJPEG(s, file) == 0) {
		Verbose("Saved capture to: %s\n", file);
	} else {
		Verbose("Capture failed: %s\n", AG_GetError());
	}
	AG_SurfaceFree(s);
out:
	AG_UnlockVFS(&agDrivers);
}
Esempio n. 5
0
static void
SelectPath(AG_Event *event)
{
	char path[AG_PATHNAME_MAX];
	AG_Window *win;
	AG_DirDlg *dd;
	char *key = AG_STRING(1);
	AG_Textbox *tbox = AG_PTR(2);

	win = AG_WindowNew(0);
	dd = AG_DirDlgNew(win, AG_DIRDLG_EXPAND|AG_DIRDLG_CLOSEWIN);
	AG_GetString(agConfig, key, path, sizeof(path));
	if (AG_DirDlgSetDirectoryS(dd, path) == -1) {
		AG_MkPath(path);
		(void)AG_DirDlgSetDirectoryS(dd, path);
	}
	AG_WindowSetGeometryAlignedPct(win, AG_WINDOW_MC, 30, 30);
	AG_WindowSetCaption(win, _("Select %s directory"), key);
	AG_DirDlgOkAction(dd, SelectPathOK, "%s,%p,%p", key, tbox, win);
	AG_WindowShow(win);
}
Esempio n. 6
0
void MainLoop(int argc, char *argv[])
{
   int c;
   char *drivers = NULL;
   char *optArg;
   char strbuf[2048];
   char homedir[2048];
   const SDL_VideoInfo *inf;
   BOOL flag;
   SDL_Surface *s;

//   mtrace();
   if(AG_GetVariable(agConfig, "font.size", NULL) == NULL) { 
	AG_SetInt(agConfig, "font.size", UI_PT);
   }
   while ((c = AG_Getopt(argc, argv, "?fWd:w:h:T:t:c:T:F:S:o:O:l:s:i:", &optArg, NULL))
          != -1) {
              switch (c) {
              case 'd':
                      drivers = optArg;
                      break;
              case 'f':
                      /* Force full screen */
                      AG_SetBool(agConfig, "view.full-screen", 1);
                      break;
              case 'W':
                      /* Force Window */
                      AG_SetBool(agConfig, "view.full-screen", 0);
                      break;
              case 'T':
                      /* Set an alternate font directory */
                      AG_SetString(agConfig, "font-path", optArg);
                      break;
              case 'F':
                      /* Set an alternate font face */
                      AG_SetString(agConfig, "font.face", optArg);
                      break;
              case 'S':
                  /* Set an alternate font face */
                  AG_SetInt(agConfig, "font.size", atoi(optArg));
                  break;
              case 'o':
                  /* Set an alternate font face */
                  AG_SetString(agConfig, "osdfont.face", optArg);
                  break;
              case 'O':
                  /* Set an alternate font face */
                  AG_SetInt(agConfig, "osdfont.size", atoi(optArg));
                  break;
              case 'l':
                  /* Set an alternate font face */
                  AG_SetString(agConfig, "load-path", optArg);
                  break;
              case 's':
                  /* Set an alternate font face */
                  AG_SetString(agConfig, "save-path", optArg);
                  break;
              case 'i':
                  /* Set an alternate font face */
                  AG_SetString(agConfig, "save-path", optArg);
                  AG_SetString(agConfig, "load-path", optArg);
                  break;
              case 't':
                  /* Change the default font */
                  AG_TextParseFontSpec(optArg);
                  break;
          case '?':
          default:
                  printf("%s [-v] [-f|-W] [-d driver] [-r fps] [-t fontspec] "
                         "[-w width] [-h height] "
                	 "[-F font.face] [-S font.size]"
			 "[-o osd-font.face] [-O osd-font.size]"
			 "[-s SavePath] [-l LoadPath] "
                         "[-T font-path]\n\n"
			 "Usage:\n"
			 "-f : FullScreen\n-W:Window Mode\n",
                         agProgName);
                  exit(0);
          }
    }
   
    if(SDL_getenv("HOME") != NULL) {
	strcpy(homedir, SDL_getenv("HOME"));
    } else {
        strcpy(homedir, ".");
    }
    XM7_DebugLog(XM7_LOG_DEBUG, "HOME = %s", homedir);

#ifdef _WINDOWS
	AG_PrtString(agConfig, "font-path", "%s:%s/xm7:%s:.",
		homedir, homedir, FONTPATH);
#else
    flag = FALSE;
    if(AG_GetString(agConfig, "font-path", strbuf, 2047) != NULL) {
       if((strlen(strbuf) <= 0) || (strncmp(strbuf, "_agFontVera", 11) == 0)){
	  flag = TRUE;
	 }
    } else {
       flag = TRUE;
    }
    if(flag) AG_PrtString(agConfig, "font-path", "%s/.fonts:%s:%s/.xm7:%s:.", 
		homedir, homedir, homedir, FONTPATH);
    flag = FALSE;
   
    XM7_DebugLog(XM7_LOG_DEBUG, "font-path = %s", strbuf);
#endif /* _WINDOWS */
    flag = FALSE;
    if(AG_GetString(agConfig, "font.face", strbuf, 511) != NULL) {
       if((strlen(strbuf) <= 0) || (strncmp(strbuf, "_agFontVera", 11) == 0)){
	  flag = TRUE;
       }
    } else {
	flag = TRUE;
    }
    if(flag) AG_SetString(agConfig, "font.face", UI_FONT);
    flag = FALSE;
    XM7_DebugLog(XM7_LOG_DEBUG, "font.face = %s", strbuf);
   
    stopreq_flag = FALSE;
    run_flag = TRUE;
    // Debug
#ifdef _XM7_FB_DEBUG // Force FB.
drivers = "sdlfb:width=1280:height=880:depth=32";
#endif
	/*
	 * Agar のメインループに入る
	 */

    if(drivers == NULL)  {
#ifdef USE_OPENGL
       if(AG_InitGraphics(NULL) == -1){
                fprintf(stderr, "%s\n", AG_GetError());
                return;
        }
#else
       if(AG_InitGraphics("cocoa,sdlfb") == -1){
                fprintf(stderr, "%s\n", AG_GetError());
                return;
        }
#endif
    } else {
        if (AG_InitGraphics(drivers) == -1) {
                fprintf(stderr, "%s\n", AG_GetError());
                return;
        }
    }
    OnCreate((AG_Widget *)NULL);
//    AG_AtExitFunc(OnDestroy);
    XM7_DebugLog(XM7_LOG_DEBUG, "Widget creation OK.");
   
   XM7_DebugLog(XM7_LOG_INFO, "Emulate version:%d", fm7_ver);
   SDL_InitSubSystem(SDL_INIT_AUDIO | SDL_INIT_JOYSTICK);
   XM7_DebugLog(XM7_LOG_DEBUG, "Audio and JOYSTICK subsystem was initialised.");

   InitInstance();
   XM7_DebugLog(XM7_LOG_DEBUG, "InitInstance() OK.");
   if(agDriverSw && AG_UsingSDL(NULL)) {
      SDL_Init(SDL_INIT_VIDEO);
      XM7_DebugLog(XM7_LOG_INFO, "Start Single WM with SDL.");
      switch(fm7_ver) {
       case 1: // FM7/77
	 if(!(LoadGlobalIconPng(NULL, "tamori.png"))) {
	    LoadGlobalIconPng(NULL, "xm7.png");
	 }
	 break;
       case 2: // FM77AV
	 if(!(LoadGlobalIconPng(NULL, "fujitsu.png"))) {
	    LoadGlobalIconPng(NULL, "xm7.png");
	 }
	 break;
       case 3: // FM77AV20/40/EX/SX
	 if(!(LoadGlobalIconPng(NULL, "fujitsu2.png"))) {
	    LoadGlobalIconPng(NULL, "xm7.png");
	 }
	 break;
       default:
	 LoadGlobalIconPng(NULL, "xm7.png");
	 break;
      }
   } else { // WM function is managed by SDL, load and set icon for WM. 
      SDL_Init(SDL_INIT_VIDEO);
      XM7_DebugLog(XM7_LOG_INFO, "Start multi window mode.");
   }
       
   stopreq_flag = FALSE;
   run_flag = TRUE;
   AG_DrawInitsub();

   inf = SDL_GetVideoInfo();
   if(inf != NULL) {
      RootVideoWidth = inf->current_w;
      RootVideoHeight = inf->current_h;
   } else {
      RootVideoWidth = 640;
      RootVideoHeight = 400;
   }

   newResize = FALSE;
   nDrawTick1D = XM7_timeGetTime();
   nDrawTick1E = nDrawTick1D;

   ResizeWindow_Agar2(nDrawWidth, nDrawHeight);
   XM7_DebugLog(XM7_LOG_DEBUG, "Screen is %d x %d.", nDrawWidth, nDrawHeight);
    switch(nErrorCode) 
     {
      case 0:
	break;
      case 1:
	ErrorPopup(gettext("Error init VM.\nPlease check ROMS and system-memory.\n"));
	break;
      case 2:
	ErrorPopup(gettext("Error init Emulator.\nPlease check window system, display and more.\n"));
	break;
      default:
	ErrorPopup(gettext("Unknown error on setup.\nPlease email to author."));
	break;
     }
#if 0
   mtrace();
#endif
   if(DrawArea != NULL) {
      AG_RedrawOnTick(DrawArea, 1000 / nDrawFPS);
      XM7_DebugLog(XM7_LOG_INFO, "Direct draw mode.");
   } else if(GLDrawArea != NULL) {
      AG_RedrawOnTick(GLDrawArea, 1000 / nDrawFPS);
      XM7_DebugLog(XM7_LOG_INFO, "OpenGL mode.");
   }
   bEventRunFlag == TRUE;
   AGDrawTaskEvent(TRUE);
//   muntrace();
   XM7_DebugLog(XM7_LOG_INFO, "All End.");
}
Esempio n. 7
0
static int
Open(void *obj, const char *path, Uint flags)
{
	char dbName[128];
	AG_DbMySQL *db = obj;
	MYSQL *my;
	unsigned long myFlags = CLIENT_REMEMBER_OPTIONS;
	char *s;
	Uint i;
	my_bool b = 1;
	
	if ((my = mysql_init(NULL)) == NULL) {
		AG_SetError("mysql_init failed");
		return (-1);
	}
	if (path != NULL) {
		Strlcpy(dbName, path, sizeof(dbName));
	} else {
		AG_GetString(db, "database", dbName, sizeof(dbName));
	}
	if (AG_GetInt(db,"compress") == 1)	{ myFlags |= CLIENT_COMPRESS; }
	if (AG_GetInt(db,"local-files") == 1)	{ myFlags |= CLIENT_LOCAL_FILES; }
	if (AG_GetInt(db,"ssl") == 1)		{ myFlags |= CLIENT_SSL; }

	if (AG_GetUint(db,"ssl-verify-cert") == 1)	 { mysql_options(my, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &b); }
	if (AG_GetUint(db,"secure-auth") == 1)		 { mysql_options(my, MYSQL_SECURE_AUTH, &b); }
	if ((s = AG_GetStringP(db,"init-cmd")) != NULL)	 { mysql_options(my, MYSQL_INIT_COMMAND, s); }
	if ((s = AG_GetStringP(db,"cnf-file")) != NULL)	 { mysql_options(my, MYSQL_READ_DEFAULT_FILE, s); }
	if ((s = AG_GetStringP(db,"cnf-group")) != NULL) { mysql_options(my, MYSQL_READ_DEFAULT_GROUP, s); }

	if ((s = AG_GetStringP(db,"protocol")) != NULL) {
		switch (tolower(s[0])) {
		case 't':	i = MYSQL_PROTOCOL_TCP;		break;
		case 's':	i = MYSQL_PROTOCOL_SOCKET;	break;
		case 'p':	i = MYSQL_PROTOCOL_PIPE;	break;
		case 'm':	i = MYSQL_PROTOCOL_MEMORY;	break;
		default:	i = MYSQL_PROTOCOL_DEFAULT;	break;
		}
		mysql_options(my, MYSQL_OPT_PROTOCOL, (const char *)&i);
	}
	if ((i = AG_GetUint(db,"read-timeout")) != 0)	 { mysql_options(my, MYSQL_OPT_READ_TIMEOUT, (const char *)&i); }
	if ((i = AG_GetUint(db,"write-timeout")) != 0)	 { mysql_options(my, MYSQL_OPT_WRITE_TIMEOUT, (const char *)&i); }
	if (AG_GetUint(db,"reconnect") == 1)		 { mysql_options(my, MYSQL_OPT_RECONNECT, (const char *)&b); }

	if ((s = AG_GetStringP(db,"charset")) != NULL)	 { mysql_options(my, MYSQL_SET_CHARSET_NAME, s); }
	if ((s = AG_GetStringP(db,"charset-dir")) != NULL) { mysql_options(my, MYSQL_SET_CHARSET_DIR, s); }

	db->my = mysql_real_connect(my,
	    AG_GetStringP(my,"host"),
	    AG_GetStringP(my,"user"),
	    AG_GetStringP(my,"pass"),
	    dbName,
	    AG_GetInt(my,"port"),
	    AG_GetStringP(my,"unix-socket"),
	    myFlags);
	if (db->my == NULL) {
		AG_SetError("MySQL: %s", mysql_error(my));
		mysql_close(my);
		return (-1);
	}
	return (0);
}
Esempio n. 8
0
static int
SDLGL_OpenVideo(void *obj, Uint w, Uint h, int depth, Uint flags)
{
	char buf[16];
	AG_Driver *drv = obj;
	AG_DriverSw *dsw = obj;
	AG_DriverSDLGL *sgl = obj;
	Uint32 sFlags = SDL_OPENGL;
	int newDepth;

	/* Set the requested display options. */
	if (flags & AG_VIDEO_RESIZABLE) { sFlags |= SDL_RESIZABLE; }
	if (flags & AG_VIDEO_ANYFORMAT) { sFlags |= SDL_ANYFORMAT; }
	if (flags & AG_VIDEO_HWPALETTE) { sFlags |= SDL_HWPALETTE; }
	if (flags & AG_VIDEO_DOUBLEBUF) { sFlags |= SDL_DOUBLEBUF; }
	if (flags & AG_VIDEO_FULLSCREEN) { sFlags |= SDL_FULLSCREEN; }
	if (flags & AG_VIDEO_NOFRAME) { sFlags |= SDL_NOFRAME; }
	
	if (flags & AG_VIDEO_OVERLAY)
		dsw->flags |= AG_DRIVER_SW_OVERLAY;
	if (flags & AG_VIDEO_BGPOPUPMENU)
		dsw->flags |= AG_DRIVER_SW_BGPOPUP;

	/* Apply the output capture settings. */
	if (AG_Defined(drv, "out")) {
		char *ext;

		AG_GetString(drv, "out", buf, sizeof(buf));
		if ((ext = strrchr(buf, '.')) != NULL &&
		    ext[1] != '\0') {
			if (Strcasecmp(&ext[1], "jpeg") == 0 ||
			    Strcasecmp(&ext[1], "jpg") == 0) {
				sgl->outMode = AG_SDLGL_OUT_JPEG;
				if ((sgl->outPath = TryStrdup(buf)) == NULL)
					return (-1);
			} else if (Strcasecmp(&ext[1], "png") == 0) {
				sgl->outMode = AG_SDLGL_OUT_PNG;
				if ((sgl->outPath = TryStrdup(buf)) == NULL)
					return (-1);
			} else {
				AG_SetError("Invalid out= argument: `%s'", buf);
				return (-1);
			}
			if (AG_Defined(drv, "outFirst")) {
				AG_GetString(drv, "outFirst", buf, sizeof(buf));
				sgl->outFrame = atoi(buf);
			} else {
				sgl->outFrame = 0;
			}
			if (AG_Defined(drv, "outLast")) {
				AG_GetString(drv, "outLast", buf, sizeof(buf));
				sgl->outLast = atoi(buf);
			}
		}
	}
	
	/* Apply the default resolution settings. */
	if (w == 0 && AG_Defined(drv, "width")) {
		AG_GetString(drv, "width", buf, sizeof(buf));
		w = atoi(buf);
	}
	if (h == 0 && AG_Defined(drv, "height")) {
		AG_GetString(drv, "height", buf, sizeof(buf));
		h = atoi(buf);
	}
	if (depth == 0 && AG_Defined(drv, "depth")) {
		AG_GetString(drv, "depth", buf, sizeof(buf));
		depth = atoi(buf);
	}

	/* Set the video mode. Force hardware palette in 8bpp. */
	Verbose(_("SDLGL: Setting mode %dx%d (%d bpp)\n"), w, h, depth);
	newDepth = SDL_VideoModeOK(w, h, depth, sFlags);
	if (newDepth == 8) {
		Verbose(_("Enabling hardware palette"));
		sFlags |= SDL_HWPALETTE;
	}
	if ((sgl->s = SDL_SetVideoMode((int)w, (int)h, newDepth, sFlags))
	    == NULL) {
		AG_SetError("Setting %dx%dx%d mode: %s", w, h, newDepth,
		    SDL_GetError());
		return (-1);
	}
	SDL_EnableUNICODE(1);

	if ((drv->videoFmt = AG_SDL_GetPixelFormat(sgl->s)) == NULL) {
		goto fail;
	}
	dsw->w = sgl->s->w;
	dsw->h = sgl->s->h;
	dsw->depth = (Uint)drv->videoFmt->BitsPerPixel;

	Verbose(_("SDLGL: New display (%dbpp)\n"),
	     (int)drv->videoFmt->BitsPerPixel);
	
	/* Initialize clipping rectangles. */
	if (InitClipRects(sgl, dsw->w, dsw->h) == -1)
		goto fail;
	
	/* Create the cursors. */
	if (AG_SDL_InitDefaultCursor(sgl) == -1 ||
	    AG_InitStockCursors(drv) == -1)
		goto fail;

	/* Initialize the GL viewport. */
	AG_GL_InitContext(
	    AG_RECT(0, 0, AGDRIVER_SW(sgl)->w, AGDRIVER_SW(sgl)->h));

	if (!(dsw->flags & AG_DRIVER_SW_OVERLAY)) {
		ClearBackground();
	}

	/* Initialize the output capture buffer. */
	Free(sgl->outBuf);
	if ((sgl->outBuf = AG_TryMalloc(dsw->w*dsw->h*4)) == NULL) {
		AG_Verbose("Out of memory for buffer; disabling capture\n");
		sgl->outMode = AG_SDLGL_OUT_NONE;
	}

	/* Toggle fullscreen if requested. */
	if (AG_CfgBool("view.full-screen")) {
		if (!SDL_WM_ToggleFullScreen(sgl->s))
			AG_SetCfgBool("view.full-screen", 0);
	}
	return (0);
fail:
	if (drv->videoFmt) {
		AG_PixelFormatFree(drv->videoFmt);
		drv->videoFmt = NULL;
	}
	return (-1);
}
Esempio n. 9
0
static AG_Window *
DEV_ConfigWindow(AG_Config *cfg)
{
	char path[AG_PATHNAME_MAX];
	AG_Window *win;
	AG_Box *hb;
	AG_Textbox *tbox;
/*	AG_Checkbox *cb; */
	AG_Notebook *nb;
	AG_NotebookTab *tab;

	if ((win = AG_WindowNewNamedS(0, "DEV_Config")) == NULL) {
		return (NULL);
	}
	AG_WindowSetCaptionS(win, _("Agar settings"));
	AG_WindowSetCloseAction(win, AG_WINDOW_DETACH);

	nb = AG_NotebookNew(win, AG_NOTEBOOK_HFILL|AG_NOTEBOOK_VFILL);
	tab = AG_NotebookAdd(nb, _("Video"), AG_BOX_VERT);
	{
		AG_NumericalNewIntR(tab, 0, "%", _("Screenshot quality: "),
		    &agScreenshotQuality, 1, 100);
	}

	tab = AG_NotebookAdd(nb, _("GUI"), AG_BOX_VERT);
	{
		AG_CheckboxNewInt(tab, 0, _("Built-in key composition"),
		    &agTextComposition);
		AG_CheckboxNewInt(tab, 0, _("Bidirectional"),
		    &agTextBidi);
		
		AG_SeparatorNewHoriz(tab);
		AG_LabelNewS(tab, 0, _("Timer settings (milliseconds):"));
		AG_NumericalNewIntR(tab, 0, NULL, _("Double click delay: "),
		    &agMouseDblclickDelay, 1, 10000);
		AG_NumericalNewIntR(tab, 0, NULL, _("Cursor spin delay: "),
		    &agMouseSpinDelay, 1, 10000);
		AG_NumericalNewIntR(tab, 0, NULL, _("Cursor spin interval: "),
		    &agMouseSpinIval, 1, 10000);
		AG_NumericalNewIntR(tab, 0, NULL, _("Key repeat delay: "),
		    &agKbdDelay, 1, 1000);
		AG_NumericalNewIntR(tab, 0, NULL, _("Key repeat interval: "),
		    &agKbdRepeat, 1, 500);
	}

	tab = AG_NotebookAdd(nb, _("Directories"), AG_BOX_VERT);
	{
		hb = AG_BoxNewHoriz(tab, AG_BOX_HFILL);
		tbox = AG_TextboxNewS(hb, AG_TEXTBOX_HFILL, _("Temporary file directory: "));
		AG_GetString(agConfig, "tmp-path", path, sizeof(path));
		AG_TextboxSetString(tbox, path);
		AG_SetEvent(tbox, "textbox-return", SetPath, "%s", "tmp-path");
		AG_TextboxSizeHint(tbox, "XXXXXXXXXXXXXXXXXXXX");
		AG_ButtonNewFn(hb, 0, "...", SelectPath, "%s,%p", "tmp-path", tbox);

		hb = AG_BoxNewHoriz(tab, AG_BOX_HFILL);
		tbox = AG_TextboxNewS(hb, AG_TEXTBOX_HFILL, _("Dataset save directory: "));
		AG_GetString(agConfig, "save-path", path, sizeof(path));
		AG_TextboxSetString(tbox, path);
		AG_SetEvent(tbox, "textbox-return", SetPath, "%s", "save-path");
		AG_ButtonNewFn(hb, 0, "...", SelectPath, "%s,%p", "save-path", tbox);
	
		hb = AG_BoxNewHoriz(tab, AG_BOX_HFILL);
		tbox = AG_TextboxNewS(hb, AG_TEXTBOX_HFILL, _("Dataset search path: "));
		AG_GetString(agConfig, "load-path", path, sizeof(path));
		AG_TextboxSetString(tbox, path);
		AG_SetEvent(tbox, "textbox-return", SetPath, "%s", "load-path");
	
		hb = AG_BoxNewHoriz(tab, AG_BOX_HFILL);
		tbox = AG_TextboxNewS(hb, AG_TEXTBOX_HFILL, _("Font search path: "));
		AG_GetString(agConfig, "font-path", path, sizeof(path));
		AG_TextboxSetString(tbox, path);
		AG_SetEvent(tbox, "textbox-return", SetPath, "%s", "font-path");
	}
#if 0
	tab = AG_NotebookAdd(nb, _("Colors"), AG_BOX_VERT);
	{
		AG_Pane *hPane;
		AG_HSVPal *hsv;
		AG_Tlist *tl;
		AG_TlistItem *it;
		AG_Label *lbl;
		int i;
	
		hPane = AG_PaneNew(tab, AG_PANE_HORIZ, AG_PANE_EXPAND);
		{
			tl = AG_TlistNew(hPane->div[0], AG_TLIST_EXPAND);
			AG_TlistSizeHint(tl, "Tileview text background", 10);
			for (i = 0; i < LAST_COLOR; i++) {
				it = AG_TlistAdd(tl, NULL, _(agColorNames[i]));
				it->p1 = &agColors[i];
			}
			hsv = AG_HSVPalNew(hPane->div[1], AG_HSVPAL_EXPAND);
			AG_SetEvent(hsv, "h-changed", SetColor, "%p", tl);
			AG_SetEvent(hsv, "sv-changed", SetColor, "%p", tl);
			AG_SetEvent(tl, "tlist-selected", BindSelectedColor,
			    "%p", hsv);
		}
		
		lbl = AG_LabelNew(tab, 0,
		    _("Warning: Some color changes will not "
		      "take effect until %s is restarted."), agProgName);
		AG_LabelSetPaddingLeft(lbl, 10);
		AG_LabelSetPaddingRight(lbl, 10);
		
		hb = AG_BoxNewHoriz(tab, AG_BOX_HOMOGENOUS|AG_BOX_HFILL);
		{
			AG_ButtonNewFn(hb, 0, _("Load scheme"),
			    LoadColorSchemeDlg, NULL);
			AG_ButtonNewFn(hb, 0, _("Save scheme"),
			    SaveColorSchemeDlg, NULL);
		}
	}
#endif

#ifdef AG_DEBUG
	tab = AG_NotebookAdd(nb, _("Debug"), AG_BOX_VERT);
	{
		AG_NumericalNewIntR(tab, 0, NULL, _("Debug level: "),
		    &agDebugLvl, 0, 255);
	}
#endif

	hb = AG_BoxNewHoriz(win, AG_BOX_HOMOGENOUS|AG_BOX_HFILL);
	{
		AG_ButtonNewFn(hb, 0, _("Close"), AGWINDETACH(win));
		AG_ButtonNewFn(hb, 0, _("Save"), SaveConfig, NULL);
	}
	return (win);
}