file.b 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. implement Filem;
  2. include "common.m";
  3. sys : Sys;
  4. dat : Dat;
  5. utils : Utils;
  6. buffm : Bufferm;
  7. textm : Textm;
  8. editlog: Editlog;
  9. FALSE, TRUE, XXX, Delete, Insert, Filename, BUFSIZE, Astring : import Dat;
  10. Buffer, newbuffer : import buffm;
  11. Text : import textm;
  12. error : import utils;
  13. init(mods : ref Dat->Mods)
  14. {
  15. sys = mods.sys;
  16. dat = mods.dat;
  17. utils = mods.utils;
  18. buffm = mods.bufferm;
  19. textm = mods.textm;
  20. editlog = mods.editlog;
  21. }
  22. #
  23. # Structure of Undo list:
  24. # The Undo structure follows any associated data, so the list
  25. # can be read backwards: read the structure, then read whatever
  26. # data is associated (insert string, file name) and precedes it.
  27. # The structure includes the previous value of the modify bit
  28. # and a sequence number; successive Undo structures with the
  29. # same sequence number represent simultaneous changes.
  30. #
  31. Undo : adt
  32. {
  33. typex : int; # Delete, Insert, Filename
  34. mod : int; # modify bit
  35. seq : int; # sequence number
  36. p0 : int; # location of change (unused in f)
  37. n : int; # # runes in string or file name
  38. };
  39. Undosize : con 8;
  40. SHM : con 16rffff;
  41. undotostr(t, m, s, p, n : int) : string
  42. {
  43. a := "01234567";
  44. a[0] = t;
  45. a[1] = m;
  46. a[2] = s&SHM;
  47. a[3] = (s>>16)&SHM;
  48. a[4] = p&SHM;
  49. a[5] = (p>>16)&SHM;
  50. a[6] = n&SHM;
  51. a[7] = (n>>16)&SHM;
  52. return a;
  53. }
  54. strtoundo(s: string): Undo
  55. {
  56. u: Undo;
  57. u.typex = s[0];
  58. u.mod = s[1];
  59. u.seq = s[2]|(s[3]<<16);
  60. u.p0 = s[4]|(s[5]<<16);
  61. u.n = s[6]|(s[7]<<16);
  62. return u;
  63. }
  64. nullfile : File;
  65. File.addtext(f : self ref File, t : ref Text) : ref File
  66. {
  67. if(f == nil) {
  68. f = ref nullfile;
  69. f.buf = newbuffer();
  70. f.delta = newbuffer();
  71. f.epsilon = newbuffer();
  72. f.ntext = 0;
  73. f.unread = TRUE;
  74. }
  75. oft := f.text;
  76. f.text = array[f.ntext+1] of ref Text;
  77. f.text[0:] = oft[0:f.ntext];
  78. oft = nil;
  79. f.text[f.ntext++] = t;
  80. f.curtext = t;
  81. return f;
  82. }
  83. File.deltext(f : self ref File, t : ref Text)
  84. {
  85. i : int;
  86. for(i=0; i<f.ntext; i++)
  87. if(f.text[i] == t)
  88. break;
  89. if (i == f.ntext)
  90. error("can't find text in File.deltext");
  91. f.ntext--;
  92. if(f.ntext == 0){
  93. f.close();
  94. return;
  95. }
  96. f.text[i:] = f.text[i+1:f.ntext+1];
  97. if(f.curtext == t)
  98. f.curtext = f.text[0];
  99. }
  100. File.insert(f : self ref File, p0 : int, s : string, ns : int)
  101. {
  102. if (p0 > f.buf.nc)
  103. error("bad assert in File.insert");
  104. if(f.seq > 0)
  105. f.uninsert(f.delta, p0, ns);
  106. f.buf.insert(p0, s, ns);
  107. if(ns)
  108. f.mod = TRUE;
  109. }
  110. File.uninsert(f : self ref File, delta : ref Buffer, p0 : int, ns : int)
  111. {
  112. # undo an insertion by deleting
  113. a := undotostr(Delete, f.mod, f.seq, p0, ns);
  114. delta.insert(delta.nc, a, Undosize);
  115. }
  116. File.delete(f : self ref File, p0 : int, p1 : int)
  117. {
  118. if (p0>p1 || p0>f.buf.nc || p1>f.buf.nc)
  119. error("bad assert in File.delete");
  120. if(f.seq > 0)
  121. f.undelete(f.delta, p0, p1);
  122. f.buf.delete(p0, p1);
  123. if(p1 > p0)
  124. f.mod = TRUE;
  125. }
  126. File.undelete(f : self ref File, delta : ref Buffer, p0 : int, p1 : int)
  127. {
  128. buf : ref Astring;
  129. i, n : int;
  130. # undo a deletion by inserting
  131. a := undotostr(Insert, f.mod, f.seq, p0, p1-p0);
  132. m := p1-p0;
  133. if(m > BUFSIZE)
  134. m = BUFSIZE;
  135. buf = utils->stralloc(m);
  136. for(i=p0; i<p1; i+=n){
  137. n = p1 - i;
  138. if(n > BUFSIZE)
  139. n = BUFSIZE;
  140. f.buf.read(i, buf, 0, n);
  141. delta.insert(delta.nc, buf.s, n);
  142. }
  143. utils->strfree(buf);
  144. buf = nil;
  145. delta.insert(delta.nc, a, Undosize);
  146. }
  147. File.setname(f : self ref File, name : string, n : int)
  148. {
  149. if(f.seq > 0)
  150. f.unsetname(f.delta);
  151. f.name = name[0:n];
  152. f.unread = TRUE;
  153. }
  154. File.unsetname(f : self ref File, delta : ref Buffer)
  155. {
  156. # undo a file name change by restoring old name
  157. a := undotostr(Filename, f.mod, f.seq, 0, len f.name);
  158. if(f.name != nil)
  159. delta.insert(delta.nc, f.name, len f.name);
  160. delta.insert(delta.nc, a, Undosize);
  161. }
  162. File.loadx(f : self ref File, p0 : int, fd : ref Sys->FD) : int
  163. {
  164. if(f.seq > 0)
  165. error("undo in file.load unimplemented");
  166. return f.buf.loadx(p0, fd);
  167. }
  168. File.undo(f : self ref File, isundo : int, q0 : int, q1 : int) : (int, int)
  169. {
  170. buf : ref Astring;
  171. i, j, n, up : int;
  172. stop : int;
  173. delta, epsilon : ref Buffer;
  174. u : Undo;
  175. a := utils->stralloc(Undosize);
  176. if(isundo){
  177. # undo; reverse delta onto epsilon, seq decreases
  178. delta = f.delta;
  179. epsilon = f.epsilon;
  180. stop = f.seq;
  181. }else{
  182. # redo; reverse epsilon onto delta, seq increases
  183. delta = f.epsilon;
  184. epsilon = f.delta;
  185. stop = 0; # don't know yet
  186. }
  187. buf = utils->stralloc(BUFSIZE);
  188. while(delta.nc > 0){
  189. up = delta.nc-Undosize;
  190. delta.read(up, a, 0, Undosize);
  191. u = strtoundo(a.s);
  192. if(isundo){
  193. if(u.seq < stop){
  194. f.seq = u.seq;
  195. utils->strfree(buf);
  196. utils->strfree(a);
  197. return (q0, q1);
  198. }
  199. }else{
  200. if(stop == 0)
  201. stop = u.seq;
  202. if(u.seq > stop){
  203. utils->strfree(buf);
  204. utils->strfree(a);
  205. return (q0, q1);
  206. }
  207. }
  208. case(u.typex){
  209. Delete =>
  210. f.seq = u.seq;
  211. f.undelete(epsilon, u.p0, u.p0+u.n);
  212. f.mod = u.mod;
  213. f.buf.delete(u.p0, u.p0+u.n);
  214. for(j=0; j<f.ntext; j++)
  215. f.text[j].delete(u.p0, u.p0+u.n, FALSE);
  216. q0 = u.p0;
  217. q1 = u.p0;
  218. Insert =>
  219. f.seq = u.seq;
  220. f.uninsert(epsilon, u.p0, u.n);
  221. f.mod = u.mod;
  222. up -= u.n;
  223. # buf = utils->stralloc(BUFSIZE);
  224. for(i=0; i<u.n; i+=n){
  225. n = u.n - i;
  226. if(n > BUFSIZE)
  227. n = BUFSIZE;
  228. delta.read(up+i, buf, 0, n);
  229. f.buf.insert(u.p0+i, buf.s, n);
  230. for(j=0; j<f.ntext; j++)
  231. f.text[j].insert(u.p0+i, buf.s, n, FALSE, 0);
  232. }
  233. # utils->strfree(buf);
  234. # buf = nil;
  235. q0 = u.p0;
  236. q1 = u.p0+u.n;
  237. Filename =>
  238. f.seq = u.seq;
  239. f.unsetname(epsilon);
  240. f.mod = u.mod;
  241. up -= u.n;
  242. f.name = nil;
  243. if(u.n == 0)
  244. f.name = nil;
  245. else {
  246. fn0 := utils->stralloc(u.n);
  247. delta.read(up, fn0, 0, u.n);
  248. f.name = fn0.s;
  249. utils->strfree(fn0);
  250. fn0 = nil;
  251. }
  252. * =>
  253. error(sys->sprint("undo: 0x%ux", u.typex));
  254. error("");
  255. }
  256. delta.delete(up, delta.nc);
  257. }
  258. utils->strfree(buf);
  259. utils->strfree(a);
  260. buf = nil;
  261. if(isundo)
  262. f.seq = 0;
  263. return (q0, q1);
  264. }
  265. File.reset(f : self ref File)
  266. {
  267. f.delta.reset();
  268. f.epsilon.reset();
  269. f.seq = 0;
  270. }
  271. File.close(f : self ref File)
  272. {
  273. f.name = nil;
  274. f.ntext = 0;
  275. f.text = nil;
  276. f.buf.close();
  277. f.delta.close();
  278. f.epsilon.close();
  279. editlog->elogclose(f);
  280. f = nil;
  281. }
  282. File.mark(f : self ref File)
  283. {
  284. if(f.epsilon.nc)
  285. f.epsilon.delete(0, f.epsilon.nc);
  286. f.seq = dat->seq;
  287. }
  288. File.redoseq(f : self ref File): int
  289. {
  290. u: Undo;
  291. delta: ref Buffer;
  292. delta = f.epsilon;
  293. if(delta.nc == 0)
  294. return ~0;
  295. buf := utils->stralloc(Undosize);
  296. delta.read(delta.nc-Undosize, buf, 0, Undosize);
  297. u = strtoundo(buf.s);
  298. utils->strfree(buf);
  299. return u.seq;
  300. }