+ * To prevent having to run the reasonably tricky bidi algorithm
+ * too many times, we maintain a cache of the last lineful of data
+ * fed to the algorithm on each line of the display.
+ */
+static int term_bidi_cache_hit(Terminal *term, int line,
+ unsigned long *lbefore, int width)
+{
+ if (!term->pre_bidi_cache)
+ return FALSE; /* cache doesn't even exist yet! */
+
+ if (line >= term->bidi_cache_size)
+ return FALSE; /* cache doesn't have this many lines */
+
+ if (!term->pre_bidi_cache[line])
+ return FALSE; /* cache doesn't contain _this_ line */
+
+ if (!memcmp(term->pre_bidi_cache[line], lbefore,
+ width * sizeof(unsigned long)))
+ return TRUE; /* aha! the line matches the cache */
+
+ return FALSE; /* it didn't match. */
+}
+
+static void term_bidi_cache_store(Terminal *term, int line,
+ unsigned long *lbefore,
+ unsigned long *lafter, int width)
+{
+ if (!term->pre_bidi_cache || term->bidi_cache_size <= line) {
+ int j = term->bidi_cache_size;
+ term->bidi_cache_size = line+1;
+ term->pre_bidi_cache = sresize(term->pre_bidi_cache,
+ term->bidi_cache_size,
+ unsigned long *);
+ term->post_bidi_cache = sresize(term->post_bidi_cache,
+ term->bidi_cache_size,
+ unsigned long *);
+ while (j < term->bidi_cache_size) {
+ term->pre_bidi_cache[j] = term->post_bidi_cache[j] = NULL;
+ j++;
+ }
+ }
+
+ sfree(term->pre_bidi_cache[line]);
+ sfree(term->post_bidi_cache[line]);
+
+ term->pre_bidi_cache[line] = snewn(width, unsigned long);
+ term->post_bidi_cache[line] = snewn(width, unsigned long);
+
+ memcpy(term->pre_bidi_cache[line], lbefore, width * sizeof(unsigned long));
+ memcpy(term->post_bidi_cache[line], lafter, width * sizeof(unsigned long));
+}
+
+/*