Advertisement
Guest User

Untitled

a guest
Mar 15th, 2025
10
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 37.19 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <sys.h>
  3. #include <stdlib.h>
  4. #include <errno.h>
  5. #include <string.h>
  6.  
  7. #define assert(expr) ((expr) ? assert_void() : assert_fail (#expr, __FILE__, __LINE__, __FUNCTION__))
  8.  
  9. #define MAX_CMD_SIZE 15
  10.  
  11. #define STATE_VIEW 0
  12. #define STATE_CMD 1
  13. #define STATE_EDIT 2
  14.  
  15. #define CODE_SPECIAL 224
  16.  
  17. #define CODE_LEFT_ARROW 1001
  18. #define CODE_UP_ARROW 1002
  19. #define CODE_RIGHT_ARROW 1003
  20. #define CODE_DOWN_ARROW 1004
  21.  
  22. #define CODE_BACKSPACE 8
  23. #define CODE_DELETE 127
  24. #define CODE_ENTER 10
  25. #define CODE_ESC 27
  26.  
  27. #define COLOR_FG_BLACK 30
  28. #define COLOR_FG_RED 31
  29. #define COLOR_FG_GREEN 32
  30. #define COLOR_FG_YELLOW 33
  31. #define COLOR_FG_BLUE 34
  32. #define COLOR_FG_MAGENTA 35
  33. #define COLOR_FG_CYAN 36
  34. #define COLOR_FG_WHITE 37
  35. #define COLOR_FG_DEFAULT 39
  36.  
  37. #define COLOR_BG_BLACK 40
  38. #define COLOR_BG_RED 41
  39. #define COLOR_BG_GREEN 42
  40. #define COLOR_BG_YELLOW 43
  41. #define COLOR_BG_BLUE 44
  42. #define COLOR_BG_MAGENTA 45
  43. #define COLOR_BG_CYAN 46
  44. #define COLOR_BG_WHITE 47
  45. #define COLOR_BG_DEFAULT 49
  46.  
  47. #define CMD_FLAG_QUIT 0x1
  48. #define CMD_FLAG_WRITE 0x02
  49. #define CMD_FLAG_FORCE 0x04
  50.  
  51. #define ROW_FLAG_WRAPPED 0x1
  52.  
  53. #define MAX_ROW_SIZE 1000
  54.  
  55. /**
  56. * INFO:
  57. * 1.) when we insert a new row, we just keep editing the current row
  58. * 2.) when we delete the row, we set ROW_FLAG_WRAPPED and empty the row
  59. */
  60.  
  61. struct row_t {
  62. int index;
  63. int seek_start;
  64. int seek_end;
  65. size_t size;
  66. int flags;
  67. char buffer[MAX_ROW_SIZE];
  68. bool free;
  69. };
  70.  
  71. struct showed_row_t {
  72. int length;
  73. int index;
  74. int num;
  75. };
  76.  
  77. /**
  78. * graphic terminal
  79. */
  80. static char *colors;
  81. static char *terminal;
  82. static char *colors2;
  83. static char *terminal2;
  84. static int g_rows;
  85. static int g_cols;
  86. static int g_size;
  87. static char filepath[200];
  88. static char app_version[] = "0.0.1";
  89.  
  90. static fd_t fd;
  91. static int state;
  92. static bool app_quit;
  93. static size_t filepos;
  94.  
  95. /**
  96. * buffer
  97. */
  98. static size_t buffer_size;
  99. static char *buffer;
  100. static size_t buffer_cursor;
  101.  
  102. static int cursorx;
  103. static int cursory;
  104.  
  105. static int pagex;
  106. static int pagey;
  107.  
  108. static int prev_pagex;
  109. static int prev_pagey;
  110.  
  111. static int prev_pagey_pos;
  112. static int next_pagey_pos;
  113.  
  114. size_t rows_max_size;
  115. size_t rows_size;
  116. size_t available_rows_count_max;
  117. size_t available_rows_count;
  118.  
  119. static struct row_t **rows;
  120. static struct row_t *available_rows;
  121. static struct showed_row_t *showed_rows;
  122.  
  123. fd_t w_fd = 0;
  124. int toprow = 0;
  125. int prev_toprow = 0;
  126. int next_toprow = 0;
  127.  
  128. void current_file_save();
  129.  
  130. void assert_void () {
  131. /** void */
  132. }
  133.  
  134. void assert_fail (const char *expr, const char *file, int line, const char *func) {
  135. printf("assertion failed: %s. %s:%d in %s\n", expr, file, line, func);
  136. exit(-1);
  137. }
  138.  
  139. void reverse(char *s) {
  140. char *j;
  141. int i = strlen(s);
  142.  
  143. strcpy(j,s);
  144. while (i-- >= 0)
  145. *(s++) = j[i];
  146. *s = '\0';
  147. }
  148.  
  149. /* itoa()
  150. * converts an integer into a string */
  151.  
  152. void itoa(int n, char *buffer, int base) {
  153. char *ptr = buffer;
  154. int lowbit;
  155.  
  156. base >>= 1;
  157. do
  158. {
  159. lowbit = n & 1;
  160. n = (n >> 1) & 32767;
  161. *ptr = ((n % base) << 1) + lowbit;
  162. if (*ptr < 10)
  163. *ptr +='0';
  164. else
  165. *ptr +=55;
  166. ++ptr;
  167. }
  168. while (n /= base);
  169. *ptr = '\0';
  170. reverse (buffer); /* reverse string */
  171. }
  172.  
  173. int g_min (int a, int b) {
  174. return a < b ? a : b;
  175. }
  176.  
  177. int g_max (int a, int b) {
  178. return a > b ? a : b;
  179. }
  180.  
  181. void g_cursor_at (int y, int x) {
  182. printf("\033[%d;%dH", y, x);
  183. }
  184.  
  185. void g_cursor_at_pos (int pos) {
  186. int rows = pos / (g_cols);
  187. g_cursor_at (rows, pos - rows * g_cols);
  188. }
  189.  
  190. void m_init () {
  191. buffer = NULL;
  192. buffer_size = 0;
  193. buffer_cursor = 0;
  194.  
  195. cursorx = 0;
  196. cursory = 0;
  197.  
  198. app_quit = false;
  199. state = STATE_VIEW;
  200.  
  201. fd = -1;
  202. filepos = 0;
  203.  
  204. g_rows = 0;
  205. g_cols = 0;
  206. g_size = 0;
  207.  
  208. pagex = 0;
  209. pagey = 0;
  210.  
  211. prev_pagex = pagex;
  212. prev_pagey = pagey;
  213.  
  214. prev_pagey_pos = 0;
  215. next_pagey_pos = -1;
  216.  
  217. rows = NULL;
  218. available_rows = NULL;
  219. rows_max_size = 0;
  220. rows_size = 0;
  221. available_rows_count = 0;
  222. w_fd = 0;
  223.  
  224. toprow = 0;
  225. prev_toprow = 0;
  226. next_toprow = -1;
  227. }
  228.  
  229. /**
  230. * graphic check
  231. */
  232.  
  233. void g_check () {
  234. g_rows = 37;
  235. g_cols = 100;
  236.  
  237. g_size = g_rows * g_cols;
  238. buffer_size = g_max(g_size, 500);
  239. }
  240.  
  241. /**
  242. * graphic init
  243. */
  244. void g_init () {
  245. memset (terminal, ' ', g_size);
  246. memset (terminal2, ' ', g_size);
  247. for (int i =0, j = 0; i < g_size; i++, j+=2) {
  248. colors[j] = (char)COLOR_BG_BLACK;
  249. colors[j+1] = (char)COLOR_FG_WHITE;
  250.  
  251. colors2[j] = (char)COLOR_BG_BLACK;
  252. colors2[j+1] = (char)COLOR_FG_WHITE;
  253. }
  254.  
  255. g_cursor_at (0,0);
  256. }
  257.  
  258.  
  259. /**
  260. * clear screen
  261. */
  262. void g_clear () {
  263. printf("\033[2J");
  264. }
  265.  
  266. /**
  267. * force flush screen
  268. */
  269. void g_flush_force () {
  270. g_clear();
  271. for (int i = 0, j = 0; i < g_size; i++, j+=2) {
  272. printf("\033[%d;%dm", (int)colors[j], (int)colors[j+1]);
  273. putchar(terminal[i]);
  274. }
  275. }
  276.  
  277. /**
  278. * smart flust
  279. */
  280. void g_flush (bool rst) {
  281. int prev_cursorx = cursorx;
  282. int prev_cursory = cursory;
  283.  
  284. int cursor_pos = cursorx+cursory*g_cols;
  285.  
  286. char prev_cursor_color[2] = {colors[cursor_pos*2], colors[cursor_pos*2+1]};
  287.  
  288. if (!rst) {
  289. colors[cursor_pos*2] = COLOR_BG_WHITE;
  290. colors[cursor_pos*2+1] = COLOR_FG_BLACK;
  291. }
  292.  
  293. for (int i = 0, j = 0; i < g_size; i++, j+=2) {
  294. int y = i / (g_cols);
  295. int x = i - y * g_cols;
  296.  
  297.  
  298. if ((colors[j] != colors2[j])||(colors[j+1]!=colors2[j+1])||terminal[i] != terminal2[i]) {
  299. g_cursor_at (y, x);
  300. printf("\033[%d;%dm", (int)colors[j], (int)colors[j+1]);
  301. colors2[j]=colors[j];
  302. colors2[j+1]=colors[j+1];
  303.  
  304. g_cursor_at (y, x);
  305. putchar(terminal[i]);
  306. terminal2[i] = terminal[i];
  307. }
  308. }
  309.  
  310. colors[cursor_pos*2] = prev_cursor_color[0];
  311. colors[cursor_pos*2+1] = prev_cursor_color[1];
  312.  
  313. cursorx = prev_cursorx;
  314. cursory = prev_cursory;
  315.  
  316. g_cursor_at (cursory, cursorx);
  317. }
  318.  
  319. void g_set_bg (size_t index, char color) {
  320. colors[index*2] = color;
  321. }
  322.  
  323. void g_set_fg (size_t index, char color) {
  324. colors[index*2+1] = color;
  325. }
  326.  
  327. void g_set_line (int row, char c, char color[2]) {
  328. for (int i = 0; i < g_cols; i++) {
  329. int tindex = row * g_cols + i;
  330. terminal[tindex] = ' ';
  331. g_set_bg(tindex, color[0]);
  332. g_set_fg(tindex, color[1]);
  333. }
  334. }
  335.  
  336. void g_empty_line (int row) {
  337. char color[2] = { COLOR_BG_BLACK, COLOR_FG_WHITE };
  338. g_set_line (row, ' ', color);
  339. }
  340.  
  341. void show_message (char *msg, size_t len) {
  342. g_empty_line (g_rows - 1);
  343. memcpy(terminal + (g_rows - 1) * g_cols, msg, g_min(len, g_cols));
  344. }
  345.  
  346. int rows_bin_search (int index) {
  347. int l = 0;
  348. int r = rows_size;
  349.  
  350. while (l + 1 < r) {
  351. int mid = (r + l) / 2;
  352. if (rows[mid]->index > index) {
  353. r = mid;
  354. }
  355. else {
  356. l = mid;
  357. }
  358. }
  359.  
  360. while (l > 0 && rows[l - 1]->index == index) {
  361. l--;
  362. }
  363.  
  364. return l;
  365. }
  366.  
  367. int rows_find (int prow) {
  368. int findex = rows_bin_search (prow);
  369.  
  370. if (findex >= 0 && findex < rows_size && rows[findex]->index == prow) {
  371. return findex;
  372. }
  373.  
  374. return -1;
  375. }
  376.  
  377. int rows_insert_n (struct row_t *row, int npos) {
  378. /** array insert (can be replaced with r/b tree) */
  379. int prow = row->index;
  380. /** approximate position determination */
  381. int findex = rows_bin_search (prow);
  382.  
  383. if (findex < rows_size && rows[findex]->index != row->index) {
  384. findex++;
  385. }
  386.  
  387. while (findex < rows_size && rows[findex]->index == row->index && npos--) {
  388. findex++;
  389. }
  390.  
  391. if (rows_size == rows_max_size) {
  392. return -1;
  393. }
  394.  
  395. memmove((rows) + (1 + findex), (rows) + findex, (rows_size - findex) * sizeof (*rows));
  396.  
  397. rows[findex] = row;
  398. rows_size++;
  399.  
  400. return findex;
  401. }
  402. int rows_insert (struct row_t *row) {
  403. return rows_insert_n(row, -1);
  404. }
  405.  
  406. void clear_content_editor () {
  407. char color[2] = {COLOR_BG_BLACK, COLOR_FG_WHITE};
  408. for (int i = 0; i < g_rows - 1; i++) {
  409. g_set_line (i, ' ', color);
  410. }
  411. }
  412.  
  413. void detect_previous_frame () {
  414. int c_row = 0;
  415. int c_col = 0;
  416. int m_rows = g_rows - 1 + 1;
  417. int left = filepos;
  418. int ltoprow = 1;
  419. int skiprows = 0;
  420.  
  421. buffer_cursor = 0;
  422.  
  423. if (pagey == 0) {
  424. prev_pagey_pos = 0;
  425. return;
  426. }
  427.  
  428. /** setup */
  429. lseek (fd, left, SEEK_SET);
  430.  
  431. bool rowupdated = true;
  432.  
  433. while ((c_row < m_rows) && left) {
  434. if (rowupdated) {
  435. int array_row_index = rows_find(toprow-ltoprow /** c_row + pagey * g_rows **/);
  436. if (array_row_index != -1) {
  437. if (!(rows[array_row_index]->flags & ROW_FLAG_WRAPPED)) {
  438. int lltoprow = toprow-ltoprow;
  439. for (int ind = array_row_index; ind < rows_size && rows[ind]->index == lltoprow; ind++) {
  440. c_row++;
  441.  
  442. /** check */
  443. if (c_row >= m_rows) {
  444. break;
  445. }
  446. }
  447. ltoprow++;
  448. }
  449. skiprows++;
  450. continue;
  451. }
  452. }
  453.  
  454. int st = g_min(left, buffer_size - buffer_cursor);
  455. int rhs = g_min(read (fd, buffer, st), st);
  456. assert ((rhs>=0&&"read failed"));
  457.  
  458.  
  459. for (int i = rhs - 1; i >= 0; i--) {
  460. if (buffer[i] == '\n') {
  461. if (skiprows) {
  462. skiprows--;
  463. }
  464. else {
  465. prev_pagey_pos = g_max(left + i + 1, 0);
  466. c_row++;
  467. ltoprow++;
  468. rowupdated=true;
  469. }
  470. /** check */
  471. if (c_row >= m_rows) {
  472. break;
  473. }
  474. }
  475. }
  476.  
  477. left -= rhs;
  478. lseek (fd, left, SEEK_SET);
  479. }
  480.  
  481. if (!left) {
  482. prev_pagey_pos = 0;
  483. prev_toprow = 0;
  484. }
  485. else {
  486. prev_toprow = toprow - ltoprow;
  487. }
  488.  
  489. buffer_cursor = 0;
  490. }
  491.  
  492. void fetch_current_frame_with_row (struct row_t *frow) {
  493. int c_row = 0;
  494. int c_col = 0;
  495. int m_rows = g_rows - 1;
  496. int eof = false;
  497. int buffer_current = 0;
  498. int ltoprow = 0;
  499. bool last_row = true;
  500. buffer_cursor = 0;
  501.  
  502. if (!frow) {
  503. /** clear screen */
  504. clear_content_editor ();
  505.  
  506. if (prev_pagey != pagey) {
  507. if (prev_pagey_pos == -1) {
  508. detect_previous_frame ();
  509. }
  510.  
  511. if (prev_pagey > pagey) {
  512. next_pagey_pos = filepos;
  513. next_toprow = toprow;
  514. filepos = prev_pagey_pos;
  515. toprow = prev_toprow;
  516. prev_pagey_pos = -1;
  517. prev_toprow = -1;
  518. }
  519. else if (next_pagey_pos != -1) {
  520. prev_pagey_pos = filepos;
  521. prev_toprow = toprow;
  522.  
  523. filepos = next_pagey_pos;
  524. toprow = next_toprow;
  525. }
  526. }
  527. }
  528.  
  529. int c_filepos = filepos;
  530. lseek (fd, c_filepos, SEEK_SET);
  531.  
  532. int max_size = lseek (fd, 0, SEEK_END);
  533. int left = max_size - c_filepos;
  534. int nline = -1;
  535.  
  536. int skipcols = pagex * g_cols;
  537. int skiprows = 0;
  538.  
  539. lseek (fd, c_filepos, SEEK_SET);
  540.  
  541. if (!frow) {
  542. next_pagey_pos = -1;
  543. }
  544.  
  545. bool updated_row = frow == NULL;
  546.  
  547. while ((skiprows || c_row < m_rows) && !eof) {
  548. nline = -1;
  549.  
  550. if (!frow && updated_row && c_row < m_rows) {
  551. int array_row_index = rows_find(ltoprow + toprow /** c_row + pagey * g_rows **/);
  552. if (array_row_index != -1) {
  553. if (!(rows[array_row_index]->flags & ROW_FLAG_WRAPPED)) {
  554. int lltoprow = rows[array_row_index]->index;
  555. for (int ind = array_row_index; ind < rows_size && rows[ind]->index == lltoprow && c_row < m_rows; ind++) {
  556. /** exists */
  557. struct row_t *row = rows[ind];
  558.  
  559. int s = row->size;
  560. int off = g_min(s, pagex * g_cols);
  561.  
  562. s -= off;
  563.  
  564. memcpy (terminal + g_cols * c_row, row->buffer + off, g_min(s, g_cols));
  565. showed_rows[c_row].length = s;
  566. showed_rows[c_row].index = lltoprow;
  567. showed_rows[c_row].num = ind - array_row_index;
  568.  
  569. c_row++;
  570.  
  571. c_col = 0;
  572. }
  573. }
  574.  
  575. ltoprow++;
  576. skiprows++;
  577. updated_row = false;
  578. last_row = false;
  579.  
  580. continue;
  581. }
  582. }
  583.  
  584. int st = g_min(buffer_size - buffer_cursor, left);
  585. assert((st>=0&&"BUG"));
  586. if (st) {
  587. int rhs = read (fd, buffer + buffer_cursor, st);
  588. rhs = g_min(rhs, st);
  589. assert ((rhs >= 0 && "read failed"));
  590. if (rhs==0) {
  591. /** eof */
  592. eof = true;
  593. }
  594. left -= rhs;
  595. c_filepos += rhs;
  596. assert((c_filepos<=max_size&&"position > max_size"));
  597. lseek(fd, c_filepos, SEEK_SET);
  598. buffer_cursor += rhs;
  599. }
  600. else {
  601. eof = true;
  602. }
  603.  
  604. for (int i = buffer_current; i < buffer_cursor; i++) {
  605. if (buffer[i] == '\n') {
  606. /** new row */
  607. nline = i+1;
  608. break;
  609. }
  610. }
  611.  
  612. if (nline!=-1) {
  613. if (frow) {
  614. if (frow->index == ltoprow + toprow/**pagey * g_rows + c_row **/) {
  615. int s = nline-buffer_current-1;
  616. if (!frow->size) {
  617. frow->seek_start = c_filepos - s + 1;
  618. }
  619. frow->seek_end = c_filepos - (buffer_cursor - nline + 1) - 1;
  620. memcpy (frow->buffer + frow->size, buffer+buffer_current, s);
  621. frow->size += s;
  622. }
  623. c_row ++;
  624. ltoprow++;
  625. }
  626. else if (skiprows) {
  627. skiprows--;
  628. }
  629. else {
  630. int avaialable = g_cols - c_col;
  631. int s = g_min(avaialable, nline-buffer_current-1);
  632. int off = g_min(s, skipcols);
  633.  
  634. skipcols -= off;
  635. s -= off;
  636. memcpy (terminal + g_cols * c_row + c_col, buffer+buffer_current+off, s);
  637. /* set row length */
  638. showed_rows[c_row].length = c_col + s;
  639. showed_rows[c_row].num = 0;
  640. showed_rows[c_row].index = ltoprow + toprow;
  641. c_row ++;
  642. ltoprow++;
  643. last_row = false;
  644. }
  645.  
  646. c_col = 0;
  647.  
  648. /** new row */
  649. updated_row = frow == NULL;
  650.  
  651. if (!frow) {
  652. next_toprow = toprow + ltoprow;
  653. next_pagey_pos = c_filepos - buffer_cursor + nline;
  654. }
  655.  
  656. buffer_current = nline;
  657. skipcols = pagex * g_cols;
  658.  
  659. if (buffer_current>=buffer_cursor) {
  660. buffer_current = 0;
  661. buffer_cursor = 0;
  662. }
  663.  
  664. if (frow && frow->index == /**pagey * g_rows + c_row**/ ltoprow + toprow - 1) {
  665. goto end;
  666. }
  667.  
  668. continue;
  669. }
  670.  
  671.  
  672. if (frow) {
  673. if (frow->index == ltoprow+toprow/* pagey * g_rows + c_row */) {
  674. int s = buffer_cursor-buffer_current;
  675. if (!frow->size) {
  676. frow->seek_start = c_filepos - s;
  677. }
  678. memcpy (frow->buffer + frow->size, buffer+buffer_current, s);
  679. frow->size += s;
  680. }
  681. }
  682. else if (skiprows) {
  683.  
  684. }
  685. else {
  686. int avaialable = g_cols - c_col;
  687. int s = g_min(avaialable, buffer_cursor-buffer_current);
  688. int off = g_min(s, skipcols);
  689.  
  690. skipcols -= off;
  691. s -= off;
  692. memcpy (terminal + g_cols * c_row + c_col, buffer+buffer_current+off, s);
  693. c_col += s;
  694. last_row = true;
  695. }
  696.  
  697.  
  698. buffer_cursor = 0;
  699. buffer_current = 0;
  700.  
  701. updated_row = false;
  702. }
  703.  
  704. if (!frow && last_row) {
  705. /** last row */
  706. showed_rows[c_row].length = c_col;
  707. showed_rows[c_row].num = 0;
  708. showed_rows[c_row].index = ltoprow + toprow;
  709.  
  710. c_row++;
  711. ltoprow++;
  712. }
  713.  
  714. if (!frow) {
  715. /** empty rows */
  716. for (; c_row < g_rows - 1; c_row++) {
  717. showed_rows[c_row].length = 0;
  718. showed_rows[c_row].index = -1;
  719. showed_rows[c_row].num = 0;
  720.  
  721. next_pagey_pos = -1;
  722. next_toprow = 0;
  723. }
  724.  
  725. prev_pagey = pagey;
  726. prev_pagex = pagex;
  727. }
  728.  
  729. end: buffer_cursor = 0;
  730. }
  731.  
  732. void fetch_current_frame () {
  733. fetch_current_frame_with_row(NULL);
  734. }
  735.  
  736. bool input_move (int c) {
  737. bool refetch = false;
  738. bool rr = false;
  739. switch (c)
  740. {
  741. case CODE_LEFT_ARROW:
  742. case 'a':
  743. if (cursorx) {
  744. cursorx--;
  745. }
  746. else {
  747. if (pagex) {
  748. pagex--;
  749. cursorx = g_cols - 1;
  750. refetch = true;
  751. }
  752. }
  753. break;
  754. case CODE_RIGHT_ARROW:
  755. case 'd':
  756. if (cursorx+1 < g_cols) {
  757. cursorx++;
  758. }
  759. else {
  760. pagex++;
  761. cursorx = 0;
  762. refetch = true;
  763. }
  764. break;
  765. case 'w':
  766. case CODE_UP_ARROW:
  767.  
  768. rr = true;
  769. if (cursory) {
  770. cursory--;
  771. }
  772. else {
  773. if (pagey) {
  774. cursory = g_rows - 1 - 1;
  775. pagey--;
  776. refetch = true;
  777. }
  778. }
  779. break;
  780. case 's':
  781. case CODE_DOWN_ARROW:
  782. rr = true;
  783. if (cursory+1 < g_rows - 1) {
  784. cursory++;
  785. }
  786. else if (next_pagey_pos >= 0) {
  787. cursory = 0;
  788. pagey++;
  789. refetch = true;
  790. }
  791. break;
  792. default:
  793. return false;
  794. }
  795.  
  796. if (refetch) {
  797. fetch_current_frame ();
  798. cursorx = g_min(cursorx, showed_rows[cursory].length);
  799. g_cursor_at(cursory, cursorx);
  800. }
  801. else {
  802. cursorx = g_min(cursorx, showed_rows[cursory].length);
  803. g_cursor_at(cursory, cursorx);
  804. }
  805.  
  806. if (rr) {
  807. snprintf (buffer, buffer_size, "index: %d num: %d size: %d", showed_rows[cursory].index, showed_rows[cursory].num, showed_rows[cursory].length);
  808. show_message (buffer, strlen(buffer));
  809. }
  810.  
  811. return true;
  812. }
  813.  
  814. void apply_command (int flg) {
  815. if ((flg & CMD_FLAG_WRITE)) {
  816. /** write */
  817. current_file_save ();
  818. }
  819. if ((flg & CMD_FLAG_QUIT)) {
  820. if ((flg & CMD_FLAG_FORCE)) {
  821. app_quit = true;
  822. }
  823. /** check */
  824. }
  825. }
  826.  
  827. void input_state_cmd (int c) {
  828. if (c == CODE_BACKSPACE || c == CODE_DELETE) {
  829. /** pop */
  830. if (buffer_cursor) {
  831. terminal[g_cols*(g_rows-1)+(--buffer_cursor)] = ' ';
  832. }
  833.  
  834. if (buffer_cursor==0) {
  835. state = STATE_VIEW;
  836. g_empty_line(g_rows-1);
  837. }
  838.  
  839. return;
  840. }
  841.  
  842. if (!(c >= 32 && c <= 126)) {
  843. if (c == CODE_ENTER) {
  844. /** apply command */
  845. int cmd_flg = 0;
  846. for (int i = 1; i < buffer_cursor; i++) {
  847. switch (buffer[i])
  848. {
  849. case '!':
  850. cmd_flg |= CMD_FLAG_FORCE;
  851. break;
  852. case 'w':
  853. cmd_flg |= CMD_FLAG_WRITE;
  854. break;
  855. case 'q':
  856. cmd_flg |= CMD_FLAG_QUIT;
  857. break;
  858. default:
  859. break;
  860. }
  861. }
  862. apply_command (cmd_flg);
  863. /** disable command mode */
  864. buffer_cursor = 0;
  865. state = STATE_VIEW;
  866. g_empty_line(g_rows-1);
  867. }
  868. else if (c == CODE_ESC) {
  869. /** disable command mode */
  870. buffer_cursor = 0;
  871. state = STATE_VIEW;
  872. g_empty_line(g_rows-1);
  873. }
  874. else {
  875. /** invalid symbol */
  876. }
  877. return;
  878. }
  879.  
  880. /** state edit */
  881. if (buffer_cursor >= MAX_CMD_SIZE) {
  882. /** no space left */
  883. return;
  884. }
  885.  
  886. terminal[g_cols*(g_rows-1)+buffer_cursor] = (char)c;
  887. buffer[buffer_cursor++] = (char)c;
  888. }
  889.  
  890. void input_state_view (int c) {
  891. /** state view */
  892. switch (c)
  893. {
  894. case ':': {
  895. /* enter command */
  896. state = STATE_CMD;
  897. input_state_cmd (c);
  898. break;
  899. }
  900. case 'i': {
  901. /* edit mode */
  902. state = STATE_EDIT;
  903. break;
  904. }
  905. default:
  906. if (input_move (c)) {}
  907. break;
  908. }
  909. }
  910.  
  911. struct row_t *get_available_row_storage () {
  912. if (available_rows_count) {
  913. struct row_t *p = &available_rows[0];
  914. available_rows = p + 1;
  915. available_rows_count--;
  916.  
  917. p->size = 0;
  918. p->seek_start = 0;
  919. p->seek_end = 0;
  920. p->flags = 0;
  921. p->index = 0;
  922. p->free = false;
  923. return p;
  924. }
  925.  
  926. return NULL;
  927. }
  928.  
  929. void fetch_row (struct row_t *row) {
  930. fetch_current_frame_with_row (row);
  931. row->buffer[row->size] = '\0';
  932. }
  933.  
  934. int get_row_storage (int row) {
  935. int index = rows_find (row);
  936. if (index != -1) {
  937. return index;
  938. }
  939.  
  940. struct row_t *p = get_available_row_storage();
  941. if (p) {
  942. p->index = row;
  943. index = rows_insert (p);
  944. if (index == -1) {
  945. /** no left space */
  946. return -1;
  947. }
  948.  
  949. fetch_row (p);
  950. }
  951.  
  952. return index;
  953. }
  954.  
  955. void ret_row_storage (struct row_t *row) {
  956. row->free = true;
  957. while (available_rows_count < available_rows_count_max) {
  958. struct row_t *next = available_rows + 1;
  959. if (next->free) {
  960. available_rows = next;
  961. available_rows_count++;
  962. }
  963. else {
  964. break;
  965. }
  966. }
  967. }
  968.  
  969. void current_file_save () {
  970. char buff[256];
  971. int index = 0;
  972.  
  973. do {
  974. assert((index < 10));
  975. snprintf(buff, sizeof (buff), "%s.%d.tmp", filepath, index++);
  976. }
  977. while ((w_fd = open (filepath, O_RDWR|O_CREAT|O_TRUNC)) <= 0);
  978.  
  979. size_t c_filepos = 0;
  980. buffer_cursor = 0;
  981.  
  982. lseek (fd, c_filepos, SEEK_SET);
  983.  
  984. while (true)
  985. {
  986. size_t s = buffer_size;
  987. if (index < rows_size) {
  988. s = g_min(s, c_filepos - rows[index]->seek_start);
  989. if (s==0) {
  990. int cursor = 0;
  991. while (cursor < rows[index]->size) {
  992. int wrhs = write (w_fd, rows[index]->buffer + cursor, rows[index]->size - cursor);
  993. wrhs = g_min(wrhs, rows[index]->size - cursor);
  994. assert((wrhs >= 0 && "Write failed"));
  995. cursor += wrhs;
  996. }
  997. c_filepos = rows[index]->seek_end;
  998. lseek (fd, c_filepos, SEEK_SET);
  999. index++;
  1000. continue;
  1001. }
  1002.  
  1003. }
  1004. int rhs = read (fd, buffer, s);
  1005. // bug
  1006. rhs = g_min(rhs, s);
  1007. assert((rhs >= 0));
  1008. if (rhs == 0) {
  1009. break;
  1010. }
  1011. c_filepos += rhs;
  1012. lseek (fd, c_filepos, SEEK_SET);
  1013.  
  1014. int cursor = 0;
  1015. while (cursor < rhs) {
  1016. int wrhs = write (w_fd, buffer + cursor, rhs - cursor);
  1017. wrhs = g_min(wrhs, rhs - cursor);
  1018. assert((wrhs >= 0 && "Write failed"));
  1019. cursor += wrhs;
  1020. }
  1021. }
  1022.  
  1023. for (int i = rows_size - 1; i >= 0; i--) {
  1024. ret_row_storage(rows[i]);
  1025. }
  1026.  
  1027. rows_size = 0;
  1028.  
  1029. close (fd);
  1030. close (w_fd);
  1031.  
  1032. pagex = 0;
  1033. pagey = 0;
  1034. cursorx = 0;
  1035. cursory = 0;
  1036. filepos = 0;
  1037. w_fd = 0;
  1038. fd = 0;
  1039.  
  1040. buffer_size = 0;
  1041. buffer_cursor = 0;
  1042. filepos = 0;
  1043.  
  1044. fd = open (buff, O_RDONLY);
  1045.  
  1046. fetch_current_frame ();
  1047. }
  1048.  
  1049. void input_state_edit (int c) {
  1050. int prow = showed_rows[cursory].index;
  1051. int pcol = pagex*g_cols + cursorx;
  1052.  
  1053. bool refresh = false;
  1054. struct row_t *row;
  1055.  
  1056. /** state edit */
  1057. if (c == CODE_ESC) {
  1058. /** disable edit mode */
  1059. state = STATE_VIEW;
  1060. buffer_cursor = 0;
  1061. }
  1062.  
  1063. else if (prow >= 0) {
  1064.  
  1065. if (c == CODE_DELETE || c == CODE_BACKSPACE) {
  1066. int row_index = get_row_storage(prow);
  1067. if (row_index!=-1) {
  1068.  
  1069. assert(rows[row_index]->index == prow);
  1070.  
  1071. int num = showed_rows[cursory].num;
  1072. row_index += num;
  1073. row=rows[row_index];
  1074. int index = cursorx + pagex * g_cols;
  1075. if (index) {
  1076. memmove(row->buffer + index - 1, row->buffer + index, row->size - index);
  1077. row->size --;
  1078.  
  1079. refresh = true;
  1080. showed_rows[cursory].length = g_min(g_cols, row->size);
  1081.  
  1082. input_move (CODE_LEFT_ARROW);
  1083. }
  1084. else {
  1085. bool res2 = row->index > 0;
  1086. bool res1 = num > 0 || (res2 && (rows_size > row_index + 1 && rows[row_index + 1]->index == row->index));
  1087.  
  1088. int xpos = g_cols - 1;
  1089.  
  1090. if (res1||res2) {
  1091. struct row_t *ltoprow = rows[row_index - 1];
  1092.  
  1093. if ((ltoprow->flags & ROW_FLAG_WRAPPED)) {
  1094. ltoprow->flags ^= ROW_FLAG_WRAPPED;
  1095. }
  1096. int s = g_min(ltoprow->size + row->size, MAX_ROW_SIZE) - ltoprow->size; /** buffer overflow */
  1097. memcpy (ltoprow->buffer + ltoprow->size, row->buffer, s);
  1098. xpos = g_min(ltoprow->size, xpos);
  1099. ltoprow->size += s;
  1100. row->size = 0;
  1101. ret_row_storage(row);
  1102. }
  1103.  
  1104. /** delete row */
  1105. if (res1) {
  1106. /** row is a child or has a child */
  1107.  
  1108. if (rows_size > row_index + 1) {
  1109. memmove ((rows) + row_index, rows + (row_index + 1), sizeof (*rows) *(rows_size - (row_index + 1)));
  1110. }
  1111. rows_size--;
  1112.  
  1113. fetch_current_frame();
  1114.  
  1115. cursorx = xpos;
  1116. input_move(CODE_UP_ARROW);
  1117. }
  1118. else if (res2) {
  1119. /** no childs */
  1120. row->flags |= ROW_FLAG_WRAPPED;
  1121. row->size = 0;
  1122.  
  1123. fetch_current_frame();
  1124. cursorx = xpos;
  1125. input_move(CODE_UP_ARROW);
  1126. }
  1127. }
  1128. }
  1129. }
  1130. else if (c >= 32 && c <= 126) {
  1131. int row_index = get_row_storage(prow);
  1132. if (row_index!=-1) {
  1133. assert(rows[row_index]->index == prow);
  1134. // snprintf (buffer, buffer_size, "row_index: %d num: %d rows_size: %d", row_index, showed_rows[cursory].num, rows_size);
  1135. // show_message (buffer, strlen(buffer));
  1136. row_index += showed_rows[cursory].num;
  1137. assert((row_index < rows_size));
  1138. row=rows[row_index];
  1139. int index = cursorx + pagex * g_cols;
  1140. memmove(row->buffer + index + 1, row->buffer + index, row->size - index);
  1141. row->buffer[index] = c;
  1142. row->size ++;
  1143.  
  1144. refresh = true;
  1145. showed_rows[cursory].length = g_min(g_cols, g_max(0, row->size - g_cols * pagex));
  1146.  
  1147. input_move (CODE_RIGHT_ARROW);
  1148. }
  1149. }
  1150. else if (c == CODE_ENTER) {
  1151. /** new line */
  1152. int row_index = get_row_storage(prow);
  1153. if (row_index!=-1) {
  1154. assert(rows[row_index]->index == prow);
  1155. int num = showed_rows[cursory].num + 1;
  1156. assert(((row_index + num - 1) < rows_size));
  1157. struct row_t *parent = rows[row_index + num - 1];
  1158.  
  1159. row = get_available_row_storage();
  1160. row->index = parent->index;
  1161. row->flags = 0;
  1162. row->size = 0;
  1163.  
  1164. int new_row_index;
  1165.  
  1166. if (rows_size > row_index + 1 && (rows[row_index+1]->flags & ROW_FLAG_WRAPPED)) {
  1167. new_row_index = row_index + 1;
  1168. rows[new_row_index]->flags = rows[new_row_index]->flags ^ ROW_FLAG_WRAPPED;
  1169. }
  1170. else {
  1171. new_row_index = rows_insert_n(row, num);
  1172. }
  1173.  
  1174. row=rows[new_row_index];
  1175.  
  1176. // for (int trow = cursory + 1; trow < g_rows && showed_rows[trow].index == row->index; trow++) {
  1177. // showed_rows[trow].num++;
  1178. // }
  1179.  
  1180. // for (int trow = g_rows - 3; trow > cursory; trow--) {
  1181. // //memmove(terminal + (trow+1) * g_cols, terminal + (trow) * g_cols, g_cols);
  1182. // //memcpy (showed_rows + trow + 1, showed_rows + trow, sizeof (struct showed_row_t));
  1183. // }
  1184.  
  1185.  
  1186. int x = cursorx+pagex*g_cols;
  1187. int s = g_max(0, parent->size - x);
  1188. memcpy (row->buffer, parent->buffer + x, s);
  1189. // memset (terminal + g_cols * cursory + cursorx, ' ', g_cols - cursorx);
  1190.  
  1191. row->size = s;
  1192. parent->size -= s;
  1193.  
  1194. // showed_rows[cursory].length = g_max(0, showed_rows[cursory].length - s);
  1195. // if (cursory + 1 != g_rows - 1) {
  1196. // showed_rows[cursory + 1].index = row->index;
  1197. // showed_rows[cursory + 1].length = g_min(g_cols, g_max(0, row->size - g_cols * pagex));
  1198. // showed_rows[cursory + 1].num = num;
  1199. // }
  1200.  
  1201. pagex = 0;
  1202. cursorx = 0;
  1203.  
  1204. input_move (CODE_DOWN_ARROW);
  1205. refresh = true;
  1206.  
  1207. fetch_current_frame();
  1208. }
  1209. }
  1210. }
  1211.  
  1212. if (refresh) {
  1213. int s = row->size;
  1214. int off = g_min(s, pagex * g_cols);
  1215.  
  1216. s -= off;
  1217. s = g_min(s, g_cols);
  1218.  
  1219. memcpy (terminal + g_cols * cursory, row->buffer + off, s);
  1220. memset (terminal + g_cols * cursory + s, ' ', g_cols - s);
  1221. }
  1222. }
  1223.  
  1224. void input_event_switch (int c) {
  1225. switch (state)
  1226. {
  1227. case STATE_VIEW:
  1228. input_state_view (c);
  1229. break;
  1230. case STATE_EDIT:
  1231. input_state_edit (c);
  1232. break;
  1233. case STATE_CMD:
  1234. input_state_cmd (c);
  1235. break;
  1236. default:
  1237. break;
  1238. }
  1239. }
  1240.  
  1241. void input_event (int c) {
  1242. if (c == '\t') {
  1243. for (int i = 0; i < 4; i++) {
  1244. input_event_switch (' ');
  1245. }
  1246. return;
  1247. }
  1248. input_event_switch (c);
  1249. }
  1250.  
  1251. void clean_up () {
  1252. for (int i = 0; i < g_rows; i++) {
  1253. g_empty_line(i);
  1254. }
  1255. g_flush(true);
  1256. g_cursor_at(0,0);
  1257.  
  1258. if (fd>=0) {
  1259. close(fd);
  1260. fd=-1;
  1261. }
  1262. }
  1263.  
  1264. void die () {
  1265. clean_up();
  1266. exit(-1);
  1267. }
  1268.  
  1269. void quit() {
  1270. clean_up();
  1271. exit(0);
  1272. }
  1273.  
  1274. void init_params (int argc, const char *argv[]) {
  1275. #define OPTION_HELP 1
  1276. #define OPTION_VERSION 2
  1277. int option = 0;
  1278.  
  1279. for (int i = 1; i < argc; i++) {
  1280. int flg = option == 0 ? 0 : 3;
  1281. size_t size = strlen(argv[i]);
  1282.  
  1283. for (int j = 0; j < size; j++) {
  1284. if (flg==2||flg==3) {
  1285. /** get full option name (2) or full option value (3) (-vhello -> name: v, value: hello) */
  1286. memcpy (buffer, (&(argv[i][0]))+j, size - j);
  1287. buffer_cursor = size - j;
  1288. break;
  1289. }
  1290.  
  1291. if (flg==4) {
  1292. /** without value */
  1293. printf("there are exists option without value\n");
  1294. exit(-1);
  1295. }
  1296.  
  1297. if (argv[i][j] == '-') {
  1298. flg++;
  1299. }
  1300. else if (flg==0) {
  1301. /** default value */
  1302. assert((size <= sizeof (filepath) && "default option buffer overflow"));
  1303. memcpy ((char *)&filepath, argv[i], size);
  1304. filepath[size]='\0';
  1305. break;
  1306. }
  1307. else {
  1308. switch (argv[i][j])
  1309. {
  1310. case 'h':
  1311. option = OPTION_HELP;
  1312. /** without value */
  1313. flg = 4;
  1314. break;
  1315. case 'v':
  1316. option = OPTION_VERSION;
  1317. flg = 4;
  1318. break;
  1319. default:
  1320. printf ("undefined option: -%c\n", argv[i][j]);
  1321. exit(-1);
  1322. }
  1323. }
  1324. }
  1325.  
  1326. if (flg == 2) {
  1327. /** need to grab full option value if needed */
  1328. buffer[buffer_cursor]='\0';
  1329. if (strcmp ((const char *)buffer, "help")==0) {
  1330. option = OPTION_HELP;
  1331. flg = 4;
  1332. }
  1333. else if (strcmp ((const char *)buffer, "version")==0) {
  1334. option = OPTION_VERSION;
  1335. flg = 4;
  1336. }
  1337. else {
  1338. printf("invalid option: %s (%d)\n", (const char *)buffer, buffer_cursor);
  1339. exit(-1);
  1340.  
  1341. }
  1342. }
  1343.  
  1344. if (flg == 3) {
  1345. /** name -> value */
  1346. continue;
  1347. }
  1348.  
  1349. if (flg == 4) {
  1350. /** name -> null */
  1351. switch (option)
  1352. {
  1353. case OPTION_HELP:
  1354. printf("Usage: minivim [options...] <filepath/>\n");
  1355. printf("-h, --help Get help for commands\n");
  1356. printf("-v, --version Show version number and quit\n");
  1357. exit(0);
  1358. break;
  1359. case OPTION_VERSION:
  1360. printf("Version: %s\n", app_version);
  1361. exit(0);
  1362. break;
  1363. }
  1364. option = 0;
  1365. continue;
  1366. }
  1367. }
  1368. #undef OPTION_VERSION
  1369. #undef OPTION_HELP
  1370.  
  1371. if (!strlen((const char *)(&filepath))) {
  1372. printf("no input file\n");
  1373. exit(-1);
  1374. }
  1375.  
  1376. fd = open ((const char *)(&filepath), O_RDWR|O_CREAT);
  1377. if (fd < 0) {
  1378. printf ("failed to open file %s. fd: %d\n", (const char *)(&filepath), (int)fd);
  1379. exit(-1);
  1380. }
  1381. }
  1382.  
  1383. int read_code () {
  1384. int c = getchar ();
  1385. assert (c <= 127);
  1386. return c;
  1387. }
  1388.  
  1389. int main(int argc, char const *argv[]) {
  1390. m_init();
  1391.  
  1392. /* get graphic size*/
  1393. g_check();
  1394.  
  1395. buffer_size = g_max(37*100, 500);
  1396. static char buffer_[37*100];
  1397. static char terminal_[37*100];
  1398. static char terminal2_[37*100];
  1399. static char colors_[37*100*2];
  1400. static char colors2_[37*100*2];
  1401. /** we can edit only [n] rows */
  1402. available_rows_count = 100;
  1403. available_rows_count_max = available_rows_count;
  1404. static struct row_t available_rows2[100];
  1405. /** we can handle only 'rows_count' rows */
  1406. rows_max_size = 1000;
  1407. rows_size = 0;
  1408. static struct row_t *rows2[1000];
  1409. static struct showed_row_t showed_rows2[37];
  1410.  
  1411. rows = (struct row_t **)&rows2;
  1412. available_rows = (struct row_t *)&available_rows2;
  1413. buffer = (char*)&buffer_;
  1414. terminal = (char*)&terminal_;
  1415. terminal2 = (char*)&terminal2_;
  1416. colors = (char*)&colors_;
  1417. colors2 = (char*)&colors2_;
  1418. showed_rows = (struct showed_row_t *)&showed_rows2;
  1419.  
  1420. /** fill */
  1421. memset(available_rows, '\0', available_rows_count * sizeof (struct row_t));
  1422. memset(showed_rows, '\0', g_rows * sizeof (struct showed_row_t));
  1423. memset(rows, '\0', rows_max_size * sizeof (struct row_t*));
  1424.  
  1425. init_params (argc, argv);
  1426.  
  1427. /** init graphic */
  1428. g_init();
  1429. g_flush_force();
  1430.  
  1431. fetch_current_frame();
  1432.  
  1433. while (!app_quit) {
  1434. /** main loop */
  1435. g_flush(false);
  1436.  
  1437. /** main loop */
  1438. int c = read_code();
  1439. input_event (c);
  1440. }
  1441.  
  1442. /** clean up */
  1443. clean_up();
  1444.  
  1445. return 0;
  1446. }
  1447.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement