+ 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);
+
+ local_modified = 1;
+
+ tg_setcursor(0, 23);
+
+ 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, progr;
+ struct ftp_dirent *ent;
+ unsigned int upd = 0;
+ char buf[128];
+ const char *remdir;
+ static int prev_status;
+ static void *prev_xfer;
+
+ if(ftp->status != prev_status) {
+ tg_fgcolor(ftp->status ? TGFX_GREEN : TGFX_RED);
+ tg_bgcolor(TGFX_BLACK);
+ tg_text(0, 0, "Srv: %s", ftp->status ? host : "-");
+ upd |= 0x8000;
+ prev_status = ftp->status;
+ }
+
+ tg_fgcolor(TGFX_WHITE);
+ tg_bgcolor(TGFX_BLACK);
+ if(cur_xfer) {
+ int dir = tg_gchar(cur_xfer->op == FTP_RETR ? TGFX_RARROW : TGFX_LARROW);
+ tg_text(40, 0, "%c%s", dir, cur_xfer->rname);
+ if(!cur_xfer->total) {
+ tg_text(75, 0, " ???%%");
+ } else {
+ progr = 100 * cur_xfer->count / cur_xfer->total;
+ if(progr < 0) progr = 0;
+ if(progr > 100) progr = 100;
+ tg_text(75, 0, " %3d%%", progr);
+ }
+ upd |= 0x8000;
+ } else if(prev_xfer) {
+ tg_rect(0, 40, 0, 40, 1, 0);
+ upd |= 0x8000;
+ }
+ prev_xfer = cur_xfer;
+
+ 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]);
+ }
+
+ if(upd) {
+ tg_redraw();
+ }
+}
+
+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;
+
+ if(stat(dent->d_name, &st) == 0) {
+ if(S_ISDIR(st.st_mode)) {
+ ent.type = FTP_DIR;
+ } else {
+ ent.type = FTP_FILE;
+ }
+ ent.size = st.st_size;
+ } else {
+ ent.type = FTP_FILE;
+ ent.size = 0;
+ }
+
+ darr_push(localdir, &ent);
+ }
+ closedir(dir);