moveto.c 2.6 KB

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