about summary refs log tree commit diff stats
path: root/edit
diff options
context:
space:
mode:
Diffstat (limited to 'edit')
-rw-r--r--edit/011-editor-undo.mu218
1 files changed, 109 insertions, 109 deletions
diff --git a/edit/011-editor-undo.mu b/edit/011-editor-undo.mu
index 5866fb52..44f55438 100644
--- a/edit/011-editor-undo.mu
+++ b/edit/011-editor-undo.mu
@@ -1265,6 +1265,115 @@ ghi]
   ]
 ]
 
+scenario editor-can-undo-multiple-arrows-in-the-same-direction [
+  # create an editor with some text
+  assume-screen 10/width, 5/height
+  1:address:shared:array:character <- new [abc
+def
+ghi]
+  2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
+  editor-render screen, 2:address:shared:editor-data
+  # move the cursor
+  assume-console [
+    left-click 2, 1
+    press right-arrow
+    press right-arrow
+    press up-arrow
+  ]
+  editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
+  3:number <- get *2:address:shared:editor-data, cursor-row:offset
+  4:number <- get *2:address:shared:editor-data, cursor-column:offset
+  memory-should-contain [
+    3 <- 1
+    4 <- 3
+  ]
+  # undo
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
+    3:number <- get *2:address:shared:editor-data, cursor-row:offset
+    4:number <- get *2:address:shared:editor-data, cursor-column:offset
+  ]
+  # up-arrow is undone
+  memory-should-contain [
+    3 <- 2
+    4 <- 3
+  ]
+  # undo again
+  assume-console [
+    press ctrl-z
+  ]
+  run [
+    editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
+    3:number <- get *2:address:shared:editor-data, cursor-row:offset
+    4:number <- get *2:address:shared:editor-data, cursor-column:offset
+  ]
+  # both right-arrows are undone
+  memory-should-contain [
+    3 <- 2
+    4 <- 1
+  ]
+]
+
+# redo cursor movement and scroll
+
+scenario editor-redo-touch [
+  # create an editor with some text, click on a character, undo
+  assume-screen 10/width, 5/height
+  1:address:shared:array:character <- new [abc
+def
+ghi]
+  2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
+  editor-render screen, 2:address:shared:editor-data
+  assume-console [
+    left-click 3, 1
+    press ctrl-z
+  ]
+  editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
+  # redo
+  assume-console [
+    press ctrl-y
+  ]
+  run [
+    editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
+    3:number <- get *2:address:shared:editor-data, cursor-row:offset
+    4:number <- get *2:address:shared:editor-data, cursor-column:offset
+  ]
+  # cursor moves to left-click
+  memory-should-contain [
+    3 <- 3
+    4 <- 1
+  ]
+  # cursor should be in the right place
+  assume-console [
+    type [1]
+  ]
+  run [
+    editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
+  ]
+  screen-should-contain [
+    .          .
+    .abc       .
+    .def       .
+    .g1hi      .
+    .┈┈┈┈┈┈┈┈┈┈.
+  ]
+]
+
+after <handle-redo> [
+  {
+    move:address:move-operation <- maybe-convert *op, move:variant
+    break-unless move
+    # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen
+    *cursor-row <- get *move, after-row:offset
+    *cursor-column <- get *move, after-column:offset
+    top:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset
+    *top <- get *move, after-top-of-screen:offset
+  }
+]
+
 scenario editor-separates-undo-insert-from-undo-cursor-move [
   # create an editor, type some text, move the cursor, type some more text
   assume-screen 10/width, 5/height
@@ -1411,115 +1520,6 @@ scenario editor-separates-undo-insert-from-undo-cursor-move [
   ]
 ]
 
-scenario editor-can-undo-multiple-arrows-in-the-same-direction [
-  # create an editor with some text
-  assume-screen 10/width, 5/height
-  1:address:shared:array:character <- new [abc
-def
-ghi]
-  2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
-  editor-render screen, 2:address:shared:editor-data
-  # move the cursor
-  assume-console [
-    left-click 2, 1
-    press right-arrow
-    press right-arrow
-    press up-arrow
-  ]
-  editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
-  3:number <- get *2:address:shared:editor-data, cursor-row:offset
-  4:number <- get *2:address:shared:editor-data, cursor-column:offset
-  memory-should-contain [
-    3 <- 1
-    4 <- 3
-  ]
-  # undo
-  assume-console [
-    press ctrl-z
-  ]
-  run [
-    editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
-    3:number <- get *2:address:shared:editor-data, cursor-row:offset
-    4:number <- get *2:address:shared:editor-data, cursor-column:offset
-  ]
-  # up-arrow is undone
-  memory-should-contain [
-    3 <- 2
-    4 <- 3
-  ]
-  # undo again
-  assume-console [
-    press ctrl-z
-  ]
-  run [
-    editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
-    3:number <- get *2:address:shared:editor-data, cursor-row:offset
-    4:number <- get *2:address:shared:editor-data, cursor-column:offset
-  ]
-  # both right-arrows are undone
-  memory-should-contain [
-    3 <- 2
-    4 <- 1
-  ]
-]
-
-# redo cursor movement and scroll
-
-scenario editor-redo-touch [
-  # create an editor with some text, click on a character, undo
-  assume-screen 10/width, 5/height
-  1:address:shared:array:character <- new [abc
-def
-ghi]
-  2:address:shared:editor-data <- new-editor 1:address:shared:array:character, screen:address:shared:screen, 0/left, 10/right
-  editor-render screen, 2:address:shared:editor-data
-  assume-console [
-    left-click 3, 1
-    press ctrl-z
-  ]
-  editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
-  # redo
-  assume-console [
-    press ctrl-y
-  ]
-  run [
-    editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
-    3:number <- get *2:address:shared:editor-data, cursor-row:offset
-    4:number <- get *2:address:shared:editor-data, cursor-column:offset
-  ]
-  # cursor moves to left-click
-  memory-should-contain [
-    3 <- 3
-    4 <- 1
-  ]
-  # cursor should be in the right place
-  assume-console [
-    type [1]
-  ]
-  run [
-    editor-event-loop screen:address:shared:screen, console:address:shared:console, 2:address:shared:editor-data
-  ]
-  screen-should-contain [
-    .          .
-    .abc       .
-    .def       .
-    .g1hi      .
-    .┈┈┈┈┈┈┈┈┈┈.
-  ]
-]
-
-after <handle-redo> [
-  {
-    move:address:move-operation <- maybe-convert *op, move:variant
-    break-unless move
-    # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen
-    *cursor-row <- get *move, after-row:offset
-    *cursor-column <- get *move, after-column:offset
-    top:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset
-    *top <- get *move, after-top-of-screen:offset
-  }
-]
-
 # undo backspace
 
 scenario editor-can-undo-and-redo-backspace [
an>, *next; double age = 0.0; DNPRINTF(XT_D_HISTORY, "%s: hl_purge_count = %d (%d is max)\n", __func__, hl_purge_count, XT_MAX_HL_PURGE_COUNT); if (hl_purge_count == XT_MAX_HL_PURGE_COUNT) { hl_purge_count = 0; for (h = RB_MIN(history_list, &hl); h != NULL; h = next) { next = RB_NEXT(history_list, &hl, h); age = difftime(time(NULL), h->time); if (age > XT_MAX_HISTORY_AGE) { DNPRINTF(XT_D_HISTORY, "%s: removing %s (age %.1f)\n", __func__, h->uri, age); RB_REMOVE(history_list, &hl, h); g_free(h->uri); g_free(h->title); g_free(h); } else { DNPRINTF(XT_D_HISTORY, "%s: keeping %s (age %.1f)\n", __func__, h->uri, age); } } } return (0); } int insert_history_item(const gchar *uri, const gchar *title, time_t time) { struct history *h; if (!(uri && strlen(uri) && title && strlen(title))) return (1); h = g_malloc(sizeof(struct history)); h->uri = g_strdup(uri); h->title = g_strdup(title); h->time = time; DNPRINTF(XT_D_HISTORY, "%s: adding %s\n", __func__, h->uri); RB_INSERT(history_list, &hl, h); completion_add_uri(h->uri); hl_purge_count++; purge_history(); update_history_tabs(NULL); return (0); } int restore_global_history(void) { char file[PATH_MAX]; FILE *f; gchar *uri, *title, *stime, *err = NULL; time_t time; struct tm tm; const char delim[3] = {'\\', '\\', '\0'}; snprintf(file, sizeof file, "%s" PS "%s", work_dir, XT_HISTORY_FILE); if ((f = fopen(file, "r")) == NULL) { warnx("%s: fopen", __func__); return (1); } for (;;) { if ((uri = fparseln(f, NULL, NULL, delim, 0)) == NULL) if (feof(f) || ferror(f)) break; if ((title = fparseln(f, NULL, NULL, delim, 0)) == NULL) if (feof(f) || ferror(f)) { err = "broken history file (title)"; goto done; } if ((stime = fparseln(f, NULL, NULL, delim, 0)) == NULL) if (feof(f) || ferror(f)) { err = "broken history file (time)"; goto done; } if (strptime(stime, "%a %b %d %H:%M:%S %Y", &tm) == NULL) { err = "strptime failed to parse time"; goto done; } time = mktime(&tm); if (insert_history_item(uri, title, time)) { err = "failed to insert item"; goto done; } free(uri); free(title); free(stime); uri = NULL; title = NULL; stime = NULL; } done: if (err && strlen(err)) { warnx("%s: %s\n", __func__, err); free(uri); free(title); free(stime); return (1); } return (0); } int save_global_history_to_disk(struct tab *t) { char file[PATH_MAX]; FILE *f; struct history *h; snprintf(file, sizeof file, "%s" PS "%s", work_dir, XT_HISTORY_FILE); if ((f = fopen(file, "w")) == NULL) { show_oops(t, "%s: global history file: %s", __func__, strerror(errno)); return (1); } RB_FOREACH_REVERSE(h, history_list, &hl) { if (h->uri && h->title && h->time) fprintf(f, "%s\n%s\n%s", h->uri, h->title, ctime(&h->time)); } fclose(f); return (0); } /* * Marshall the internal record of visited URIs into a Javascript hash table in * string form. */ char * color_visited_helper(void) { char *d, *s = NULL, *t; struct history *h; RB_FOREACH_REVERSE(h, history_list, &hl) { if (s == NULL) s = g_strdup_printf("'%s':'dummy'", h->uri); else { d = g_strdup_printf("'%s':'dummy'", h->uri); t = g_strjoin(",", s, d, NULL); g_free(d); g_free(s); s = t; } } t = g_strdup_printf("{%s}", s); g_free(s); s = t; DNPRINTF(XT_D_VISITED, "%s: s = %s\n", __func__, s); return (s); } int color_visited(struct tab *t, char *visited) { char *s, *v; if (t == NULL || visited == NULL) { show_oops(NULL, "%s: invalid parameters", __func__); return (1); } /* * Create a string representing an annonymous Javascript function, which * takes a hash table of visited URIs as an argument, goes through the * links at the current web page and colors them if they indeed been * visited. */ v = g_strdup_printf("(%s);", visited), s = g_strconcat( "(function(visitedUris) {", " for (var i = 0; i < document.links.length; i++)", " if (visitedUris[document.links[i].href])", " document.links[i].style.color = 'purple';", "})", v, NULL); run_script(t, s); g_free(s); g_free(v); g_free(visited); return (0); }