/* PDCurses */ #include "pdcx11.h" #include #ifdef PDC_WIDE # include "../common/acsuni.h" #else chtype acs_map[128] = { PDC_ACS(0), PDC_ACS(1), PDC_ACS(2), PDC_ACS(3), PDC_ACS(4), PDC_ACS(5), PDC_ACS(6), PDC_ACS(7), PDC_ACS(8), PDC_ACS(9), PDC_ACS(10), PDC_ACS(11), PDC_ACS(12), PDC_ACS(13), PDC_ACS(14), PDC_ACS(15), PDC_ACS(16), PDC_ACS(17), PDC_ACS(18), PDC_ACS(19), PDC_ACS(20), PDC_ACS(21), PDC_ACS(22), PDC_ACS(23), PDC_ACS(24), PDC_ACS(25), PDC_ACS(26), PDC_ACS(27), PDC_ACS(28), PDC_ACS(29), PDC_ACS(30), PDC_ACS(31), ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '>', '<', '^', 'v', '/', PDC_ACS(0), '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', PDC_ACS(1), PDC_ACS(2), 'b', 'c', 'd', 'e', PDC_ACS(7), PDC_ACS(8), '#', 0xa4, PDC_ACS(11), PDC_ACS(12), PDC_ACS(13), PDC_ACS(14), PDC_ACS(15), PDC_ACS(16), PDC_ACS(17), PDC_ACS(18), PDC_ACS(19), PDC_ACS(20), PDC_ACS(21), PDC_ACS(22), PDC_ACS(23), PDC_ACS(24), PDC_ACS(25), PDC_ACS(26), PDC_ACS(27), PDC_ACS(28), PDC_ACS(29), PDC_ACS(30), 0xb7, PDC_ACS(127) }; #endif bool pdc_blinked_off; bool pdc_visible_cursor = FALSE; bool pdc_vertical_cursor = FALSE; /* Convert character positions x and y to pixel positions, stored in xpos and ypos */ static void _make_xy(int x, int y, int *xpos, int *ypos) { *xpos = x * pdc_fwidth; *ypos = pdc_app_data.normalFont->ascent + (y * pdc_fheight); } static void _set_cursor_color(chtype *ch, short *fore, short *back) { int attr; short f, b; attr = PAIR_NUMBER(*ch); if (attr) { pair_content(attr, &f, &b); *fore = 7 - (f % 8); *back = 7 - (b % 8); } else { if (*ch & A_REVERSE) { *back = COLOR_BLACK; *fore = COLOR_WHITE; } else { *back = COLOR_WHITE; *fore = COLOR_BLACK; } } } static void _display_cursor(int old_row, int old_x, int new_row, int new_x) { int xpos, ypos, i; chtype *ch; short fore = 0, back = 0; PDC_LOG(("_display_cursor() - draw char at row: %d col %d\n", old_row, old_x)); /* if the cursor position is outside the boundary of the screen, ignore the request */ if (old_row >= SP->lines || old_x >= COLS || new_row >= SP->lines || new_x >= COLS) return; /* display the character at the current cursor position */ PDC_LOG(("_display_cursor() - draw char at row: %d col %d\n", old_row, old_x)); PDC_transform_line(old_row, old_x, 1, curscr->_y[old_row] + old_x); /* display the cursor at the new cursor position */ if (!SP->visibility) return; /* cursor not displayed, no more to do */ _make_xy(new_x, new_row, &xpos, &ypos); ch = curscr->_y[new_row] + new_x; _set_cursor_color(ch, &fore, &back); if (pdc_vertical_cursor) { XSetForeground(XCURSESDISPLAY, pdc_cursor_gc, pdc_color[back]); for (i = 1; i <= SP->visibility; i++) XDrawLine(XCURSESDISPLAY, XCURSESWIN, pdc_cursor_gc, xpos + i, ypos - pdc_app_data.normalFont->ascent, xpos + i, ypos - pdc_app_data.normalFont->ascent + pdc_fheight - 1); } else { /* For block cursors, paint the block with invert. */ int yp, yh; if (SP->visibility == 2) { yp = ypos - pdc_fheight + pdc_fdescent; yh = pdc_fheight; } else { yp = ypos - pdc_fheight / 4 + pdc_fdescent; yh = pdc_fheight / 4; } XSetFunction(XCURSESDISPLAY, pdc_cursor_gc, GXinvert); XFillRectangle(XCURSESDISPLAY, XCURSESWIN, pdc_cursor_gc, xpos, yp, pdc_fwidth, yh); } PDC_LOG(("_display_cursor() - draw cursor at row %d col %d\n", new_row, new_x)); } void PDC_redraw_cursor(void) { _display_cursor(SP->cursrow, SP->curscol, SP->cursrow, SP->curscol); } void PDC_blink_text(XtPointer unused, XtIntervalId *id) { int row; int j, k; chtype *ch; PDC_LOG(("PDC_blink_text() - called:\n")); pdc_blinked_off = !pdc_blinked_off; /* Redraw changed lines on the screen to match the blink state */ for (row = 0; row < SP->lines; row++) { ch = curscr->_y[row]; for (j = 0; j < COLS; j++) if (ch[j] & A_BLINK) { k = j; while (ch[k] & A_BLINK && k < COLS) k++; PDC_transform_line(row, j, k - j, ch + j); j = k; } } PDC_redraw_cursor(); if ((SP->termattrs & A_BLINK) || !pdc_blinked_off) XtAppAddTimeOut(pdc_app_context, pdc_app_data.textBlinkRate, PDC_blink_text, NULL); } static void _toggle_cursor(void) { PDC_LOG(("_toggle_cursor - called. Vis now: ")); PDC_LOG((pdc_visible_cursor ? "1\n" : "0\n")); /* If the window is not active, ignore this command. The cursor will stay solid. */ if (pdc_window_entered) { if (pdc_visible_cursor) { /* Cursor currently ON, turn it off */ int save_visibility = SP->visibility; SP->visibility = 0; PDC_redraw_cursor(); SP->visibility = save_visibility; pdc_visible_cursor = FALSE; } else { /* Cursor currently OFF, turn it on */ PDC_redraw_cursor(); pdc_visible_cursor = TRUE; } } } int PDC_display_cursor(int oldrow, int oldcol, int newrow, int newcol, int visibility) { PDC_LOG(("PDC_display_cursor() - called: NEW row %d col %d, vis %d\n", newrow, newcol, visibility)); if (visibility == -1) _toggle_cursor(); else { pdc_visible_cursor = TRUE; _display_cursor(oldrow, oldcol, newrow, newcol); } return OK; } void PDC_blink_cursor(XtPointer unused, XtIntervalId *id) { PDC_LOG(("PDC_blink_cursor() - called:\n")); _toggle_cursor(); XtAppAddTimeOut(pdc_app_context, pdc_app_data.cursorBlinkRate, PDC_blink_cursor, NULL); } /* position hardware cursor at (y, x) */ void PDC_gotoyx(int row, int col) { PDC_LOG(("PDC_gotoyx() - called: row %d col %d\n", row, col)); PDC_display_cursor(SP->cursrow, SP->curscol, row, col, SP->visibility); } /* update the given physical line to look like the corresponding line in curscr */ /* Output a block of characters with common attributes */ static int _new_packet(chtype attr, int len, int col, int row, #ifdef PDC_WIDE XChar2b *text) #else char *text) #endif { XRectangle bounds; GC gc; int xpos, ypos; short fore, back; attr_t sysattrs; bool rev; pair_content(PAIR_NUMBER(attr), &fore, &back); /* Specify the color table offsets */ sysattrs = SP->termattrs; if ((attr & A_BOLD) && !(sysattrs & A_BOLD)) fore |= 8; if ((attr & A_BLINK) && !(sysattrs & A_BLINK)) back |= 8; rev = !!(attr & A_REVERSE); /* Determine which GC to use - normal, italic or bold */ if ((attr & A_ITALIC) && (sysattrs & A_ITALIC)) gc = pdc_italic_gc; else if ((attr & A_BOLD) && (sysattrs & A_BOLD)) gc = pdc_bold_gc; else gc = pdc_normal_gc; _make_xy(col, row, &xpos, &ypos); bounds.x = xpos; bounds.y = ypos - pdc_fascent; bounds.width = pdc_fwidth * len; bounds.height = pdc_fheight; XSetClipRectangles(XCURSESDISPLAY, gc, 0, 0, &bounds, 1, Unsorted); if (pdc_blinked_off && (sysattrs & A_BLINK) && (attr & A_BLINK)) { XSetForeground(XCURSESDISPLAY, gc, pdc_color[rev ? fore : back]); XFillRectangle(XCURSESDISPLAY, XCURSESWIN, gc, xpos, bounds.y, bounds.width, pdc_fheight); } else { /* Draw it */ XSetForeground(XCURSESDISPLAY, gc, pdc_color[rev ? back : fore]); XSetBackground(XCURSESDISPLAY, gc, pdc_color[rev ? fore : back]); #ifdef PDC_WIDE XDrawImageString16( #else XDrawImageString( #endif XCURSESDISPLAY, XCURSESWIN, gc, xpos, ypos, text, len); /* Underline, etc. */ if (attr & (A_LEFT | A_RIGHT | A_UNDERLINE)) { int k; if (SP->line_color != -1) XSetForeground(XCURSESDISPLAY, gc, pdc_color[SP->line_color]); if (attr & A_UNDERLINE) XDrawLine(XCURSESDISPLAY, XCURSESWIN, gc, xpos, ypos + 1, xpos + pdc_fwidth * len, ypos + 1); if (attr & A_LEFT) for (k = 0; k < len; k++) { int x = xpos + pdc_fwidth * k; XDrawLine(XCURSESDISPLAY, XCURSESWIN, gc, x, ypos - pdc_fascent, x, ypos + pdc_fdescent); } if (attr & A_RIGHT) for (k = 0; k < len; k++) { int x = xpos + pdc_fwidth * (k + 1) - 1; XDrawLine(XCURSESDISPLAY, XCURSESWIN, gc, x, ypos - pdc_fascent, x, ypos + pdc_fdescent); } } } PDC_LOG(("_new_packet() - row: %d col: %d " "num_cols: %d fore: %d back: %d text:<%s>\n", row, col, len, fore, back, text)); return OK; } /* The core display routine -- update one line of text */ void PDC_transform_line(int lineno, int x, int len, const chtype *srcp) { #ifdef PDC_WIDE XChar2b text[513]; #else char text[513]; #endif chtype old_attr, attr; int i, j; PDC_LOG(("PDC_transform_line() - called: lineno: %d x: %d " "len: %d\n", lineno, x, len)); if (!len) return; old_attr = *srcp & A_ATTRIBUTES; for (i = 0, j = 0; j < len; j++) { chtype curr = srcp[j]; attr = curr & A_ATTRIBUTES; if (attr & A_ALTCHARSET && !(curr & 0xff80)) { attr ^= A_ALTCHARSET; curr = acs_map[curr & 0x7f]; } #ifndef PDC_WIDE /* Special handling for ACS_BLOCK */ if (!(curr & A_CHARTEXT)) { curr |= ' '; attr ^= A_REVERSE; } #endif if (attr != old_attr) { if (_new_packet(old_attr, i, x, lineno, text) == ERR) return; old_attr = attr; x += i; i = 0; } #ifdef PDC_WIDE text[i].byte1 = (curr & 0xff00) >> 8; text[i++].byte2 = curr & 0x00ff; #else text[i++] = curr & 0xff; #endif } _new_packet(old_attr, i, x, lineno, text); } void PDC_doupdate(void) { XSync(XtDisplay(pdc_toplevel), False); }