rasp.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include <thread.h>
  5. #include <mouse.h>
  6. #include <keyboard.h>
  7. #include <frame.h>
  8. #include "flayer.h"
  9. #include "samterm.h"
  10. void
  11. rinit(Rasp *r)
  12. {
  13. r->nrunes=0;
  14. r->sect=0;
  15. }
  16. void
  17. rclear(Rasp *r)
  18. {
  19. Section *s, *ns;
  20. for(s=r->sect; s; s=ns){
  21. ns = s->next;
  22. free(s->text);
  23. free(s);
  24. }
  25. r->sect = 0;
  26. }
  27. Section*
  28. rsinsert(Rasp *r, Section *s) /* insert before s */
  29. {
  30. Section *t;
  31. Section *u;
  32. t = alloc(sizeof(Section));
  33. if(r->sect == s){ /* includes empty list case: r->sect==s==0 */
  34. r->sect = t;
  35. t->next = s;
  36. }else{
  37. u = r->sect;
  38. if(u == 0)
  39. panic("rsinsert 1");
  40. do{
  41. if(u->next == s){
  42. t->next = s;
  43. u->next = t;
  44. goto Return;
  45. }
  46. u=u->next;
  47. }while(u);
  48. panic("rsinsert 2");
  49. }
  50. Return:
  51. return t;
  52. }
  53. void
  54. rsdelete(Rasp *r, Section *s)
  55. {
  56. Section *t;
  57. if(s == 0)
  58. panic("rsdelete");
  59. if(r->sect == s){
  60. r->sect = s->next;
  61. goto Free;
  62. }
  63. for(t=r->sect; t; t=t->next)
  64. if(t->next == s){
  65. t->next = s->next;
  66. Free:
  67. if(s->text)
  68. free(s->text);
  69. free(s);
  70. return;
  71. }
  72. panic("rsdelete 2");
  73. }
  74. void
  75. splitsect(Rasp *r, Section *s, long n0)
  76. {
  77. if(s == 0)
  78. panic("splitsect");
  79. rsinsert(r, s->next);
  80. if(s->text == 0)
  81. s->next->text = 0;
  82. else{
  83. s->next->text = alloc(RUNESIZE*(TBLOCKSIZE+1));
  84. Strcpy(s->next->text, s->text+n0);
  85. s->text[n0] = 0;
  86. }
  87. s->next->nrunes = s->nrunes-n0;
  88. s->nrunes = n0;
  89. }
  90. Section *
  91. findsect(Rasp *r, Section *s, long p, long q) /* find sect containing q and put q on a sect boundary */
  92. {
  93. if(s==0 && p!=q)
  94. panic("findsect");
  95. for(; s && p+s->nrunes<=q; s=s->next)
  96. p += s->nrunes;
  97. if(p != q){
  98. splitsect(r, s, q-p);
  99. s = s->next;
  100. }
  101. return s;
  102. }
  103. void
  104. rresize(Rasp *r, long a, long old, long new)
  105. {
  106. Section *s, *t, *ns;
  107. s = findsect(r, r->sect, 0L, a);
  108. t = findsect(r, s, a, a+old);
  109. for(; s!=t; s=ns){
  110. ns=s->next;
  111. rsdelete(r, s);
  112. }
  113. /* now insert the new piece before t */
  114. if(new > 0){
  115. ns=rsinsert(r, t);
  116. ns->nrunes=new;
  117. ns->text=0;
  118. }
  119. r->nrunes += new-old;
  120. }
  121. void
  122. rdata(Rasp *r, long p0, long p1, Rune *cp)
  123. {
  124. Section *s, *t, *ns;
  125. s = findsect(r, r->sect, 0L, p0);
  126. t = findsect(r, s, p0, p1);
  127. for(; s!=t; s=ns){
  128. ns=s->next;
  129. if(s->text)
  130. panic("rdata");
  131. rsdelete(r, s);
  132. }
  133. p1 -= p0;
  134. s = rsinsert(r, t);
  135. s->text = alloc(RUNESIZE*(TBLOCKSIZE+1));
  136. memmove(s->text, cp, RUNESIZE*p1);
  137. s->text[p1] = 0;
  138. s->nrunes = p1;
  139. }
  140. void
  141. rclean(Rasp *r)
  142. {
  143. Section *s;
  144. for(s=r->sect; s; s=s->next)
  145. while(s->next && (s->text!=0)==(s->next->text!=0)){
  146. if(s->text){
  147. if(s->nrunes+s->next->nrunes>TBLOCKSIZE)
  148. break;
  149. Strcpy(s->text+s->nrunes, s->next->text);
  150. }
  151. s->nrunes += s->next->nrunes;
  152. rsdelete(r, s->next);
  153. }
  154. }
  155. void
  156. Strcpy(Rune *to, Rune *from)
  157. {
  158. do; while(*to++ = *from++);
  159. }
  160. Rune*
  161. rload(Rasp *r, ulong p0, ulong p1, ulong *nrp)
  162. {
  163. Section *s;
  164. long p;
  165. int n, nb;
  166. nb = 0;
  167. Strgrow(&scratch, &nscralloc, p1-p0+1);
  168. scratch[0] = 0;
  169. for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next)
  170. p += s->nrunes;
  171. while(p<p1 && s){
  172. /*
  173. * Subtle and important. If we are preparing to handle an 'rdata'
  174. * call, it's because we have an 'rresize' hole here, so the
  175. * screen doesn't have data for that space anyway (it got cut
  176. * first). So pretend it isn't there.
  177. */
  178. if(s->text){
  179. n = s->nrunes-(p0-p);
  180. if(n>p1-p0) /* all in this section */
  181. n = p1-p0;
  182. memmove(scratch+nb, s->text+(p0-p), n*RUNESIZE);
  183. nb += n;
  184. scratch[nb] = 0;
  185. }
  186. p += s->nrunes;
  187. p0 = p;
  188. s = s->next;
  189. }
  190. if(nrp)
  191. *nrp = nb;
  192. return scratch;
  193. }
  194. int
  195. rmissing(Rasp *r, ulong p0, ulong p1)
  196. {
  197. Section *s;
  198. long p;
  199. int n, nm=0;
  200. for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next)
  201. p += s->nrunes;
  202. while(p<p1 && s){
  203. if(s->text == 0){
  204. n = s->nrunes-(p0-p);
  205. if(n > p1-p0) /* all in this section */
  206. n = p1-p0;
  207. nm += n;
  208. }
  209. p += s->nrunes;
  210. p0 = p;
  211. s = s->next;
  212. }
  213. return nm;
  214. }
  215. int
  216. rcontig(Rasp *r, ulong p0, ulong p1, int text)
  217. {
  218. Section *s;
  219. long p, n;
  220. int np=0;
  221. for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next)
  222. p += s->nrunes;
  223. while(p<p1 && s && (text? (s->text!=0) : (s->text==0))){
  224. n = s->nrunes-(p0-p);
  225. if(n > p1-p0) /* all in this section */
  226. n = p1-p0;
  227. np += n;
  228. p += s->nrunes;
  229. p0 = p;
  230. s = s->next;
  231. }
  232. return np;
  233. }
  234. void
  235. Strgrow(Rune **s, long *n, int want) /* can always toss the old data when called */
  236. {
  237. if(*n >= want)
  238. return;
  239. free(*s);
  240. *s = alloc(RUNESIZE*want);
  241. *n = want;
  242. }