+ uilist[0] = tui_list("Remote", 0, 1, 40, 21, 0, 0);
+ uilist[1] = tui_list("Local", 40, 1, 40, 21, 0, 0);
+ focus = 0;
+ tui_focus(uilist[focus], 1);
+
+ tg_fgcolor(TGFX_RED);
+ tg_bgcolor(TGFX_BLACK);
+ tg_rect("No conn.", 0, 0, 80, 1, 0);
+
+ tg_setcursor(0, 23);
+
+ tui_draw(uilist[0]);
+ tui_draw(uilist[1]);
+
+ for(;;) {
+ FD_ZERO(&rdset);
+ maxfd = 0;
+
+ numsock = ftp_sockets(ftp, ftpsock, sizeof ftpsock);
+ for(i=0; i<numsock; i++) {
+ FD_SET(ftpsock[i], &rdset);
+ if(ftpsock[i] > maxfd) maxfd = ftpsock[i];
+ }
+
+#ifdef __unix__
+ FD_SET(0, &rdset);
+ tv.tv_sec = 120;
+ tv.tv_usec = 0;
+#else
+ tv.tv_sec = tv.tv_usec = 0;
+#endif
+
+ if(select(maxfd + 1, &rdset, 0, 0, &tv) == -1 && errno == EINTR) {
+ continue;
+ }
+
+#ifdef __unix__
+ if(FD_ISSET(0, &rdset)) {
+ if(proc_input() == -1) {
+ break;
+ }
+ }
+#else
+ if(proc_input() == -1) {
+ break;
+ }
+#endif
+
+ for(i=0; i<numsock; i++) {
+ if(FD_ISSET(ftpsock[i], &rdset)) {
+ ftp_handle(ftp, ftpsock[i]);
+ }
+ }
+
+ updateui();
+ }
+
+ tg_cleanup();
+ cleanup_input();
+ ftp_close(ftp);
+ ftp_free(ftp);
+ return 0;
+}
+
+void updateui(void)
+{
+ int i, num;
+ struct ftp_dirent *ent;
+ unsigned int upd = 0;
+ char buf[128];
+ const char *remdir;
+
+ if(ftp->status != FTP_DISC) {
+ tg_fgcolor(TGFX_GREEN);
+ tg_bgcolor(TGFX_BLACK);
+ tg_text(0, 0, "Conn: %s", host);
+ }
+
+ remdir = ftp_curdir(ftp);
+ if(remdir && strcmp(tui_get_title(uilist[0]), remdir) != 0) {
+ tui_set_title(uilist[0], remdir);
+ upd |= 1;
+ }
+
+ if(ftp->modified & FTP_MOD_DIR) {
+ tui_clear_list(uilist[0]);
+
+ num = ftp_num_dirent(ftp);
+ for(i=0; i<num; i++) {
+ ent = ftp_dirent(ftp, i);
+ if(ent->type == FTP_DIR) {
+ sprintf(buf, "%s/", ent->name);
+ tui_add_list_item(uilist[0], buf);
+ } else {
+ tui_add_list_item(uilist[0], ent->name);
+ }
+ }
+
+ tui_list_select(uilist[0], 0);
+
+ ftp->modified &= ~FTP_MOD_DIR;
+ upd |= 1;
+ }
+
+ if(local_modified || strcmp(tui_get_title(uilist[1]), curdir) != 0) {
+ tui_clear_list(uilist[1]);
+ num = darr_size(localdir);
+ for(i=0; i<num; i++) {
+ ent = localdir + i;
+ if(ent->type == FTP_DIR) {
+ sprintf(buf, "%s/", ent->name);
+ tui_add_list_item(uilist[1], buf);
+ } else {
+ tui_add_list_item(uilist[1], ent->name);
+ }
+ }
+ tui_list_select(uilist[1], 0);
+ tui_set_title(uilist[1], curdir);
+
+ local_modified = 0;
+ upd |= 2;
+ }
+
+ if(tui_isdirty(uilist[0]) || upd & 1) {
+ tui_draw(uilist[0]);
+ }
+ if(tui_isdirty(uilist[1]) || upd & 2) {
+ tui_draw(uilist[1]);
+ }
+}
+
+int update_localdir(void)
+{
+ DIR *dir;
+ struct dirent *dent;
+ struct stat st;
+ struct ftp_dirent ent;
+
+ if(!(dir = opendir(curdir))) {
+ errmsg("failed to open directory: %s\n", curdir);
+ return -1;
+ }
+
+ darr_clear(localdir);
+ while((dent = readdir(dir))) {
+ ent.name = strdup_nf(dent->d_name);
+ if(strcmp(dent->d_name, ".") == 0) continue;