PageRenderTime 24ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/usr.bin/window/wwwrite.c

https://gitlab.com/HowTheStoryEnds/freebsd11-psm-port
C | 298 lines | 247 code | 8 blank | 43 comment | 46 complexity | 08a99c40e3c2a2d6b048b14290fdf607 MD5 | raw file
  1. /* @(#)wwwrite.c 8.1 (Berkeley) 6/6/93 */
  2. /* $NetBSD: wwwrite.c,v 1.9 2009/04/14 08:50:06 lukem Exp $ */
  3. /*
  4. * Copyright (c) 1983, 1993
  5. * The Regents of the University of California. All rights reserved.
  6. *
  7. * This code is derived from software contributed to Berkeley by
  8. * Edward Wang at The University of California, Berkeley.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. * 3. Neither the name of the University nor the names of its contributors
  19. * may be used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. */
  34. #include "ww.h"
  35. #include "tt.h"
  36. #include "xx.h"
  37. #include "char.h"
  38. #define UPDATE() \
  39. if (!ISSET(w->ww_wflags, WWW_NOUPDATE) && w->ww_cur.r >= 0 && \
  40. w->ww_cur.r < wwnrow && wwtouched[w->ww_cur.r]) \
  41. wwupdate1(w->ww_cur.r, w->ww_cur.r + 1)
  42. /*
  43. * To support control character expansion, we save the old
  44. * p and q values in r and s, and point p at the beginning
  45. * of the expanded string, and q at some safe place beyond it
  46. * (p + 10). At strategic points in the loops, we check
  47. * for (r && !*p) and restore the saved values back into
  48. * p and q. Essentially, we implement a stack of depth 2,
  49. * to avoid recursion, which might be a better idea.
  50. */
  51. int
  52. wwwrite(struct ww *w, const char *p, int n)
  53. {
  54. int hascursor;
  55. const char *savep = p;
  56. const char *q = p + n;
  57. const char *r = NULL;
  58. const char *s = NULL;
  59. #ifdef lint
  60. s = NULL; /* define it before possible use */
  61. #endif
  62. hascursor = ISSET(w->ww_wflags, WWW_HASCURSOR);
  63. if (hascursor)
  64. wwcursor(w, 0);
  65. while (p < q && !ISSET(w->ww_pflags, WWP_STOPPED) &&
  66. (!wwinterrupt() || ISSET(w->ww_wflags, WWW_NOINTR))) {
  67. if (r && !*p) {
  68. p = r;
  69. q = s;
  70. r = NULL;
  71. continue;
  72. }
  73. if (w->ww_wstate == 0 &&
  74. (isprt(*p) ||
  75. (ISSET(w->ww_wflags, WWW_UNCTRL) && isunctrl(*p)))) {
  76. int i;
  77. union ww_char *bp;
  78. int col, col1;
  79. if (ISSET(w->ww_wflags, WWW_INSERT)) {
  80. /* this is very slow */
  81. if (*p == '\t') {
  82. p++;
  83. w->ww_cur.c += 8 -
  84. ((w->ww_cur.c - w->ww_w.l) & 7);
  85. goto chklf;
  86. }
  87. if (!isprt(*p)) {
  88. r = p + 1;
  89. s = q;
  90. p = unctrl(*p);
  91. q = p + 10;
  92. }
  93. wwinschar(w, w->ww_cur.r, w->ww_cur.c,
  94. *p++, w->ww_modes);
  95. goto right;
  96. }
  97. bp = &w->ww_buf[w->ww_cur.r][w->ww_cur.c];
  98. i = w->ww_cur.c;
  99. while (i < w->ww_w.r && p < q)
  100. if (!*p && r) {
  101. p = r;
  102. q = s;
  103. r = NULL;
  104. } else if (*p == '\t') {
  105. int tmp = 8 - ((i - w->ww_w.l) & 7);
  106. p++;
  107. i += tmp;
  108. bp += tmp;
  109. } else if (isprt(*p)) {
  110. bp++->c_w = *p++
  111. | w->ww_modes << WWC_MSHIFT;
  112. i++;
  113. } else if (ISSET(w->ww_wflags, WWW_UNCTRL) &&
  114. isunctrl(*p)) {
  115. r = p + 1;
  116. s = q;
  117. p = unctrl(*p);
  118. q = p + 10;
  119. } else
  120. break;
  121. col = MAX(w->ww_cur.c, w->ww_i.l);
  122. col1 = MIN(i, w->ww_i.r);
  123. w->ww_cur.c = i;
  124. if (w->ww_cur.r >= w->ww_i.t
  125. && w->ww_cur.r < w->ww_i.b) {
  126. union ww_char *ns = wwns[w->ww_cur.r];
  127. unsigned char *smap =
  128. &wwsmap[w->ww_cur.r][col];
  129. char *win = w->ww_win[w->ww_cur.r];
  130. int nchanged = 0;
  131. bp = w->ww_buf[w->ww_cur.r];
  132. for (i = col; i < col1; i++)
  133. if (*smap++ == w->ww_index) {
  134. nchanged++;
  135. ns[i].c_w = bp[i].c_w
  136. ^ win[i] << WWC_MSHIFT;
  137. }
  138. if (nchanged > 0)
  139. wwtouched[w->ww_cur.r] |= WWU_TOUCHED;
  140. }
  141. chklf:
  142. if (w->ww_cur.c >= w->ww_w.r)
  143. goto crlf;
  144. } else switch (w->ww_wstate) {
  145. case 0:
  146. switch (*p++) {
  147. case '\n':
  148. if (ISSET(w->ww_wflags, WWW_MAPNL))
  149. crlf:
  150. w->ww_cur.c = w->ww_w.l;
  151. lf:
  152. UPDATE();
  153. if (++w->ww_cur.r >= w->ww_w.b) {
  154. w->ww_cur.r = w->ww_w.b - 1;
  155. if (w->ww_w.b < w->ww_b.b) {
  156. (void) wwscroll1(w, w->ww_i.t,
  157. w->ww_i.b, 1, 0);
  158. w->ww_buf++;
  159. w->ww_b.t--;
  160. w->ww_b.b--;
  161. } else
  162. wwdelline(w, w->ww_b.t);
  163. }
  164. break;
  165. case '\b':
  166. if (--w->ww_cur.c < w->ww_w.l) {
  167. w->ww_cur.c = w->ww_w.r - 1;
  168. goto up;
  169. }
  170. break;
  171. case '\r':
  172. w->ww_cur.c = w->ww_w.l;
  173. break;
  174. case ctrl('g'):
  175. ttputc(ctrl('g'));
  176. break;
  177. case ctrl('['):
  178. w->ww_wstate = 1;
  179. break;
  180. }
  181. break;
  182. case 1:
  183. w->ww_wstate = 0;
  184. switch (*p++) {
  185. case '@':
  186. SET(w->ww_wflags, WWW_INSERT);
  187. break;
  188. case 'A':
  189. up:
  190. UPDATE();
  191. if (--w->ww_cur.r < w->ww_w.t) {
  192. w->ww_cur.r = w->ww_w.t;
  193. if (w->ww_w.t > w->ww_b.t) {
  194. (void) wwscroll1(w, w->ww_i.t,
  195. w->ww_i.b, -1, 0);
  196. w->ww_buf--;
  197. w->ww_b.t++;
  198. w->ww_b.b++;
  199. } else
  200. wwinsline(w, w->ww_b.t);
  201. }
  202. break;
  203. case 'B':
  204. goto lf;
  205. case 'C':
  206. right:
  207. w->ww_cur.c++;
  208. goto chklf;
  209. case 'E':
  210. w->ww_buf -= w->ww_w.t - w->ww_b.t;
  211. w->ww_b.t = w->ww_w.t;
  212. w->ww_b.b = w->ww_b.t + w->ww_b.nr;
  213. w->ww_cur.r = w->ww_w.t;
  214. w->ww_cur.c = w->ww_w.l;
  215. wwclreos(w, w->ww_w.t, w->ww_w.l);
  216. break;
  217. case 'H':
  218. UPDATE();
  219. w->ww_cur.r = w->ww_w.t;
  220. w->ww_cur.c = w->ww_w.l;
  221. break;
  222. case 'J':
  223. wwclreos(w, w->ww_cur.r, w->ww_cur.c);
  224. break;
  225. case 'K':
  226. wwclreol(w, w->ww_cur.r, w->ww_cur.c);
  227. break;
  228. case 'L':
  229. UPDATE();
  230. wwinsline(w, w->ww_cur.r);
  231. break;
  232. case 'M':
  233. wwdelline(w, w->ww_cur.r);
  234. break;
  235. case 'N':
  236. wwdelchar(w, w->ww_cur.r, w->ww_cur.c);
  237. break;
  238. case 'O':
  239. CLR(w->ww_wflags, WWW_INSERT);
  240. break;
  241. case 'P':
  242. wwinschar(w, w->ww_cur.r, w->ww_cur.c, ' ', 0);
  243. break;
  244. case 'X':
  245. wwupdate();
  246. break;
  247. case 'Y':
  248. UPDATE();
  249. w->ww_wstate = 2;
  250. break;
  251. case 'Z':
  252. wwupdate();
  253. xxflush(0);
  254. break;
  255. case 's':
  256. w->ww_wstate = 4;
  257. break;
  258. case 'r':
  259. w->ww_wstate = 5;
  260. break;
  261. }
  262. break;
  263. case 2:
  264. w->ww_cur.r = w->ww_w.t +
  265. (unsigned)(*p++ - ' ') % w->ww_w.nr;
  266. w->ww_wstate = 3;
  267. break;
  268. case 3:
  269. w->ww_cur.c = w->ww_w.l +
  270. (unsigned)(*p++ - ' ') % w->ww_w.nc;
  271. w->ww_wstate = 0;
  272. break;
  273. case 4:
  274. w->ww_modes |= *p++ & wwavailmodes;
  275. w->ww_wstate = 0;
  276. break;
  277. case 5:
  278. w->ww_modes &= ~*p++;
  279. w->ww_wstate = 0;
  280. break;
  281. }
  282. }
  283. if (hascursor)
  284. wwcursor(w, 1);
  285. wwnwwr++;
  286. wwnwwra += n;
  287. n = p - savep;
  288. wwnwwrc += n;
  289. return n;
  290. }