file.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include <thread.h>
  5. #include <cursor.h>
  6. #include <mouse.h>
  7. #include <keyboard.h>
  8. #include <frame.h>
  9. #include <fcall.h>
  10. #include <plumb.h>
  11. #include "dat.h"
  12. #include "fns.h"
  13. /*
  14. * Structure of Undo list:
  15. * The Undo structure follows any associated data, so the list
  16. * can be read backwards: read the structure, then read whatever
  17. * data is associated (insert string, file name) and precedes it.
  18. * The structure includes the previous value of the modify bit
  19. * and a sequence number; successive Undo structures with the
  20. * same sequence number represent simultaneous changes.
  21. */
  22. typedef struct Undo Undo;
  23. struct Undo
  24. {
  25. short type; /* Delete, Insert, Filename */
  26. short mod; /* modify bit */
  27. uint seq; /* sequence number */
  28. uint p0; /* location of change (unused in f) */
  29. uint n; /* # runes in string or file name */
  30. };
  31. enum
  32. {
  33. Undosize = sizeof(Undo)/sizeof(Rune),
  34. };
  35. File*
  36. fileaddtext(File *f, Text *t)
  37. {
  38. if(f == nil){
  39. f = emalloc(sizeof(File));
  40. f->unread = TRUE;
  41. }
  42. f->text = realloc(f->text, (f->ntext+1)*sizeof(Text*));
  43. f->text[f->ntext++] = t;
  44. f->curtext = t;
  45. return f;
  46. }
  47. void
  48. filedeltext(File *f, Text *t)
  49. {
  50. int i;
  51. for(i=0; i<f->ntext; i++)
  52. if(f->text[i] == t)
  53. goto Found;
  54. error("can't find text in filedeltext");
  55. Found:
  56. f->ntext--;
  57. if(f->ntext == 0){
  58. fileclose(f);
  59. return;
  60. }
  61. memmove(f->text+i, f->text+i+1, (f->ntext-i)*sizeof(Text*));
  62. if(f->curtext == t)
  63. f->curtext = f->text[0];
  64. }
  65. void
  66. fileinsert(File *f, uint p0, Rune *s, uint ns)
  67. {
  68. if(p0 > f->nc)
  69. error("internal error: fileinsert");
  70. if(f->seq > 0)
  71. fileuninsert(f, &f->delta, p0, ns);
  72. bufinsert(f, p0, s, ns);
  73. if(ns)
  74. f->mod = TRUE;
  75. }
  76. void
  77. fileuninsert(File *f, Buffer *delta, uint p0, uint ns)
  78. {
  79. Undo u;
  80. /* undo an insertion by deleting */
  81. u.type = Delete;
  82. u.mod = f->mod;
  83. u.seq = f->seq;
  84. u.p0 = p0;
  85. u.n = ns;
  86. bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
  87. }
  88. void
  89. filedelete(File *f, uint p0, uint p1)
  90. {
  91. if(!(p0<=p1 && p0<=f->nc && p1<=f->nc))
  92. error("internal error: filedelete");
  93. if(f->seq > 0)
  94. fileundelete(f, &f->delta, p0, p1);
  95. bufdelete(f, p0, p1);
  96. if(p1 > p0)
  97. f->mod = TRUE;
  98. }
  99. void
  100. fileundelete(File *f, Buffer *delta, uint p0, uint p1)
  101. {
  102. Undo u;
  103. Rune *buf;
  104. uint i, n;
  105. /* undo a deletion by inserting */
  106. u.type = Insert;
  107. u.mod = f->mod;
  108. u.seq = f->seq;
  109. u.p0 = p0;
  110. u.n = p1-p0;
  111. buf = fbufalloc();
  112. for(i=p0; i<p1; i+=n){
  113. n = p1 - i;
  114. if(n > RBUFSIZE)
  115. n = RBUFSIZE;
  116. bufread(f, i, buf, n);
  117. bufinsert(delta, delta->nc, buf, n);
  118. }
  119. fbuffree(buf);
  120. bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
  121. }
  122. void
  123. filesetname(File *f, Rune *name, int n)
  124. {
  125. if(f->seq > 0)
  126. fileunsetname(f, &f->delta);
  127. free(f->name);
  128. f->name = runemalloc(n);
  129. runemove(f->name, name, n);
  130. f->nname = n;
  131. f->unread = TRUE;
  132. }
  133. void
  134. fileunsetname(File *f, Buffer *delta)
  135. {
  136. Undo u;
  137. /* undo a file name change by restoring old name */
  138. u.type = Filename;
  139. u.mod = f->mod;
  140. u.seq = f->seq;
  141. u.p0 = 0; /* unused */
  142. u.n = f->nname;
  143. if(f->nname)
  144. bufinsert(delta, delta->nc, f->name, f->nname);
  145. bufinsert(delta, delta->nc, (Rune*)&u, Undosize);
  146. }
  147. uint
  148. fileload(File *f, uint p0, int fd, int *nulls)
  149. {
  150. if(f->seq > 0)
  151. error("undo in file.load unimplemented");
  152. return bufload(f, p0, fd, nulls);
  153. }
  154. /* return sequence number of pending redo */
  155. uint
  156. fileredoseq(File *f)
  157. {
  158. Undo u;
  159. Buffer *delta;
  160. delta = &f->epsilon;
  161. if(delta->nc == 0)
  162. return 0;
  163. bufread(delta, delta->nc-Undosize, (Rune*)&u, Undosize);
  164. return u.seq;
  165. }
  166. void
  167. fileundo(File *f, int isundo, uint *q0p, uint *q1p)
  168. {
  169. Undo u;
  170. Rune *buf;
  171. uint i, j, n, up;
  172. uint stop;
  173. Buffer *delta, *epsilon;
  174. if(isundo){
  175. /* undo; reverse delta onto epsilon, seq decreases */
  176. delta = &f->delta;
  177. epsilon = &f->epsilon;
  178. stop = f->seq;
  179. }else{
  180. /* redo; reverse epsilon onto delta, seq increases */
  181. delta = &f->epsilon;
  182. epsilon = &f->delta;
  183. stop = 0; /* don't know yet */
  184. }
  185. buf = fbufalloc();
  186. while(delta->nc > 0){
  187. up = delta->nc-Undosize;
  188. bufread(delta, up, (Rune*)&u, Undosize);
  189. if(isundo){
  190. if(u.seq < stop){
  191. f->seq = u.seq;
  192. goto Return;
  193. }
  194. }else{
  195. if(stop == 0)
  196. stop = u.seq;
  197. if(u.seq > stop)
  198. goto Return;
  199. }
  200. switch(u.type){
  201. default:
  202. fprint(2, "undo: 0x%ux\n", u.type);
  203. abort();
  204. break;
  205. case Delete:
  206. f->seq = u.seq;
  207. fileundelete(f, epsilon, u.p0, u.p0+u.n);
  208. f->mod = u.mod;
  209. bufdelete(f, u.p0, u.p0+u.n);
  210. for(j=0; j<f->ntext; j++)
  211. textdelete(f->text[j], u.p0, u.p0+u.n, FALSE);
  212. *q0p = u.p0;
  213. *q1p = u.p0;
  214. break;
  215. case Insert:
  216. f->seq = u.seq;
  217. fileuninsert(f, epsilon, u.p0, u.n);
  218. f->mod = u.mod;
  219. up -= u.n;
  220. for(i=0; i<u.n; i+=n){
  221. n = u.n - i;
  222. if(n > RBUFSIZE)
  223. n = RBUFSIZE;
  224. bufread(delta, up+i, buf, n);
  225. bufinsert(f, u.p0+i, buf, n);
  226. for(j=0; j<f->ntext; j++)
  227. textinsert(f->text[j], u.p0+i, buf, n, FALSE);
  228. }
  229. *q0p = u.p0;
  230. *q1p = u.p0+u.n;
  231. break;
  232. case Filename:
  233. f->seq = u.seq;
  234. fileunsetname(f, epsilon);
  235. f->mod = u.mod;
  236. up -= u.n;
  237. free(f->name);
  238. if(u.n == 0)
  239. f->name = nil;
  240. else
  241. f->name = runemalloc(u.n);
  242. bufread(delta, up, f->name, u.n);
  243. f->nname = u.n;
  244. break;
  245. }
  246. bufdelete(delta, up, delta->nc);
  247. }
  248. if(isundo)
  249. f->seq = 0;
  250. Return:
  251. fbuffree(buf);
  252. }
  253. void
  254. filereset(File *f)
  255. {
  256. bufreset(&f->delta);
  257. bufreset(&f->epsilon);
  258. f->seq = 0;
  259. }
  260. void
  261. fileclose(File *f)
  262. {
  263. free(f->name);
  264. f->nname = 0;
  265. f->name = nil;
  266. free(f->text);
  267. f->ntext = 0;
  268. f->text = nil;
  269. bufclose(f);
  270. bufclose(&f->delta);
  271. bufclose(&f->epsilon);
  272. elogclose(f);
  273. free(f);
  274. }
  275. void
  276. filemark(File *f)
  277. {
  278. if(f->epsilon.nc)
  279. bufdelete(&f->epsilon, 0, f->epsilon.nc);
  280. f->seq = seq;
  281. }