term->seen_disp_event = 0;
need_sbar_update = TRUE;
}
+
+ /* Allocate temporary buffers for Arabic shaping and bidi. */
+ if (!term->cfg.arabicshaping || !term->cfg.bidi)
+ {
+ term->wcFrom = sresize(term->wcFrom, term->cols, bidi_char);
+ term->ltemp = sresize(term->ltemp, term->cols+1, unsigned long);
+ term->wcTo = sresize(term->wcTo, term->cols, bidi_char);
+ }
+
if (need_sbar_update)
update_sbar(term);
do_paint(term, ctx, TRUE);
term->resize_fn = NULL;
term->resize_ctx = NULL;
term->in_term_out = FALSE;
+ term->ltemp = NULL;
+ term->wcFrom = NULL;
+ term->wcTo = NULL;
+
+ term->bidi_cache_size = 0;
+ term->pre_bidi_cache = term->post_bidi_cache = NULL;
return term;
}
{
unsigned long *line;
struct beeptime *beep;
+ int i;
while ((line = delpos234(term->scrollback, 0)) != NULL)
sfree(line);
printer_finish_job(term->print_job);
bufchain_clear(&term->printer_buf);
sfree(term->paste_buffer);
+ sfree(term->ltemp);
+ sfree(term->wcFrom);
+ sfree(term->wcTo);
+
+ for (i = 0; i < term->bidi_cache_size; i++) {
+ sfree(term->pre_bidi_cache[i]);
+ sfree(term->post_bidi_cache[i]);
+ }
+ sfree(term->pre_bidi_cache);
+ sfree(term->post_bidi_cache);
+
sfree(term);
}
#endif
/*
+ * 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));
+}
+
+/*
* Given a context, update the window. Out of paranoia, we don't
* allow WM_PAINT responses to do scrolling optimisations.
*/
static void do_paint(Terminal *term, Context ctx, int may_optimise)
{
- int i, j, our_curs_y, our_curs_x;
+ int i, it, j, our_curs_y, our_curs_x;
unsigned long rv, cursor;
pos scrpos;
char ch[1024];
if (term->in_vbell) {
ticks = GETTICKCOUNT();
if (ticks - term->vbell_startpoint >= VBELL_TIMEOUT)
- term->in_vbell = FALSE;
- }
+ term->in_vbell = FALSE;
+ }
rv = (!term->rvideo ^ !term->in_vbell ? ATTR_REVERSE : 0);
term->disptext[idx + term->cols]);
term->disptext[idx + term->cols] = ldata[term->cols];
+ /* Do Arabic shaping and bidi. */
+ if(!term->cfg.bidi || !term->cfg.arabicshaping) {
+
+ if (!term_bidi_cache_hit(term, i, ldata, term->cols)) {
+
+ for(it=0; it<term->cols ; it++)
+ {
+ int uc = (ldata[it] & 0xFFFF);
+
+ switch (uc & CSET_MASK) {
+ case ATTR_LINEDRW:
+ if (!term->cfg.rawcnp) {
+ uc = term->ucsdata->unitab_xterm[uc & 0xFF];
+ break;
+ }
+ case ATTR_ASCII:
+ uc = term->ucsdata->unitab_line[uc & 0xFF];
+ break;
+ case ATTR_SCOACS:
+ uc = term->ucsdata->unitab_scoacs[uc&0xFF];
+ break;
+ }
+ switch (uc & CSET_MASK) {
+ case ATTR_ACP:
+ uc = term->ucsdata->unitab_font[uc & 0xFF];
+ break;
+ case ATTR_OEMCP:
+ uc = term->ucsdata->unitab_oemcp[uc & 0xFF];
+ break;
+ }
+
+ term->wcFrom[it].origwc = term->wcFrom[it].wc = uc;
+ term->wcFrom[it].index = it;
+ }
+
+ if(!term->cfg.bidi)
+ do_bidi(term->wcFrom, term->cols);
+
+ /* this is saved iff done from inside the shaping */
+ if(!term->cfg.bidi && term->cfg.arabicshaping)
+ for(it=0; it<term->cols; it++)
+ term->wcTo[it] = term->wcFrom[it];
+
+ if(!term->cfg.arabicshaping)
+ do_shape(term->wcFrom, term->wcTo, term->cols);
+
+ for(it=0; it<term->cols ; it++)
+ {
+ term->ltemp[it] = ldata[term->wcTo[it].index];
+
+ if (term->wcTo[it].origwc != term->wcTo[it].wc)
+ term->ltemp[it] = ((term->ltemp[it] & 0xFFFF0000) |
+ term->wcTo[it].wc);
+ }
+ term_bidi_cache_store(term, i, ldata, term->ltemp, term->cols);
+ ldata = term->ltemp;
+ } else {
+ ldata = term->post_bidi_cache[i];
+ }
+ }
+
for (j = 0; j < term->cols; j++, idx++) {
unsigned long tattr, tchar;
unsigned long *d = ldata + j;