moveto.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "sam.h"
  10. void
  11. moveto(File *f, Range r)
  12. {
  13. Posn p1 = r.p1, p2 = r.p2;
  14. f->dot.r.p1 = p1;
  15. f->dot.r.p2 = p2;
  16. if(f->rasp){
  17. telldot(f);
  18. outTsl(Hmoveto, f->tag, f->dot.r.p1);
  19. }
  20. }
  21. void
  22. telldot(File *f)
  23. {
  24. if(f->rasp == 0)
  25. panic("telldot");
  26. if(f->dot.r.p1==f->tdot.p1 && f->dot.r.p2==f->tdot.p2)
  27. return;
  28. outTsll(Hsetdot, f->tag, f->dot.r.p1, f->dot.r.p2);
  29. f->tdot = f->dot.r;
  30. }
  31. void
  32. tellpat(void)
  33. {
  34. outTS(Hsetpat, &lastpat);
  35. patset = FALSE;
  36. }
  37. #define CHARSHIFT 128
  38. void
  39. lookorigin(File *f, Posn p0, Posn ls)
  40. {
  41. int nl, nc, c;
  42. Posn p, oldp0;
  43. if(p0 > f->nc)
  44. p0 = f->nc;
  45. oldp0 = p0;
  46. p = p0;
  47. for(nl=nc=c=0; c!=-1 && nl<ls && nc<ls*CHARSHIFT; nc++)
  48. if((c=filereadc(f, --p)) == '\n'){
  49. nl++;
  50. oldp0 = p0-nc;
  51. }
  52. if(c == -1)
  53. p0 = 0;
  54. else if(nl==0){
  55. if(p0>=CHARSHIFT/2)
  56. p0-=CHARSHIFT/2;
  57. else
  58. p0 = 0;
  59. }else
  60. p0 = oldp0;
  61. outTsl(Horigin, f->tag, p0);
  62. }
  63. int
  64. alnum(int c)
  65. {
  66. /*
  67. * Hard to get absolutely right. Use what we know about ASCII
  68. * and assume anything above the Latin control characters is
  69. * potentially an alphanumeric.
  70. */
  71. if(c<=' ')
  72. return 0;
  73. if(0x7F<=c && c<=0xA0)
  74. return 0;
  75. if(utfrune("!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~", c))
  76. return 0;
  77. return 1;
  78. }
  79. int
  80. clickmatch(File *f, int cl, int cr, int dir, Posn *p)
  81. {
  82. int c;
  83. int nest = 1;
  84. for(;;){
  85. if(dir > 0){
  86. if(*p >= f->nc)
  87. break;
  88. c = filereadc(f, (*p)++);
  89. }else{
  90. if(*p == 0)
  91. break;
  92. c = filereadc(f, --(*p));
  93. }
  94. if(c == cr){
  95. if(--nest==0)
  96. return 1;
  97. }else if(c == cl)
  98. nest++;
  99. }
  100. return cl=='\n' && nest==1;
  101. }
  102. Rune*
  103. strrune(Rune *s, Rune c)
  104. {
  105. Rune c1;
  106. if(c == 0) {
  107. while(*s++)
  108. ;
  109. return s-1;
  110. }
  111. while(c1 = *s++)
  112. if(c1 == c)
  113. return s-1;
  114. return 0;
  115. }
  116. void
  117. doubleclick(File *f, Posn p1)
  118. {
  119. int c, i;
  120. Rune *r, *l;
  121. Posn p;
  122. if(p1 > f->nc)
  123. return;
  124. f->dot.r.p1 = f->dot.r.p2 = p1;
  125. for(i=0; left[i]; i++){
  126. l = left[i];
  127. r = right[i];
  128. /* try left match */
  129. p = p1;
  130. if(p1 == 0)
  131. c = '\n';
  132. else
  133. c = filereadc(f, p - 1);
  134. if(strrune(l, c)){
  135. if(clickmatch(f, c, r[strrune(l, c)-l], 1, &p)){
  136. f->dot.r.p1 = p1;
  137. f->dot.r.p2 = p-(c!='\n');
  138. }
  139. return;
  140. }
  141. /* try right match */
  142. p = p1;
  143. if(p1 == f->nc)
  144. c = '\n';
  145. else
  146. c = filereadc(f, p);
  147. if(strrune(r, c)){
  148. if(clickmatch(f, c, l[strrune(r, c)-r], -1, &p)){
  149. f->dot.r.p1 = p;
  150. if(c!='\n' || p!=0 || filereadc(f, 0)=='\n')
  151. f->dot.r.p1++;
  152. f->dot.r.p2 = p1+(p1<f->nc && c=='\n');
  153. }
  154. return;
  155. }
  156. }
  157. /* try filling out word to right */
  158. p = p1;
  159. while(p < f->nc && alnum(filereadc(f, p++)))
  160. f->dot.r.p2++;
  161. /* try filling out word to left */
  162. p = p1;
  163. while(--p >= 0 && alnum(filereadc(f, p)))
  164. f->dot.r.p1--;
  165. }