frbox.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include <thread.h>
  5. #include <mouse.h>
  6. #include <frame.h>
  7. #define SLOP 25
  8. void
  9. _fraddbox(Frame *f, int bn, int n) /* add n boxes after bn, shift the rest up,
  10. * box[bn+n]==box[bn] */
  11. {
  12. int i;
  13. if(bn > f->nbox)
  14. drawerror(f->display, "_fraddbox");
  15. if(f->nbox+n > f->nalloc)
  16. _frgrowbox(f, n+SLOP);
  17. for(i=f->nbox; --i>=bn; )
  18. f->box[i+n] = f->box[i];
  19. f->nbox+=n;
  20. }
  21. void
  22. _frclosebox(Frame *f, int n0, int n1) /* inclusive */
  23. {
  24. int i;
  25. if(n0>=f->nbox || n1>=f->nbox || n1<n0)
  26. drawerror(f->display, "_frclosebox");
  27. n1++;
  28. for(i=n1; i<f->nbox; i++)
  29. f->box[i-(n1-n0)] = f->box[i];
  30. f->nbox -= n1-n0;
  31. }
  32. void
  33. _frdelbox(Frame *f, int n0, int n1) /* inclusive */
  34. {
  35. if(n0>=f->nbox || n1>=f->nbox || n1<n0)
  36. drawerror(f->display, "_frdelbox");
  37. _frfreebox(f, n0, n1);
  38. _frclosebox(f, n0, n1);
  39. }
  40. void
  41. _frfreebox(Frame *f, int n0, int n1) /* inclusive */
  42. {
  43. int i;
  44. if(n1<n0)
  45. return;
  46. if(n0>=f->nbox || n1>=f->nbox)
  47. drawerror(f->display, "_frfreebox");
  48. n1++;
  49. for(i=n0; i<n1; i++)
  50. if(f->box[i].nrune >= 0)
  51. free(f->box[i].ptr);
  52. }
  53. void
  54. _frgrowbox(Frame *f, int delta)
  55. {
  56. f->nalloc += delta;
  57. f->box = realloc(f->box, f->nalloc*sizeof(Frbox));
  58. if(f->box == 0)
  59. drawerror(f->display, "_frgrowbox");
  60. }
  61. static
  62. void
  63. dupbox(Frame *f, int bn)
  64. {
  65. uchar *p;
  66. if(f->box[bn].nrune < 0)
  67. drawerror(f->display, "dupbox");
  68. _fraddbox(f, bn, 1);
  69. if(f->box[bn].nrune >= 0){
  70. p = _frallocstr(f, NBYTE(&f->box[bn])+1);
  71. strcpy((char*)p, (char*)f->box[bn].ptr);
  72. f->box[bn+1].ptr = p;
  73. }
  74. }
  75. static
  76. uchar*
  77. runeindex(uchar *p, int n)
  78. {
  79. int i, w;
  80. Rune rune;
  81. for(i=0; i<n; i++,p+=w)
  82. if(*p < Runeself)
  83. w = 1;
  84. else{
  85. w = chartorune(&rune, (char*)p);
  86. USED(rune);
  87. }
  88. return p;
  89. }
  90. static
  91. void
  92. truncatebox(Frame *f, Frbox *b, int n) /* drop last n chars; no allocation done */
  93. {
  94. if(b->nrune<0 || b->nrune<n)
  95. drawerror(f->display, "truncatebox");
  96. b->nrune -= n;
  97. runeindex(b->ptr, b->nrune)[0] = 0;
  98. b->wid = stringwidth(f->font, (char *)b->ptr);
  99. }
  100. static
  101. void
  102. chopbox(Frame *f, Frbox *b, int n) /* drop first n chars; no allocation done */
  103. {
  104. char *p;
  105. if(b->nrune<0 || b->nrune<n)
  106. drawerror(f->display, "chopbox");
  107. p = (char*)runeindex(b->ptr, n);
  108. memmove((char*)b->ptr, p, strlen(p)+1);
  109. b->nrune -= n;
  110. b->wid = stringwidth(f->font, (char *)b->ptr);
  111. }
  112. void
  113. _frsplitbox(Frame *f, int bn, int n)
  114. {
  115. dupbox(f, bn);
  116. truncatebox(f, &f->box[bn], f->box[bn].nrune-n);
  117. chopbox(f, &f->box[bn+1], n);
  118. }
  119. void
  120. _frmergebox(Frame *f, int bn) /* merge bn and bn+1 */
  121. {
  122. Frbox *b;
  123. b = &f->box[bn];
  124. _frinsure(f, bn, NBYTE(&b[0])+NBYTE(&b[1])+1);
  125. strcpy((char*)runeindex(b[0].ptr, b[0].nrune), (char*)b[1].ptr);
  126. b[0].wid += b[1].wid;
  127. b[0].nrune += b[1].nrune;
  128. _frdelbox(f, bn+1, bn+1);
  129. }
  130. int
  131. _frfindbox(Frame *f, int bn, ulong p, ulong q) /* find box containing q and put q on a box boundary */
  132. {
  133. Frbox *b;
  134. for(b = &f->box[bn]; bn<f->nbox && p+NRUNE(b)<=q; bn++, b++)
  135. p += NRUNE(b);
  136. if(p != q)
  137. _frsplitbox(f, bn++, (int)(q-p));
  138. return bn;
  139. }