1*37da2899SCharles.Forsythimplement Commandline; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsythinclude "sys.m"; 4*37da2899SCharles.Forsyth sys: Sys; 5*37da2899SCharles.Forsythinclude "draw.m"; 6*37da2899SCharles.Forsythinclude "tk.m"; 7*37da2899SCharles.Forsyth tk: Tk; 8*37da2899SCharles.Forsythinclude "tkclient.m"; 9*37da2899SCharles.Forsyth tkclient: Tkclient; 10*37da2899SCharles.Forsythinclude "commandline.m"; 11*37da2899SCharles.Forsyth 12*37da2899SCharles.ForsythDebug: con 0; 13*37da2899SCharles.Forsyth 14*37da2899SCharles.Forsythnomodule(modpath: string) 15*37da2899SCharles.Forsyth{ 16*37da2899SCharles.Forsyth sys->fprint(stderr(), "fibs: couldn't load %s: %r\n", modpath); 17*37da2899SCharles.Forsyth raise "fail:bad module"; 18*37da2899SCharles.Forsyth} 19*37da2899SCharles.Forsyth 20*37da2899SCharles.Forsythinit() 21*37da2899SCharles.Forsyth{ sys = load Sys Sys->PATH; 22*37da2899SCharles.Forsyth 23*37da2899SCharles.Forsyth tk = load Tk Tk->PATH; 24*37da2899SCharles.Forsyth if (tk == nil) nomodule(Tk->PATH); 25*37da2899SCharles.Forsyth 26*37da2899SCharles.Forsyth tkclient = load Tkclient Tkclient->PATH; 27*37da2899SCharles.Forsyth if (tkclient == nil) nomodule(Tkclient->PATH); 28*37da2899SCharles.Forsyth tkclient->init(); 29*37da2899SCharles.Forsyth} 30*37da2899SCharles.Forsyth 31*37da2899SCharles.ForsythCmdline.new(top: ref Tk->Toplevel, w, textopts: string): (ref Cmdline, chan of string) 32*37da2899SCharles.Forsyth{ 33*37da2899SCharles.Forsyth window_cfg := array[] of { 34*37da2899SCharles.Forsyth "frame " + w, 35*37da2899SCharles.Forsyth "scrollbar " + w + ".scroll -command {" + w + ".t yview}", 36*37da2899SCharles.Forsyth "text " + w + ".t -yscrollcommand {" + w + ".scroll set} " + textopts, 37*37da2899SCharles.Forsyth "pack " + w + ".scroll -side left -fill y", 38*37da2899SCharles.Forsyth "pack " + w + ".t -fill both -expand 1", 39*37da2899SCharles.Forsyth 40*37da2899SCharles.Forsyth "bind " + w + ".t <Key> {send evch k {%A}}", 41*37da2899SCharles.Forsyth "bind " + w + ".t <Control-d> {send evch k {%A}}", 42*37da2899SCharles.Forsyth "bind " + w + ".t <Control-u> {send evch k {%A}}", 43*37da2899SCharles.Forsyth "bind " + w + ".t <Control-w> {send evch k {%A}}", 44*37da2899SCharles.Forsyth "bind " + w + ".t <Control-h> {send evch k {%A}}", 45*37da2899SCharles.Forsyth # treat button 2 and button 3 the same so we're alright with a 2-button mouse 46*37da2899SCharles.Forsyth "bind " + w + ".t <ButtonPress-2> {send evch b %x %y}", 47*37da2899SCharles.Forsyth "bind " + w + ".t <ButtonPress-3> {send evch b %x %y}", 48*37da2899SCharles.Forsyth w + ".t mark set outpoint end", 49*37da2899SCharles.Forsyth w + ".t mark gravity outpoint left", 50*37da2899SCharles.Forsyth w + ".t mark set inpoint end", 51*37da2899SCharles.Forsyth w + ".t mark gravity inpoint left", 52*37da2899SCharles.Forsyth }; 53*37da2899SCharles.Forsyth evch := chan of string; 54*37da2899SCharles.Forsyth tk->namechan(top, evch, "evch"); 55*37da2899SCharles.Forsyth 56*37da2899SCharles.Forsyth for (i := 0; i < len window_cfg; i++) { 57*37da2899SCharles.Forsyth e := cmd(top, window_cfg[i]); 58*37da2899SCharles.Forsyth if (e != nil && e[0] == '!') 59*37da2899SCharles.Forsyth break; 60*37da2899SCharles.Forsyth } 61*37da2899SCharles.Forsyth 62*37da2899SCharles.Forsyth err := tk->cmd(top, "variable lasterror"); 63*37da2899SCharles.Forsyth if (err != nil) { 64*37da2899SCharles.Forsyth sys->fprint(stderr(), "error in commandline config: %s\n", err); 65*37da2899SCharles.Forsyth raise "fail:commandline config error"; 66*37da2899SCharles.Forsyth } 67*37da2899SCharles.Forsyth cmd(top, w + ".t mark set insert end;" + w + ".t see insert"); 68*37da2899SCharles.Forsyth return (ref Cmdline(w, top), evch); 69*37da2899SCharles.Forsyth} 70*37da2899SCharles.Forsyth 71*37da2899SCharles.ForsythCmdline.focus(cmdl: self ref Cmdline) 72*37da2899SCharles.Forsyth{ 73*37da2899SCharles.Forsyth cmd(cmdl.top, "focus " + cmdl.w + ".t"); 74*37da2899SCharles.Forsyth} 75*37da2899SCharles.Forsyth 76*37da2899SCharles.ForsythCmdline.event(cmdl: self ref Cmdline, e: string): list of string 77*37da2899SCharles.Forsyth{ 78*37da2899SCharles.Forsyth case e[0] { 79*37da2899SCharles.Forsyth 'k' => 80*37da2899SCharles.Forsyth return handle_key(cmdl, e[2:]); 81*37da2899SCharles.Forsyth 'b' => 82*37da2899SCharles.Forsyth ; 83*37da2899SCharles.Forsyth } 84*37da2899SCharles.Forsyth return nil; 85*37da2899SCharles.Forsyth} 86*37da2899SCharles.Forsyth 87*37da2899SCharles.ForsythBS: con 8; # ^h backspace character 88*37da2899SCharles.ForsythBSW: con 23; # ^w bacspace word 89*37da2899SCharles.ForsythBSL: con 21; # ^u backspace line 90*37da2899SCharles.Forsyth 91*37da2899SCharles.Forsythhandle_key(cmdl: ref Cmdline, c: string): list of string 92*37da2899SCharles.Forsyth{ 93*37da2899SCharles.Forsyth (w, top) := (cmdl.w, cmdl.top); 94*37da2899SCharles.Forsyth # don't allow editing of the text before the inpoint. 95*37da2899SCharles.Forsyth if (int cmd(top, w + ".t compare insert < inpoint")) 96*37da2899SCharles.Forsyth return nil; 97*37da2899SCharles.Forsyth lines: list of string; 98*37da2899SCharles.Forsyth char := c[1]; 99*37da2899SCharles.Forsyth if (char == '\\') 100*37da2899SCharles.Forsyth char = c[2]; 101*37da2899SCharles.Forsyth case char { 102*37da2899SCharles.Forsyth * => 103*37da2899SCharles.Forsyth cmd(top, w + ".t insert insert "+c+" {}"); 104*37da2899SCharles.Forsyth '\n' => 105*37da2899SCharles.Forsyth cmd(top, w + ".t insert insert "+c+" {}"); 106*37da2899SCharles.Forsyth lines = sendinput(cmdl); 107*37da2899SCharles.Forsyth BSL or BSW or BS => 108*37da2899SCharles.Forsyth delpoint: string; 109*37da2899SCharles.Forsyth case char { 110*37da2899SCharles.Forsyth BSL => delpoint = "{insert linestart}"; 111*37da2899SCharles.Forsyth BSW => delpoint = "{insert -1char wordstart}"; # wordstart isn't ideal 112*37da2899SCharles.Forsyth BS => delpoint = "{insert-1char}"; 113*37da2899SCharles.Forsyth } 114*37da2899SCharles.Forsyth if (int cmd(top, w + ".t compare inpoint < " + delpoint)) 115*37da2899SCharles.Forsyth cmd(top, w + ".t delete "+delpoint+" insert"); 116*37da2899SCharles.Forsyth else 117*37da2899SCharles.Forsyth cmd(top, w + ".t delete inpoint insert"); 118*37da2899SCharles.Forsyth } 119*37da2899SCharles.Forsyth cmd(top, w + ".t see insert;update"); 120*37da2899SCharles.Forsyth return lines; 121*37da2899SCharles.Forsyth} 122*37da2899SCharles.Forsyth 123*37da2899SCharles.Forsythsendinput(cmdl: ref Cmdline): list of string 124*37da2899SCharles.Forsyth{ 125*37da2899SCharles.Forsyth (w, top) := (cmdl.w, cmdl.top); 126*37da2899SCharles.Forsyth # loop through all the lines that have been entered, 127*37da2899SCharles.Forsyth # processing each one in turn. 128*37da2899SCharles.Forsyth nl, lines: list of string; 129*37da2899SCharles.Forsyth for (;;) { 130*37da2899SCharles.Forsyth input: string; 131*37da2899SCharles.Forsyth input = cmd(top, w + ".t get inpoint end"); 132*37da2899SCharles.Forsyth if (len input == 0) 133*37da2899SCharles.Forsyth break; 134*37da2899SCharles.Forsyth for (i := 0; i < len input; i++) 135*37da2899SCharles.Forsyth if (input[i] == '\n') 136*37da2899SCharles.Forsyth break; 137*37da2899SCharles.Forsyth if (i >= len input) 138*37da2899SCharles.Forsyth break; 139*37da2899SCharles.Forsyth cmd(top, w + ".t mark set outpoint inpoint+"+string (i+1)+"chars"); 140*37da2899SCharles.Forsyth cmd(top, w + ".t mark set inpoint outpoint"); 141*37da2899SCharles.Forsyth lines = input[0:i+1] :: lines; 142*37da2899SCharles.Forsyth } 143*37da2899SCharles.Forsyth for (; lines != nil; lines = tl lines) 144*37da2899SCharles.Forsyth nl = hd lines :: nl; 145*37da2899SCharles.Forsyth return nl; 146*37da2899SCharles.Forsyth} 147*37da2899SCharles.Forsyth 148*37da2899SCharles.Forsythadd(cmdl: ref Cmdline, t: string, n: int) 149*37da2899SCharles.Forsyth{ 150*37da2899SCharles.Forsyth (w, top) := (cmdl.w, cmdl.top); 151*37da2899SCharles.Forsyth cmd(top, w + ".t insert outpoint " + t); 152*37da2899SCharles.Forsyth cmd(top, w + ".t mark set outpoint outpoint+"+string n+"chars"); 153*37da2899SCharles.Forsyth cmd(top, w + ".t mark set inpoint outpoint"); 154*37da2899SCharles.Forsyth cmd(top, w + ".t see insert"); 155*37da2899SCharles.Forsyth} 156*37da2899SCharles.Forsyth 157*37da2899SCharles.ForsythCmdline.tagaddtext(cmdl: self ref Cmdline, t: list of (string, string)) 158*37da2899SCharles.Forsyth{ 159*37da2899SCharles.Forsyth txt := ""; 160*37da2899SCharles.Forsyth n := 0; 161*37da2899SCharles.Forsyth for (; t != nil; t = tl t) { 162*37da2899SCharles.Forsyth (tags, s) := hd t; 163*37da2899SCharles.Forsyth txt += " " + tk->quote(s) + " {" + tags + "}"; 164*37da2899SCharles.Forsyth n += len s; 165*37da2899SCharles.Forsyth } 166*37da2899SCharles.Forsyth add(cmdl, txt, n); 167*37da2899SCharles.Forsyth} 168*37da2899SCharles.Forsyth 169*37da2899SCharles.ForsythCmdline.addtext(cmdl: self ref Cmdline, txt: string) 170*37da2899SCharles.Forsyth{ 171*37da2899SCharles.Forsyth if (Debug) sys->print("%s", txt); 172*37da2899SCharles.Forsyth add(cmdl, tk->quote(txt) + " {}" , len txt); 173*37da2899SCharles.Forsyth} 174*37da2899SCharles.Forsyth 175*37da2899SCharles.ForsythCmdline.maketag(cmdl: self ref Cmdline, name, options: string) 176*37da2899SCharles.Forsyth{ 177*37da2899SCharles.Forsyth cmd(cmdl.top, cmdl.w + ".t tag configure " + name + " " + options); 178*37da2899SCharles.Forsyth} 179*37da2899SCharles.Forsyth 180*37da2899SCharles.Forsythstderr(): ref Sys->FD 181*37da2899SCharles.Forsyth{ 182*37da2899SCharles.Forsyth return sys->fildes(2); 183*37da2899SCharles.Forsyth} 184*37da2899SCharles.Forsyth 185*37da2899SCharles.Forsythcmd(top: ref Tk->Toplevel, s: string): string 186*37da2899SCharles.Forsyth{ 187*37da2899SCharles.Forsyth e := tk->cmd(top, s); 188*37da2899SCharles.Forsyth if (e != nil && e[0] == '!') 189*37da2899SCharles.Forsyth sys->fprint(stderr(), "cmd error on '%s': %s\n", s, e); 190*37da2899SCharles.Forsyth return e; 191*37da2899SCharles.Forsyth} 192