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);   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]; } }
static void do_paint(Terminal *term, Context ctx, int may_optimise){    int i, j, our_curs_y, our_curs_x;    unsigned long rv, cursor;    pos scrpos;    char ch[1024];    long cursor_background = ERASE_CHAR;    unsigned long ticks;#ifdef OPTIMISE_SCROLL    struct scrollregion *sr;#endif /* OPTIMISE_SCROLL */    /*     * Check the visual bell state.     */    if (term->in_vbell) {	ticks = GETTICKCOUNT();	if (ticks - term->vbell_startpoint >= VBELL_TIMEOUT)	    term->in_vbell = FALSE;    }    rv = (!term->rvideo ^ !term->in_vbell ? ATTR_REVERSE : 0);    /* Depends on:     * screen array, disptop, scrtop,     * selection, rv,      * cfg.blinkpc, blink_is_real, tblinker,      * curs.y, curs.x, blinker, cfg.blink_cur, cursor_on, has_focus, wrapnext     */    /* Has the cursor position or type changed ? */    if (term->cursor_on) {	if (term->has_focus) {	    if (term->blinker || !term->cfg.blink_cur)		cursor = TATTR_ACTCURS;	    else		cursor = 0;	} else	    cursor = TATTR_PASCURS;	if (term->wrapnext)	    cursor |= TATTR_RIGHTCURS;    } else	cursor = 0;    our_curs_y = term->curs.y - term->disptop;    {	/*	 * Adjust the cursor position in the case where it's	 * resting on the right-hand half of a CJK wide character.	 * xterm's behaviour here, which seems adequate to me, is	 * to display the cursor covering the _whole_ character,	 * exactly as if it were one space to the left.	 */	unsigned long *ldata = lineptr(term->curs.y);	our_curs_x = term->curs.x;	if (our_curs_x > 0 &&	    (ldata[our_curs_x] & (CHAR_MASK | CSET_MASK)) == UCSWIDE)	    our_curs_x--;    }    if (term->dispcurs && (term->curstype != cursor ||			   term->dispcurs !=			   term->disptext + our_curs_y * (term->cols + 1) +			   our_curs_x)) {	if (term->dispcurs > term->disptext && 	    (*term->dispcurs & (CHAR_MASK | CSET_MASK)) == UCSWIDE)	    term->dispcurs[-1] |= ATTR_INVALID;	if ( (term->dispcurs[1] & (CHAR_MASK | CSET_MASK)) == UCSWIDE)	    term->dispcurs[1] |= ATTR_INVALID;	*term->dispcurs |= ATTR_INVALID;	term->curstype = 0;    }    term->dispcurs = NULL;#ifdef OPTIMISE_SCROLL    /* Do scrolls */    sr = term->scrollhead;    while (sr) {	struct scrollregion *next = sr->next;	do_scroll(ctx, sr->topline, sr->botline, sr->lines);	sfree(sr);	sr = next;    }    term->scrollhead = term->scrolltail = NULL;#endif /* OPTIMISE_SCROLL */    /* The normal screen data */    for (i = 0; i < term->rows; i++) {	unsigned long *ldata;	int lattr;	int idx, dirty_line, dirty_run, selected;	unsigned long attr = 0;	int updated_line = 0;	int start = 0;	int ccount = 0;	int last_run_dirty = 0;	scrpos.y = i + term->disptop;	ldata = lineptr(scrpos.y);	lattr = (ldata[term->cols] & LATTR_MODE);	idx = i * (term->cols + 1);	dirty_run = dirty_line = (ldata[term->cols] !=				  term->disptext[idx + term->cols]);	term->disptext[idx + term->cols] = ldata[term->cols];	for (j = 0; j < term->cols; j++, idx++) {	    unsigned long tattr, tchar;	    unsigned long *d = ldata + j;	    int break_run;	    scrpos.x = j;	    tchar = (*d & (CHAR_MASK | CSET_MASK));	    tattr = (*d & (ATTR_MASK ^ CSET_MASK));	    switch (tchar & CSET_MASK) {	      case ATTR_ASCII:		tchar = term->ucsdata->unitab_line[tchar & 0xFF];		break;	      case ATTR_LINEDRW:		tchar = term->ucsdata->unitab_xterm[tchar & 0xFF];		break;	      case ATTR_SCOACS:  		tchar = term->ucsdata->unitab_scoacs[tchar&0xFF]; 		break;	    }	    tattr |= (tchar & CSET_MASK);	    tchar &= CHAR_MASK;	    if ((d[1] & (CHAR_MASK | CSET_MASK)) == UCSWIDE)		    tattr |= ATTR_WIDE;	    /* Video reversing things */	    if (term->selstate == DRAGGING || term->selstate == SELECTED) {		if (term->seltype == LEXICOGRAPHIC)		    selected = (posle(term->selstart, scrpos) &&				poslt(scrpos, term->selend));		else		    selected = (posPle(term->selstart, scrpos) &&				posPlt(scrpos, term->selend));	    } else		selected = FALSE;	    tattr = (tattr ^ rv		     ^ (selected ? ATTR_REVERSE : 0));	    /* 'Real' blinking ? */	    if (term->blink_is_real && (tattr & ATTR_BLINK)) {		if (term->has_focus && term->tblinker) {		    tchar = term->ucsdata->unitab_line[(unsigned char)' '];		}		tattr &= ~ATTR_BLINK;	    }	    /*	     * Check the font we'll _probably_ be using to see if 	     * the character is wide when we don't want it to be.	     */	    if ((tchar | tattr) != (term->disptext[idx]& ~ATTR_NARROW)) {		if ((tattr & ATTR_WIDE) == 0 && 		    char_width(ctx, (tchar | tattr) & 0xFFFF) == 2)		    tattr |= ATTR_NARROW;	    } else if (term->disptext[idx]&ATTR_NARROW)		tattr |= ATTR_NARROW;	    /* Cursor here ? Save the 'background' */	    if (i == our_curs_y && j == our_curs_x) {		cursor_background = tattr | tchar;		term->dispcurs = term->disptext + idx;	    }	    if ((term->disptext[idx] ^ tattr) & ATTR_WIDE)		dirty_line = TRUE;	    break_run = (((tattr ^ attr) & term->attr_mask) ||		j - start >= sizeof(ch));	    /* Special hack for VT100 Linedraw glyphs */	    if ((attr & CSET_MASK) == 0x2300 && tchar >= 0xBA		&& tchar <= 0xBD) break_run = TRUE;	    if (!term->ucsdata->dbcs_screenfont && !dirty_line) {		if ((tchar | tattr) == term->disptext[idx])		    break_run = TRUE;		else if (!dirty_run && ccount == 1)		    break_run = TRUE;	    }	    if (break_run) {		if ((dirty_run || last_run_dirty) && ccount > 0) {		    do_text(ctx, start, i, ch, ccount, attr, lattr);		    updated_line = 1;		}		start = j;		ccount = 0;		attr = tattr;		if (term->ucsdata->dbcs_screenfont)		    last_run_dirty = dirty_run;		dirty_run = dirty_line;	    }	    if ((tchar | tattr) != term->disptext[idx])		dirty_run = TRUE;	    ch[ccount++] = (char) tchar;	    term->disptext[idx] = tchar | tattr;	    /* If it's a wide char step along to the next one. */	    if (tattr & ATTR_WIDE) {		if (++j < term->cols) {		    idx++;		    d++;		    /*		     * By construction above, the cursor should not		     * be on the right-hand half of this character.		     * Ever.		     */		    assert(!(i == our_curs_y && j == our_curs_x));		    if (term->disptext[idx] != *d)			dirty_run = TRUE;		    term->disptext[idx] = *d;		}	    }	}	if (dirty_run && ccount > 0) {	    do_text(ctx, start, i, ch, ccount, attr, lattr);	    updated_line = 1;	}	/* Cursor on this line ? (and changed) */	if (i == our_curs_y && (term->curstype != cursor || updated_line)) {	    ch[0] = (char) (cursor_background & CHAR_MASK);	    attr = (cursor_background & ATTR_MASK) | cursor;	    do_cursor(ctx, our_curs_x, i, ch, 1, attr, lattr);	    term->curstype = cursor;	}    }}