예제 #1
0
파일: sdl.c 프로젝트: GGGO/baresip
static void event_handler(void *arg)
{
	SDL_Event event;
	char ch;

	(void)arg;

	tmr_start(&sdl.tmr, 100, event_handler, NULL);

	while (SDL_PollEvent(&event)) {

		switch (event.type) {

		case SDL_KEYDOWN:

			switch (event.key.keysym.sym) {

			case SDLK_ESCAPE:
				if (!sdl.fullscreen)
					break;

				sdl.fullscreen = false;
				sdl_reset();
				break;

			case SDLK_f:
				if (sdl.fullscreen)
					break;

				sdl.fullscreen = true;
				sdl_reset();
				break;

			default:
				ch = event.key.keysym.unicode & 0x7f;

				/* Relay key-press to UI subsystem */
				if (isprint(ch)) {
					tmr_start(&sdl.tmr, KEY_RELEASE_VAL,
						  timeout, NULL);
					ui_input(ch);
				}
				break;
			}

			break;

		case SDL_VIDEORESIZE:
			handle_resize(event.resize.w, event.resize.h);
			break;

		case SDL_QUIT:
			ui_input('q');
			break;

		default:
			break;
		}
	}
}
예제 #2
0
static int finger_submit_init(void *dummy) 
{
   char finger[FINGER_LEN + 1];
   char os[OS_LEN + 1];
   
   /* don't display messages while operating */
   GBL_OPTIONS->quiet = 1;
 
   memset(finger, 0, sizeof(finger));
   memset(os, 0, sizeof(finger));
   
   /* get the user input */
   ui_input("Fingerprint      ('quit' to exit) : ", finger, sizeof(finger), NULL);
   
   /* exit on user request */
   if (!strcasecmp(finger, "quit") || !strcmp(finger, ""))
      return PLUGIN_FINISHED;
   
   ui_input("Operating System ('quit' to exit) : ", os, sizeof(os), NULL);

   /* exit on user request */
   if (!strcasecmp(os, "quit") || !strcmp(os, ""))
      return PLUGIN_FINISHED;
   
   USER_MSG("\n");

   /* send the fingerprint */
   fingerprint_submit(finger, os);

   /* flush all the messages */
   ui_msg_flush(MSG_ALL);
   
   return PLUGIN_FINISHED;
}
예제 #3
0
static int dos_attack_init(void *dummy) 
{ 
   char dos_addr[MAX_ASCII_ADDR_LEN];
   char unused_addr[MAX_ASCII_ADDR_LEN];
   struct port_list *p;
         
   /* It doesn't work if unoffensive */
   if (GBL_OPTIONS->unoffensive) {
      INSTANT_USER_MSG("dos_attack: plugin doesn't work in UNOFFENSIVE mode\n");
      return PLUGIN_FINISHED;
   }
   
   /* don't show packets while operating */
   GBL_OPTIONS->quiet = 1;

   memset(dos_addr, 0, sizeof(dos_addr));
   memset(unused_addr, 0, sizeof(dos_addr));

   ui_input("Insert victim IP: ", dos_addr, sizeof(dos_addr), NULL);
   if (ip_addr_pton(dos_addr, &victim_host) == -EINVALID) {
      INSTANT_USER_MSG("dos_attack: Invalid IP address.\n");
      return PLUGIN_FINISHED;
   }

   ui_input("Insert unused IP: ", unused_addr, sizeof(unused_addr), NULL);
   if (ip_addr_pton(unused_addr, &fake_host) == -EINVALID) {
      INSTANT_USER_MSG("dos_attack: Invalid IP address.\n");
      return PLUGIN_FINISHED;
   }

   if(victim_host.addr_type != fake_host.addr_type) {
      INSTANT_USER_MSG("dos_attack: Address' families don't match.\n");
      return PLUGIN_FINISHED;
   }

   INSTANT_USER_MSG("dos_attack: Starting scan against %s [Fake Host: %s]\n", dos_addr, unused_addr);

   /* Delete the "open" port list just in case of previous executions */
   while (!SLIST_EMPTY(&port_table)) {
      p = SLIST_FIRST(&port_table);
      SLIST_REMOVE_HEAD(&port_table, next);
      SAFE_FREE(p);
   }

   /* Add the hook to "create" the fake host */
   if(ntohs(fake_host.addr_type) == AF_INET)
      hook_add(HOOK_PACKET_ARP_RQ, &parse_arp);
#ifdef WITH_IPV6
   else if(ntohs(fake_host.addr_type) == AF_INET6)
      hook_add(HOOK_PACKET_ICMP6_NSOL, &parse_icmp6);
#endif

   /* Add the hook for SYN-ACK reply */
   hook_add(HOOK_PACKET_TCP, &parse_tcp);

   /* create the flooding thread */
   ec_thread_new("golem", "SYN flooder thread", &syn_flooder, NULL);

   return PLUGIN_RUNNING;
}
예제 #4
0
static int gre_relay_init(void *dummy) 
{
   char tmp[MAX_ASCII_ADDR_LEN];

   /* It doesn't work if unoffensive */
   if (GBL_OPTIONS->unoffensive) {
      INSTANT_USER_MSG("gre_relay: plugin doesn't work in UNOFFENSIVE mode\n");
      return PLUGIN_FINISHED;
   }

   /* don't display messages while operating */
   GBL_OPTIONS->quiet = 1;

   memset(tmp, 0, sizeof(tmp));
   
   ui_input("Unused IP address: ", tmp, sizeof(tmp), NULL);
   if (!inet_aton(tmp, &fake_ip)) {
      INSTANT_USER_MSG("gre_relay: Bad IP address\n");
      return PLUGIN_FINISHED;
   }

   USER_MSG("gre_relay: plugin running...\n");
   
   hook_add(HOOK_PACKET_GRE, &parse_gre);
   hook_add(HOOK_PACKET_ARP_RQ, &parse_arp);

   return PLUGIN_RUNNING;      
}
예제 #5
0
파일: gl-form.c 프로젝트: TamirEvan/mupdf
static void cert_password_dialog(void)
{
	int is;
	ui_dialog_begin(400, (ui.gridsize+4)*3);
	{
		ui_layout(T, X, NW, 2, 2);
		ui_label("Password:"******"Cancel"))
				ui.dialog = NULL;
			ui_spacer();
			if (ui_button("Okay") || is == UI_INPUT_ACCEPT)
			{
				ui.dialog = NULL;
				do_sign();
			}
		}
		ui_panel_end();
	}
	ui_dialog_end();
}
예제 #6
0
파일: gl-form.c 프로젝트: TamirEvan/mupdf
static void tx_dialog(void)
{
	int ff = pdf_field_flags(ctx, tx_widget->obj);
	const char *label = pdf_field_label(ctx, tx_widget->obj);
	int tx_h = (ff & PDF_TX_FIELD_IS_MULTILINE) ? 10 : 1;
	int lbl_h = ui_break_lines((char*)label, NULL, 20, 394, NULL);
	int is;

	ui_dialog_begin(400, (ui.gridsize+4)*3 + ui.lineheight*(tx_h+lbl_h-2));
	{
		ui_layout(T, X, NW, 2, 2);
		ui_label("%s", label);
		is = ui_input(&tx_input, 200, tx_h);

		ui_layout(B, X, NW, 2, 2);
		ui_panel_begin(0, ui.gridsize, 0, 0, 0);
		{
			ui_layout(R, NONE, S, 0, 0);
			if (ui_button("Cancel") || (!ui.focus && ui.key == KEY_ESCAPE))
				ui.dialog = NULL;
			ui_spacer();
			if (ui_button("Okay") || is == UI_INPUT_ACCEPT)
			{
				pdf_set_text_field_value(ctx, tx_widget, tx_input.text);
				if (pdf_update_page(ctx, tx_widget->page))
					render_page();
				ui.dialog = NULL;
			}
		}
		ui_panel_end();
	}
	ui_dialog_end();
}
예제 #7
0
void * keyserver(void *args)
{
	static int ch, i = 0, c = 'a';
	while(ch = ui_input()) {
		switch(ch) {
			case 'q':
			case 'Q':
			ui_print("preparing to quit ...\n");
			stop = 1;
			break;
			case 0x60:
			ui_scroll(-5);
			break;
			case 0x61:
			ui_scroll(5);
			break;
			case ' ':
			ui_pausemsg(0);
			break;
			case 1: // Ctrl-A
			ui_pausemsg(1);
			break;
			case 3: // Ctrl-C
			ui_deinit();
			io_deinit();
			exit(1);
			break;
			default:
//			ui_print("key code: %d", ch);
;
		}
	}
}
예제 #8
0
파일: sdl.c 프로젝트: GGGO/baresip
static void timeout(void *arg)
{
	(void)arg;

	tmr_start(&sdl.tmr, 1, event_handler, NULL);

	/* Emulate key-release */
	ui_input(KEYCODE_REL);
}
예제 #9
0
파일: evilloop.c 프로젝트: pscha/tines
Node *evilloop (Node *pos)
{
	cli_outfun = set_status;

	while (!quit_tines) {
		Tbinding *binding;

		ui_draw (pos, inputbuf, 0);
		binding = parsekey (ui_input (), ui_current_scope);
		do {

			switch (binding->action) {
				case ui_action_quit:
					remove_temp (&pos);
					quit_tines = 1;
					break;
				case ui_action_command:
					if(!string_isoneof(binding->action_param, no_remove_temp_commands))
						remove_temp (&pos);
					pos = docmd (pos, binding->action_param);
					if(!string_isoneof(binding->action_param,keep_inputbuf))
						inputbuf[0] = 0;
					break;
				case ui_action_top:
					remove_temp (&pos);
					inputbuf[0] = 0;
					pos = node_top (pos);
					break;
				case ui_action_bottom:
					remove_temp (&pos);
					inputbuf[0] = 0;
					pos = node_bottom (pos);
					break;
				case ui_action_up:
					if (!remove_temp (&pos)) {
						if(forced_up){
							if (node_forced_up (pos)){
								pos = node_forced_up (pos);
							}
						} else {
							if (node_up (pos)){
								pos = node_up (pos);
							}
						}
					}
					inputbuf[0] = 0;
					break;
				case ui_action_down:
					if (!remove_temp (&pos)) {
						if(forced_down){
							if(node_forced_down(pos))
								pos = node_forced_down (pos);
						} else {
							if(node_down(pos))
								pos = node_down (pos);
						}							
						inputbuf[0] = 0;
						break;
					}
				case ui_action_pagedown:
					remove_temp (&pos);
					inputbuf[0] = 0;
					{
						int n;

						for (n = 0; n < tines_nodes_down; n++)
							if (node_down (pos)) {
								pos = node_down (pos);
							}
					}
					break;
				case ui_action_pageup:
					remove_temp (&pos);
					inputbuf[0] = 0;
					{
						int n;

						for (n = 0; n < tines_nodes_up; n++)
							if (node_up (pos))
								pos = node_up (pos);
					}
					break;
				case ui_action_left:
					if (!remove_temp (&pos)) {
						if (node_left (pos))
							pos = node_left (pos);
					}
					inputbuf[0] = 0;
					break;
				case ui_action_right:
					if (node_right (pos)) {
						pos = node_right (pos);
					} else {
						if (fixnullstring (node_get (pos, TEXT))[0]) {
							node_insert_right (pos);
							if (node_getflag (pos, F_temp))
								node_setflag (pos, F_temp, 0);
							if (!strcmp(fixnullstring(node_get(pos,"type")),"todo")){
								node_set (node_right (pos), "type","todo");
								node_set (node_right (pos), "done","no");
							}
							node_setflag (node_right (pos), F_temp, 1);
							pos = node_right (pos);
						}
					}
					inputbuf[0] = 0;
					break;
				case ui_action_complete:
					if (strcmp
						(inputbuf,
						 fixnullstring (node_get (pos, TEXT))) == 0) {
						if (node_right (pos)) {
							pos = node_right (pos);
						} else {
							if (fixnullstring (node_get (pos, TEXT))[0]) {
								node_insert_right (pos);
								if (node_getflag (pos, F_temp))
									node_setflag (pos, F_temp, 0);
								if (!strcmp(fixnullstring(node_get(pos,"type")),"todo")){
									node_set (node_right (pos), "type","todo");
									node_set (node_right (pos), "done","no");
								}
								node_setflag (node_right (pos), F_temp, 1);

								pos = node_right (pos);
							}
						}
						inputbuf[0] = 0;
					} else {
						strcpy (inputbuf,
								fixnullstring (node_get (pos, TEXT)));
					}
					break;
				case ui_action_cancel:
					if (node_getflag (pos, F_temp)) {
						pos = node_remove (pos);
					} else {
						/*stop = ui_quit (pos); */
					}
					inputbuf[0] = 0;
					break;
				case ui_action_backspace:
					if (!strlen (inputbuf)) {
						/*pos = ui_remove (pos); */
					} else {
						inputbuf[strlen (inputbuf) - 1] = 0;
						if (node_getflag (pos, F_temp))
							if (node_up (pos))
								pos = node_remove (pos);
					}
					break;
				case ui_action_unbound:
					undefined_key (ui_scope_names[ui_current_scope],
								   binding->key !=
								   1000 ? binding->key : *((int *) &binding->
														   action_param[0]));
				case ui_action_ignore:
					break;
				default:
					if (binding->action > 31 && binding->action < 255) {	/*  input for buffer */
						inputbuf[strlen (inputbuf) + 1] = 0;
						inputbuf[strlen (inputbuf)] = binding->action;
					} else
						undefined_key (ui_scope_names[ui_current_scope],
									   binding->key !=
									   1000 ? binding->
									   key : *((int *) &binding->
											   action_param[0]));
					break;
			}
		} while ((++binding)->key == 999);


		if (strlen (inputbuf)) {
			if (node_getflag (pos, F_temp)) {
				node_set (pos, TEXT, inputbuf);
			} else {
				if (node_match (inputbuf, pos)) {
					pos = node_match (inputbuf, pos);
				} else {
				  if (add_at_top) {
					pos = node_insert_up (node_top (pos));
				  } else {
					pos = node_insert_down (node_bottom (pos));
				  }
					node_setflag (pos, F_temp, 1);
					node_set (pos, TEXT, inputbuf);
					if (node_left (pos))
							if (!strcmp(fixnullstring(node_get(node_left(pos),"type")),"todo")){
								node_set (pos, "type","todo");
								node_set (pos, "done","no");
							}
				}
			}
		} else {
			docmd(pos, "autosave_check_timeout"); 
		}
	}
	return pos;
}
예제 #10
0
static void run_main_loop(void)
{
    glViewport(0, 0, window_w, window_h);
    glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, window_w, window_h, 0, -1, 1);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    ui_begin();

    if (search_active)
    {
        float start_time = glfwGetTime();

        if (ui.key == KEY_ESCAPE)
            search_active = 0;

        /* ignore events during search */
        ui.key = ui.mod = 0;
        ui.down = ui.middle = ui.right = 0;

        while (glfwGetTime() < start_time + 0.2)
        {
            search_hit_count = fz_search_page_number(ctx, doc, search_page, search_needle,
                               search_hit_bbox, nelem(search_hit_bbox));
            if (search_hit_count)
            {
                search_active = 0;
                search_hit_page = search_page;
                jump_to_page(search_hit_page);
                break;
            }
            else
            {
                search_page += search_dir;
                if (search_page < 0 || search_page == fz_count_pages(ctx, doc))
                {
                    search_active = 0;
                    break;
                }
            }
        }

        /* keep searching later */
        if (search_active)
            ui_needs_update = 1;
    }

    do_app();

    canvas_w = window_w - canvas_x;
    canvas_h = window_h - canvas_y;

    do_canvas();

    if (showinfo)
        do_info();

    if (showoutline)
        do_outline(outline, canvas_x);

    if (showsearch)
    {
        int state = ui_input(canvas_x, 0, canvas_x + canvas_w, ui.lineheight+4, &search_input);
        if (state == -1)
        {
            ui.focus = NULL;
            showsearch = 0;
        }
        else if (state == 1)
        {
            ui.focus = NULL;
            showsearch = 0;
            search_page = -1;
            if (search_needle)
            {
                fz_free(ctx, search_needle);
                search_needle = NULL;
            }
            if (search_input.end > search_input.text)
            {
                search_needle = fz_strdup(ctx, search_input.text);
                search_active = 1;
                search_page = currentpage;
            }
        }
        ui_needs_update = 1;
    }

    if (search_active)
    {
        char buf[256];
        sprintf(buf, "Searching page %d of %d.", search_page + 1, fz_count_pages(ctx, doc));
        ui_label_draw(canvas_x, 0, canvas_x + canvas_w, ui.lineheight+4, buf);
    }

    ui_end();

    glfwSwapBuffers(window);

    ogl_assert(ctx, "swap buffers");
}
예제 #11
0
파일: main.c 프로젝트: Tilka/ncdc
static void handle_input() {
  /* Mapping from get_wch() to input_key_t:
   *  KEY_CODE_YES -> KEY(code)
   *  KEY_CODE_NO:
   *    char == 127           -> KEY(KEY_BACKSPACE)
   *    char <= 31            -> CTRL(char)
   *    !'^['                 -> CHAR(char)
   *    ('^[', !)             -> KEY(KEY_ESCAPE)
   *    ('^[', !CHAR)         -> ignore both characters (1)
   *    ('^[', CHAR && '[')   -> ignore both characters and the character after that (2)
   *    ('^[', CHAR && !'[')  -> ALT(second char)
   *
   * 1. this is something like ctrl+alt+X, which we won't use
   * 2. these codes indicate a 'Key' that somehow wasn't captured with
   *    KEY_CODE_YES. We won't attempt to interpret these ourselves.
   *
   * There are still several unhandled issues:
   * - Ncurses does not catch all key codes, and there is no way of knowing how
   *   many bytes a key code spans. Things like ^[[1;3C won't be handled correctly. :-(
   * - Ncurses can actually return key codes > KEY_MAX, but does not provide
   *   any mechanism for figuring out which key it actually was.
   * - It may be useful to use define_key() for some special (and common) codes
   * - Modifier keys will always be a problem. Most alt+key things work, except
   *   for those that may start a control code. alt+[ is a famous one, but
   *   there are others (like alt+O on my system). This is system-dependent,
   *   and again we have no way of knowing these things. (except perhaps by
   *   reading termcap entries on our own?)
   */

  guint64 key;
  char buf[9];
  int r;
  wint_t code;
  int lastesc = 0, curignore = 0;
  while((r = get_wch(&code)) != ERR) {
    if(curignore) {
      curignore = 0;
      continue;
    }
    // we use SIGWINCH, so KEY_RESIZE can be ignored
    if(r == KEY_CODE_YES && code == KEY_RESIZE)
      continue;
    // backspace (outside of an escape sequence) is often sent as DEL control character, correct this
    if(!lastesc && r != KEY_CODE_YES && code == 127) {
      r = KEY_CODE_YES;
      code = KEY_BACKSPACE;
    }
    // backspace inside an escape sequence is also possible, convert the other way around
    if(lastesc && r == KEY_CODE_YES && code == KEY_BACKSPACE) {
      r = !KEY_CODE_YES;
      code = 127;
    }
    key = r == KEY_CODE_YES ? INPT_KEY(code) : code == 27 ? INPT_ALT(0) : code <= 31 ? INPT_CTRL(ctrl_to_ascii(code)) : INPT_CHAR(code);
    // convert wchar_t into gunichar
    if(INPT_TYPE(key) == 1) {
      if((r = wctomb(buf, code)) < 0)
        g_warning("Cannot encode character 0x%X", code);
      buf[r] = 0;
      key = INPT_CHAR(g_utf8_get_char_validated(buf, -1));
      if(INPT_CODE(key) == (gunichar)-1 || INPT_CODE(key) == (gunichar)-2) {
        g_warning("Invalid UTF-8 sequence in keyboard input. Are you sure you are running a UTF-8 locale?");
        continue;
      }
    }
    // check for escape sequence
    if(lastesc) {
      lastesc = 0;
      if(INPT_TYPE(key) != 1)
        continue;
      if(INPT_CODE(key) == '[') {
        curignore = 1;
        continue;
      }
      key |= (guint64)3<<32; // a not very nice way of saying "turn this key into a INPT_ALT"
      ui_input(key);
      continue;
    }
    if(INPT_TYPE(key) == 3) {
      lastesc = 1;
      continue;
    }
    ui_input(key);
  }
  if(lastesc)
    ui_input(INPT_KEY(KEY_ESCAPE));

  ui_draw();
}
예제 #12
0
파일: gl-file.c 프로젝트: JorjMcKie/mupdf
int ui_save_file(char filename[PATH_MAX], void (*extra_panel)(void))
{
	int i, rv = 0;

	ui_panel_begin(0, 0, 4, 4, 1);
	{
		ui_layout(L, Y, NW, 0, 0);
		ui_panel_begin(150, 0, 0, 0, 0);
		{
			ui_layout(T, X, NW, 2, 2);
			list_drives();
			if (extra_panel)
			{
				ui_spacer();
				extra_panel();
			}
			ui_layout(B, X, NW, 2, 2);
			if (ui_button("Cancel") || (!ui.focus && ui.key == KEY_ESCAPE))
			{
				filename[0] = 0;
				rv = 1;
			}
		}
		ui_panel_end();

		ui_layout(T, X, NW, 2, 2);
		if (ui_input(&fc.input_dir, 0, 1) == UI_INPUT_ACCEPT)
			load_dir(fc.input_dir.text);

		ui_layout(T, X, NW, 2, 2);
		ui_panel_begin(0, ui.gridsize, 0, 0, 0);
		{
			ui_layout(R, NONE, CENTER, 0, 0);
			if (ui_button("Save"))
			{
				fz_snprintf(filename, PATH_MAX, "%s/%s", fc.curdir, fc.input_file.text);
				rv = 1;
			}
			ui_spacer();
			if (ui_button("\xe2\x9e\x95")) /* U+2795 HEAVY PLUS */
				bump_file_version(1);
			if (ui_button("\xe2\x9e\x96")) /* U+2796 HEAVY MINUS */
				bump_file_version(-1);
			ui_spacer();
			ui_layout(ALL, X, CENTER, 0, 0);
			ui_input(&fc.input_file, 0, 1);
		}
		ui_panel_end();

		ui_layout(ALL, BOTH, NW, 2, 2);
		ui_list_begin(&fc.list_dir, fc.count, 0, 0);
		for (i = 0; i < fc.count; ++i)
		{
			const char *name = fc.files[i].name;
			char buf[PATH_MAX];
			if (fc.files[i].is_dir)
				fz_snprintf(buf, sizeof buf, "\xf0\x9f\x93\x81 %s", name);
			else
				fz_snprintf(buf, sizeof buf, "\xf0\x9f\x93\x84 %s", name);
			if (ui_list_item(&fc.list_dir, &fc.files[i], buf, i==fc.selected))
			{
				fc.selected = i;
				if (fc.files[i].is_dir)
				{
					fz_snprintf(buf, sizeof buf, "%s/%s", fc.curdir, name);
					load_dir(buf);
					ui.active = NULL;
				}
				else
				{
					ui_input_init(&fc.input_file, name);
				}
			}
		}
		ui_list_end(&fc.list_dir);
	}
	ui_panel_end();

	return rv;
}
예제 #13
0
파일: gl-file.c 프로젝트: JorjMcKie/mupdf
int ui_open_file(char filename[PATH_MAX])
{
	static int last_click_time = 0;
	static int last_click_sel = -1;
	int i, rv = 0;

	ui_panel_begin(0, 0, 4, 4, 1);
	{
		ui_layout(L, Y, NW, 0, 0);
		ui_panel_begin(150, 0, 0, 0, 0);
		{
			ui_layout(T, X, NW, 2, 2);
			list_drives();
			ui_layout(B, X, NW, 2, 2);
			if (ui_button("Cancel") || (!ui.focus && ui.key == KEY_ESCAPE))
			{
				filename[0] = 0;
				rv = 1;
			}
		}
		ui_panel_end();

		ui_layout(T, X, NW, 2, 2);
		ui_panel_begin(0, ui.gridsize, 0, 0, 0);
		{
			if (fc.selected >= 0)
			{
				ui_layout(R, NONE, CENTER, 0, 0);
				if (ui_button("Open") || (!ui.focus && ui.key == KEY_ENTER))
				{
					fz_snprintf(filename, PATH_MAX, "%s/%s", fc.curdir, fc.files[fc.selected].name);
					rv = 1;
				}
				ui_spacer();
			}
			ui_layout(ALL, X, CENTER, 0, 0);
			if (ui_input(&fc.input_dir, 0, 1) == UI_INPUT_ACCEPT)
				load_dir(fc.input_dir.text);
		}
		ui_panel_end();

		ui_layout(ALL, BOTH, NW, 2, 2);
		ui_list_begin(&fc.list_dir, fc.count, 0, 0);
		for (i = 0; i < fc.count; ++i)
		{
			const char *name = fc.files[i].name;
			char buf[PATH_MAX];
			if (fc.files[i].is_dir)
				fz_snprintf(buf, sizeof buf, "%C %s", ICON_FOLDER, name);
			else
				fz_snprintf(buf, sizeof buf, "%C %s", ICON_DOCUMENT, name);
			if (ui_list_item(&fc.list_dir, &fc.files[i], buf, i==fc.selected))
			{
				fc.selected = i;
				if (fc.files[i].is_dir)
				{
					fz_snprintf(buf, sizeof buf, "%s/%s", fc.curdir, name);
					load_dir(buf);
					ui.active = NULL;
					last_click_sel = -1;
				}
				else
				{
					int click_time = glutGet(GLUT_ELAPSED_TIME);
					if (i == last_click_sel && click_time < last_click_time + 250)
					{
						fz_snprintf(filename, PATH_MAX, "%s/%s", fc.curdir, name);
						rv = 1;
					}
					last_click_time = click_time;
					last_click_sel = i;
				}
			}
		}
		ui_list_end(&fc.list_dir);
	}
	ui_panel_end();

	return rv;
}