xfid.b 21 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087
  1. implement Xfidm;
  2. include "common.m";
  3. sys : Sys;
  4. dat : Dat;
  5. graph : Graph;
  6. utils : Utils;
  7. regx : Regx;
  8. bufferm : Bufferm;
  9. diskm : Diskm;
  10. filem : Filem;
  11. textm : Textm;
  12. columnm : Columnm;
  13. scrl : Scroll;
  14. look : Look;
  15. exec : Exec;
  16. windowm : Windowm;
  17. fsys : Fsys;
  18. editm: Edit;
  19. ecmd: Editcmd;
  20. styxaux: Styxaux;
  21. UTFmax : import Sys;
  22. sprint : import sys;
  23. Smsg0 : import Dat;
  24. TRUE, FALSE, XXX, BUFSIZE, MAXRPC : import Dat;
  25. EM_NORMAL, EM_RAW, EM_MASK : import Dat;
  26. Qdir, Qcons, Qlabel, Qindex, Qeditout : import Dat;
  27. QWaddr, QWdata, QWevent, QWconsctl, QWctl, QWbody, QWeditout, QWtag, QWrdsel, QWwrsel : import Dat;
  28. seq, cxfidfree, Lock, Ref, Range, Mntdir, Astring : import dat;
  29. error, warning, max, min, stralloc, strfree, strncmp : import utils;
  30. address : import regx;
  31. Buffer : import bufferm;
  32. File : import filem;
  33. Text : import textm;
  34. scrdraw : import scrl;
  35. Window : import windowm;
  36. bflush : import graph;
  37. Column : import columnm;
  38. row : import dat;
  39. FILE, QID, respond : import fsys;
  40. oldtag, name, offset, count, data, setcount, setdata : import styxaux;
  41. init(mods : ref Dat->Mods)
  42. {
  43. sys = mods.sys;
  44. dat = mods.dat;
  45. graph = mods.graph;
  46. utils = mods.utils;
  47. regx = mods.regx;
  48. filem = mods.filem;
  49. bufferm = mods.bufferm;
  50. diskm = mods.diskm;
  51. textm = mods.textm;
  52. columnm = mods.columnm;
  53. scrl = mods.scroll;
  54. look = mods.look;
  55. exec = mods.exec;
  56. windowm = mods.windowm;
  57. fsys = mods.fsys;
  58. editm = mods.edit;
  59. ecmd = mods.editcmd;
  60. styxaux = mods.styxaux;
  61. }
  62. nullxfid : Xfid;
  63. newxfid() : ref Xfid
  64. {
  65. x := ref Xfid;
  66. *x = nullxfid;
  67. x.buf = array[fsys->messagesize+UTFmax] of byte;
  68. return x;
  69. }
  70. Ctlsize : con 5*12;
  71. Edel := "deleted window";
  72. Ebadctl := "ill-formed control message";
  73. Ebadaddr := "bad address syntax";
  74. Eaddr := "address out of range";
  75. Einuse := "already in use";
  76. Ebadevent:= "bad event syntax";
  77. clampaddr(w : ref Window)
  78. {
  79. if(w.addr.q0 < 0)
  80. w.addr.q0 = 0;
  81. if(w.addr.q1 < 0)
  82. w.addr.q1 = 0;
  83. if(w.addr.q0 > w.body.file.buf.nc)
  84. w.addr.q0 = w.body.file.buf.nc;
  85. if(w.addr.q1 > w.body.file.buf.nc)
  86. w.addr.q1 = w.body.file.buf.nc;
  87. }
  88. xfidtid : array of int;
  89. nxfidtid := 0;
  90. xfidkill()
  91. {
  92. if (sys == nil)
  93. return;
  94. thispid := sys->pctl(0, nil);
  95. for (i := 0; i < nxfidtid; i++)
  96. utils->postnote(Utils->PNPROC, thispid, xfidtid[i], "kill");
  97. }
  98. Xfid.ctl(x : self ref Xfid)
  99. {
  100. x.tid = sys->pctl(0, nil);
  101. ox := xfidtid;
  102. xfidtid = array[nxfidtid+1] of int;
  103. xfidtid[0:] = ox[0:nxfidtid];
  104. xfidtid[nxfidtid++] = x.tid;
  105. ox = nil;
  106. for (;;) {
  107. f := <- x.c;
  108. case (f) {
  109. Xnil => ;
  110. Xflush => x.flush();
  111. Xwalk => x.walk(nil);
  112. Xopen => x.open();
  113. Xclose => x.close();
  114. Xread => x.read();
  115. Xwrite => x.write();
  116. * => error("bad case in Xfid.ctl()");
  117. }
  118. bflush();
  119. cxfidfree <-= x;
  120. }
  121. }
  122. Xfid.flush(x : self ref Xfid)
  123. {
  124. fc : Smsg0;
  125. i, j : int;
  126. w : ref Window;
  127. c : ref Column;
  128. wx : ref Xfid;
  129. # search windows for matching tag
  130. row.qlock.lock();
  131. loop:
  132. for(j=0; j<row.ncol; j++){
  133. c = row.col[j];
  134. for(i=0; i<c.nw; i++){
  135. w = c.w[i];
  136. w.lock('E');
  137. wx = w.eventx;
  138. if(wx!=nil && wx.fcall.tag==oldtag(x.fcall)){
  139. w.eventx = nil;
  140. wx.flushed = TRUE;
  141. wx.c <-= Xnil;
  142. w.unlock();
  143. break loop;
  144. }
  145. w.unlock();
  146. }
  147. }
  148. row.qlock.unlock();
  149. respond(x, fc, nil);
  150. }
  151. Xfid.walk(nil : self ref Xfid, cw: chan of ref Window)
  152. {
  153. # fc : Smsg0;
  154. w : ref Window;
  155. # if(name(x.fcall) != "new")
  156. # error("unknown path in walk\n");
  157. row.qlock.lock(); # tasks->procs now
  158. w = utils->newwindow(nil);
  159. w.settag();
  160. # w.refx.inc();
  161. # x.f.w = w;
  162. # x.f.qid.path = big QID(w.id, Qdir);
  163. # x.f.qid.qtype = Sys->QTDIR;
  164. # fc.qid = x.f.qid;
  165. row.qlock.unlock();
  166. # respond(x, fc, nil);
  167. cw <-= w;
  168. }
  169. Xfid.open(x : self ref Xfid)
  170. {
  171. fc : Smsg0;
  172. w : ref Window;
  173. q : int;
  174. fc.iounit = 0;
  175. w = x.f.w;
  176. if(w != nil){
  177. t := w.body;
  178. row.qlock.lock(); # tasks->procs now
  179. w.lock('E');
  180. q = FILE(x.f.qid);
  181. case(q){
  182. QWaddr or QWdata or QWevent =>
  183. if(w.nopen[q]++ == byte 0){
  184. if(q == QWaddr){
  185. w.addr = (Range)(0,0);
  186. w.limit = (Range)(-1,-1);
  187. }
  188. if(q==QWevent && !w.isdir && w.col!=nil){
  189. w.filemenu = FALSE;
  190. w.settag();
  191. }
  192. }
  193. QWrdsel =>
  194. #
  195. # Use a temporary file.
  196. # A pipe would be the obvious, but we can't afford the
  197. # broken pipe notification. Using the code to read QWbody
  198. # is n², which should probably also be fixed. Even then,
  199. # though, we'd need to squirrel away the data in case it's
  200. # modified during the operation, e.g. by |sort
  201. #
  202. if(w.rdselfd != nil){
  203. w.unlock();
  204. respond(x, fc, Einuse);
  205. return;
  206. }
  207. w.rdselfd = diskm->tempfile();
  208. if(w.rdselfd == nil){
  209. w.unlock();
  210. respond(x, fc, "can't create temp file");
  211. return;
  212. }
  213. w.nopen[q]++;
  214. q0 := t.q0;
  215. q1 := t.q1;
  216. r := utils->stralloc(BUFSIZE);
  217. while(q0 < q1){
  218. n := q1 - q0;
  219. if(n > BUFSIZE)
  220. n = BUFSIZE;
  221. t.file.buf.read(q0, r, 0, n);
  222. s := array of byte r.s[0:n];
  223. m := len s;
  224. if(sys->write(w.rdselfd, s, m) != m){
  225. warning(nil, "can't write temp file for pipe command %r\n");
  226. break;
  227. }
  228. s = nil;
  229. q0 += n;
  230. }
  231. utils->strfree(r);
  232. QWwrsel =>
  233. w.nopen[q]++;
  234. seq++;
  235. t.file.mark();
  236. exec->cut(t, t, FALSE, TRUE);
  237. w.wrselrange = (Range)(t.q1, t.q1);
  238. w.nomark = TRUE;
  239. QWeditout =>
  240. if(editm->editing == FALSE){
  241. w.unlock();
  242. respond(x, fc, "permission denied");
  243. return;
  244. }
  245. w.wrselrange = (Range)(t.q1, t.q1);
  246. break;
  247. }
  248. w.unlock();
  249. row.qlock.unlock();
  250. }
  251. fc.qid = x.f.qid;
  252. fc.iounit = fsys->messagesize-Styx->IOHDRSZ;
  253. x.f.open = TRUE;
  254. respond(x, fc, nil);
  255. }
  256. Xfid.close(x : self ref Xfid)
  257. {
  258. fc : Smsg0;
  259. w : ref Window;
  260. q : int;
  261. w = x.f.w;
  262. # BUG in C version ? fsysclunk() has just set busy, open to FALSE
  263. # x.f.busy = FALSE;
  264. # if(!x.f.open){
  265. # if(w != nil)
  266. # w.close();
  267. # respond(x, fc, nil);
  268. # return;
  269. # }
  270. # x.f.open = FALSE;
  271. if(w != nil){
  272. row.qlock.lock(); # tasks->procs now
  273. w.lock('E');
  274. q = FILE(x.f.qid);
  275. case(q){
  276. QWctl =>
  277. if(w.ctlfid!=~0 && w.ctlfid==x.f.fid){
  278. w.ctlfid = ~0;
  279. w.ctllock.unlock();
  280. }
  281. QWdata or QWaddr or QWevent =>
  282. # BUG: do we need to shut down Xfid?
  283. if (q == QWdata)
  284. w.nomark = FALSE;
  285. if(--w.nopen[q] == byte 0){
  286. if(q == QWdata)
  287. w.nomark = FALSE;
  288. if(q==QWevent && !w.isdir && w.col!=nil){
  289. w.filemenu = TRUE;
  290. w.settag();
  291. }
  292. if(q == QWevent){
  293. w.dumpstr = nil;
  294. w.dumpdir = nil;
  295. }
  296. }
  297. QWrdsel =>
  298. w.rdselfd = nil;
  299. QWwrsel =>
  300. w.nomark = FALSE;
  301. t :=w.body;
  302. # before: only did this if !w->noscroll, but that didn't seem right in practice
  303. t.show(min(w.wrselrange.q0, t.file.buf.nc),
  304. min(w.wrselrange.q1, t.file.buf.nc), TRUE);
  305. scrdraw(t);
  306. QWconsctl=>
  307. w.echomode = EM_NORMAL;
  308. }
  309. w.close();
  310. w.unlock();
  311. row.qlock.unlock();
  312. }
  313. respond(x, fc, nil);
  314. }
  315. Xfid.read(x : self ref Xfid)
  316. {
  317. fc : Smsg0;
  318. n, q : int;
  319. off : int;
  320. sbuf : string;
  321. buf : array of byte;
  322. w : ref Window;
  323. sbuf = nil;
  324. q = FILE(x.f.qid);
  325. w = x.f.w;
  326. if(w == nil){
  327. fc.count = 0;
  328. case(q){
  329. Qcons or Qlabel =>
  330. ;
  331. Qindex =>
  332. x.indexread();
  333. return;
  334. * =>
  335. warning(nil, sprint("unknown qid %d\n", q));
  336. }
  337. respond(x, fc, nil);
  338. return;
  339. }
  340. w.lock('F');
  341. if(w.col == nil){
  342. w.unlock();
  343. respond(x, fc, Edel);
  344. return;
  345. }
  346. off = int offset(x.fcall);
  347. case(q){
  348. QWaddr =>
  349. w.body.commit(TRUE);
  350. clampaddr(w);
  351. sbuf = sprint("%11d %11d ", w.addr.q0, w.addr.q1);
  352. QWbody =>
  353. x.utfread(w.body, 0, w.body.file.buf.nc, QWbody);
  354. QWctl =>
  355. sbuf = w.ctlprint(1);
  356. QWevent =>
  357. x.eventread(w);
  358. QWdata =>
  359. # BUG: what should happen if q1 > q0?
  360. if(w.addr.q0 > w.body.file.buf.nc){
  361. respond(x, fc, Eaddr);
  362. break;
  363. }
  364. w.addr.q0 += x.runeread(w.body, w.addr.q0, w.body.file.buf.nc);
  365. w.addr.q1 = w.addr.q0;
  366. QWtag =>
  367. x.utfread(w.tag, 0, w.tag.file.buf.nc, QWtag);
  368. QWrdsel =>
  369. sys->seek(w.rdselfd, big off, 0);
  370. n = count(x.fcall);
  371. if(n > BUFSIZE)
  372. n = BUFSIZE;
  373. b := array[n] of byte;
  374. n = sys->read(w.rdselfd, b, n);
  375. if(n < 0){
  376. respond(x, fc, "I/O error in temp file");
  377. break;
  378. }
  379. fc.count = n;
  380. fc.data = b;
  381. respond(x, fc, nil);
  382. b = nil;
  383. * =>
  384. sbuf = sprint("unknown qid %d in read", q);
  385. respond(x, fc, sbuf);
  386. sbuf = nil;
  387. }
  388. if (sbuf != nil) {
  389. buf = array of byte sbuf;
  390. sbuf = nil;
  391. n = len buf;
  392. if(off > n)
  393. off = n;
  394. if(off+count(x.fcall) > n)
  395. setcount(x.fcall, n-off);
  396. fc.count = count(x.fcall);
  397. fc.data = buf[off:];
  398. respond(x, fc, nil);
  399. buf = nil;
  400. }
  401. w.unlock();
  402. }
  403. Xfid.write(x : self ref Xfid)
  404. {
  405. fc : Smsg0;
  406. c, cnt, qid, q, nb, nr, eval : int;
  407. w : ref Window;
  408. r : string;
  409. a : Range;
  410. t : ref Text;
  411. q0, tq0, tq1 : int;
  412. md : ref Mntdir;
  413. qid = FILE(x.f.qid);
  414. w = x.f.w;
  415. row.qlock.lock(); # tasks->procs now
  416. if(w != nil){
  417. c = 'F';
  418. if(qid==QWtag || qid==QWbody)
  419. c = 'E';
  420. w.lock(c);
  421. if(w.col == nil){
  422. w.unlock();
  423. row.qlock.unlock();
  424. respond(x, fc, Edel);
  425. return;
  426. }
  427. }
  428. bodytag := 0;
  429. case(qid){
  430. Qcons =>
  431. md = x.f.mntdir;
  432. warning(md, string data(x.fcall));
  433. fc.count = count(x.fcall);
  434. respond(x, fc, nil);
  435. QWconsctl =>
  436. if (w != nil) {
  437. r = string data(x.fcall);
  438. if (strncmp(r, "rawon", 5) == 0)
  439. w.echomode = EM_RAW;
  440. else if (strncmp(r, "rawoff", 6) == 0)
  441. w.echomode = EM_NORMAL;
  442. }
  443. fc.count = count(x.fcall);
  444. respond(x, fc, nil);
  445. Qlabel =>
  446. fc.count = count(x.fcall);
  447. respond(x, fc, nil);
  448. QWaddr =>
  449. r = string data(x.fcall);
  450. nr = len r;
  451. t = w.body;
  452. w.commit(t);
  453. (eval, nb, a) = address(x.f.mntdir, t, w.limit, w.addr, nil, r, 0, nr, TRUE);
  454. r = nil;
  455. if(nb < nr){
  456. respond(x, fc, Ebadaddr);
  457. break;
  458. }
  459. if(!eval){
  460. respond(x, fc, Eaddr);
  461. break;
  462. }
  463. w.addr = a;
  464. fc.count = count(x.fcall);
  465. respond(x, fc, nil);
  466. Qeditout or
  467. QWeditout =>
  468. r = string data(x.fcall);
  469. nr = len r;
  470. if(w!=nil)
  471. err := ecmd->edittext(w.body.file, w.wrselrange.q1, r, nr);
  472. else
  473. err = ecmd->edittext(nil, 0, r, nr);
  474. r = nil;
  475. if(err != nil){
  476. respond(x, fc, err);
  477. break;
  478. }
  479. fc.count = count(x.fcall);
  480. respond(x, fc, nil);
  481. break;
  482. QWbody or QWwrsel =>
  483. t = w.body;
  484. bodytag = 1;
  485. QWctl =>
  486. x.ctlwrite(w);
  487. QWdata =>
  488. t = w.body;
  489. w.commit(t);
  490. if(w.addr.q0>t.file.buf.nc || w.addr.q1>t.file.buf.nc){
  491. respond(x, fc, Eaddr);
  492. break;
  493. }
  494. nb = sys->utfbytes(data(x.fcall), count(x.fcall));
  495. r = string data(x.fcall)[0:nb];
  496. nr = len r;
  497. if(w.nomark == FALSE){
  498. seq++;
  499. t.file.mark();
  500. }
  501. q0 = w.addr.q0;
  502. if(w.addr.q1 > q0){
  503. t.delete(q0, w.addr.q1, TRUE);
  504. w.addr.q1 = q0;
  505. }
  506. tq0 = t.q0;
  507. tq1 = t.q1;
  508. t.insert(q0, r, nr, TRUE, 0);
  509. if(tq0 >= q0)
  510. tq0 += nr;
  511. if(tq1 >= q0)
  512. tq1 += nr;
  513. if(!t.w.noscroll)
  514. t.show(tq0, tq1, TRUE);
  515. scrdraw(t);
  516. w.settag();
  517. r = nil;
  518. w.addr.q0 += nr;
  519. w.addr.q1 = w.addr.q0;
  520. fc.count = count(x.fcall);
  521. respond(x, fc, nil);
  522. QWevent =>
  523. x.eventwrite(w);
  524. QWtag =>
  525. t = w.tag;
  526. bodytag = 1;
  527. * =>
  528. r = sprint("unknown qid %d in write", qid);
  529. respond(x, fc, r);
  530. r = nil;
  531. }
  532. if (bodytag) {
  533. q = x.f.nrpart;
  534. cnt = count(x.fcall);
  535. if(q > 0){
  536. nd := array[cnt+q] of byte;
  537. nd[q:] = data(x.fcall)[0:cnt];
  538. nd[0:] = x.f.rpart[0:q];
  539. setdata(x.fcall, nd);
  540. cnt += q;
  541. x.f.nrpart = 0;
  542. }
  543. nb = sys->utfbytes(data(x.fcall), cnt);
  544. r = string data(x.fcall)[0:nb];
  545. nr = len r;
  546. if(nb < cnt){
  547. x.f.rpart = data(x.fcall)[nb:cnt];
  548. x.f.nrpart = cnt-nb;
  549. }
  550. if(nr > 0){
  551. t.w.commit(t);
  552. if(qid == QWwrsel){
  553. q0 = w.wrselrange.q1;
  554. if(q0 > t.file.buf.nc)
  555. q0 = t.file.buf.nc;
  556. }else
  557. q0 = t.file.buf.nc;
  558. if(qid == QWbody || qid == QWwrsel){
  559. if(!w.nomark){
  560. seq++;
  561. t.file.mark();
  562. }
  563. (q0, nr) = t.bsinsert(q0, r, nr, TRUE);
  564. if(qid!=QWwrsel && !t.w.noscroll)
  565. t.show(q0+nr, q0+nr, TRUE);
  566. scrdraw(t);
  567. }else
  568. t.insert(q0, r, nr, TRUE, 0);
  569. w.settag();
  570. if(qid == QWwrsel)
  571. w.wrselrange.q1 += nr;
  572. r = nil;
  573. }
  574. fc.count = count(x.fcall);
  575. respond(x, fc, nil);
  576. }
  577. if(w != nil)
  578. w.unlock();
  579. row.qlock.unlock();
  580. }
  581. Xfid.ctlwrite(x : self ref Xfid, w : ref Window)
  582. {
  583. fc : Smsg0;
  584. i, m, n, nb : int;
  585. r, err, p, pp : string;
  586. q : int;
  587. scrdrw, settag : int;
  588. t : ref Text;
  589. err = nil;
  590. scrdrw = FALSE;
  591. settag = FALSE;
  592. w.tag.commit(TRUE);
  593. nb = sys->utfbytes(data(x.fcall), count(x.fcall));
  594. r = string data(x.fcall)[0:nb];
  595. loop :
  596. for(n=0; n<len r; n+=m){
  597. p = r[n:];
  598. if(strncmp(p, "lock", 4) == 0){ # make window exclusive use
  599. w.ctllock.lock();
  600. w.ctlfid = x.f.fid;
  601. m = 4;
  602. }else
  603. if(strncmp(p, "unlock", 6) == 0){ # release exclusive use
  604. w.ctlfid = ~0;
  605. w.ctllock.unlock();
  606. m = 6;
  607. }else
  608. if(strncmp(p, "clean", 5) == 0){ # mark window 'clean', seq=0
  609. t = w.body;
  610. t.eq0 = ~0;
  611. t.file.reset();
  612. t.file.mod = FALSE;
  613. w.dirty = FALSE;
  614. settag = TRUE;
  615. m = 5;
  616. }else
  617. if(strncmp(p, "show", 4) == 0){ # show dot
  618. t = w.body;
  619. t.show(t.q0, t.q1, TRUE);
  620. m = 4;
  621. }else
  622. if(strncmp(p, "name ", 5) == 0){ # set file name
  623. pp = p[5:];
  624. m = 5;
  625. q = utils->strchr(pp, '\n');
  626. if(q<=0){
  627. err = Ebadctl;
  628. break;
  629. }
  630. nm := pp[0:q];
  631. for(i=0; i<len nm; i++)
  632. if(nm[i] <= ' '){
  633. err = "bad character in file name";
  634. break loop;
  635. }
  636. seq++;
  637. w.body.file.mark();
  638. w.setname(nm, len nm);
  639. m += (q+1);
  640. }else
  641. if(strncmp(p, "dump ", 5) == 0){ # set dump string
  642. pp = p[5:];
  643. m = 5;
  644. q = utils->strchr(pp, '\n');
  645. if(q<=0){
  646. err = Ebadctl;
  647. break;
  648. }
  649. nm := pp[0:q];
  650. w.dumpstr = nm;
  651. m += (q+1);
  652. }else
  653. if(strncmp(p, "dumpdir ", 8) == 0){ # set dump directory
  654. pp = p[8:];
  655. m = 8;
  656. q = utils->strchr(pp, '\n');
  657. if(q<=0){
  658. err = Ebadctl;
  659. break;
  660. }
  661. nm := pp[0:q];
  662. w.dumpdir = nm;
  663. m += (q+1);
  664. }else
  665. if(strncmp(p, "delete", 6) == 0){ # delete for sure
  666. w.col.close(w, TRUE);
  667. m = 6;
  668. }else
  669. if(strncmp(p, "del", 3) == 0){ # delete, but check dirty
  670. if(!w.clean(TRUE, FALSE)){
  671. err = "file dirty";
  672. break;
  673. }
  674. w.col.close(w, TRUE);
  675. m = 3;
  676. }else
  677. if(strncmp(p, "get", 3) == 0){ # get file
  678. exec->get(w.body, nil, nil, FALSE, nil, 0);
  679. m = 3;
  680. }else
  681. if(strncmp(p, "put", 3) == 0){ # put file
  682. exec->put(w.body, nil, nil, 0);
  683. m = 3;
  684. }else
  685. if(strncmp(p, "dot=addr", 8) == 0){ # set dot
  686. w.body.commit(TRUE);
  687. clampaddr(w);
  688. w.body.q0 = w.addr.q0;
  689. w.body.q1 = w.addr.q1;
  690. w.body.setselect(w.body.q0, w.body.q1);
  691. settag = TRUE;
  692. m = 8;
  693. }else
  694. if(strncmp(p, "addr=dot", 8) == 0){ # set addr
  695. w.addr.q0 = w.body.q0;
  696. w.addr.q1 = w.body.q1;
  697. m = 8;
  698. }else
  699. if(strncmp(p, "limit=addr", 10) == 0){ # set limit
  700. w.body.commit(TRUE);
  701. clampaddr(w);
  702. w.limit.q0 = w.addr.q0;
  703. w.limit.q1 = w.addr.q1;
  704. m = 10;
  705. }else
  706. if(strncmp(p, "nomark", 6) == 0){ # turn off automatic marking
  707. w.nomark = TRUE;
  708. m = 6;
  709. }else
  710. if(strncmp(p, "mark", 4) == 0){ # mark file
  711. seq++;
  712. w.body.file.mark();
  713. settag = TRUE;
  714. m = 4;
  715. }else
  716. if(strncmp(p, "noscroll", 8) == 0){ # turn off automatic scrolling
  717. w.noscroll = TRUE;
  718. m = 8;
  719. }else
  720. if(strncmp(p, "cleartag", 8) == 0){ # wipe tag right of bar
  721. w.cleartag();
  722. settag = TRUE;
  723. m = 8;
  724. }else
  725. if(strncmp(p, "scroll", 6) == 0){ # turn on automatic scrolling (writes to body only)
  726. w.noscroll = FALSE;
  727. m = 6;
  728. }else
  729. if(strncmp(p, "noecho", 6) == 0){ # don't echo chars - mask them
  730. w.echomode = EM_MASK;
  731. m = 6;
  732. }else
  733. if (strncmp(p, "echo", 4) == 0){ # echo chars (normal state)
  734. w.echomode = EM_NORMAL;
  735. m = 4;
  736. }else{
  737. err = Ebadctl;
  738. break;
  739. }
  740. while(m < len p && p[m] == '\n')
  741. m++;
  742. }
  743. ab := array of byte r[0:n];
  744. n = len ab;
  745. ab = nil;
  746. r = nil;
  747. if(err != nil)
  748. n = 0;
  749. fc.count = n;
  750. respond(x, fc, err);
  751. if(settag)
  752. w.settag();
  753. if(scrdrw)
  754. scrdraw(w.body);
  755. }
  756. Xfid.eventwrite(x : self ref Xfid, w : ref Window)
  757. {
  758. fc : Smsg0;
  759. m, n, nb : int;
  760. r, err : string;
  761. p, q : int;
  762. t : ref Text;
  763. c : int;
  764. q0, q1 : int;
  765. err = nil;
  766. nb = sys->utfbytes(data(x.fcall), count(x.fcall));
  767. r = string data(x.fcall)[0:nb];
  768. loop :
  769. for(n=0; n<len r; n+=m){
  770. p = n;
  771. w.owner = r[p++]; # disgusting
  772. c = r[p++];
  773. while(r[p] == ' ')
  774. p++;
  775. q0 = int r[p:];
  776. q = p;
  777. if (r[q] == '+' || r[q] == '-')
  778. q++;
  779. while (r[q] >= '0' && r[q] <= '9')
  780. q++;
  781. if(q == p) {
  782. err = Ebadevent;
  783. break;
  784. }
  785. p = q;
  786. while(r[p] == ' ')
  787. p++;
  788. q1 = int r[p:];
  789. q = p;
  790. if (r[q] == '+' || r[q] == '-')
  791. q++;
  792. while (r[q] >= '0' && r[q] <= '9')
  793. q++;
  794. if(q == p) {
  795. err = Ebadevent;
  796. break;
  797. }
  798. p = q;
  799. while(r[p] == ' ')
  800. p++;
  801. if(r[p++] != '\n') {
  802. err = Ebadevent;
  803. break;
  804. }
  805. m = p-n;
  806. if('a'<=c && c<='z')
  807. t = w.tag;
  808. else if('A'<=c && c<='Z')
  809. t = w.body;
  810. else {
  811. err = Ebadevent;
  812. break;
  813. }
  814. if(q0>t.file.buf.nc || q1>t.file.buf.nc || q0>q1) {
  815. err = Ebadevent;
  816. break;
  817. }
  818. # row.qlock.lock();
  819. case(c){
  820. 'x' or 'X' =>
  821. exec->execute(t, q0, q1, TRUE, nil);
  822. 'l' or 'L' =>
  823. look->look3(t, q0, q1, TRUE);
  824. * =>
  825. err = Ebadevent;
  826. break loop;
  827. }
  828. # row.qlock.unlock();
  829. }
  830. ab := array of byte r[0:n];
  831. n = len ab;
  832. ab = nil;
  833. r = nil;
  834. if(err != nil)
  835. n = 0;
  836. fc.count = n;
  837. respond(x, fc, err);
  838. }
  839. Xfid.utfread(x : self ref Xfid, t : ref Text, q0, q1 : int, qid : int)
  840. {
  841. fc : Smsg0;
  842. w : ref Window;
  843. r : ref Astring;
  844. b, b1 : array of byte;
  845. q, off, boff : int;
  846. m, n, nr, nb : int;
  847. w = t.w;
  848. w.commit(t);
  849. off = int offset(x.fcall);
  850. r = stralloc(BUFSIZE);
  851. b1 = array[MAXRPC] of byte;
  852. n = 0;
  853. if(qid==w.utflastqid && off>=w.utflastboff && w.utflastq<=q1){
  854. boff = w.utflastboff;
  855. q = w.utflastq;
  856. }else{
  857. # BUG: stupid code: scan from beginning
  858. boff = 0;
  859. q = q0;
  860. }
  861. w.utflastqid = qid;
  862. while(q<q1 && n<count(x.fcall)){
  863. w.utflastboff = boff;
  864. w.utflastq = q;
  865. nr = q1-q;
  866. if(nr > BUFSIZE)
  867. nr = BUFSIZE;
  868. t.file.buf.read(q, r, 0, nr);
  869. b = array of byte r.s[0:nr];
  870. nb = len b;
  871. if(boff >= off){
  872. m = nb;
  873. if(boff+m > off+count(x.fcall))
  874. m = off+count(x.fcall) - boff;
  875. b1[n:] = b[0:m];
  876. n += m;
  877. }else if(boff+nb > off){
  878. if(n != 0)
  879. error("bad count in utfrune");
  880. m = nb - (off-boff);
  881. if(m > count(x.fcall))
  882. m = count(x.fcall);
  883. b1[0:] = b[off-boff:off-boff+m];
  884. n += m;
  885. }
  886. b = nil;
  887. boff += nb;
  888. q += nr;
  889. }
  890. strfree(r);
  891. r = nil;
  892. fc.count = n;
  893. fc.data = b1;
  894. respond(x, fc, nil);
  895. b1 = nil;
  896. }
  897. Xfid.runeread(x : self ref Xfid, t : ref Text, q0, q1 : int) : int
  898. {
  899. fc : Smsg0;
  900. w : ref Window;
  901. r : ref Astring;
  902. junk, ok : int;
  903. b, b1 : array of byte;
  904. q, boff : int;
  905. i, rw, m, n, nr, nb : int;
  906. w = t.w;
  907. w.commit(t);
  908. r = stralloc(BUFSIZE);
  909. b1 = array[MAXRPC] of byte;
  910. n = 0;
  911. q = q0;
  912. boff = 0;
  913. while(q<q1 && n<count(x.fcall)){
  914. nr = q1-q;
  915. if(nr > BUFSIZE)
  916. nr = BUFSIZE;
  917. t.file.buf.read(q, r, 0, nr);
  918. b = array of byte r.s[0:nr];
  919. nb = len b;
  920. m = nb;
  921. if(boff+m > count(x.fcall)){
  922. i = count(x.fcall) - boff;
  923. # copy whole runes only
  924. m = 0;
  925. nr = 0;
  926. while(m < i){
  927. (junk, rw, ok) = sys->byte2char(b, m);
  928. if(m+rw > i)
  929. break;
  930. m += rw;
  931. nr++;
  932. }
  933. if(m == 0)
  934. break;
  935. }
  936. b1[n:] = b[0:m];
  937. b = nil;
  938. n += m;
  939. boff += nb;
  940. q += nr;
  941. }
  942. strfree(r);
  943. r = nil;
  944. fc.count = n;
  945. fc.data = b1;
  946. respond(x, fc, nil);
  947. b1 = nil;
  948. return q-q0;
  949. }
  950. Xfid.eventread(x : self ref Xfid, w : ref Window)
  951. {
  952. fc : Smsg0;
  953. b : string;
  954. i, n : int;
  955. i = 0;
  956. x.flushed = FALSE;
  957. while(w.nevents == 0){
  958. if(i){
  959. if(!x.flushed)
  960. respond(x, fc, "window shut down");
  961. return;
  962. }
  963. w.eventx = x;
  964. w.unlock();
  965. <- x.c;
  966. w.lock('F');
  967. i++;
  968. }
  969. eveb := array of byte w.events;
  970. ne := len eveb;
  971. n = w.nevents;
  972. if(ne > count(x.fcall)) {
  973. ne = count(x.fcall);
  974. while (sys->utfbytes(eveb, ne) != ne)
  975. --ne;
  976. s := string eveb[0:ne];
  977. n = len s;
  978. s = nil;
  979. }
  980. fc.count = ne;
  981. fc.data = eveb;
  982. respond(x, fc, nil);
  983. b = w.events;
  984. w.events = w.events[n:];
  985. b = nil;
  986. w.nevents -= n;
  987. eveb = nil;
  988. }
  989. Xfid.indexread(x : self ref Xfid)
  990. {
  991. fc : Smsg0;
  992. i, j, m, n, nmax, cnt, off : int;
  993. w : ref Window;
  994. b : array of byte;
  995. r : ref Astring;
  996. c : ref Column;
  997. row.qlock.lock();
  998. nmax = 0;
  999. for(j=0; j<row.ncol; j++){
  1000. c = row.col[j];
  1001. for(i=0; i<c.nw; i++){
  1002. w = c.w[i];
  1003. nmax += Ctlsize + w.tag.file.buf.nc*UTFmax + 1;
  1004. }
  1005. }
  1006. nmax++;
  1007. b = array[nmax] of byte;
  1008. r = stralloc(BUFSIZE);
  1009. n = 0;
  1010. for(j=0; j<row.ncol; j++){
  1011. c = row.col[j];
  1012. for(i=0; i<c.nw; i++){
  1013. w = c.w[i];
  1014. # only show the currently active window of a set
  1015. if(w.body.file.curtext != w.body)
  1016. continue;
  1017. ctls := w.ctlprint(0);
  1018. ctlb := array of byte ctls;
  1019. if (len ctls != Ctlsize || len ctlb != Ctlsize)
  1020. error("bad length in indexread");
  1021. b[n:] = ctlb[0:];
  1022. n += Ctlsize;
  1023. ctls = nil;
  1024. ctlb = nil;
  1025. m = min(BUFSIZE, w.tag.file.buf.nc);
  1026. w.tag.file.buf.read(0, r, 0, m);
  1027. rb := array of byte r.s[0:m];
  1028. b[n:] = rb[0:len rb];
  1029. m = n+len rb;
  1030. rb = nil;
  1031. while(n<m && b[n]!=byte '\n')
  1032. n++;
  1033. b[n++] = byte '\n';
  1034. }
  1035. }
  1036. row.qlock.unlock();
  1037. off = int offset(x.fcall);
  1038. cnt = count(x.fcall);
  1039. if(off > n)
  1040. off = n;
  1041. if(off+cnt > n)
  1042. cnt = n-off;
  1043. fc.count = cnt;
  1044. fc.data = b[off:off+cnt];
  1045. respond(x, fc, nil);
  1046. b = nil;
  1047. strfree(r);
  1048. r = nil;
  1049. }