Exemple #1
0
/* Prompts for an integer of input. */
void EditHostWinGetNum(int *dst)
{
	WGetsParams wgp;
	char str[256];
	int maxy, maxx;

	getmaxyx(gEditHostWin, maxy, maxx);
	WAttr(gEditHostWin, kBold, 1);
	DrawStrAt(gEditHostWin, maxy - 1, 0, "> ");
	WAttr(gEditHostWin, kBold, 0);
	wclrtoeol(gEditHostWin);
	wrefresh(gEditHostWin);
	curs_set(1);

	wgp.w = gEditHostWin;
	wgp.sy = maxy - 1;
	wgp.sx = 2;
	wgp.fieldLen = maxx - 3;
	wgp.dst = str;
	wgp.dstSize = sizeof(str);
	wgp.useCurrentContents = 0;
	wgp.echoMode = wg_RegularEcho;
	wgp.history = wg_NoHistory;
	(void) wg_Gets(&wgp);
	cbreak();						/* wg_Gets turns off cbreak and delay. */

	AtoIMaybe(dst, str);
	wmove(gEditHostWin, maxy - 1, 0);
	wclrtoeol(gEditHostWin);
	wrefresh(gEditHostWin);
	curs_set(0);
}	/* EditHostWinGetNum */
Exemple #2
0
/* Prompts for a line of input. */
void EditHostWinGetStr(char *dst, size_t size, int canBeEmpty, int canEcho)
{
	char str[256];
	WGetsParams wgp;
	int maxy, maxx;

	WAttr(gEditHostWin, kBold, 1);
	getmaxyx(gEditHostWin, maxy, maxx);
	DrawStrAt(gEditHostWin, maxy - 1, 0, "> ");
	WAttr(gEditHostWin, kBold, 0);
	wclrtoeol(gEditHostWin);
	wrefresh(gEditHostWin);
	curs_set(1);

	wgp.w = gEditHostWin;
	wgp.sy = maxy - 1;
	wgp.sx = 2;
	wgp.fieldLen = maxx - 3;
	wgp.dst = str;
	wgp.dstSize = size;
	wgp.useCurrentContents = 0;
	wgp.echoMode = canEcho ? wg_RegularEcho : wg_BulletEcho;
	wgp.history = wg_NoHistory;
	(void) wg_Gets(&wgp);
	cbreak();						/* wg_Gets turns off cbreak and delay. */

	/* See if the user just hit return.  We may not want to overwrite
	 * the dst here, which would make it an empty string.
	 */
	if ((wgp.changed) || (canBeEmpty == kOkayIfEmpty))
		strcpy(dst, str);

	wmove(gEditHostWin, maxy - 1, 0);
	wclrtoeol(gEditHostWin);
	wrefresh(gEditHostWin);
	curs_set(0);
}	/* EditHostWinGetStr */
Exemple #3
0
/* This one is the brainchild of my comrade, Phil Dietz.  It shows the
 * progress as a fancy bar graph.
 */
int PrPhilBar(XferSpecPtr xp, int mode)
{
	int result = kPrWantStatsMsg;
	int perc;
	long s;
	int curBarLen;
	static int maxBarLen;
	str64 spec1, spec3;
	static string bar;
	int i;
	int secsLeft, minLeft;

	switch (mode) {
		case kPrInitMsg:
			EPrintF("%s file: %s \n",
				NETREADING(xp) ? "Receiving" : "Sending",
				xp->localFileName
			);
			
			for (i=0; i < (int) sizeof(bar) - 1; i++)
				bar[i] = '=';
			bar[i] = '\0';

			/* Compute the size of the bar itself.  This sits between
			 * two numbers, one on each side of the screen.  So the
			 * bar length will vary, depending on how many digits we
			 * need to display the size of the file.
			 */
			maxBarLen = gScreenWidth - 1 - 28;
			for (s = xp->expectedSize; s > 0; s /= 10L)
				maxBarLen--;
			
			/* Create a specification we can hand to printf. */
			(void) sprintf(spec1, "      0 %%%ds %%ld bytes. ETA: --:--",
				maxBarLen);
				
			/* Print the first invocation, which is an empty graph
			 * plus the other stuff.
			 */
			EPrintF(spec1, " ", xp->expectedSize);
			break;
		case kPrUpdateMsg:
			/* Compute how much of the bar should be colored in. */
			curBarLen = (int) (xp->frac * (double)maxBarLen);

			/* Colored portion must be at least one character so
			 * the spec isn't '%0s' which would screw the right side
			 * of the indicator.
			 */
			if (curBarLen < 1)
				curBarLen = 1;
			
			bar[curBarLen - 1] = '>';
			bar[curBarLen] = '\0';

			/* Make the spec, so we can print the bar and the other stuff. */
			STRNCPY(spec1, "\r%3d%%  0 ");
			(void) sprintf(spec3, "%%%ds %%ld bytes. %s%%3d:%%02d", 
				maxBarLen - curBarLen,
				"ETA:"
			);
			
			/* We also show the percentage as a number at the left side. */
			perc = (int) (100.0 * xp->frac);
			
			/* Guess how much time is remaining in the transfer, based on
			 * the current transfer statistics.
			 */
			secsLeft = (int) ((xp->bytesLeft / xp->bytesPerSec) + 0.5);
			minLeft = secsLeft / 60;
			secsLeft = secsLeft - (minLeft * 60);
			if (minLeft > 999) {
				minLeft = 999;
				secsLeft = 59;
			}
			
			/* Print the updated information. */
#ifdef USE_CURSES
			if (gWinInit) {
				EPrintF(spec1, perc);	
				WAttr(gListWin, kReverse, 1);
				EPrintF("%s", bar);
				WAttr(gListWin, kReverse, 0);
				EPrintF(spec3,
					"",
					xp->expectedSize,
					minLeft,
					secsLeft
				);
			} else
#endif	/* USE_CURSES */
			{
				EPrintF(spec1, perc);	
				EPrintF("%s", bar);
				EPrintF(spec3,
					"",
					xp->expectedSize,
					minLeft,
					secsLeft
				);
			}

			bar[curBarLen - 1] = '=';
			bar[curBarLen] = '=';

			break;
		case kPrEndMsg:
			result = kPrWantStatsMsg;
			EPrintF("\n");
			break;
	}
	return result;
}	/* PrPhilBar */
Exemple #4
0
/* This opens and handles the site options window. */
void HostWinEdit(void)
{
	int c, field;
	int needUpdate;
	char bmname[128];
	BookmarkPtr rsip;

	if (gCurHostListItem != NULL) {
		gEditHostWin = newwin(LINES, COLS, 0, 0);
		if (gEditHostWin == NULL)
			return;
	
		STRNCPY(bmname, gCurHostListItem->bookmarkName);
		
		/* Set the clear flag for the first update. */
		wclear(gEditHostWin);

		/* leaveok(gEditHostWin, TRUE);	* Not sure if I like this... */
		WAttr(gEditHostWin, kBold, 1);
		WAddCenteredStr(gEditHostWin, 0, "Bookmark Options");
		WAttr(gEditHostWin, kBold, 0);
		
		/* We'll be editing a copy of the current host's settings. */
		gEditRsi = *gCurHostListItem;

		EditHostWinDraw(kAllWindowItems, kNoHilite);
		field = 1;
		for (;;) {
			EditHostWinMsg("Select an item to edit by typing its corresponding letter.");
			c = wgetch(gEditHostWin);
			if (islower(c))
				c = toupper(c);
			if (!isupper(c))
				continue;
			if (c == 'X')
				break;
			field = c - 'A';
			needUpdate = 1;
			
			/* Hilite the current item to edit. */
			EditHostWinDraw(BIT(field), kHilite);
			switch(field) {
				case kNicknameEditWindowItem:
					EditHostWinMsg("Type a new bookmark name, or hit <RETURN> to continue.");
					EditHostWinGetStr(gEditRsi.bookmarkName, sizeof(gEditRsi.bookmarkName), kNotOkayIfEmpty, kGetAndEcho);
					break;
					
				case kHostnameEditWindowItem:
					EditHostWinMsg("Type a new hostname, or hit <RETURN> to continue.");
					EditHostWinGetStr(gEditRsi.name, sizeof(gEditRsi.name), kNotOkayIfEmpty, kGetAndEcho);
					gEditRsi.lastIP[0] = '\0';	/* In case it changed. */
					break;

				case kUserEditWindowItem:
					EditHostWinMsg("Type a username, or hit <RETURN> to signify anonymous.");
					EditHostWinGetStr(gEditRsi.user, sizeof(gEditRsi.user), kOkayIfEmpty, kGetAndEcho);
					break;

				case kPassEditWindowItem:
					EditHostWinMsg("Type a password, or hit <RETURN> if no password is required.");
					EditHostWinGetStr(gEditRsi.pass, sizeof(gEditRsi.pass), kOkayIfEmpty, kGetNoEcho);
					break;

				case kAcctEditWindowItem:
					EditHostWinMsg("Type an account name, or hit <RETURN> if no account is required.");
					EditHostWinGetStr(gEditRsi.acct, sizeof(gEditRsi.acct), kOkayIfEmpty, kGetAndEcho);
					break;

				case kDirEditWindowItem:
					EditHostWinMsg("Type a remote directory path to start in after a connection is established.");
					EditHostWinGetStr(gEditRsi.dir, sizeof(gEditRsi.dir), kOkayIfEmpty, kGetAndEcho);
					break;

				case kLDirEditWindowItem:
					EditHostWinMsg("Type a local directory path to start in after a connection is established.");
					EditHostWinGetStr(gEditRsi.ldir, sizeof(gEditRsi.ldir), kOkayIfEmpty, kGetAndEcho);
					break;

				case kXferTypeEditWindowItem:
					EditHostWinMsg(kToggleMsg);
					ToggleXferType();
					break;

				case kPortEditWindowItem:
					EditHostWinMsg("Type a port number to use for FTP.");
					EditHostWinGetNum((int *) &gEditRsi.port);
					break;

#if 0
				case kSizeEditWindowItem:
					EditHostWinMsg(kToggleMsg);
					EditWinToggle(&gEditRsi.hasSIZE, field, 0, 1);
					break;

				case kMdtmEditWindowItem:
					EditHostWinMsg(kToggleMsg);
					EditWinToggle(&gEditRsi.hasMDTM, field, 0, 1);
					break;

				case kPasvEditWindowItem:
					EditHostWinMsg(kToggleMsg);
					EditWinToggle(&gEditRsi.hasPASV, field, 0, 1);
					break;

				case kOSEditWindowItem:
					EditHostWinMsg(kToggleMsg);
					EditWinToggle(&gEditRsi.isUnix, field, 0, 1);
					break;
#endif

				case kCommentEditWindowItem:
					EditHostWinMsg("Enter a line of information to store about this site.");
					EditHostWinGetStr(gEditRsi.comment, sizeof(gEditRsi.comment), kOkayIfEmpty, kGetAndEcho);
					break;
				
				default:
					needUpdate = 0;
					break;
			}
			if (needUpdate)
				EditHostWinDraw(BIT(field), kNoHilite);
		}
		delwin(gEditHostWin);
		gEditHostWin = NULL;
		*gCurHostListItem = gEditRsi;

		SaveAndReload();
		/* Note:  newly reallocated array, modified gNumBookmarks */

		rsip = SearchBookmarkTable(bmname);
		if (rsip == NULL)
			rsip = &gBookmarkTable[0];
		gCurHostListItem = rsip;
		gHilitedHost = BMTINDEX(rsip);
		gHostListWinStart = BMTINDEX(rsip) - gHostListPageSize + 1;
		if (gHostListWinStart < 0)
			gHostListWinStart = 0;
		UpdateHostWindows(1);
	}
}	/* HostWinEdit */
Exemple #5
0
/* This is the meat of the site options window.  We can selectively update
 * portions of the window by using a bitmask with bits set for items
 * we want to update.
 */
void EditHostWinDraw(int flags, int hilite)
{
	int maxy, maxx;
	int i, f;
	char str[256];
	char spec[32];
	const char *cp;

	/* Draw the keys the user can type in reverse text. */
	WAttr(gEditHostWin, kReverse, 1);
	f = 5;
	for (i = kFirstEditWindowItem; i <= kLastEditWindowItem; i++) {
		if (TESTBIT(flags, i))
			mvwaddch(gEditHostWin, f + i, 2, 'A' + i);
	}
	
	/* The "quit" item is a special item that is offset a line, and
	 * always has the "X" key assigned to it.
	 */
	i = kQuitEditWindowItem;
	if (TESTBIT(flags, i))
		mvwaddch(gEditHostWin, 1 + f + i, 2, 'X');
	WAttr(gEditHostWin, kReverse, 0);
	
	/* We can use this to hilite a whole line, to indicate to the
	 * user that a certain item is being edited.
	 */
	if (hilite)
		WAttr(gEditHostWin, kReverse, 1);
	getmaxyx(gEditHostWin, maxy, maxx);
	sprintf(spec, " %%-26s%%-%ds",
		maxx - 32);

	/* Now draw the items on a case-by-case basis. */
	if (TESTBIT(flags, kNicknameEditWindowItem)) {
		mvwprintw(gEditHostWin, kNicknameEditWindowItem + f, 3, spec,
			"Bookmark name:",
			gEditRsi.bookmarkName
		);
		wclrtoeol(gEditHostWin);
	}
	if (TESTBIT(flags, kHostnameEditWindowItem)) {
		mvwprintw(gEditHostWin, kHostnameEditWindowItem + f, 3, spec,
			"Hostname:",
			gEditRsi.name
		);
		wclrtoeol(gEditHostWin);
	}
	if (TESTBIT(flags, kUserEditWindowItem)) {
		mvwprintw(gEditHostWin, kUserEditWindowItem + f, 3, spec,
			"User:"******"anonymous" : gEditRsi.user
		);
		wclrtoeol(gEditHostWin);
	}
	if (TESTBIT(flags, kPassEditWindowItem)) {
		if (gEditRsi.pass[0] == '\0' && gEditRsi.user[0] == '\0')
			STRNCPY(str, gLib.defaultAnonPassword);
		mvwprintw(gEditHostWin, kPassEditWindowItem + f, 3, spec,
			"Password:"******"********" : str
		);
		wclrtoeol(gEditHostWin);
	}
	if (TESTBIT(flags, kAcctEditWindowItem)) {
		mvwprintw(gEditHostWin, kAcctEditWindowItem + f, 3, spec,
			"Account:",
			gEditRsi.acct[0] == '\0' ? "none" : gEditRsi.acct
		);
		wclrtoeol(gEditHostWin);
	}
	if (TESTBIT(flags, kDirEditWindowItem)) {
		if (gEditRsi.dir[0] == '\0')
			STRNCPY(str, "/");
		else
			AbbrevStr(str, gEditRsi.dir, (size_t) maxx - 32, 0);
		mvwprintw(gEditHostWin, kDirEditWindowItem + f, 3, spec,
			"Remote Directory:",
			str
		);
		wclrtoeol(gEditHostWin);
	}
	if (TESTBIT(flags, kLDirEditWindowItem)) {
		if (gEditRsi.ldir[0] == '\0')
			STRNCPY(str, "(current)");
		else
			AbbrevStr(str, gEditRsi.ldir, (size_t) maxx - 32, 0);
		mvwprintw(gEditHostWin, kLDirEditWindowItem + f, 3, spec,
			"Local Directory:",
			str
		);
		wclrtoeol(gEditHostWin);
	}
	if (TESTBIT(flags, kXferTypeEditWindowItem)) {
		if ((gEditRsi.xferType == 'I') || (gEditRsi.xferType == 'B'))
			cp = "Binary";
		else if (gEditRsi.xferType == 'A')
			cp = "ASCII Text";
		else
			cp = "Tenex";
		mvwprintw(gEditHostWin, kXferTypeEditWindowItem + f, 3, spec,
			"Transfer type:",
			cp
		);
		wclrtoeol(gEditHostWin);
	}
	if (TESTBIT(flags, kPortEditWindowItem)) {
		sprintf(str, "%u", (gEditRsi.port == 0) ? 21 : (unsigned int) gEditRsi.port);
		mvwprintw(gEditHostWin, kPortEditWindowItem + f, 3, spec,
			"Port:",
			str
		);
		wclrtoeol(gEditHostWin);
	}
#if 0
	if (TESTBIT(flags, kSizeEditWindowItem)) {
		mvwprintw(gEditHostWin, kSizeEditWindowItem + f, 3, spec,
			"Has SIZE command:",
			gEditRsi.hasSIZE ? "Yes" : "No"
		);
		wclrtoeol(gEditHostWin);
	}
	if (TESTBIT(flags, kMdtmEditWindowItem)) {
		mvwprintw(gEditHostWin, kMdtmEditWindowItem + f, 3, spec,
			"Has MDTM command:",
			gEditRsi.hasMDTM ? "Yes" : "No"
		);
		wclrtoeol(gEditHostWin);
	}
	if (TESTBIT(flags, kPasvEditWindowItem)) {
		mvwprintw(gEditHostWin, kPasvEditWindowItem + f, 3, spec,
			"Can use passive FTP:",
			gEditRsi.hasPASV ? "Yes" : "No"
		);
		wclrtoeol(gEditHostWin);
	}
	if (TESTBIT(flags, kOSEditWindowItem)) {
		mvwprintw(gEditHostWin, kOSEditWindowItem + f, 3, spec,
			"Operating System:",
			(gEditRsi.isUnix == 1) ? "UNIX" : "Non-UNIX"
		);
		wclrtoeol(gEditHostWin);
	} 
#endif
	if (TESTBIT(flags, kCommentEditWindowItem)) {
		if (gEditRsi.comment[0] == '\0')
			STRNCPY(str, "(none)");
		else
			AbbrevStr(str, gEditRsi.comment, (size_t) maxx - 32, 0);
		mvwprintw(gEditHostWin, kCommentEditWindowItem + f, 3, spec,
			"Comment:",
			str
		);
		wclrtoeol(gEditHostWin);
	}
	if (TESTBIT(flags, kQuitEditWindowItem)) {
		mvwprintw(gEditHostWin, kQuitEditWindowItem + f + 1, 3, spec,
			"(Done editing)",
			""
		);
		wclrtoeol(gEditHostWin);
	}

	if (hilite)
		WAttr(gEditHostWin, kReverse, 0);

	wmove(gEditHostWin, maxy - 1, 0);
	wrefresh(gEditHostWin);
}	/* EditHostWinDraw */
Exemple #6
0
/* This draws the scrolling list of bookmarks, and hilites the currently
 * selected host.
 */
void DrawHostList(void)
{
	int lastLine, i;
	BookmarkPtr rsip;
	char str[256];
	char url[256];
	int maxy, maxx;
	int lmaxy, lmaxx;
	int begy, begx;
	char spec[32];

	getmaxyx(gHostListWin, lmaxy, lmaxx);
	getbegyx(gHostListWin, begy, begx);
	getmaxyx(gHostWin, maxy, maxx);
	/* We have a status line saying how many bookmarks there are in
	 * the list.  That way the user knows something is supposed to
	 * be there when the host list is totally empty, and also that
	 * there are more bookmarks to look at when the entire host list
	 * doesn't fit in the scroll window.
	 */
	WAttr(gHostWin, kUnderline, 1);
	mvwprintw(
		gHostWin,
		begy - 1,
		begx,
		strcpy(spec, "%s"),	/* avoid warnings on BSD */
		"Number of bookmarks"
	);
	WAttr(gHostWin, kUnderline, 0);
	wprintw(
		gHostWin,
		strcpy(spec, ": %3d"),
		gNumBookmarks
	);

	if (gHostListWinWide == 0) {
		sprintf(spec, "%%-16.16s %%-%ds", lmaxx - 17);
		lastLine = lmaxy + gHostListWinStart;
		for (i=gHostListWinStart; (i<lastLine) && (i<gNumBookmarks); i++) {
			rsip = &gBookmarkTable[i];
			if (rsip == gCurHostListItem)
				WAttr(gHostListWin, kReverse, 1);
			sprintf(str, spec, rsip->bookmarkName, rsip->name);
			str[lmaxx] = '\0';
			DrawStrAt(gHostListWin, i - gHostListWinStart, 0, str);
			swclrtoeol(gHostListWin);
			if (rsip == gCurHostListItem) {
				WAttr(gHostListWin, kReverse, 0);
			}
		}
	} else {
		lastLine = lmaxy + gHostListWinStart;
		for (i=gHostListWinStart; (i<lastLine) && (i<gNumBookmarks); i++) {
			rsip = &gBookmarkTable[i];
			if (rsip == gCurHostListItem)
				WAttr(gHostListWin, kReverse, 1);
			BookmarkToURL(rsip, url, sizeof(url));
			sprintf(str, "%-16.16s  ", rsip->bookmarkName);
			STRNCAT(str, url);
			memset(url, 0, sizeof(url));
			AbbrevStr(url, str, (size_t) lmaxx, 1);
			DrawStrAt(gHostListWin, i - gHostListWinStart, 0, url);
			swclrtoeol(gHostListWin);
			if (rsip == gCurHostListItem) {
				WAttr(gHostListWin, kReverse, 0);
			}
		}
	}


	/* Add 'vi' style empty-lines. */
	for ( ; i<lastLine; ++i) {
		DrawStrAt(gHostListWin, i - gHostListWinStart, 0, "~");
		swclrtoeol(gHostListWin);
	}
	wmove(gHostWin, maxy - 3, 2);
	sprintf(spec, "%%-%ds", maxx - 4);
	if (gCurHostListItem == NULL) {
		str[0] = '\0';
	} else if (gCurHostListItem->comment[0] == '\0') {
		memset(str, 0, sizeof(str));
		if (gHostListWinWide == 0) {
			BookmarkToURL(gCurHostListItem, url, sizeof(url));
			AbbrevStr(str, url, (size_t) maxx - 2, 1);
		}
	} else {
		STRNCPY(str, "``");
		STRNCAT(str, gCurHostListItem->comment);
		AbbrevStr(str + 2, gCurHostListItem->comment, (size_t) maxx - 8, 1);
		STRNCAT(str, "''");
	}
	wprintw(gHostWin, spec, str);
	wmove(gHostWin, maxy - 1, 0);
	UpdateHostWindows(0);
}	/* DrawHostList */
Exemple #7
0
/* Runs the host editor.  Another big use for this is to open sites
 * that are in your host list.
 */
int HostWindow(void)
{
	int c;
	char cmd[256];
	volatile BookmarkPtr toOpen;
	vsigproc_t si;
	int maxy, maxx;
	int lmaxy;

	si = (sigproc_t) (-1);
	if (gWinInit) {
		gHostListWin = NULL;
		gHostWin = NULL;

		gHostWin = newwin(LINES, COLS, 0, 0);
		if (gHostWin == NULL)
			return (-1);

		curs_set(0);
		cbreak();
		
		/* Set the clear flag for the first update. */
		wclear(gHostWin);
		keypad(gHostWin, TRUE);		/* For arrow keys. */
#ifdef HAVE_NOTIMEOUT
		notimeout(gHostWin, TRUE);
#endif

#ifdef HAVE_SIGSETJMP
		if (sigsetjmp(gHostWinJmp, 1) == 0) {
#else	/* HAVE_SIGSETJMP */
		if (setjmp(gHostWinJmp) == 0) {
#endif	/* HAVE_SIGSETJMP */
			/* Gracefully cleanup the screen if the user ^C's. */
			si = NcSignal(SIGINT, SigIntHostWin);
			
			/* Initialize the page start and select a host to be
			 * the current one.
			 */
			gHostListWinStart = 0;
			gHilitedHost = 0;
			if (gNumBookmarks == 0)
				gCurHostListItem = NULL;
			else
				gCurHostListItem = &gBookmarkTable[gHilitedHost];
			
			/* Initially, we don't want to connect to any site in
			 * the host list.
			 */
			toOpen = NULL;
	
			getmaxyx(gHostWin, maxy, maxx);
			WAttr(gHostWin, kBold, 1);
			WAddCenteredStr(gHostWin, 0, "NcFTP Bookmark Editor");
			WAttr(gHostWin, kBold, 0);
			
			DrawStrAt(gHostWin, 3, 2, "Open selected site:       <enter>");
			DrawStrAt(gHostWin, 4, 2, "Edit selected site:       /ed");
			DrawStrAt(gHostWin, 5, 2, "Delete selected site:     /del");
			DrawStrAt(gHostWin, 6, 2, "Duplicate selected site:  /dup");
			DrawStrAt(gHostWin, 7, 2, "Add a new site:           /new");
			DrawStrAt(gHostWin, 9, 2, "Up one:                   <u>");
			DrawStrAt(gHostWin, 10, 2, "Down one:                 <d>");
			DrawStrAt(gHostWin, 11, 2, "Previous page:            <p>");
			DrawStrAt(gHostWin, 12, 2, "Next page:                <n>");
			DrawStrAt(gHostWin, 14, 2, "Capital letters selects first");
			DrawStrAt(gHostWin, 15, 2, "  site starting with the letter.");
			DrawStrAt(gHostWin, 17, 2, "Exit the bookmark editor: <x>");
		
			/* Initialize the scrolling host list window. */
			if (maxx < 110) {
				gHostListWinWide = 0;
				gHostListWin = subwin(
					gHostWin,
					LINES - 7,
					40,
					3,
					COLS - 40 - 2
				);
			} else {
				gHostListWinWide = COLS - 42;
				gHostListWin = subwin(
					gHostWin,
					LINES - 7,
					gHostListWinWide,
					3,
					38	
				);
			}

			if (gHostListWin == NULL)
				return (-1);
			lmaxy = getmaxy(gHostListWin);
			gHostListPageSize = lmaxy;
			DrawHostList();
			wmove(gHostWin, maxy - 1, 0);
			UpdateHostWindows(1);

			for (;;) {
				c = HostWinGetKey();
				if (gNeedToClearMsg) {
					wmove(gHostWin, maxy - 2, 0);
					wclrtoeol(gHostWin);
					wrefresh(gHostWin);
				}
				if ((c >= 'A') && (c <= 'Z')) {
					/* isupper can coredump if wgetch returns a meta key. */
					HostWinZoomTo(c);
				} else if (c == '/') {
					/* Get an "extended" command.  Sort of like vi's
					 * :colon commands.
					 */
					HostWinGetStr(cmd, sizeof(cmd));
	
					if (ISTREQ(cmd, "ed"))
						HostWinEdit();
					else if (ISTREQ(cmd, "dup"))
						HostWinDup();
					else if (ISTREQ(cmd, "del"))
						HostWinDelete();
					else if (ISTREQ(cmd, "new"))
						HostWinNew();
					else
						HostWinMsg("Invalid bookmark editor command.");
				} else switch(c) {
					case 10:	/* ^J == newline */
						goto enter;
					case 13:	/* ^M == carriage return */
						goto enter;
#ifdef KEY_ENTER
					case KEY_ENTER:
						Trace(1, "  [0x%04X, %s]\n", c, "ENTER");
#endif
enter:
						if (gCurHostListItem == NULL)
							HostWinMsg("Nothing to open.  Try 'open sitename' from the main screen.");
						else {
							toOpen = (BookmarkPtr) gCurHostListItem;
							goto done;
						}
						break;
	
					case kControl_L:
						UpdateHostWindows(1);
						break;
	
					case 'u':
					case 'k':	/* vi up key */
					case 'h':	/* vi left key */
						HostListLineUp();
						break;
#ifdef KEY_UP
					case KEY_UP:
						Trace(1, "  [0x%04X, %s]\n", c, "UP");
						HostListLineUp();
						break;
#endif

#ifdef KEY_LEFT
					case KEY_LEFT:
						Trace(1, "  [0x%04X, %s]\n", c, "LEFT");
						HostListLineUp();
						break;
#endif
					
					case 'd':
					case 'j':	/* vi down key */
					case 'l':	/* vi right key */
						HostListLineDown();
						break;

#ifdef KEY_DOWN
					case KEY_DOWN:
						Trace(1, "  [0x%04X, %s]\n", c, "DOWN");
						HostListLineDown();
						break;
#endif

#ifdef KEY_RIGHT
					case KEY_RIGHT:
						Trace(1, "  [0x%04X, %s]\n", c, "RIGHT");
						HostListLineDown();
						break;
#endif
						
					case 'p':
						HostListPageUp();
						break;

#ifdef KEY_PPAGE
					case KEY_PPAGE:
						Trace(1, "  [0x%04X, %s]\n", c, "PPAGE");
						HostListPageUp();
						break;
#endif

					case 'n':
						HostListPageDown();
						break;

#ifdef KEY_NPAGE
					case KEY_NPAGE:
						Trace(1, "  [0x%04X, %s]\n", c, "NPAGE");
						HostListPageDown();
						break;
#endif

					case 'x':
					case 'q':
						goto done;
	
					default:
						HostWinMsg("Invalid key.");
						Trace(1, "  [0x%04X, %s]\n", c, "<invalid>");
						break;
				}
			}
		}
		NcSignal(SIGINT, (FTPSigProc) SIG_IGN);
done:
		if (gHostListWin != NULL)
			delwin(gHostListWin);
		if (gHostWin != NULL)
			delwin(gHostWin);
		gHostListWin = gHostWin = NULL;
		if (si != (sigproc_t) (-1))
			NcSignal(SIGINT, si);
		if (toOpen != (BookmarkPtr) 0) {
			/* If the user selected a site to open, connect to it now. */
			if (gStandAlone != 0) {
				LaunchNcFTP(toOpen->bookmarkName);
				/*NOTREACHED*/
				Exit(0);
			} else if (gBookmarkSelectionFile != NULL) {
				WriteSelectedBMToFile(toOpen->bookmarkName);
			}
			return (kNoErr);
		}
	}
	return (kNoErr);
}	/* HostWindow */




main_void_return_t
main(int argc, const char **argv)
{
	int result;
	int argi;

	gStandAlone = 1;
	gBookmarkSelectionFile = NULL;

	InitUserInfo();
	if (LoadBookmarkTable() < 0) {
		exit(7);
	}
	if (argc > 1) {
		/* The following hack is used by NcFTP
		 * to get the number of columns without
		 * having to link with curses/termcap.
		 * This simplifies things since the
		 * system may or may not have a good
		 * curses implementation, and we don't
		 * want to complicate NcFTP itself with
		 * that.
		 */
		argi = 1;
		if (strcmp(argv[1], "--dimensions") == 0) {
			result = PrintDimensions(0);
			exit((result == 0) ? 0 : 1);
		} else if (strcmp(argv[1], "--dimensions-terse") == 0) {
			result = PrintDimensions(1);
			exit((result == 0) ? 0 : 1);
		} else if (strcmp(argv[1], "--debug") == 0) {
			SetDebug(1);
			argi++;
		}
		/* Requested that we were run from ncftp. */
		gStandAlone = 0;
		if ((argc > argi) && (argv[argi][0] == '/'))
			gBookmarkSelectionFile = (const char *) argv[argi];
		if (gNumBookmarks < 1)
			exit(7);
	}

	result = FTPInitLibrary(&gLib);
	if (result < 0) {
		(void) fprintf(stderr, "ncftp: init library error %d (%s).\n", result, FTPStrError(result));
		exit(1);
	}

	result = FTPInitConnectionInfo(&gLib, &gConn, kDefaultFTPBufSize);
	if (result < 0) {
		(void) fprintf(stderr, "ncftp: init connection info error %d (%s).\n", result, FTPStrError(result));
		exit(1);
	}

	if (gDebug > 0)
		OpenTrace();
	InitPrefs();
	LoadFirewallPrefs(0);
	LoadPrefs();

	InitWindows();
	Trace(1, "Terminal size is %d columns by %d rows.\n", gScreenWidth, gScreenHeight);
	HostWindow();
	if (gDebug > 0)
		CloseTrace();
	EndWin();
	exit(0);
}	/* main */
static void
et_inittextmode(struct ite_softc *ip, et_sv_reg_t *etregs, int loadfont)
{
	volatile u_char *ba;
	font_info	*fd;
	u_char		*fb;
	u_char		*c, *f, tmp;
	u_short		z, y;
	int		s;
	view_t		*v   = viewview(ip->grf->g_viewdev);
	et_sv_reg_t	loc_regs;

	if (etregs == NULL) {
		etregs = &loc_regs;
		et_hwsave(etregs);
	}

	ba = ((ipriv_t*)ip->priv)->regkva;
	fb = v->bitmap->plane;

#if defined(KFONT_8X8)
	fd = &font_info_8x8;
#else
	fd = &font_info_8x16;
#endif

	if (loadfont) { /* XXX: We should set the colormap */
		/*
		 * set colors (B&W)
		 */
		vgaw(ba, VDAC_ADDRESS_W, 0);
		for (z = 0; z < 256; z++) {
			y = (z & 1) ? ((z > 7) ? 2 : 1) : 0;
    
			vgaw(ba, VDAC_DATA, etconscolors[y][0]);
			vgaw(ba, VDAC_DATA, etconscolors[y][1]);
			vgaw(ba, VDAC_DATA, etconscolors[y][2]);
		}

		/*
		 * Enter a suitable mode to download the font. This
		 * basically means sequential addressing mode
		 */
		s = splhigh();

		WAttr(ba, 0x20 | ACT_ID_ATTR_MODE_CNTL, 0x0a);
		WSeq(ba, SEQ_ID_MAP_MASK,	 0x04);
		WSeq(ba, SEQ_ID_MEMORY_MODE,	 0x06);
		WGfx(ba, GCT_ID_READ_MAP_SELECT, 0x02);
		WGfx(ba, GCT_ID_GRAPHICS_MODE,	 0x00);
		WGfx(ba, GCT_ID_MISC,		 0x04);
		splx(s);
	
		/*
		 * load text font into beginning of display memory. Each
		 * character cell is 32 bytes long (enough for 4 planes)
		 */
		for (z = 0, c = fb; z < 256 * 32; z++)
			*c++ = 0;

		c = (unsigned char *) (fb) + (32 * fd->font_lo);
		f = fd->font_p;
		z = fd->font_lo;
		for (; z <= fd->font_hi; z++, c += (32 - fd->height))
			for (y = 0; y < fd->height; y++) {
				*c++ = *f++;
			}
	}

	/*
	 * Odd/Even addressing
	 */
	etregs->seq[SEQ_ID_MAP_MASK]        = 0x03;
	etregs->seq[SEQ_ID_MEMORY_MODE]     = 0x03;
	etregs->grf[GCT_ID_READ_MAP_SELECT] = 0x00;
	etregs->grf[GCT_ID_GRAPHICS_MODE]   = 0x10;
	etregs->grf[GCT_ID_MISC]            = 0x06;

	/*
	 * Font height + underline location
	 */
	tmp = etregs->crt[CRT_ID_MAX_ROW_ADDRESS] & 0xe0;
	etregs->crt[CRT_ID_MAX_ROW_ADDRESS] = tmp | (fd->height - 1);
	tmp = etregs->crt[CRT_ID_UNDERLINE_LOC] & 0xe0;
	etregs->crt[CRT_ID_UNDERLINE_LOC] = tmp | (fd->height - 1);

	/*
	 * Cursor setup
	 */
	etregs->crt[CRT_ID_CURSOR_START]    = 0x00;
	etregs->crt[CRT_ID_CURSOR_END]      = fd->height - 1;
	etregs->crt[CRT_ID_CURSOR_LOC_HIGH] = 0x00;
	etregs->crt[CRT_ID_CURSOR_LOC_LOW]  = 0x00;

	/*
	 * Enter text mode
	 */
	etregs->crt[CRT_ID_MODE_CONTROL]    = 0xa3;
	etregs->attr[ACT_ID_ATTR_MODE_CNTL] = 0x0a;

#if 1
	if (loadfont || (etregs == &loc_regs))
#else
	if (etregs == &loc_regs)
#endif
		et_hwrest(etregs);
}