code: 9ferno

ref: 6bfe4cf8107de7a01ff8a0667db7f28f08e4d238
dir: /appl/cmd/ip/ppp/pppgui.b/

View raw version
#
# Copyright © 1998 Lucent Technologies Inc.  All rights reserved.
# Revisions copyright © 2000,2001 Vita Nuova Holdings Limited.  All rights reserved.
#
# Originally Written by N. W. Knauft
# Adapted by E. V. Hensbergen (ericvh@lucent.com)
# Further adapted by Vita Nuova
#

implement PPPGUI;

include "sys.m";
	sys: Sys;

include "draw.m";
	draw: Draw;

include "tk.m";
	tk: Tk;

include "tkclient.m";
	tkclient: Tkclient;

include "translate.m";
	translate: Translate;
	Dict: import translate;
	dict: ref Dict;

include "lock.m";
include "modem.m";
include "script.m";
include "pppclient.m";
	ppp: PPPClient;

include "pppgui.m";

#Screen constants
BBG: con "#C0C0C0";             # Background color for button
PBG: con "#808080";             # Background color for progress bar
LTGRN: con "#00FF80";           # Color for progress bar
BARW: con 216;			# Progress bar width
BARH: con " 9";			# Progress bar height
INCR: con 30;			# Progress bar increment size
N_INCR: con 7;			# Number of increments in progress bar width
BSIZE: con 25;			# Icon button size
ISIZE: con BSIZE + 4;		# Icon window size
DIALQUANTA : con 1000;
ICONQUANTA : con 5000;

#Globals
pppquanta := DIALQUANTA;

#Font
FONT: con "/fonts/lucidasans/unicode.6.font";

#Messages
stat_msgs := array[] of {
	"Initializing Modem",
	"Dialling Service Provider",
	"Logging Into Network",
	"Executing Login Script",
	"Script Execution Complete",
	"Logging Into Network",
	"Verifying Password",
	"Connected",
	"",
};

config_icon := array[] of {
	"button .btn -text X -width "+string BSIZE+" -height "+string BSIZE+" -command {send tsk open} -bg "+BBG,
	"pack .btn",

	"pack propagate . no",
	". configure -bd 0",
	". unmap",
	"update",
};


# Create internet connect window, spawn event handler
init(ctxt: ref Draw->Context, stat: chan of int, pppmod: PPPClient, args: list of string): chan of int
{
	sys = load Sys Sys->PATH;
	draw = load Draw Draw->PATH;
	tk = load Tk Tk->PATH;
	tkclient = load Tkclient Tkclient->PATH;

	if (draw == nil || tk == nil || tkclient == nil) {
		sys->fprint(sys->fildes(2), "pppgui: can't load Draw or Tk: %r\n");
		return nil;
	}

	translate = load Translate Translate->PATH;
	if(translate != nil) {
		translate->init();
		dictname := translate->mkdictname("", "pppgui");
		dicterr: string;
		(dict, dicterr) = translate->opendict(dictname);
		if(dicterr != nil)
			sys->fprint(sys->fildes(2), "pppgui: can't open %s: %s\n", dictname, dicterr);
	}else
		sys->fprint(sys->fildes(2), "pppgui: can't load %s: %r\n", Translate->PATH);
	ppp = pppmod;		# set the global

	tkargs := "";

	if (args != nil) {
		tkargs = hd args;
		args = tl args;
	} else
		tkargs="-x 340 -y 4";

	tkclient->init();
		
	(t, wmctl) := tkclient->toplevel(ctxt, tkargs, "PPP", Tkclient->Plain);

	config_win := array[] of {
		"frame .f",
		"frame .fprog",

		"canvas .cprog -bg "+PBG+" -bd 2 -width "+string BARW+" -height "+BARH+" -relief ridge",	
		"pack .cprog -in .fprog -pady 6",

		"label .stat -text {"+X("Initializing connection...")+"} -width 164 -font "+FONT,
		"pack .stat -in .f -side left -fill y -anchor w",

		"button .done -text {"+X("Cancel")+"} -width 60 -command {send cmd cancel} -bg "+BBG+" -font "+FONT,
		"pack .fprog -side bottom -expand 1 -fill x",
		"pack .done -side right -padx 1 -pady 1 -fill y -anchor e",
		"pack .f -side left -expand 1 -padx 5 -pady 3 -fill both -anchor w",

		"pack propagate . no",
		". configure -bd 2 -relief raised -width "+string WIDTH,
		"update",
	};

	for(i := 0; i < len config_win; i++)
		tk->cmd(t, config_win[i]);

	itkargs := "";
	if (args != nil) {
		itkargs = hd args;
		args = tl args;
	}
	tkclient->onscreen(t, nil);
	tkclient->startinput(t, "ptr" :: nil);

	if (itkargs == "") {
		x := int tk->cmd(t, ". cget x");
		y := int tk->cmd(t, ". cget y");
		x += WIDTH - ISIZE;
		itkargs = "-x "+string x+" -y "+string y;
	}

	(ticon, iconctl) := tkclient->toplevel(ctxt, itkargs, "PPP", Tkclient->Plain);

	for( i = 0; i < len config_icon; i++)
		tk->cmd(ticon, config_icon[i]);

	tk->cmd(ticon, "image create bitmap Network -file network.bit -maskfile network.bit");
	tk->cmd(ticon, ".btn configure -image Network");
	tkclient->startinput(ticon, "ptr"::nil);

	chn := chan of int;
	spawn handle_events(t, wmctl, ticon, iconctl, stat, chn);
	return chn;
}

ppp_timer(sync: chan of int, stat: chan of int)
{
	for(;;) {
		sys->sleep(pppquanta);
		alt {
		<-sync =>
			return;
		stat <-= -1 =>
			;
		}
	}
}

send(cmd: chan of string, msg: string)
{
	cmd <-= msg;
}

# Process events and pass disconnect cmd to calling app
handle_events(t: ref Tk->Toplevel, wmctl: chan of string, ticon: ref Tk->Toplevel, iconctl: chan of string, stat, chn: chan of int)
{
	sys->pctl(Sys->NEWPGRP, nil);
	cmd := chan of string;
	tk->namechan(t, cmd, "cmd");

	tsk := chan of string;
	tk->namechan(ticon, tsk, "tsk");

	connected := 0;
	winmapped := 1;
	timecount := 0;
	xmin := 0;
	x := 0;

	iocmd := sys->file2chan("/chan", "pppgui");
	if (iocmd == nil) {
		sys->print("fail: pppgui: file2chan: /chan/pppgui: %r\n");
		return;
	}

	pppquanta = DIALQUANTA;
	sync_chan := chan of int;
	spawn ppp_timer(sync_chan, stat);

Work:
	for(;;) alt {
	s := <-t.ctxt.kbd =>
		tk->keyboard(t, s);

	s := <-t.ctxt.ptr =>
		tk->pointer(t, *s);

	s := <-t.ctxt.ctl or
	s = <-t.wreq or
	s = <-wmctl =>
		tkclient->wmctl(t, s);

	s := <-ticon.ctxt.kbd =>
		tk->keyboard(ticon, s);
	s := <-ticon.ctxt.ptr =>
		tk->pointer(ticon, *s);
	s := <-ticon.ctxt.ctl or
	s = <-ticon.wreq or
	s = <-iconctl =>
		tkclient->wmctl(ticon, s);

	(off, data, fid, wc) := <-iocmd.write =>	# remote io control
		if (wc == nil)
			break;
		spawn send(cmd, string data[0:len data]);
		wc <-= (len data, nil);

	(nil, nbytes, fid, rc) := <-iocmd.read =>
		if (rc != nil)
			rc <-= (nil, "not readable");

	press := <-cmd =>
		case press {
		"cancel" or "disconnect" =>
			tk->cmd(t, ".stat configure -text 'Disconnecting...");
			tk->cmd(t, "update");
			ppp->reset();
			if (!connected) {
				# other end may have gone away
				alt {
					chn <-= 666 => ;
					* => ;
				}
			}
			break Work;
		* => ;
		}

	prs := <-tsk =>
		case prs {
		"open" =>
			tk->cmd(ticon, ". unmap; update");
			tk->cmd(t, ". map; raise .; update");
			winmapped = 1;
			timecount = 0;
		* => ;
		}

	s := <-stat =>
		if (s == -1) {	# just an update event
			if(winmapped){
				if(!connected) {	# increment status bar
					if (x < xmin+INCR) {
						x++;
						tk->cmd(t, ".cprog create rectangle 0 0 "+string x + BARH+" -fill "+LTGRN);
					}
				}else{
					timecount++;
					if(timecount > 1){
						winmapped = 0;
						timecount = 0;
						tk->cmd(t, ". unmap; update");
						tk->cmd(ticon, ". map; raise .; update");
						continue;
					}
				}
				tk->cmd(t, "raise .; update");
			} else {
				tk->cmd(ticon, "raise .; update");
				timecount = 0;
			}
			continue;
		}
		if (s == ppp->s_Error) {
			tk->cmd(t, ".stat configure -text '"+ppp->lasterror);
			if (!winmapped) {
				tk->cmd(ticon, ". unmap; update");
				tk->cmd(t, ". map; raise .");
			}
			tk->cmd(t, "update");
			sys->sleep(3000);	
			ppp->reset();
			if (!connected)
				chn <-= 0;			# Failure	
			break Work;
		}
	
		if (s == ppp->s_Initialized)
			tk->cmd(t,".cprog create rectangle 0 0 "+string BARW + BARH+" -fill "+PBG);
		
		x = xmin = s * INCR;
		if (xmin > BARW)
			xmin = BARW;
		tk->cmd(t, ".cprog create rectangle 0 0 "+string xmin + BARH+" -fill "+LTGRN);
		tk->cmd(t, "raise .; update");
		tk->cmd(t, ".stat configure -text '"+X(stat_msgs[s]));

		if (s == ppp->s_SuccessPPP || s == ppp->s_Done) {
			if(!connected){
				chn <-= 1;
				connected = 1;
			}
			pppquanta = ICONQUANTA;

			# find and display connection speed
			speed := findrate("/dev/modemstat", "rcvrate" :: "baud" :: nil);
			if(speed != nil)
				tk->cmd(t, ".stat configure -text {"+X(stat_msgs[s])+" "+speed+" bps}");
			else
				tk->cmd(t, ".stat configure -text {"+X(stat_msgs[s])+"}");
			tk->cmd(t, ".done configure -text Disconnect -command 'send cmd disconnect");
			tk->cmd(t, "update");
			sys->sleep(2000);	
			tk->cmd(t, ". unmap; pack forget .fprog; update");
			winmapped = 0;
			tk->cmd(ticon, ". map; raise .; update");
		}

		tk->cmd(t, "update");
	}
	sync_chan <-= 1;	# stop ppp_timer
}

findrate(file: string, opt: list of string): string
{
	fd := sys->open(file, sys->OREAD);
	if(fd == nil)
		return nil;
	buf := array [1024] of byte;
	n := sys->read(fd, buf, len buf);
	if(n <= 1)
		return nil;
	(nil, flds) := sys->tokenize(string buf[0:n], " \t\r\n");
	for(; flds != nil; flds = tl flds)
		for(l := opt; l != nil; l = tl l)
			if (hd flds == hd l)
				return hd tl flds;
	return nil;
}



# Translate a string 

X(s : string) : string
{
	if (dict== nil) return s;
	return dict.xlate(s);
}