look.b 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. implement Look;
  2. include "common.m";
  3. sys : Sys;
  4. draw : Draw;
  5. utils : Utils;
  6. dat : Dat;
  7. graph : Graph;
  8. acme : Acme;
  9. framem : Framem;
  10. regx : Regx;
  11. bufferm : Bufferm;
  12. textm : Textm;
  13. windowm : Windowm;
  14. columnm : Columnm;
  15. exec : Exec;
  16. scrl : Scroll;
  17. plumbmsg : Plumbmsg;
  18. sprint : import sys;
  19. Point : import draw;
  20. warning, isalnum, stralloc, strfree, strchr, tgetc : import utils;
  21. Range, TRUE, FALSE, XXX, BUFSIZE, Astring : import Dat;
  22. Expand, seltext, row : import dat;
  23. cursorset : import graph;
  24. frptofchar : import framem;
  25. isaddrc, isregexc, address : import regx;
  26. Buffer : import bufferm;
  27. Text : import textm;
  28. Window : import windowm;
  29. Column : import columnm;
  30. Msg : import plumbmsg;
  31. init(mods : ref Dat->Mods)
  32. {
  33. sys = mods.sys;
  34. draw = mods.draw;
  35. utils = mods.utils;
  36. graph = mods.graph;
  37. acme = mods.acme;
  38. framem = mods.framem;
  39. regx = mods.regx;
  40. dat = mods.dat;
  41. bufferm = mods.bufferm;
  42. textm = mods.textm;
  43. windowm = mods.windowm;
  44. columnm = mods.columnm;
  45. exec = mods.exec;
  46. scrl = mods.scroll;
  47. plumbmsg = mods.plumbmsg;
  48. }
  49. nuntitled : int;
  50. look3(t : ref Text, q0 : int, q1 : int, external : int)
  51. {
  52. n, c, f : int;
  53. ct : ref Text;
  54. e : Expand;
  55. r : ref Astring;
  56. expanded : int;
  57. ct = seltext;
  58. if(ct == nil)
  59. seltext = t;
  60. (expanded, e) = expand(t, q0, q1);
  61. if(!external && t.w!=nil && t.w.nopen[Dat->QWevent]>byte 0){
  62. if(!expanded)
  63. return;
  64. f = 0;
  65. if((e.at!=nil && t.w!=nil) || (e.name!=nil && lookfile(e.name, len e.name)!=nil))
  66. f = 1; # acme can do it without loading a file
  67. if(q0!=e.q0 || q1!=e.q1)
  68. f |= 2; # second (post-expand) message follows
  69. if(e.name != nil)
  70. f |= 4; # it's a file name
  71. c = 'l';
  72. if(t.what == Textm->Body)
  73. c = 'L';
  74. n = q1-q0;
  75. if(n <= Dat->EVENTSIZE){
  76. r = stralloc(n);
  77. t.file.buf.read(q0, r, 0, n);
  78. t.w.event(sprint("%c%d %d %d %d %s\n", c, q0, q1, f, n, r.s[0:n]));
  79. strfree(r);
  80. r = nil;
  81. }else
  82. t.w.event(sprint("%c%d %d %d 0 \n", c, q0, q1, f));
  83. if(q0==e.q0 && q1==e.q1)
  84. return;
  85. if(e.name != nil){
  86. n = len e.name;
  87. if(e.a1 > e.a0)
  88. n += 1+(e.a1-e.a0);
  89. r = stralloc(n);
  90. for (i := 0; i < len e.name; i++)
  91. r.s[i] = e.name[i];
  92. if(e.a1 > e.a0){
  93. r.s[len e.name] = ':';
  94. e.at.file.buf.read(e.a0, r, len e.name+1, e.a1-e.a0);
  95. }
  96. }else{
  97. n = e.q1 - e.q0;
  98. r = stralloc(n);
  99. t.file.buf.read(e.q0, r, 0, n);
  100. }
  101. f &= ~2;
  102. if(n <= Dat->EVENTSIZE)
  103. t.w.event(sprint("%c%d %d %d %d %s\n", c, e.q0, e.q1, f, n, r.s[0:n]));
  104. else
  105. t.w.event(sprint("%c%d %d %d 0 \n", c, e.q0, e.q1, f));
  106. strfree(r);
  107. r = nil;
  108. return;
  109. }
  110. if(0 && dat->plumbed){ # don't do yet : 2 acmes running => only 1 receives msg
  111. m := ref Msg;
  112. m.src = "acme";
  113. m.dst = nil;
  114. (dir, nil) := dirname(t, nil, 0);
  115. if(dir == ".") # sigh
  116. dir = nil;
  117. if(dir == nil)
  118. dir = acme->wdir;
  119. m.dir = dir;
  120. m.kind = "text";
  121. m.attr = nil;
  122. if(q1 == q0){
  123. if(t.q1>t.q0 && t.q0<=q0 && q0<=t.q1){
  124. q0 = t.q0;
  125. q1 = t.q1;
  126. }else{
  127. p := q0;
  128. while(q0 > 0 && (c = tgetc(t, q0-1)) != ' ' && c != '\t' && c != '\n')
  129. q0--;
  130. while(q1 < t.file.buf.nc && (c = tgetc(t, q1)) != ' ' && c != '\t' && c != '\n')
  131. q1++;
  132. if(q1 == q0)
  133. return;
  134. m.attr = "click=" + string (p-q0);
  135. }
  136. }
  137. r = stralloc(q1-q0);
  138. t.file.buf.read(q0, r, 0, q1-q0);
  139. m.data = array of byte r.s;
  140. strfree(r);
  141. if(m.send() >= 0)
  142. return;
  143. # plumber failed to match : fall through
  144. }
  145. if(!expanded)
  146. return;
  147. if(e.name != nil || e.at != nil)
  148. (nil, e) = openfile(t, e);
  149. else{
  150. if(t.w == nil)
  151. return;
  152. ct = t.w.body;
  153. if(t.w != ct.w)
  154. ct.w.lock('M');
  155. if(t == ct)
  156. ct.setselect(e.q1, e.q1);
  157. n = e.q1 - e.q0;
  158. r = stralloc(n);
  159. t.file.buf.read(e.q0, r, 0, n);
  160. if(search(ct, r.s, n) && e.jump)
  161. cursorset(frptofchar(ct.frame, ct.frame.p0).add((4, ct.frame.font.height-4)));
  162. if(t.w != ct.w)
  163. ct.w.unlock();
  164. strfree(r);
  165. r = nil;
  166. }
  167. e.name = nil;
  168. e.bname = nil;
  169. }
  170. plumblook(m : ref Msg)
  171. {
  172. e : Expand;
  173. if (len m.data > Dat->PLUMBSIZE) {
  174. warning(nil, sys->sprint("plumb message too long : %s\n", string m.data));
  175. return;
  176. }
  177. e.q0 = e.q1 = 0;
  178. if (len m.data == 0)
  179. return;
  180. e.ar = nil;
  181. e.name = string m.data;
  182. if(e.name[0] != '/' && m.dir != nil)
  183. e.name = m.dir + "/" + e.name;
  184. (e.name, nil) = cleanname(e.name, len e.name);
  185. e.bname = e.name;
  186. e.jump = TRUE;
  187. e.a0 = e.a1 = 0;
  188. (found, addr) := plumbmsg->lookup(plumbmsg->string2attrs(m.attr), "addr");
  189. if (found && addr != nil) {
  190. e.ar = addr;
  191. e.a1 = len addr;
  192. }
  193. openfile(nil, e);
  194. e.at = nil;
  195. }
  196. plumbshow(m : ref Msg)
  197. {
  198. w := utils->newwindow(nil);
  199. (found, name) := plumbmsg->lookup(plumbmsg->string2attrs(m.attr), "filename");
  200. if (!found || name == nil) {
  201. nuntitled++;
  202. name = "Untitled-" + string nuntitled;
  203. }
  204. if (name[0] != '/' && m.dir != nil)
  205. name = m.dir + "/" + name;
  206. (name, nil) = cleanname(name, len name);
  207. w.setname(name, len name);
  208. d := string m.data;
  209. w.body.insert(0, d, len d, TRUE, FALSE);
  210. w.body.file.mod = FALSE;
  211. w.dirty = FALSE;
  212. w.settag();
  213. scrl->scrdraw(w.body);
  214. w.tag.setselect(w.tag.file.buf.nc, w.tag.file.buf.nc);
  215. }
  216. search(ct : ref Text, r : string, n : int) : int
  217. {
  218. q, nb, maxn : int;
  219. around : int;
  220. s : ref Astring;
  221. b, c : int;
  222. if(n==0 || n>ct.file.buf.nc)
  223. return FALSE;
  224. if(2*n > BUFSIZE){
  225. warning(nil, "string too long\n");
  226. return FALSE;
  227. }
  228. maxn = utils->max(2*n, BUFSIZE);
  229. s = utils->stralloc(BUFSIZE);
  230. b = nb = 0;
  231. around = 0;
  232. q = ct.q1;
  233. for(;;){
  234. if(q >= ct.file.buf.nc){
  235. q = 0;
  236. around = 1;
  237. nb = 0;
  238. }
  239. if(nb > 0){
  240. for (c = 0; c < nb; c++)
  241. if (s.s[b+c] == r[0])
  242. break;
  243. if(c >= nb){
  244. q += nb;
  245. nb = 0;
  246. if(around && q>=ct.q1)
  247. break;
  248. continue;
  249. }
  250. q += c;
  251. nb -= c;
  252. b += c;
  253. }
  254. # reload if buffer covers neither string nor rest of file
  255. if(nb<n && nb!=ct.file.buf.nc-q){
  256. nb = ct.file.buf.nc-q;
  257. if(nb >= maxn)
  258. nb = maxn-1;
  259. ct.file.buf.read(q, s, 0, nb);
  260. b = 0;
  261. }
  262. if(n <= nb && s.s[b:b+n] == r[0:n]){
  263. if(ct.w != nil){
  264. ct.show(q, q+n, TRUE);
  265. ct.w.settag();
  266. }else{
  267. ct.q0 = q;
  268. ct.q1 = q+n;
  269. }
  270. seltext = ct;
  271. utils->strfree(s);
  272. s = nil;
  273. return TRUE;
  274. }
  275. if(around && q>=ct.q1)
  276. break;
  277. --nb;
  278. b++;
  279. q++;
  280. }
  281. utils->strfree(s);
  282. s = nil;
  283. return FALSE;
  284. }
  285. isfilec(r : int) : int
  286. {
  287. if(isalnum(r))
  288. return TRUE;
  289. if(strchr(".-+/:", r) >= 0)
  290. return TRUE;
  291. return FALSE;
  292. }
  293. cleanname(b : string, n : int) : (string, int)
  294. {
  295. i, j, found : int;
  296. b = b[0:n];
  297. # compress multiple slashes
  298. for(i=0; i<n-1; i++)
  299. if(b[i]=='/' && b[i+1]=='/'){
  300. b = b[0:i] + b[i+1:];
  301. --n;
  302. --i;
  303. }
  304. # eliminate ./
  305. for(i=0; i<n-1; i++)
  306. if(b[i]=='.' && b[i+1]=='/' && (i==0 || b[i-1]=='/')){
  307. b = b[0:i] + b[i+2:];
  308. n -= 2;
  309. --i;
  310. }
  311. # eliminate trailing .
  312. if(n>=2 && b[n-2]=='/' && b[n-1]=='.') {
  313. --n;
  314. b = b[0:n];
  315. }
  316. do{
  317. # compress xx/..
  318. found = FALSE;
  319. for(i=1; i<=n-3; i++)
  320. if(b[i:i+3] == "/.."){
  321. if(i==n-3 || b[i+3]=='/'){
  322. found = TRUE;
  323. break;
  324. }
  325. }
  326. if(found)
  327. for(j=i-1; j>=0; --j)
  328. if(j==0 || b[j-1]=='/'){
  329. i += 3; # character beyond ..
  330. if(i<n && b[i]=='/')
  331. ++i;
  332. b = b[0:j] + b[i:];
  333. n -= (i-j);
  334. break;
  335. }
  336. }while(found);
  337. if(n == 0){
  338. b = ".";
  339. n = 1;
  340. }
  341. return (b, n);
  342. }
  343. includefile(dir : string, file : string, nfile : int) : (string, int)
  344. {
  345. m, n : int;
  346. a : string;
  347. if (dir == ".") {
  348. m = 0;
  349. a = file;
  350. }
  351. else {
  352. m = 1 + len dir;
  353. a = dir + "/" + file;
  354. }
  355. n = utils->access(a);
  356. if(n < 0) {
  357. a = nil;
  358. return (nil, 0);
  359. }
  360. file = nil;
  361. return cleanname(a, m+nfile);
  362. }
  363. objdir : string;
  364. includename(t : ref Text , r : string, n : int) : (string, int)
  365. {
  366. file : string;
  367. i, nfile : int;
  368. w : ref Window;
  369. {
  370. w = t.w;
  371. if(n==0 || r[0]=='/' || w==nil)
  372. raise "e";
  373. if(n>2 && r[0]=='.' && r[1]=='/')
  374. raise "e";
  375. file = nil;
  376. nfile = 0;
  377. (file, nfile) = includefile(".", r, n);
  378. if (file == nil) {
  379. (dr, dn) := dirname(t, r, n);
  380. (file, nfile) = includefile(".", dr, dn);
  381. }
  382. if (file == nil) {
  383. for(i=0; i<w.nincl && file==nil; i++)
  384. (file, nfile) = includefile(w.incl[i], r, n);
  385. }
  386. if(file == nil)
  387. (file, nfile) = includefile("/module", r, n);
  388. if(file == nil)
  389. (file, nfile) = includefile("/include", r, n);
  390. if(file==nil && objdir!=nil)
  391. (file, nfile) = includefile(objdir, r, n);
  392. if(file == nil)
  393. raise "e";
  394. return (file, nfile);
  395. }
  396. exception{
  397. * =>
  398. return (r, n);
  399. }
  400. return (nil, 0);
  401. }
  402. dirname(t : ref Text, r : string, n : int) : (string, int)
  403. {
  404. b : ref Astring;
  405. c : int;
  406. m, nt : int;
  407. slash : int;
  408. {
  409. b = nil;
  410. if(t == nil || t.w == nil)
  411. raise "e";
  412. nt = t.w.tag.file.buf.nc;
  413. if(nt == 0)
  414. raise "e";
  415. if(n>=1 && r[0]=='/')
  416. raise "e";
  417. b = stralloc(nt+n+1);
  418. t.w.tag.file.buf.read(0, b, 0, nt);
  419. slash = -1;
  420. for(m=0; m<nt; m++){
  421. c = b.s[m];
  422. if(c == '/')
  423. slash = m;
  424. if(c==' ' || c=='\t')
  425. break;
  426. }
  427. if(slash < 0)
  428. raise "e";
  429. for (i := 0; i < n; i++)
  430. b.s[slash+1+i] = r[i];
  431. r = nil;
  432. return cleanname(b.s, slash+1+n);
  433. }
  434. exception{
  435. * =>
  436. b = nil;
  437. if(r != nil)
  438. return cleanname(r, n);
  439. return (r, n);
  440. }
  441. return (nil, 0);
  442. }
  443. expandfile(t : ref Text, q0 : int, q1 : int, e : Expand) : (int, Expand)
  444. {
  445. i, n, nname, colon : int;
  446. amin, amax : int;
  447. r : ref Astring;
  448. c : int;
  449. w : ref Window;
  450. amax = q1;
  451. if(q1 == q0){
  452. colon = -1;
  453. while(q1<t.file.buf.nc && isfilec(c=t.readc(q1))){
  454. if(c == ':'){
  455. colon = q1;
  456. break;
  457. }
  458. q1++;
  459. }
  460. while(q0>0 && (isfilec(c=t.readc(q0-1)) || isaddrc(c) || isregexc(c))){
  461. q0--;
  462. if(colon==-1 && c==':')
  463. colon = q0;
  464. }
  465. #
  466. # if it looks like it might begin file: , consume address chars after :
  467. # otherwise terminate expansion at :
  468. #
  469. if(colon>=0 && colon<t.file.buf.nc-1 && isaddrc(t.readc(colon+1))){
  470. q1 = colon+1;
  471. while(q1<t.file.buf.nc-1 && isaddrc(t.readc(q1)))
  472. q1++;
  473. }else if(colon >= 0)
  474. q1 = colon;
  475. if(q1 > q0)
  476. if(colon >= 0){ # stop at white space
  477. for(amax=colon+1; amax<t.file.buf.nc; amax++)
  478. if((c=t.readc(amax))==' ' || c=='\t' || c=='\n')
  479. break;
  480. }else
  481. amax = t.file.buf.nc;
  482. }
  483. amin = amax;
  484. e.q0 = q0;
  485. e.q1 = q1;
  486. n = q1-q0;
  487. if(n == 0)
  488. return (FALSE, e);
  489. # see if it's a file name
  490. r = stralloc(n);
  491. t.file.buf.read(q0, r, 0, n);
  492. # first, does it have bad chars?
  493. nname = -1;
  494. for(i=0; i<n; i++){
  495. c = r.s[i];
  496. if(c==':' && nname<0){
  497. if(q0+i+1<t.file.buf.nc && (i==n-1 || isaddrc(t.readc(q0+i+1))))
  498. amin = q0+i;
  499. else {
  500. strfree(r);
  501. r = nil;
  502. return (FALSE, e);
  503. }
  504. nname = i;
  505. }
  506. }
  507. if(nname == -1)
  508. nname = n;
  509. for(i=0; i<nname; i++)
  510. if(!isfilec(r.s[i])) {
  511. strfree(r);
  512. r = nil;
  513. return (FALSE, e);
  514. }
  515. #
  516. # See if it's a file name in <>, and turn that into an include
  517. # file name if so. Should probably do it for "" too, but that's not
  518. # restrictive enough syntax and checking for a #include earlier on the
  519. # line would be silly.
  520. #
  521. isfile := 0;
  522. if(q0>0 && t.readc(q0-1)=='<' && q1<t.file.buf.nc && t.readc(q1)=='>')
  523. (r.s, nname) = includename(t, r.s, nname);
  524. else if(q0>0 && t.readc(q0-1)=='"' && q1<t.file.buf.nc && t.readc(q1)=='"')
  525. (r.s, nname) = includename(t, r.s, nname);
  526. else if(amin == q0)
  527. isfile = 1;
  528. else
  529. (r.s, nname) = dirname(t, r.s, nname);
  530. if (!isfile) {
  531. e.bname = r.s;
  532. # if it's already a window name, it's a file
  533. w = lookfile(r.s, nname);
  534. # if it's the name of a file, it's a file
  535. if(w == nil && utils->access(e.bname) < 0){
  536. e.bname = nil;
  537. strfree(r);
  538. r = nil;
  539. return (FALSE, e);
  540. }
  541. }
  542. e.name = r.s[0:nname];
  543. e.at = t;
  544. e.a0 = amin+1;
  545. (nil, e.a1, nil) = address(nil, nil, (Range)(-1,-1), (Range)(0, 0), t, nil, e.a0, amax, FALSE);
  546. strfree(r);
  547. r = nil;
  548. return (TRUE, e);
  549. }
  550. expand(t : ref Text, q0 : int, q1 : int) : (int, Expand)
  551. {
  552. e : Expand;
  553. ok : int;
  554. e.q0 = e.q1 = e.a0 = e.a1 = 0;
  555. e.name = e.bname = nil;
  556. e.at = nil;
  557. # if in selection, choose selection
  558. e.jump = TRUE;
  559. if(q1==q0 && t.q1>t.q0 && t.q0<=q0 && q0<=t.q1){
  560. q0 = t.q0;
  561. q1 = t.q1;
  562. if(t.what == Textm->Tag)
  563. e.jump = FALSE;
  564. }
  565. (ok, e) = expandfile(t, q0, q1, e);
  566. if (ok)
  567. return (TRUE, e);
  568. if(q0 == q1){
  569. while(q1<t.file.buf.nc && isalnum(t.readc(q1)))
  570. q1++;
  571. while(q0>0 && isalnum(t.readc(q0-1)))
  572. q0--;
  573. }
  574. e.q0 = q0;
  575. e.q1 = q1;
  576. return (q1 > q0, e);
  577. }
  578. lookfile(s : string, n : int) : ref Window
  579. {
  580. i, j, k : int;
  581. w : ref Window;
  582. c : ref Column;
  583. t : ref Text;
  584. # avoid terminal slash on directories
  585. if(n > 1 && s[n-1] == '/')
  586. --n;
  587. for(j=0; j<row.ncol; j++){
  588. c = row.col[j];
  589. for(i=0; i<c.nw; i++){
  590. w = c.w[i];
  591. t = w.body;
  592. k = len t.file.name;
  593. if(k>0 && t.file.name[k-1] == '/')
  594. k--;
  595. if(t.file.name[0:k] == s[0:n]){
  596. w = w.body.file.curtext.w;
  597. if(w.col != nil) # protect against race deleting w
  598. return w;
  599. }
  600. }
  601. }
  602. return nil;
  603. }
  604. lookid(id : int, dump : int) : ref Window
  605. {
  606. i, j : int;
  607. w : ref Window;
  608. c : ref Column;
  609. for(j=0; j<row.ncol; j++){
  610. c = row.col[j];
  611. for(i=0; i<c.nw; i++){
  612. w = c.w[i];
  613. if(dump && w.dumpid == id)
  614. return w;
  615. if(!dump && w.id == id)
  616. return w;
  617. }
  618. }
  619. return nil;
  620. }
  621. openfile(t : ref Text, e : Expand) : (ref Window, Expand)
  622. {
  623. r : Range;
  624. w, ow : ref Window;
  625. eval, i, n : int;
  626. if(e.name == nil){
  627. w = t.w;
  628. if(w == nil)
  629. return (nil, e);
  630. }else
  631. w = lookfile(e.name, len e.name);
  632. if(w != nil){
  633. t = w.body;
  634. if(!t.col.safe && t.frame.maxlines==0) # window is obscured by full-column window
  635. t.col.grow(t.col.w[0], 1, 1);
  636. }
  637. else{
  638. ow = nil;
  639. if(t != nil)
  640. ow = t.w;
  641. w = utils->newwindow(t);
  642. t = w.body;
  643. w.setname(e.name, len e.name);
  644. t.loadx(0, e.bname, 1);
  645. t.file.mod = FALSE;
  646. t.w.dirty = FALSE;
  647. t.w.settag();
  648. t.w.tag.setselect(t.w.tag.file.buf.nc, t.w.tag.file.buf.nc);
  649. if(ow != nil)
  650. for(i=ow.nincl; --i>=0; ){
  651. n = len ow.incl[i];
  652. w.addincl(ow.incl[i], n); # really do want to copy here
  653. }
  654. }
  655. if(e.a1 == e.a0)
  656. eval = FALSE;
  657. else
  658. (eval, nil, r) = address(nil, t, (Range)(-1, -1), (Range)(t.q0, t.q1), e.at, e.ar, e.a0, e.a1, TRUE);
  659. # was (eval, nil, r) = address(nil, t, (Range)(-1, -1), (Range)(t.q0, t.q1), e.at, nil, e.a0, e.a1, TRUE);
  660. if(eval == FALSE){
  661. r.q0 = t.q0;
  662. r.q1 = t.q1;
  663. }
  664. t.show(r.q0, r.q1, TRUE);
  665. t.w.settag();
  666. seltext = t;
  667. if(e.jump)
  668. cursorset(frptofchar(t.frame, t.frame.p0).add((4, t.frame.font.height-4)));
  669. return (w, e);
  670. }
  671. new(et : ref Text, t : ref Text, argt : ref Text, flag1 : int, flag2 : int, arg : string, narg : int)
  672. {
  673. ndone : int;
  674. a, f : string;
  675. na, nf : int;
  676. e : Expand;
  677. (nil, a, na) = exec->getarg(argt, FALSE, TRUE);
  678. if(a != nil){
  679. new(et, t, nil, flag1, flag2, a, na);
  680. if(narg == 0)
  681. return;
  682. }
  683. # loop condition: *arg is not a blank
  684. for(ndone=0; ; ndone++){
  685. (a, na) = utils->findbl(arg, narg);
  686. if(a == arg){
  687. if(ndone==0 && et.col!=nil)
  688. et.col.add(nil, nil, -1).settag();
  689. break;
  690. }
  691. nf = narg-na;
  692. f = arg[0:nf]; # want a copy
  693. (f, nf) = dirname(et, f, nf);
  694. e.q0 = e.q1 = e.a0 = e.a1 = 0;
  695. e.at = nil;
  696. e.name = f;
  697. e.bname = f;
  698. e.jump = TRUE;
  699. (nil, e) = openfile(et, e);
  700. f = nil;
  701. e.bname = nil;
  702. (arg, narg) = utils->skipbl(a, na);
  703. }
  704. }