mlterm-3.8.9004075500017600000144000000000001356600661000114605ustar kenusersmlterm-3.8.9/libvterm004075500017600000144000000000001356600660700133125ustar kenusersmlterm-3.8.9/libvterm/Makefile.in010064400017600000144000000020431356600660700154320ustar kenuserstop_builddir = .. top_srcdir = @top_srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ libexecdir = @libexecdir@ CC = @CC@ LIBTOOL = @LIBTOOL@ INSTALL = @INSTALL@ BINDIR = $(DESTDIR)$(bindir) LIBDIR = $(DESTDIR)$(libdir) VPATH = $(top_srcdir)/libvterm CFLAGS = $(CFLAGS_LOCAL) @DEB_CFLAGS@ @POBL_CFLAGS@ @MEF_CFLAGS@ @SSH2_CFLAGS@ \ @CFLAGS@ @CPPFLAGS@ -I$(top_srcdir)/vtemu -I/usr/local/include LIBS = $(LIBS_LOCAL) @LPOBL@ @LMEF@ OBJ = vterm.o LIBNAME = libvterm LIBTOOL_CC = $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) all: $(LIBNAME).la $(LIBNAME).la: $(OBJ) (cd ../vtemu;make mlterm.o) $(LIBTOOL_LINK) -o $(LIBNAME).la $(OBJ:.o=.lo) ../vtemu/*.lo \ @NO_UNDEFINED_FLAG@ -rpath $(libdir) -version-info 0:0:0 $(LIBS) .c.o: $(LIBTOOL_CC) -c $< clean: rm -rf $(OBJ) $(OBJ:.o=.lo) $(LIBNAME).la *.core .libs distclean: clean rm -f Makefile install: $(LIBTOOL_INSTALL) $(LIBNAME).la $(LIBDIR) mlterm-3.8.9/libvterm/README010064400017600000144000000035161356600660700142530ustar kenuserscomment -*- mode: text -*- How to build & install libvterm compatible library using mlterm engine. * Requirements o libvterm library and headers o neovim and other applications using libvterm. * Build $ ./configure $ make $ make vterm (== "cd libvterm ; make") * Install (Replace official libvterm) $ cd baselib ; make install-la $ cd encodefilter ; make install-la $ make install-vterm (== "cd libvterm ; make install") $ ln -sf [where libvterm of mlterm is installed]/libvterm.so.0 \ [where official libvterm is installed]/libvterm.so.0 * Start neovim terminal using libvterm $ nvim => :terminal * Notice o Sixel graphics is available under these conditions. - Terminal emulators mlterm 3.8.5 or later RLogin 2.23.1 or later - (mlterm) "col_size_of_width_a" option should be 1. - Applications using libvterm should regard the column width of ambiguous width characters as 1. (e.g. "set ambiwidth=single" on vim) o Unsupported vte api functions - vterm_new_with_allocator - vterm_keyboard_start_paste - vterm_keyboard_end_paste - vterm_parser_set_callbacks - vterm_parser_get_cbdata - vterm_state_set_callbacks - vterm_state_get_cbdata - vterm_state_set_unrecognised_fallbacks - vterm_state_get_unrecognised_fbdata - vterm_state_set_bold_highbright - vterm_state_get_penattr - vterm_state_set_termprop - vterm_state_get_lineinfo - vterm_screen_set_unrecognised_fallbacks - vterm_screen_get_unrecognized_fbdata - vterm_screen_enable_altscreen - vterm_screen_set_damage_merge - vterm_screen_get_chars - vterm_screen_get_text - vterm_screen_get_attrs_extent - vterm_screen_is_eol - vterm_scroll_rect - vterm_copy_cells * Tested environment o Arch Linux libvterm 0.1.git3.7a3913a-1.0 neovim 0.3.4-2.0 mlterm-3.8.9/libvterm/vterm.c010064400017600000144000000662331356600660700147010ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include /* sprintf */ #include #include /* getenv */ #include /* STDOUT_FILENO */ #include /* TIOCGWINSZ */ #include #include /* WORDS_BIGENDIGN */ #include #include #include #include #include #include #include #include #define SIXEL_1BPP #include "../common/c_sixel.c" typedef struct VTerm { vt_term_t *term; vt_pty_ptr_t pty; vt_pty_event_listener_t pty_listener; vt_config_event_listener_t config_listener; vt_screen_event_listener_t screen_listener; vt_xterm_event_listener_t xterm_listener; VTermColor default_fg; VTermColor default_bg; int mouse_col; int mouse_row; int mouse_button; u_char drcs_charset; u_char drcs_plane; /* '0'(94) or '1'(96) */ u_int col_width; u_int line_height; const VTermScreenCallbacks *vterm_screen_cb; void *vterm_screen_cbdata; } VTerm; /* --- static functions --- */ static int final(vt_pty_ptr_t pty) { return 1; } static ssize_t pty_write(vt_pty_ptr_t pty, u_char* buf, size_t len) { return 0; } static ssize_t pty_read(vt_pty_ptr_t pty, u_char* buf, size_t len) { return 0; } static int set_winsize(vt_pty_ptr_t pty, u_int cols, u_int rows, u_int width, u_int height) { return 1; } static vt_pty_ptr_t loopback_pty(void) { vt_pty_ptr_t pty; if ((pty = calloc(1, sizeof(vt_pty_t)))) { pty->master = pty->slave = -1; pty->child_pid = -1; pty->write = pty_write; pty->read = pty_read; pty->final = final; pty->set_winsize = set_winsize; vt_config_menu_init(&pty->config_menu); } return pty; } static void pty_closed(void *p) { ((VTerm*)p)->term = NULL; } static void set_config(void *p, char *dev, char *key, char *value) { VTerm *vterm; vterm = p; if (vt_term_set_config(vterm->term, key, value)) { /* do nothing */ } else if (strcmp(key, "encoding") == 0) { vt_char_encoding_t encoding; if ((encoding = vt_get_char_encoding(value)) != VT_UNKNOWN_ENCODING) { vt_term_change_encoding(vterm->term, encoding); } } } static void get_config(void *p, char *dev, char *key, int to_menu) { VTerm *vterm = p; vt_term_t *term; char *value; if (dev) { if (!(term = vt_get_term(dev))) { return; } } else { term = vterm->term; } if (vt_term_get_config(term, vterm->term, key, /* to_menu */ 0, NULL)) { return; } value = NULL; if (strcmp(key, "pty_list") == 0) { value = vt_get_pty_list(); } if (!value) { vt_term_response_config(vterm->term, "error", NULL, to_menu); } else { vt_term_response_config(vterm->term, key, value, to_menu); } } static VTermPos get_cursor_pos(vt_term_t *term) { VTermPos pos; pos.col = vt_term_cursor_col(term); pos.row = vt_term_cursor_row(term); return pos; } static void update_screen(VTerm *vterm) { int row; for (row = 0; row < vt_term_get_rows(vterm->term); row++) { vt_line_t *line; if ((line = vt_term_get_line_in_screen(vterm->term, row)) && vt_line_is_modified(line)) { VTermRect r; r.start_row = r.end_row = row; r.start_col = line->change_beg_col; r.end_col = line->change_end_col; #ifdef __DEBUG bl_debug_printf("MODIFIED %d-%d at %d\n", r.start_col, r.end_col, r.end_row); #endif (*vterm->vterm_screen_cb->damage)(r, vterm->vterm_screen_cbdata); vt_line_set_updated(line); } } } static void get_cell_size(VTerm *vterm) { #ifdef TIOCGWINSZ struct winsize ws; if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_xpixel > 0 && ws.ws_col > 0 && ws.ws_ypixel > 0 && ws.ws_row > 0) { vterm->col_width = ws.ws_xpixel / ws.ws_col; vterm->line_height = ws.ws_ypixel / ws.ws_row; bl_msg_printf("Cell size is %dx%d\n", vterm->col_width, vterm->line_height); return; } #endif bl_msg_printf("Regard cell size as 8x16\n"); vterm->col_width = 8; vterm->line_height = 16; } static void write_to_stdout(u_char *buf, size_t len) { ssize_t written; while (1) { if ((written = write(STDOUT_FILENO, buf, len)) < 0) { if (errno == EAGAIN) { usleep(100); /* 0.1 msec */ } else { return; } } else if (written == len) { return; } else { buf += written; len -= written; } } } static inline void switch_94_96_cs(VTerm *vterm) { if (vterm->drcs_plane == '0') { vterm->drcs_plane = '1'; } else { vterm->drcs_plane = '0'; } vterm->drcs_charset = '0'; } static vt_char_t *xterm_get_picture_data(void *p, char *file_path, int *num_cols, /* If *num_cols > 0, ignored. */ int *num_rows, /* If *num_rows > 0, ignored. */ int *num_cols_small /* set only if drcs_sixel is 1. */, int *num_rows_small /* set only if drcs_sixel is 1. */, u_int32_t **sixel_palette, int drcs_sixel) { static int old_drcs_sixel = -1; VTerm *vterm = p; u_int width; u_int height; FILE *fp; u_char data[1024]; u_char *data_p; u_char *all_data; size_t len; size_t skipped_len; int x, y; vt_char_t *buf; u_int buf_size; char seq[24 + 4 /*%dx2*/ + 2 /*%cx2*/ + 1]; /* \x1b[?8800h\x1bP1;0;0;%d;1;3;%d;%c{ %c */ if (strcasecmp(file_path + strlen(file_path) - 4, ".six") != 0 || /* accepts sixel alone */ !(fp = fopen(file_path, "r"))) { return NULL; } len = fread(data, 1, sizeof(data) - 1, fp); if (len < 2) { goto error_closing_fp; } data[len] = '\0'; if (*data == 0x90) { data_p = data + 1; } else if (strncmp(data, "\x1bP", 2) == 0) { data_p = data + 2; } else { goto error_closing_fp; } while ('0' <= *data_p && *data_p <= ';') { data_p++; } if (*data_p != 'q') { goto error_closing_fp; } data_p ++; if (old_drcs_sixel == -1) { const char *env = getenv("DRCS_SIXEL"); if (env && strcmp(env, "old") == 0) { old_drcs_sixel = 1; write_to_stdout("\x1b]5379;old_drcs_sixel=true\x07", 27); /* for mlterm */ } else { old_drcs_sixel = 0; write_to_stdout("\x1b]5379;old_drcs_sixel=false\x07", 28); /* for mlterm */ } } if (sscanf(data_p, "\"%d;%d;%d;%d", &x, &y, &width, &height) != 4 || width == 0 || height == 0) { struct stat st; u_char *picture; fstat(fileno(fp), &st); if (!(all_data = malloc(st.st_size + 1))) { goto error_closing_fp; } memcpy(all_data, data, len); len += fread(all_data + len, 1, st.st_size - len, fp); all_data[len] = '\0'; if (!(picture = load_sixel_from_data_1bpp(all_data, &width, &height))) { free(all_data); goto error_closing_fp; } free(picture); skipped_len = (data_p - data); /* skip DCS P ... q */ data_p = all_data + skipped_len; } else { /* "%d;%d;%d;%d */ if (old_drcs_sixel) { /* skip "X;X;X;X (rlogin 2.23.0 doesn't recognize it) */ data_p++; while ('0' <= *data_p && *data_p <= ';') { data_p++; } } skipped_len = (data_p - data); all_data = NULL; } len -= skipped_len; if (vterm->drcs_charset == '\0') { vterm->drcs_charset = '0'; vterm->drcs_plane = '0'; get_cell_size(vterm); /* Pcmw >= 5 in DECDLD */ if (vterm->col_width < 5 || 99 < vterm->col_width || 99 < vterm->line_height) { free(all_data); goto error_closing_fp; } } if (old_drcs_sixel) { /* compatible with old rlogin (2.23.0 or before) */ *num_cols = width / vterm->col_width; *num_rows = height / vterm->line_height; } else { *num_cols = (width + vterm->col_width - 1) / vterm->col_width; *num_rows = (height + vterm->line_height - 1) / vterm->line_height; } buf_size = (*num_cols) * (*num_rows); #if 0 /* * XXX * The way of drcs_charset increment from 0x7e character set may be different * between terminal emulators. */ if (vterm->drcs_charset > '0' && (buf_size + 0x5f) / 0x60 > 0x7e - vterm->drcs_charset + 1) { switch_94_96_cs(vterm); } #endif sprintf(seq, "\x1b[?8800h\x1bP1;0;0;%d;1;3;%d;%c{ %c", vterm->col_width, vterm->line_height, vterm->drcs_plane, vterm->drcs_charset); write_to_stdout(seq, strlen(seq)); while (1) { write_to_stdout(data_p, len); if ((len = fread(data, 1, sizeof(data), fp)) == 0) { break; } data_p = data; } free(all_data); fclose(fp); #if 0 bl_debug_printf("Image cols %d/%d=%d rows %d/%d=%d\n", width, vterm->col_width, *num_cols, height, vterm->line_height, *num_rows); #endif if ((buf = vt_str_new(buf_size))) { vt_char_t *buf_p; int col; int row; u_int code; code = 0x100020 + (vterm->drcs_plane == '1' ? 0x80 : 0) + vterm->drcs_charset * 0x100; buf_p = buf; for (row = 0; row < *num_rows; row++) { for (col = 0; col < *num_cols; col++) { #if 0 /* for old rlogin */ if (code == 0x20) { vt_char_copy(buf_p++, vt_sp_ch()); } else #endif { /* pua is ambiguous width but always regarded as halfwidth. */ vt_char_set(buf_p++, code++, ISO10646_UCS4_1, 0 /* fullwidth */, 0 /* comb */, VT_FG_COLOR, VT_BG_COLOR, 0 /* bold */, 0 /* italic */, 0 /* line_style */, 0 /* blinking */, 0 /* protected */); if ((code & 0x7f) == 0x0) { #if 0 /* for old rlogin */ code = 0x20; #else if (vterm->drcs_charset == 0x7e) { switch_94_96_cs(vterm); } else { vterm->drcs_charset++; } code = 0x100020 + (vterm->drcs_plane == '1' ? 0x80 : 0) + vterm->drcs_charset * 0x100; #endif } } } } if (vterm->drcs_charset == 0x7e) { switch_94_96_cs(vterm); } else { vterm->drcs_charset++; } return buf; } return NULL; error_closing_fp: fclose(fp); return NULL; } static void xterm_bel(void *p) { VTerm *vterm = p; (*vterm->vterm_screen_cb->bell)(vterm->vterm_screen_cbdata); } static void line_scrolled_out(void *p) { VTerm *vterm = p; VTermScreenCell *cells; u_int cols = vt_term_get_cols(vterm->term); if ((cells = alloca(sizeof(VTermScreenCell) * cols))) { VTermPos pos; /* * Note that scrolled out line hasn't been added to vt_logs_t yet here. * (see receive_scrolled_out_line() in vt_screen.c) */ pos.row = 0; for (pos.col = 0; pos.col < cols; pos.col++) { vterm_screen_get_cell(vterm, pos, cells + pos.col); } (*vterm->vterm_screen_cb->sb_pushline)(cols, cells, vterm->vterm_screen_cbdata); } } /* --- global functions --- */ VTerm *vterm_new(int rows, int cols) { VTerm *vterm; if (!(vterm = calloc(1, sizeof(VTerm)))) { return NULL; } vterm->pty_listener.self = vterm; vterm->pty_listener.closed = pty_closed; #if 0 vterm->pty_listener.show_config = show_config; #endif vterm->config_listener.self = vterm; vterm->config_listener.set = set_config; vterm->config_listener.get = get_config; #if 0 vterm->config_listener.exec = exec_cmd; #endif vterm->screen_listener.self = vterm; vterm->screen_listener.line_scrolled_out = line_scrolled_out; vterm->xterm_listener.self = vterm; #if 0 vterm->xterm_listener.resize = resize; vterm->xterm_listener.set_mouse_report = xterm_set_mouse_report; /* * XXX * If xterm_get_rgb is implemented, "#0;9;X;X;X" is prepended to sixel sequence * stored in file_path of xterm_get_picture_data, so the way of skipping "\"%d;%d;%d;%d" * in xterm_get_picture_data should be fixed. */ vterm->xterm_listener.get_rgb = xterm_get_rgb; #endif vterm->xterm_listener.bel = xterm_bel; vterm->xterm_listener.get_picture_data = xterm_get_picture_data; vterm->pty = loopback_pty(); vterm->term = mlterm_open(NULL, NULL, cols, rows, 1, NULL, NULL, &vterm->xterm_listener, &vterm->config_listener, &vterm->screen_listener, &vterm->pty_listener, 0); #if 1 /* col_size_of_width_a is forcibly 1 if locale is ja_XX.XX */ vterm->term->parser->col_size_of_width_a = 1; #endif vt_term_plug_pty(vterm->term, vterm->pty); vterm->default_fg.red = vterm->default_fg.green = vterm->default_fg.blue = 240; vterm->default_bg.red = vterm->default_bg.green = vterm->default_bg.blue = 0; return vterm; } VTerm *vterm_new_with_allocator(int rows, int cols, VTermAllocatorFunctions *funcs, void *allocdata) { return NULL; } void vterm_free(VTerm* vterm) { vt_destroy_term(vterm->term); free(vterm); #if 0 mlterm_final(); bl_mem_dump_all(); #endif } void vterm_get_size(const VTerm *vterm, int *rowsp, int *colsp) { *rowsp = vt_term_get_rows(vterm->term); *colsp = vt_term_get_cols(vterm->term); } void vterm_set_size(VTerm *vterm, int rows, int cols) { #ifdef __DEBUG bl_debug_printf("Resize screen to cols %d rows %d\n", cols, rows); #endif vt_term_resize(vterm->term, cols, rows, 0, 0); } int vterm_get_utf8(const VTerm *vterm) { if (vt_term_get_encoding(vterm->term) == VT_UTF8) { return 1; } else { return 0; } } void vterm_set_utf8(VTerm *vterm, int is_utf8) { vt_char_encoding_t encoding; if (is_utf8) { encoding = VT_UTF8; } else { encoding = vt_get_char_encoding("auto"); } vt_term_change_encoding(vterm->term, encoding); } size_t vterm_input_write(VTerm *vterm, const char *bytes, size_t len) { VTermPos oldpos = get_cursor_pos(vterm->term); vt_term_write_loopback(vterm->term, bytes, len); if (vterm->vterm_screen_cb) { (*vterm->vterm_screen_cb->movecursor)(get_cursor_pos(vterm->term), oldpos, vt_term_is_visible_cursor(vterm->term), vterm->vterm_screen_cbdata); } return len; } size_t vterm_output_get_buffer_size(const VTerm *vterm) { return vterm->pty->size; } size_t vterm_output_get_buffer_current(const VTerm *vterm) { return vterm->pty->size; } size_t vterm_output_get_buffer_remaining(const VTerm *vterm) { return vterm->pty->left; } size_t vterm_output_read(VTerm *vterm, char *buffer, size_t len) { if (vterm->pty->left == 0) { return 0; } if (len < vterm->pty->left) { memcpy(buffer, vterm->pty->buf, len); memmove(vterm->pty->buf, vterm->pty->buf + len, vterm->pty->left - len); vterm->pty->left -= len; } else { len = vterm->pty->left; vterm->pty->left = 0; memcpy(buffer, vterm->pty->buf, len); } return len; } void vterm_keyboard_unichar(VTerm *vterm, uint32_t c, VTermModifier mod) { static ef_parser_t *utf32_parser; static ef_conv_t *utf8_conv; u_char buf[UTF_MAX_SIZE]; size_t len; if (!utf32_parser) { #ifdef WORDS_BIGENDIAN utf32_parser = ef_utf32_parser_new(); #else utf32_parser = ef_utf32le_parser_new(); #endif utf8_conv = ef_utf8_conv_new(); } (*utf32_parser->init)(utf32_parser); (*utf32_parser->set_str)(utf32_parser, &c, 4); (*utf8_conv->init)(utf8_conv); len = (*utf8_conv->convert)(utf8_conv, buf, sizeof(buf), utf32_parser); vt_term_write(vterm->term, buf, len); } void vterm_keyboard_key(VTerm *vterm, VTermKey key, VTermModifier mod) { u_char buf[1]; vt_special_key_t mlkey; if (key == VTERM_KEY_ENTER) { buf[0] = '\r'; } else if (key == VTERM_KEY_TAB) { buf[0] = '\t'; } else { if (VTERM_KEY_FUNCTION_0 + 1 <= key && key <= VTERM_KEY_FUNCTION_0 + 37) { mlkey = SPKEY_F1 + (key - VTERM_KEY_FUNCTION_0 - 1); } else { switch(key) { case VTERM_KEY_BACKSPACE: mlkey = SPKEY_BACKSPACE; break; case VTERM_KEY_ESCAPE: mlkey = SPKEY_ESCAPE; break; case VTERM_KEY_UP: mlkey = SPKEY_UP; break; case VTERM_KEY_DOWN: mlkey = SPKEY_DOWN; break; case VTERM_KEY_LEFT: mlkey = SPKEY_LEFT; break; case VTERM_KEY_RIGHT: mlkey = SPKEY_RIGHT; break; case VTERM_KEY_INS: mlkey = SPKEY_INSERT; break; case VTERM_KEY_DEL: mlkey = SPKEY_DELETE; break; case VTERM_KEY_HOME: mlkey = SPKEY_HOME; break; case VTERM_KEY_END: mlkey = SPKEY_END; break; case VTERM_KEY_PAGEUP: mlkey = SPKEY_PRIOR; break; case VTERM_KEY_PAGEDOWN: mlkey = SPKEY_NEXT; break; case VTERM_KEY_KP_0: /* mlkey = SPKEY_KP_0; */ buf[0] = '0'; goto next_step; case VTERM_KEY_KP_1: /* mlkey = SPKEY_KP_1; */ buf[0] = '1'; goto next_step; case VTERM_KEY_KP_2: /* mlkey = SPKEY_KP_2; */ buf[0] = '2'; goto next_step; case VTERM_KEY_KP_3: /* mlkey = SPKEY_KP_3; */ buf[0] = '3'; goto next_step; case VTERM_KEY_KP_4: /* mlkey = SPKEY_KP_4; */ buf[0] = '4'; goto next_step; case VTERM_KEY_KP_5: /* mlkey = SPKEY_KP_5; */ buf[0] = '5'; goto next_step; case VTERM_KEY_KP_6: /* mlkey = SPKEY_KP_6; */ buf[0] = '6'; goto next_step; case VTERM_KEY_KP_7: /* mlkey = SPKEY_KP_7; */ buf[0] = '7'; goto next_step; case VTERM_KEY_KP_8: /* mlkey = SPKEY_KP_8; */ buf[0] = '8'; goto next_step; case VTERM_KEY_KP_9: /* mlkey = SPKEY_KP_9; */ buf[0] = '9'; goto next_step; case VTERM_KEY_KP_MULT: mlkey = SPKEY_KP_MULTIPLY; break; case VTERM_KEY_KP_PLUS: mlkey = SPKEY_KP_ADD; break; case VTERM_KEY_KP_COMMA: /* mlkey = SPKEY_KP_COMMA; */ buf[0] = ','; goto next_step; case VTERM_KEY_KP_MINUS: mlkey = SPKEY_KP_SUBTRACT; break; case VTERM_KEY_KP_PERIOD: mlkey = SPKEY_KP_DELETE; break; case VTERM_KEY_KP_DIVIDE: mlkey = SPKEY_KP_DIVIDE; break; case VTERM_KEY_KP_ENTER: mlkey = SPKEY_KP_SEPARATOR; break; case VTERM_KEY_KP_EQUAL: /* mlkey = SPKEY_KP_EQUAL; */ buf[0] = '='; goto next_step; default: return; } } if (vt_term_write_special_key(vterm->term, mlkey, mod, 0)) { return; } } next_step: vt_term_write(vterm->term, buf, 1); } void vterm_keyboard_start_paste(VTerm *vterm) {} void vterm_keyboard_end_paste(VTerm *vterm) {} void vterm_mouse_move(VTerm *vterm, int row, int col, VTermModifier mod) { #if 0 bl_debug_printf("MOUSE col %d row %d\n", col, row); #endif vterm->mouse_col = col; vterm->mouse_row = row; if (vt_term_get_mouse_report_mode(vterm->term) >= BUTTON_EVENT_MOUSE_REPORT) { vt_term_report_mouse_tracking(vterm->term, col + 1, row + 1, vterm->mouse_button, vterm->mouse_button ? 1 : 0, mod, 0); } } void vterm_mouse_button(VTerm *vterm, int button, bool pressed, VTermModifier mod) { #if 0 bl_debug_printf("MOUSE button %d %s\n", button, pressed ? "pressed" : "released"); #endif if (pressed) { vterm->mouse_button = button; } else { vterm->mouse_button = 0; } if (vt_term_get_mouse_report_mode(vterm->term)) { vt_term_report_mouse_tracking(vterm->term, vterm->mouse_col + 1, vterm->mouse_row + 1, button, !pressed, mod, 0); } } void vterm_parser_set_callbacks(VTerm *vterm, const VTermParserCallbacks *callbacks, void *user) { bl_warn_printf("vterm_parser_set_callbacks() is not supported.\n"); } void *vterm_parser_get_cbdata(VTerm *vterm) { return NULL; } VTermState *vterm_obtain_state(VTerm *vterm) { return vterm; } void vterm_state_set_callbacks(VTermState *state, const VTermStateCallbacks *callbacks, void *user) { bl_warn_printf("vterm_state_set_callbacks() is not supported.\n"); } void *vterm_state_get_cbdata(VTermState *state) { return NULL; } void vterm_state_set_unrecognised_fallbacks(VTermState *state, const VTermParserCallbacks *fallbacks, void *user) {} void *vterm_state_get_unrecognised_fbdata(VTermState *state) { return NULL; } void vterm_state_reset(VTermState *state, int hard) { VTerm *vterm = state; if (hard) { vt_term_write_loopback(vterm->term, "\x1bc", 2); /* RIS */ } else { vt_term_write_loopback(vterm->term, "\x1b[!p", 4); /* DECSTR */ } } void vterm_state_get_cursorpos(const VTermState *state, VTermPos *cursorpos) { *cursorpos = get_cursor_pos((VTerm*)state); } void vterm_state_get_default_colors(const VTermState *state, VTermColor *default_fg, VTermColor *default_bg) { VTerm *vterm = state; *default_fg = vterm->default_fg; *default_bg = vterm->default_bg; } void vterm_state_get_palette_color(const VTermState *state, int index, VTermColor *col) { u_int8_t r, g, b; vt_get_color_rgba(index, &r, &g, &b, NULL); col->red = r; col->green = g; col->blue = b; } void vterm_state_set_default_colors(VTermState *state, const VTermColor *default_fg, const VTermColor *default_bg) { VTerm *vterm = state; vterm->default_fg = *default_fg; vterm->default_bg = *default_bg; } void vterm_state_set_palette_color(VTermState *state, int index, const VTermColor *col) { char rgb[8]; sprintf(rgb, "#%.2x%.2x%.2x", col->red, col->green, col->blue); vt_customize_color_file(vt_get_color_name(index), rgb, 0); } void vterm_state_set_bold_highbright(VTermState *state, int bold_is_highbright) {} int vterm_state_get_penattr(const VTermState *state, VTermAttr attr, VTermValue *val) { /* XXX */ return 0; } int vterm_state_set_termprop(VTermState *state, VTermProp prop, VTermValue *val) { /* XXX */ return 0; } const VTermLineInfo *vterm_state_get_lineinfo(const VTermState *state, int row) { /* XXX */ return NULL; } VTermScreen *vterm_obtain_screen(VTerm *vterm) { return vterm; } void vterm_screen_set_callbacks(VTermScreen *screen, const VTermScreenCallbacks *callbacks, void *user) { VTerm *vterm = screen; vterm->vterm_screen_cbdata = user; vterm->vterm_screen_cb = callbacks; } void *vterm_screen_get_cbdata(VTermScreen *screen) { return NULL; } void vterm_screen_set_unrecognised_fallbacks(VTermScreen *screen, const VTermParserCallbacks *fallbacks, void *user) {} void *vterm_screen_get_unrecognised_fbdata(VTermScreen *screen) { return NULL; } void vterm_screen_enable_altscreen(VTermScreen *screen, int altscreen) {} void vterm_screen_flush_damage(VTermScreen *screen) { update_screen(screen); } void vterm_screen_set_damage_merge(VTermScreen *screen, VTermDamageSize size) {} void vterm_screen_reset(VTermScreen *screen, int hard) { vterm_state_reset(screen, hard); vterm_screen_flush_damage(screen); } size_t vterm_screen_get_chars(const VTermScreen *screen, uint32_t *chars, size_t len, const VTermRect rect) { /* XXX */ return 0; } size_t vterm_screen_get_text(const VTermScreen *screen, char *str, size_t len, const VTermRect rect) { /* XXX */ return 0; } int vterm_screen_get_attrs_extent(const VTermScreen *screen, VTermRect *extent, VTermPos pos, VTermAttrMask attrs) { /* XXX */ return 0; } int vterm_screen_get_cell(const VTermScreen *screen, VTermPos pos, VTermScreenCell *cell) { VTerm *vterm = screen; vt_line_t *line; int col = pos.col; int row = pos.row; vt_color_t fg = VT_FG_COLOR; vt_color_t bg = VT_BG_COLOR; u_int8_t r, g, b; memset(cell, 0, sizeof(*cell)); cell->width = 1; if ((line = vt_term_get_line(vterm->term, row))) { int char_index = vt_convert_col_to_char_index(line, &col, col, 0); if (char_index < line->num_filled_chars) { vt_font_t font = vt_char_font(line->chars + char_index); vt_line_style_t line_style = vt_char_line_style(line->chars + char_index); ef_charset_t cs = vt_char_cs(line->chars + char_index); fg = vt_char_fg_color(line->chars + char_index); bg = vt_char_bg_color(line->chars + char_index); /* XXX */ if (bg == VT_FG_COLOR && fg == VT_BG_COLOR) { vt_color_t tmp = fg; fg = bg; bg = tmp; cell->attrs.reverse = 1; } if (font & FONT_BOLD) { cell->attrs.bold = 1; } if (font & FONT_ITALIC) { cell->attrs.italic = 1; } if (line_style & LS_UNDERLINE) { cell->attrs.underline = (line_style & LS_UNDERLINE); } if (line_style == LS_CROSSED_OUT) { cell->attrs.strike = 1; } if (vt_char_is_blinking(line->chars + char_index)) { cell->attrs.blink = 1; } if (line->size_attr & DOUBLE_WIDTH) { cell->attrs.dwl = 1; } if (line->size_attr >= DOUBLE_HEIGHT_TOP) { cell->attrs.dhl = (line->size_attr & DOUBLE_HEIGHT_TOP) ? 1 : 2; } cell->width = vt_char_cols(line->chars + char_index); if (cell->width == 2 && col == 1) { cell->chars[0] = (u_int32_t)-1; cell->width = 1; } else { cell->chars[0] = vt_char_code(line->chars + char_index); if (cs != US_ASCII && !IS_ISO10646_UCS4(cs)) { ef_char_t ch; ch.size = CS_SIZE(cs); ef_int_to_bytes(ch.ch, ch.size, cell->chars[0]); ch.cs = cs; ch.property = 0; ef_map_to_ucs4(&ch, &ch); cell->chars[0] = ef_bytes_to_int(ch.ch, 4); } } } } if (fg == VT_FG_COLOR) { cell->fg = vterm->default_fg; } else if (fg == VT_BG_COLOR) { cell->fg = vterm->default_bg; } else { vt_get_color_rgba(fg, &r, &g, &b, NULL); cell->fg.red = r; cell->fg.green = g; cell->fg.blue = b; } if (bg == VT_FG_COLOR) { cell->bg = vterm->default_fg; } else if (bg == VT_BG_COLOR) { cell->bg = vterm->default_bg; } else { vt_get_color_rgba(bg, &r, &g, &b, NULL); cell->bg.red = r; cell->bg.green = g; cell->bg.blue = b; } return 1; } int vterm_screen_is_eol(const VTermScreen *screen, VTermPos pos) { return 0; } VTermValueType vterm_get_attr_type(VTermAttr attr) { switch(attr) { case VTERM_ATTR_BOLD: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_UNDERLINE: return VTERM_VALUETYPE_INT; case VTERM_ATTR_ITALIC: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_BLINK: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_REVERSE: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_STRIKE: return VTERM_VALUETYPE_BOOL; case VTERM_ATTR_FONT: return VTERM_VALUETYPE_INT; case VTERM_ATTR_FOREGROUND: return VTERM_VALUETYPE_COLOR; case VTERM_ATTR_BACKGROUND: return VTERM_VALUETYPE_COLOR; } return 0; } VTermValueType vterm_get_prop_type(VTermProp prop) { switch(prop) { case VTERM_PROP_CURSORVISIBLE: return VTERM_VALUETYPE_BOOL; case VTERM_PROP_CURSORBLINK: return VTERM_VALUETYPE_BOOL; case VTERM_PROP_ALTSCREEN: return VTERM_VALUETYPE_BOOL; case VTERM_PROP_TITLE: return VTERM_VALUETYPE_STRING; case VTERM_PROP_ICONNAME: return VTERM_VALUETYPE_STRING; case VTERM_PROP_REVERSE: return VTERM_VALUETYPE_BOOL; case VTERM_PROP_CURSORSHAPE: return VTERM_VALUETYPE_INT; case VTERM_PROP_MOUSE: return VTERM_VALUETYPE_INT; } return 0; } void vterm_scroll_rect(VTermRect rect, int downward, int rightward, int (*moverect)(VTermRect src, VTermRect dest, void *user), int (*eraserect)(VTermRect rect, int selective, void *user), void *user) {} void vterm_copy_cells(VTermRect dest, VTermRect src, void (*copycell)(VTermPos dest, VTermPos src, void *user), void *user) { /* XXX */ } mlterm-3.8.9/vtemu004075500017600000144000000000001356600660700126265ustar kenusersmlterm-3.8.9/vtemu/libptyssh004075500017600000144000000000001356600660700146475ustar kenusersmlterm-3.8.9/vtemu/libptyssh/Makefile.in010064400017600000144000000020451356600660700167710ustar kenuserstop_builddir = ../.. top_srcdir = @top_srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ libdir = @libdir@ LIBDIR = $(DESTDIR)$(libdir)/mlterm VPATH = ${top_srcdir}/vtemu/libptyssh CFLAGS = $(CFLAGS_LOCAL) @DEB_CFLAGS@ @POBL_CFLAGS@ @MEF_CFLAGS@ \ @SSH2_CFLAGS@ @CFLAGS@ @CPPFLAGS@ \ -I/usr/local/include -DLIBDIR=\"$(libdir)\" LIBS = $(LIBS_LOCAL) @LPOBL@ @SSH2_LIBS@ OBJ = vt_pty_ssh.o CC = @CC@ INSTALL = @INSTALL@ LIBTOOL = @LIBTOOL@ LIBTOOL_CC = $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) all: libptyssh.la libptyssh.la: $(OBJ) $(LIBTOOL_LINK) -o libptyssh.la $(OBJ:.o=.lo) \ -rpath $(libdir)/mlterm -module -avoid-version @NO_UNDEFINED_FLAG@ \ $(LIBS) .SUFFIXES: .o .c .c.o: $(LIBTOOL_CC) -c $(CFLAGS) $< $(LIBDIR): mkdir -p $(LIBDIR) install: $(LIBDIR) $(LIBTOOL_INSTALL) libptyssh.la $(LIBDIR) uninstall: rm -f $(LIBDIR)/*ptyssh.* clean: rm -rf $(OBJ) $(OBJ:.o=.lo) *ptyssh.* .libs distclean: clean rm -f Makefile mlterm-3.8.9/vtemu/libptyssh/vt_pty_ssh.c010064400017600000144000001524051356600660700173000ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include /* _FILE_OFFSET_BITS for the size of struct stat (libssh2_struct_stat) */ #include "../vt_pty_intern.h" #include #include #include #include #include #include #include #include /* bl_usleep */ #include #include /* getaddrinfo/socket/connect/sockaddr_un */ #include /* bl_get_user_rc_path */ #include /* bl_get_user_name */ #if !defined(USE_WIN32API) && defined(HAVE_PTHREAD) #include #endif #include /* open */ #include /* close/pipe */ #include /* sprintf */ #ifdef __CYGWIN__ #include #include /* GetModuleHandle */ #endif #ifdef __HAIKU__ #include /* fd_set */ #endif #ifndef USE_WIN32API #define closesocket(sock) close(sock) #endif #ifndef LIBSSH2_FLAG_COMPRESS #define LIBSSH2_FLAG_COMPRESS 2 #endif #ifndef LIBSSH2_ERROR_SOCKET_RECV #define LIBSSH2_ERROR_SOCKET_RECV -43 #endif #if 0 #define __DEBUG #endif typedef struct ssh_session { char *host; char *port; char *user; struct { char *pass; char *pubkey; char *privkey; char *cmd_path; char **argv; char **env; u_int cols; u_int rows; u_int width_pix; u_int height_pix; } *stored; LIBSSH2_SESSION *obj; int sock; int use_x11_forwarding; int suspended; LIBSSH2_CHANNEL **pty_channels; u_int num_ptys; int *x11_fds; LIBSSH2_CHANNEL **x11_channels; u_int num_x11; int lo_buf_pending; } ssh_session_t; typedef struct vt_pty_ssh { vt_pty_t pty; ssh_session_t *session; LIBSSH2_CHANNEL *channel; char *lo_buf; size_t lo_size; int is_eof; } vt_pty_ssh_t; typedef struct scp { LIBSSH2_CHANNEL *remote; int local; int src_is_remote; size_t src_size; u_int progress_len; vt_pty_ssh_t *pty_ssh; } scp_t; /* --- static variables --- */ static char *pass_response; static ssh_session_t **sessions; static u_int num_sessions = 0; #ifdef USE_WIN32API static HANDLE rd_ev; #endif static const char *cipher_list; static u_int keepalive_msec; static u_int keepalive_msec_left; static int use_x11_forwarding; static int display_port = -1; static int auth_agent_is_available; static int auto_reconnect; /* --- static functions --- */ #ifdef USE_WIN32API static void (*trigger_pty_read)(void); static u_int __stdcall wait_pty_read(LPVOID thr_param) { u_int count; struct timeval tval; fd_set read_fds; int maxfd; tval.tv_usec = 500000; /* 0.5 sec */ tval.tv_sec = 0; #ifdef __DEBUG bl_debug_printf("Starting wait_pty_read thread.\n"); #endif while (num_sessions > 0) { FD_ZERO(&read_fds); maxfd = 0; for (count = 0; count < num_sessions; count++) { u_int count2; FD_SET(sessions[count]->sock, &read_fds); if (sessions[count]->sock > maxfd) { maxfd = sessions[count]->sock; } for (count2 = 0; count2 < sessions[count]->num_x11; count2++) { FD_SET(sessions[count]->x11_fds[count2], &read_fds); if (sessions[count]->x11_fds[count2] > maxfd) { maxfd = sessions[count]->x11_fds[count2]; } } } if (select(maxfd + 1, &read_fds, NULL, NULL, &tval) > 0) { (*trigger_pty_read)(); WaitForSingleObject(rd_ev, INFINITE); } #ifdef __DEBUG bl_debug_printf("Select socket...\n"); #endif } #ifdef __DEBUG bl_debug_printf("Exiting wait_pty_read thread.\n"); #endif CloseHandle(rd_ev); rd_ev = 0; /* Not necessary if thread started by _beginthreadex */ #if 0 ExitThread(0); #endif return 0; } #endif /* USE_WIN32API */ /* libssh2 frees response[0].text internally. */ #ifdef BL_DEBUG #undef strdup #endif static void kbd_callback(const char *name, int name_len, const char *instruction, int instruction_len, int num_prompts, const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, void **abstract) { (void)name; (void)name_len; (void)instruction; (void)instruction_len; if (num_prompts == 1) { responses[0].text = strdup(pass_response); responses[0].length = strlen(pass_response); pass_response = NULL; } (void)prompts; (void)abstract; } #ifdef BL_DEBUG #define strdup(str) __bl_str_dup(str, __FILE__, __LINE__, __FUNCTION__) #endif #ifdef OPEN_PTY_ASYNC #ifdef USE_WIN32API static HANDLE *openssl_locks; static void openssl_lock_callback(int mode, int type, const char *file, int line) { if (mode & 1 /* CRYPTO_LOCK */) { WaitForSingleObject(openssl_locks[type], INFINITE); } else { ReleaseMutex(openssl_locks[type]); } } #else static pthread_mutex_t *openssl_locks; static void openssl_lock_callback(int mode, int type, const char *file, int line) { if (mode & 1 /* CRYPTO_LOCK */) { pthread_mutex_lock(&openssl_locks[type]); } else { pthread_mutex_unlock(&openssl_locks[type]); } } #endif int CRYPTO_num_locks(void); void CRYPTO_set_locking_callback(void (*func)(int, int, const char *, int)); /* gcrypt is not supported. */ static void set_use_multi_thread(int use) { static int num_locks; int count; if (use) { num_locks = CRYPTO_num_locks(); if ((openssl_locks = malloc(num_locks * sizeof(*openssl_locks)))) { for (count = 0; count < num_locks; count++) { #ifdef USE_WIN32API openssl_locks[count] = CreateMutex(NULL, FALSE, NULL); #else /* * "openssl_locks[count] = PTHREAD_MUTEX_INITIALIZER" fails in some environments * such as HaikuOS(x86, gcc-2.95.3) */ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; openssl_locks[count] = mutex; #endif } CRYPTO_set_locking_callback(openssl_lock_callback); } else { num_locks = 0; } } else { if (openssl_locks) { CRYPTO_set_locking_callback(NULL); #ifdef USE_WIN32API for (count = 0; count < num_locks; count++) { CloseHandle(openssl_locks[count]); } #endif free(openssl_locks); openssl_locks = NULL; } } } #else #define set_use_multi_thread(use) (0) #endif #ifdef AI_PASSIVE #define HAVE_GETADDRINFO #endif static void x11_callback(LIBSSH2_SESSION *session, LIBSSH2_CHANNEL *channel, char *shost, int sport, void **abstract); /* * Return session which is non-blocking mode because opening a new channel * can work as multi threading. */ static ssh_session_t *ssh_connect(const char *host, const char *port, const char *user, const char *pass, const char *pubkey, const char *privkey) { ssh_session_t *session; #ifdef HAVE_GETADDRINFO struct addrinfo hints; struct addrinfo *addr; struct addrinfo *addr_p; #else struct hostent *hent; struct sockaddr_in addr; int count; #endif const char *hostkey; size_t hostkey_len; int hostkey_type; char *userauthlist; int auth_success = 0; if ((session = vt_search_ssh_session(host, port, user))) { return session; } if (!(session = calloc(1, sizeof(ssh_session_t)))) { return NULL; } set_use_multi_thread(1); if (num_sessions == 0 && libssh2_init(0) != 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " libssh2_init failed.\n"); #endif goto error1; } #ifdef HAVE_GETADDRINFO memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if (getaddrinfo(host, port, &hints, &addr) != 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " getaddrinfo failed.\n"); #endif goto error2; } addr_p = addr; while (1) { if ((session->sock = socket(addr_p->ai_family, addr_p->ai_socktype, addr_p->ai_protocol)) >= 0) { if (connect(session->sock, addr_p->ai_addr, addr_p->ai_addrlen) == 0) { break; } else { closesocket(session->sock); } } if ((addr_p = addr_p->ai_next) == NULL) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " socket/connect failed.\n"); #endif freeaddrinfo(addr); goto error2; } } freeaddrinfo(addr); #else if (!(hent = gethostbyname(host))) { goto error2; } memset(&addr, 0, sizeof(addr)); addr.sin_port = htons(atoi(port)); addr.sin_family = AF_INET; count = 0; while (1) { if (!hent->h_addr_list[count]) { goto error2; } if (hent->h_addrtype == AF_INET) { addr.sin_addr.s_addr = *((u_int *)hent->h_addr_list[count]); if ((session->sock = socket(addr.sin_family, SOCK_STREAM, 0)) >= 0) { if (connect(session->sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { break; } else { closesocket(session->sock); } } } count++; } #endif /* HAVE_GETADDRINFO */ if (!(session->obj = libssh2_session_init())) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " libssh2_session_init failed.\n"); #endif goto error3; } #ifdef DEBUG libssh2_trace(session->obj, -1); #endif libssh2_session_set_blocking(session->obj, 1); libssh2_session_set_timeout(session->obj, 30000); /* 30 sec */ if (cipher_list) { libssh2_session_method_pref(session->obj, LIBSSH2_METHOD_CRYPT_CS, cipher_list); libssh2_session_method_pref(session->obj, LIBSSH2_METHOD_CRYPT_SC, cipher_list); } libssh2_session_callback_set(session->obj, LIBSSH2_CALLBACK_X11, x11_callback); #if !defined(LIBSSH2_VERSION_NUM) || LIBSSH2_VERSION_NUM < 0x010500 #ifndef LIBSSH2_FIX_DECOMPRESS_BUG /* * XXX * libssh2 1.4.3 or before fails to decompress zipped packets and breaks X11 * forwarding. * Camellia branch of http://bitbucket.org/araklen/libssh2/ fixes this bug * and defines LIBSSH2_FIX_DECOMPRESS_BUG macro. * libssh2 1.5.0 or later fixes this bug. */ if (!use_x11_forwarding) #endif #endif { libssh2_session_flag(session->obj, LIBSSH2_FLAG_COMPRESS, 1); } session->use_x11_forwarding = use_x11_forwarding; if (libssh2_session_handshake(session->obj, session->sock) != 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " libssh2_session_handshake failed.\n"); #endif goto error4; } /* * Check ~/.ssh/knownhosts. */ if ((hostkey = libssh2_session_hostkey(session->obj, &hostkey_len, &hostkey_type))) { char *home; char *path; LIBSSH2_KNOWNHOSTS *nhs; if ((home = bl_get_home_dir()) && (path = alloca(strlen(home) + 20)) && (nhs = libssh2_knownhost_init(session->obj))) { struct libssh2_knownhost *nh; #ifdef USE_WIN32API sprintf(path, "%s\\mlterm\\known_hosts", home); #elif defined(__ANDROID__) sprintf(path, "%s/.mlterm/known_hosts", home); #else sprintf(path, "%s/.ssh/known_hosts", home); #endif libssh2_knownhost_readfile(nhs, path, LIBSSH2_KNOWNHOST_FILE_OPENSSH); if (libssh2_knownhost_checkp(nhs, host, atoi(port), hostkey, hostkey_len, LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW, &nh) != LIBSSH2_KNOWNHOST_CHECK_MATCH) { const char *hash; size_t count; char *msg; char *p; hash = libssh2_hostkey_hash(session->obj, LIBSSH2_HOSTKEY_HASH_SHA1); msg = alloca(strlen(host) + 31 + 3 * 20 + 1); sprintf(msg, "Connecting to unknown host: %s (", host); p = msg + strlen(msg); for (count = 0; count < 20; count++) { sprintf(p + count * 3, "%02x:", (u_char)hash[count]); } msg[strlen(msg) - 1] = ')'; /* replace ':' with ')' */ if (!bl_dialog(BL_DIALOG_OKCANCEL, msg)) { libssh2_knownhost_free(nhs); goto error4; } libssh2_knownhost_add(nhs, host, NULL, hostkey, hostkey_len, LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW | LIBSSH2_KNOWNHOST_KEY_SSHRSA, NULL); libssh2_knownhost_writefile(nhs, path, LIBSSH2_KNOWNHOST_FILE_OPENSSH); bl_msg_printf("Add to %s and continue connecting.\n", path); } libssh2_knownhost_free(nhs); } } if (!(userauthlist = libssh2_userauth_list(session->obj, user, strlen(user)))) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " No authentication method.\n"); #endif if (libssh2_session_last_errno(session->obj) == 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Skip authentication.\n"); #endif goto auth_end; } else { goto error4; } } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Authentication methods: %s\n", userauthlist); #endif if (strstr(userauthlist, "publickey")) { char *home; char *p; LIBSSH2_AGENT *agent; if (*pass == '\0' && (agent = libssh2_agent_init(session->obj))) { if (libssh2_agent_connect(agent) == 0) { if (libssh2_agent_list_identities(agent) == 0) { struct libssh2_agent_publickey *ident; struct libssh2_agent_publickey *prev_ident; prev_ident = NULL; while (libssh2_agent_get_identity(agent, &ident, prev_ident) == 0) { if (libssh2_agent_userauth(agent, user, ident) == 0) { libssh2_agent_disconnect(agent); libssh2_agent_free(agent); auth_agent_is_available = 1; goto pubkey_success; } prev_ident = ident; } } libssh2_agent_disconnect(agent); } libssh2_agent_free(agent); } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Unable to use ssh-agent.\n"); #endif if ((home = bl_get_home_dir()) && ((p = alloca(strlen(home) * 2 + 36 /* __ANDROID__ */)))) { /* * man of libssh2_userauth_publickey_fromfile_ex() * publickey - Path name of the public key file. (e.g. /etc/ssh/hostkey.pub) * If libssh2 is built against OpenSSL, this option can be set to NULL. * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ #if 0 if (!pubkey) { #ifdef USE_WIN32API sprintf(p, "%s\\mlterm\\id_rsa.pub", home); #elif defined(__ANDROID__) sprintf(p, "%s/.mlterm/id_rsa.pub", home); #else sprintf(p, "%s/.ssh/id_rsa.pub", home); #endif pubkey = p; p += (strlen(pubkey) + 1); } #endif if (!privkey) { #ifdef USE_WIN32API sprintf(p, "%s\\mlterm\\id_rsa", home); #elif defined(__ANDROID__) sprintf(p, "%s/.mlterm/id_rsa", home); #else sprintf(p, "%s/.ssh/id_rsa", home); #endif privkey = p; } } else { #if 0 if (!pubkey) { #ifdef USE_WIN32API pubkey = "mlterm\\ssh_host_rsa_key.pub"; #else pubkey = "/etc/ssh/ssh_host_rsa_key.pub"; #endif } #endif if (!privkey) { #ifdef USE_WIN32API privkey = "mlterm\\ssh_host_rsa_key"; #else privkey = "/etc/ssh/ssh_host_rsa_key"; #endif } } if (libssh2_userauth_publickey_fromfile(session->obj, user, pubkey, privkey, pass) == 0) { pubkey_success: bl_msg_printf("Authentication by public key succeeded.\n"); auth_success = 1; } #ifdef DEBUG else { bl_debug_printf(BL_DEBUG_TAG " Authentication by public key failed.\n"); } #endif } if (!auth_success && strstr(userauthlist, "keyboard-interactive")) { pass_response = pass; if (libssh2_userauth_keyboard_interactive(session->obj, user, &kbd_callback) == 0) { bl_msg_printf("Authentication by keyboard-interactive succeeded.\n"); auth_success = 1; } #ifdef DEBUG else { bl_debug_printf(BL_DEBUG_TAG " Authentication by keyboard-interactive failed.\n"); } #endif } if (!auth_success) { if (!strstr(userauthlist, "password")) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " No supported authentication methods found.\n"); #endif goto error4; } if (libssh2_userauth_password(session->obj, user, pass) != 0) { bl_msg_printf("Authentication by password failed.\n"); goto error4; } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Authentication by password succeeded.\n"); #endif } auth_end: { void *p; if (!(p = realloc(sessions, sizeof(ssh_session_t) * (num_sessions + 1)))) { goto error4; } sessions = p; } libssh2_session_set_timeout(session->obj, 0); libssh2_session_set_blocking(session->obj, 0); session->host = strdup(host); session->port = strdup(port); session->user = strdup(user); sessions[num_sessions++] = session; return session; error4: libssh2_session_disconnect(session->obj, "Normal shutdown, Thank you for playing"); libssh2_session_free(session->obj); error3: closesocket(session->sock); error2: if (num_sessions == 0) { libssh2_exit(); } error1: set_use_multi_thread(0); free(session); return NULL; } static void close_x11(ssh_session_t *session, int idx); /* * Call with in blocking mode. */ static int ssh_disconnect(ssh_session_t *session) { u_int count; if (session->num_ptys > 0) { libssh2_session_set_blocking(session->obj, 0); return 0; } for (count = 0; count < num_sessions; count++) { if (sessions[count] == session) { sessions[count] = sessions[--num_sessions]; if (num_sessions == 0) { free(sessions); sessions = NULL; } break; } } for (count = session->num_x11; count > 0; count--) { close_x11(session, count - 1); } libssh2_session_disconnect(session->obj, "Normal shutdown, Thank you for playing"); libssh2_session_free(session->obj); closesocket(session->sock); if (num_sessions == 0) { libssh2_exit(); } free(session->host); free(session->port); free(session->user); free(session->stored); free(session->pty_channels); free(session->x11_fds); free(session->x11_channels); free(session); #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Closed session.\n"); #endif return 1; } static void remove_channel_from_session(ssh_session_t *session, LIBSSH2_CHANNEL *channel) { u_int count; for (count = 0; count < session->num_ptys; count++) { if (session->pty_channels[count] == channel) { session->pty_channels[count] = session->pty_channels[--session->num_ptys]; break; } } } static int unuse_loopback(vt_pty_t *pty); static int final(vt_pty_t *pty) { ssh_session_t *session; unuse_loopback(pty); session = ((vt_pty_ssh_t *)pty)->session; libssh2_session_set_blocking(session->obj, 1); remove_channel_from_session(session, ((vt_pty_ssh_t *)pty)->channel); libssh2_channel_free(((vt_pty_ssh_t *)pty)->channel); ssh_disconnect(session); return 1; } static int set_winsize(vt_pty_t *pty, u_int cols, u_int rows, u_int width_pix, u_int height_pix) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " win size cols %d rows %d width %d height %d.\n", cols, rows, width_pix, height_pix); #endif libssh2_channel_request_pty_size_ex(((vt_pty_ssh_t *)pty)->channel, cols, rows, width_pix, height_pix); return 1; } /* use_loopback() should be called before this. */ static void write_loopback(vt_pty_t *pty, const char *buf, size_t len) { #ifdef USE_WIN32API while (send(pty->slave, buf, len, 0) < 0 && errno == EAGAIN); #else while (write(pty->slave, buf, len) < 0 && errno == EAGAIN); #endif } static int reconnect(vt_pty_ssh_t *pty); static int use_loopback(vt_pty_t *pty); static int zombie(vt_pty_ssh_t *pty) { if (use_loopback(&pty->pty)) { write_loopback(&pty->pty, "=== Press any key to exit ===", 29); pty->is_eof = 1; /* * vt_pty_ssh_poll() may access an invalid channel object without this. * After calling this, remove_channel_from_session() in final() does nothing. */ remove_channel_from_session(pty->session, pty->channel); return 1; } return 0; } static ssize_t write_to_pty(vt_pty_t *pty, u_char *buf, size_t len) { ssize_t ret; if (((vt_pty_ssh_t *)pty)->session->suspended) { return 0; } ret = libssh2_channel_write(((vt_pty_ssh_t *)pty)->channel, buf, len); if (ret == LIBSSH2_ERROR_SOCKET_SEND || ret == LIBSSH2_ERROR_SOCKET_RECV || libssh2_channel_eof(((vt_pty_ssh_t *)pty)->channel)) { if ((ret < 0 && reconnect((vt_pty_ssh_t*)pty)) || zombie((vt_pty_ssh_t *)pty)) { return 0; } bl_trigger_sig_child(pty->child_pid); return -1; } else { return ret < 0 ? 0 : ret; } } static ssize_t read_pty(vt_pty_t *pty, u_char *buf, size_t len) { ssize_t ret; if (((vt_pty_ssh_t *)pty)->lo_buf) { if (((vt_pty_ssh_t *)pty)->lo_size < len) { len = ((vt_pty_ssh_t *)pty)->lo_size; } memcpy(buf, ((vt_pty_ssh_t *)pty)->lo_buf, len); /* XXX */ free(((vt_pty_ssh_t *)pty)->lo_buf); ((vt_pty_ssh_t *)pty)->lo_buf = NULL; ((vt_pty_ssh_t *)pty)->lo_size = 0; return len; } if (((vt_pty_ssh_t *)pty)->session->suspended) { return 0; } ret = libssh2_channel_read(((vt_pty_ssh_t *)pty)->channel, buf, len); #ifdef USE_WIN32API SetEvent(rd_ev); #endif if (ret <= 0 && (ret == LIBSSH2_ERROR_SOCKET_SEND || ret == LIBSSH2_ERROR_SOCKET_RECV || libssh2_channel_eof(((vt_pty_ssh_t *)pty)->channel))) { if ((ret < 0 && reconnect((vt_pty_ssh_t*)pty)) || zombie((vt_pty_ssh_t *)pty)) { return 0; } bl_trigger_sig_child(pty->child_pid); return -1; } else { return ret < 0 ? 0 : ret; } } static int scp_stop(vt_pty_ssh_t *pty_ssh) { pty_ssh->session->suspended = -1; return 1; } #ifdef USE_WIN32API /* Same as vt_pty_mosh.cpp */ static ssize_t lo_recv_pty(vt_pty_t *pty, u_char *buf, size_t len) { return recv(pty->master, buf, len, 0); } /* Same as vt_pty_mosh.cpp */ static ssize_t lo_send_to_pty(vt_pty_t *pty, u_char *buf, size_t len) { if (len == 1 && buf[0] == '\x03') { /* ^C */ scp_stop(pty); } else if (((vt_pty_ssh_t *)pty)->is_eof) { bl_trigger_sig_child(pty->child_pid); return -1; } return send(pty->slave, buf, len, 0); } /* Same as vt_pty_mosh.cpp */ static int _socketpair(int af, int type, int proto, SOCKET sock[2]) { SOCKET listen_sock; SOCKADDR_IN addr; int addr_len; if ((listen_sock = WSASocket(af, type, proto, NULL, 0, 0)) == INVALID_SOCKET) { return -1; } addr_len = sizeof(addr); memset((void *)&addr, 0, sizeof(addr)); addr.sin_family = af; addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = 0; if (bind(listen_sock, (SOCKADDR *)&addr, addr_len) != 0) { goto error1; } if (getsockname(listen_sock, (SOCKADDR *)&addr, &addr_len) != 0) { goto error1; } if (listen(listen_sock, 1) != 0) { goto error1; } /* select() and receive() can call simultaneously on java. */ if ((sock[0] = WSASocket(af, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { goto error1; } if (connect(sock[0], (SOCKADDR *)&addr, addr_len) != 0) { goto error2; } if ((sock[1] = accept(listen_sock, 0, 0)) == -1) { goto error2; } closesocket(listen_sock); return 0; error2: closesocket(sock[0]); error1: closesocket(listen_sock); return -1; } #endif /* USE_WIN32API */ #ifdef __CYGWIN__ static int check_sig_child(pid_t pid) { /* SIGCHLD signal isn't delivered on cygwin even if mlconfig exits. */ int status; if (pid > 0 && waitpid(pid, &status, WNOHANG) == pid) { bl_trigger_sig_child(pid); return 1; } else { return 0; } } #endif static ssize_t lo_read_pty(vt_pty_t *pty, u_char *buf, size_t len) { #ifdef __CYGWIN__ if (check_sig_child(pty->config_menu.pid)) { /* vt_pty_ssh_set_use_loopback(0) is called from sig_child() in vt_config_menu.c. */ return 0; } #endif return read(pty->master, buf, len); } static ssize_t lo_write_to_pty(vt_pty_t *pty, u_char *buf, size_t len) { #ifdef __CYGWIN__ if (check_sig_child(pty->config_menu.pid)) { /* * vt_pty_ssh_set_use_loopback(0) is called from sig_child() * in vt_config_menu.c is called */ return 0; } #endif if (len == 1 && buf[0] == '\x03') { /* ^C */ scp_stop((vt_pty_ssh_t *)pty); } else if (((vt_pty_ssh_t *)pty)->is_eof) { bl_trigger_sig_child(pty->child_pid); return -1; } return write(pty->slave, buf, len); } static int use_loopback(vt_pty_t *pty) { int fds[2]; if (pty->stored) { pty->stored->ref_count++; return 1; } if ((pty->stored = malloc(sizeof(*(pty->stored)))) == NULL) { return 0; } pty->stored->master = pty->master; pty->stored->slave = pty->slave; pty->stored->read = pty->read; pty->stored->write = pty->write; #ifdef USE_WIN32API if (_socketpair(AF_INET, SOCK_STREAM, 0, fds) == 0) { u_long val; val = 1; ioctlsocket(fds[0], FIONBIO, &val); val = 1; ioctlsocket(fds[1], FIONBIO, &val); pty->read = lo_recv_pty; pty->write = lo_send_to_pty; } else if (_pipe(fds, 256, O_BINARY) == 0) { pty->read = lo_read_pty; pty->write = lo_write_to_pty; } #else if (pipe(fds) == 0) { fcntl(fds[0], F_SETFL, O_NONBLOCK | fcntl(pty->master, F_GETFL, 0)); fcntl(fds[1], F_SETFL, O_NONBLOCK | fcntl(pty->slave, F_GETFL, 0)); pty->read = lo_read_pty; pty->write = lo_write_to_pty; } #endif else { free(pty->stored); pty->stored = NULL; return 0; } pty->master = fds[0]; pty->slave = fds[1]; pty->stored->ref_count = 1; ((vt_pty_ssh_t *)pty)->session->suspended = 1; return 1; } static int unuse_loopback(vt_pty_t *pty) { char buf[128]; ssize_t len; if (!pty->stored || --(pty->stored->ref_count) > 0) { return 0; } while ((len = (*pty->read)(pty, buf, sizeof(buf))) > 0) { char *p; if (!(p = realloc(((vt_pty_ssh_t *)pty)->lo_buf, ((vt_pty_ssh_t *)pty)->lo_size + len))) { break; } memcpy(p + ((vt_pty_ssh_t *)pty)->lo_size, buf, len); ((vt_pty_ssh_t *)pty)->lo_buf = p; ((vt_pty_ssh_t *)pty)->lo_size += len; ((vt_pty_ssh_t *)pty)->session->lo_buf_pending = 1; } #ifdef USE_WIN32API if (pty->read == lo_recv_pty) { closesocket(pty->slave); closesocket(pty->master); } else #endif { close(pty->slave); close(pty->master); } pty->master = pty->stored->master; pty->slave = pty->stored->slave; pty->read = pty->stored->read; pty->write = pty->stored->write; free(pty->stored); pty->stored = NULL; ((vt_pty_ssh_t *)pty)->session->suspended = 0; return 1; } #ifdef USE_WIN32API static u_int __stdcall #else static void * #endif scp_thread(void *p) { scp_t *scp; size_t rd_len; char buf[8192]; int progress; char msg1[] = "\x1b[?25l\r\nTransferring data.\r\n|"; char *msg2; char err_msg[] = "\r\nInterrupted.\x1b[?25h\r\n"; #if !defined(USE_WIN32API) && defined(HAVE_PTHREAD) pthread_detach(pthread_self()); #endif scp = p; /* suspended is 1 before calling scp_thread() (See vt_pty_ssh_scp_intern()) */ scp->pty_ssh->session->suspended = 2; #define MSG2_LEN (scp->progress_len + 9) if ((msg2 = alloca(MSG2_LEN + 1))) { memset(msg2, ' ', scp->progress_len); strcpy(msg2 + scp->progress_len, "|\x1b[?25h\r\n"); } rd_len = 0; progress = 0; write_loopback(&scp->pty_ssh->pty, msg1, sizeof(msg1) - 1); while (rd_len < scp->src_size && scp->pty_ssh->session->suspended > 0 /* scp_stop() sets suspended = -1*/) { int new_progress; ssize_t len; if (scp->src_is_remote) { if ((len = libssh2_channel_read(scp->remote, buf, sizeof(buf))) < 0) { if (len == LIBSSH2_ERROR_EAGAIN) { bl_usleep(1); continue; } else { break; } } write(scp->local, buf, len); } else { if ((len = read(scp->local, buf, sizeof(buf))) < 0) { break; } while (libssh2_channel_write(scp->remote, buf, len) == LIBSSH2_ERROR_EAGAIN) { bl_usleep(1); } } rd_len += len; new_progress = scp->progress_len * rd_len / scp->src_size; if (progress < new_progress && new_progress < scp->progress_len) { memset(msg2 + progress, '*', new_progress - progress); write_loopback(&scp->pty_ssh->pty, msg2, scp->progress_len); write_loopback(&scp->pty_ssh->pty, "|\r|", 3); progress = new_progress; #ifdef USE_WIN32API /* Exit GetMessage() in x_display_receive_next_event(). */ (*trigger_pty_read)(); #endif } } if (scp->pty_ssh->session->suspended > 0) { memset(msg2, '*', scp->progress_len); write_loopback(&scp->pty_ssh->pty, msg2, MSG2_LEN); /* Revert from 2 to 1 */ scp->pty_ssh->session->suspended = 1; } else { write_loopback(&scp->pty_ssh->pty, err_msg, sizeof(err_msg) - 1); } #if 1 bl_usleep(100000); /* Expect to switch to main thread and call vt_read_pty(). */ #else pthread_yield(); #endif while (libssh2_channel_free(scp->remote) == LIBSSH2_ERROR_EAGAIN) ; close(scp->local); unuse_loopback(&scp->pty_ssh->pty); scp->pty_ssh->session->suspended = 0; free(scp); /* Not necessary if thread started by _beginthreadex */ #if 0 ExitThread(0); #endif return 0; } #if 0 #define TRUSTED #endif static int setup_x11(LIBSSH2_CHANNEL *channel) { char *display; char *display_port_str; char *p; char *proto; char *data; #if !defined(USE_WIN32API) && !defined(OPEN_PTY_ASYNC) char *cmd; FILE *fp; char line[512]; #ifndef TRUSTED char *xauth_file; #endif #endif int ret; if (!(display = getenv("DISPLAY"))) { display = ":0.0"; } if (strncmp(display, "unix:", 5) == 0) { p = display + 5; } else if (display[0] == ':') { p = display + 1; } else { return 0; } if (!(display_port_str = alloca(strlen(p) + 1))) { return 0; } strcpy(display_port_str, p); if ((p = strrchr(display_port_str, '.'))) { *p = '\0'; } display_port = atoi(display_port_str); proto = NULL; data = NULL; /* I don't know why but system() and popen() can freeze if OPEN_PTY_ASYNC. */ #if !defined(USE_WIN32API) && !defined(OPEN_PTY_ASYNC) #ifdef TRUSTED if ((cmd = alloca(24 + strlen(display) + 1))) { sprintf(cmd, "xauth list %s 2> /dev/null", display); #else if ((xauth_file = bl_get_user_rc_path("mlterm/xauthfile"))) { if ((cmd = alloca(61 + strlen(xauth_file) + strlen(display) + 1))) { sprintf(cmd, "xauth -f %s generate %s MIT-MAGIC-COOKIE-1 " "untrusted 2> /dev/null", xauth_file, display); system(cmd); sprintf(cmd, "xauth -f %s list %s 2> /dev/null", xauth_file, display); #endif if ((fp = popen(cmd, "r"))) { if (fgets(line, sizeof(line), fp)) { if ((proto = strchr(line, ' '))) { proto += 2; if ((data = strchr(proto, ' '))) { *data = '\0'; data += 2; if ((p = strchr(data, '\n'))) { *p = '\0'; } } } } pclose(fp); } #ifdef TRUSTED } #else unlink(xauth_file); } free(xauth_file); } #endif #endif #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " libssh2_channel_x11_req_ex (with xauth %s %s)\n", proto, data); #endif while ((ret = libssh2_channel_x11_req_ex(channel, 0, proto, data, 0)) == LIBSSH2_ERROR_EAGAIN) ; return ret == 0; } static int open_channel(vt_pty_ssh_t *pty, /* pty->session is non-blocking */ const char *cmd_path, /* can be NULL */ char **cmd_argv, /* can be NULL(only if cmd_path is NULL) */ char **env, /* can be NULL */ u_int cols, u_int rows, u_int width_pix, u_int height_pix) { char *term; void *p; int ret; if (pty->session->suspended) { goto error2; } if (!(p = realloc(pty->session->pty_channels, (pty->session->num_ptys + 1) * sizeof(LIBSSH2_CHANNEL *)))) { goto error2; } pty->session->pty_channels = p; #if 0 while (!(pty->channel = libssh2_channel_open_session(pty->session->obj))) #else while (!(pty->channel = libssh2_channel_open_ex( pty->session->obj, "session", sizeof("session") - 1, /* RLogin's window size */ 64 * LIBSSH2_CHANNEL_PACKET_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0))) #endif { if (libssh2_session_last_errno(pty->session->obj) != LIBSSH2_ERROR_EAGAIN) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Unable to open a channel\n"); #endif goto error2; } } pty->session->suspended = 0; if (auth_agent_is_available) { #if defined(__CYGWIN__) static int (*func)(LIBSSH2_CHANNEL *); static int is_tried; if (!is_tried) { func = GetProcAddress(GetModuleHandle("cygssh2-1"), "libssh2_channel_request_auth_agent"); is_tried = 1; } if (func) { while ((ret = (*func)(pty->channel)) == LIBSSH2_ERROR_EAGAIN) ; if (ret == 0) { bl_msg_printf("Agent forwarding.\n"); } } #elif defined(LIBSSH2_FORWARD_AGENT) while ((ret = libssh2_channel_request_auth_agent(pty->channel)) == LIBSSH2_ERROR_EAGAIN) ; if (ret == 0) { bl_msg_printf("Agent forwarding.\n"); } #endif auth_agent_is_available = 0; } term = NULL; if (env) { while (*env) { char *val; size_t key_len; if ((val = strchr(*env, '='))) { key_len = val - *env; val++; } else { key_len = strlen(*env); val = ""; } while (libssh2_channel_setenv_ex(pty->channel, *env, key_len, val, strlen(val)) == LIBSSH2_ERROR_EAGAIN) ; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Env %s => key_len %d val %s\n", *env, key_len, val); #endif if (strncmp(*env, "TERM=", 5) == 0) { term = val; } env++; } } while ((ret = libssh2_channel_request_pty(pty->channel, term ? term : "xterm")) < 0) { if (ret != LIBSSH2_ERROR_EAGAIN) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to request pty. (Err %d)\n", ret); #endif goto error3; } } if (pty->session->use_x11_forwarding) { if (!setup_x11(pty->channel)) { bl_msg_printf("X11 forwarding failed.\n"); } } if (cmd_path) { int count; size_t cmd_line_len; /* Because cmd_path == cmd_argv[0], cmd_argv[0] is ignored. */ /* 1 = NULL terminator */ cmd_line_len = strlen(cmd_path) + 1; for (count = 1; cmd_argv[count] != NULL; count++) { /* 3 = " " */ cmd_line_len += (strlen(cmd_argv[count]) + 3); } if ((pty->pty.cmd_line = malloc(sizeof(char) * cmd_line_len)) == NULL) { goto error3; } strcpy(pty->pty.cmd_line, cmd_path); for (count = 1; cmd_argv[count] != NULL; count++) { sprintf(pty->pty.cmd_line + strlen(pty->pty.cmd_line), strchr(cmd_argv[count], ' ') ? " \"%s\"" : " %s", cmd_argv[count]); } while ((ret = libssh2_channel_exec(pty->channel, pty->pty.cmd_line)) < 0) { if (ret != LIBSSH2_ERROR_EAGAIN) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Unable to exec %s on allocated pty. (Err %d)\n", pty->pty.cmd_line, ret); #endif goto error3; } } } else { /* Open a SHELL on that pty */ while ((ret = libssh2_channel_shell(pty->channel)) < 0) { if (ret != LIBSSH2_ERROR_EAGAIN) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Unable to request shell on allocated pty. (Err %d)\n", ret); #endif goto error3; } } } pty->pty.master = pty->session->sock; pty->pty.slave = -1; pty->pty.child_pid = (pid_t)pty->channel; /* XXX regarding pid_t as channel */ pty->pty.final = final; pty->pty.set_winsize = set_winsize; pty->pty.write = write_to_pty; pty->pty.read = read_pty; pty->pty.mode = PTY_SSH; if (set_winsize(&pty->pty, cols, rows, width_pix, height_pix) == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_set_pty_winsize() failed.\n"); #endif } if (keepalive_msec >= 1000) { libssh2_keepalive_config(pty->session->obj, 1, keepalive_msec / 1000); } #ifdef USE_WIN32API if (!rd_ev) { HANDLE thrd; u_int tid; rd_ev = CreateEvent(NULL, FALSE, FALSE, "PTY_READ_READY"); if (GetLastError() != ERROR_ALREADY_EXISTS) { /* Launch the thread that wait for receiving data from pty. */ if (!(thrd = _beginthreadex(NULL, 0, wait_pty_read, NULL, 0, &tid))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreateThread() failed.\n"); #endif goto error3; } CloseHandle(thrd); } else { /* java/MLTerm.java has already watched pty. */ } } #endif pty->session->pty_channels[pty->session->num_ptys++] = pty->channel; set_use_multi_thread(0); return 1; error3: libssh2_session_set_blocking(pty->session->obj, 1); /* unblock in ssh_disconnect */ libssh2_channel_free(pty->channel); error2: ssh_disconnect(pty->session); set_use_multi_thread(0); return 0; } #ifdef USE_WIN32API static int connect_to_x11(void) { int sock; struct sockaddr_in addr; int count; if (display_port == -1 || (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { return -1; } for (count = 0; count < 5; count++) { memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(6000 + display_port + count); addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { u_long val; val = 1; ioctlsocket(sock, FIONBIO, &val); return sock; } } closesocket(sock); return -1; } #else static int connect_to_x11(void) { int sock; struct sockaddr_un addr; if (display_port == -1 || (sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { return -1; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; snprintf(addr.sun_path, sizeof(addr.sun_path), "/tmp/.X11-unix/X%d", display_port); if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { closesocket(sock); return -1; } fcntl(sock, F_SETFL, O_NONBLOCK | fcntl(sock, F_GETFL, 0)); return sock; } #endif static void x11_callback(LIBSSH2_SESSION *session_obj, LIBSSH2_CHANNEL *channel, char *shost, int sport, void **abstract) { u_int count; ssh_session_t *session; void *p; int display_sock; for (count = 0;; count++) { if (count == num_sessions) { /* XXX count must not reache num_sessions. */ return; } if (session_obj == sessions[count]->obj) { session = sessions[count]; break; } } if (!(p = realloc(session->x11_fds, (session->num_x11 + 1) * sizeof(int)))) { /* XXX channel resource is leaked. */ return; } session->x11_fds = p; if (!(p = realloc(session->x11_channels, (session->num_x11 + 1) * sizeof(LIBSSH2_CHANNEL *)))) { /* XXX channel resource is leaked. */ return; } session->x11_channels = p; if ((display_sock = connect_to_x11()) < 0) { bl_error_printf("Failed to connect X Server.\n"); /* Don't call libssh2_channel_free() which causes segfault here. */ } session->x11_channels[session->num_x11] = channel; session->x11_fds[session->num_x11++] = display_sock; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " x11 forwarding %d (display %d <=> ssh %p) started. => channel num %d\n", session->num_x11 - 1, display_sock, channel, session->num_x11); #endif } static int reconnect(vt_pty_ssh_t *pty) { ssh_session_t *session; vt_pty_ssh_t orig_pty; if (!(session = vt_search_ssh_session(pty->session->host, pty->session->port, pty->session->user)) || session == pty->session) { char *host; host = pty->session->host; pty->session->host = "***dummy***"; #ifdef __DEBUG bl_debug_printf("Reconnect to %s@%s:%s pw %s pubkey %s privkey %s\n", pty->session->user, host, pty->session->port, pty->session->stored->pass, pty->session->stored->pubkey, pty->session->stored->privkey); #endif bl_usleep(1000); if (!pty->session->stored || !(session = ssh_connect(host, pty->session->port, pty->session->user, pty->session->stored->pass, pty->session->stored->pubkey, pty->session->stored->privkey))) { pty->session->host = host; return 0; } pty->session->host = host; session->stored = pty->session->stored; pty->session->stored = NULL; } orig_pty = *pty; pty->session = session; if (!open_channel(pty, session->stored->cmd_path, session->stored->argv, session->stored->env, session->stored->cols, session->stored->rows, session->stored->width_pix, session->stored->height_pix)) { *pty = orig_pty; return 0; } free(orig_pty.pty.cmd_line); /* newly allocated in open_channel() */ final(&orig_pty.pty); return 1; } static void close_x11(ssh_session_t *session, int idx) { closesocket(session->x11_fds[idx]); while (libssh2_channel_free(session->x11_channels[idx]) == LIBSSH2_ERROR_EAGAIN) ; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " x11 forwarding %d (display %d <=> ssh %p) stopped. => channel num %d\n", idx, session->x11_fds[idx], session->x11_channels[idx], session->num_x11 - 1); #endif if (--session->num_x11 > 0) { session->x11_channels[idx] = session->x11_channels[session->num_x11]; session->x11_fds[idx] = session->x11_fds[session->num_x11]; } } static int xserver_to_ssh(LIBSSH2_CHANNEL *channel, int display) { char buf[8192]; ssize_t len; while ((len = recv(display, buf, sizeof(buf), 0)) > 0) { ssize_t w_len; char *p; p = buf; while ((w_len = libssh2_channel_write(channel, p, len)) < len) { if (w_len > 0) { len -= w_len; p += w_len; } else if (w_len < 0) { if (libssh2_channel_eof(channel)) { #if 0 shutdown(display, SHUT_RDWR); #endif return 0; } bl_usleep(1); } } #if 0 bl_debug_printf("X SERVER(%d) -> CHANNEL %d\n", display, len); #endif } if (len == 0) { return 0; } else { return 1; } } static int ssh_to_xserver(LIBSSH2_CHANNEL *channel, int display) { char buf[8192]; ssize_t len; while ((len = libssh2_channel_read(channel, buf, sizeof(buf))) > 0) { ssize_t w_len; char *p; p = buf; while ((w_len = send(display, p, len, 0)) < len) { if (w_len > 0) { len -= w_len; p += w_len; } else if (w_len < 0) { bl_usleep(1); } } #if 0 bl_debug_printf("CHANNEL -> X SERVER(%d) %d\n", display, len); #endif } if (libssh2_channel_eof(channel)) { #if 0 shutdown(display, SHUT_RDWR); #endif return 0; } else { return 1; } } /* cmd_path, cmd_argv, env, pubkey and privkey can be NULL. */ static void save_data_for_reconnect(ssh_session_t *session, const char *cmd_path, char **argv, char **env, const char *pass, const char *pubkey, const char *privkey, u_int cols, u_int rows, u_int width_pix, u_int height_pix) { size_t len; u_int array_size[2]; int idx; char **src; len = sizeof(*session->stored); len += (strlen(pass) + 1); if (cmd_path) len += (strlen(cmd_path) + 1); if (pubkey) len += (strlen(pubkey) + 1); if (privkey) len += (strlen(privkey) + 1); for (src = argv, idx = 0; idx < 2; src = env, idx++) { if (src) { array_size[idx] = 1; for ( ; *src; src++) { array_size[idx]++; len += (strlen(*src) + 1 + sizeof(*src)); } len += sizeof(*src); } else { array_size[idx] = 0; } } if ((session->stored = calloc(len, 1))) { char *str; char **dst; session->stored->argv = session->stored + 1; session->stored->env = session->stored->argv + array_size[0]; str = session->stored->env + array_size[1]; session->stored->pass = strcpy(str, pass); str += (strlen(pass) + 1); if (cmd_path) { session->stored->cmd_path = strcpy(str, cmd_path); str += (strlen(cmd_path) + 1); } if (pubkey) { session->stored->pubkey = strcpy(str, pubkey); str += (strlen(pubkey) + 1); } if (privkey) { session->stored->privkey = strcpy(str, privkey); str += (strlen(privkey) + 1); } for (src = argv, dst = session->stored->argv, idx = 0; idx < 2; src = env, dst = session->stored->env, idx++) { if (src) { for ( ; *src; src++) { *(dst++) = strcpy(str, *src); str += (strlen(str) + 1); } *dst = NULL; } else { if (idx == 0) { session->stored->argv = NULL; } else { session->stored->env = NULL; } } } session->stored->cols = cols; session->stored->rows = rows; session->stored->width_pix = width_pix; session->stored->height_pix = height_pix; } } /* --- global functions --- */ #ifdef USE_WIN32API void vt_pty_ssh_set_pty_read_trigger(void (*func)(void)) { trigger_pty_read = func; } #endif /* * Thread-safe. */ vt_pty_t *vt_pty_ssh_new(const char *cmd_path, /* can be NULL */ char **cmd_argv, /* can be NULL(only if cmd_path is NULL) */ char **env, /* can be NULL */ const char *uri, const char *pass, const char *pubkey, /* can be NULL */ const char *privkey, /* can be NULL */ u_int cols, u_int rows, u_int width_pix, u_int height_pix) { vt_pty_ssh_t *pty; char *uri_dup; char *user; char *proto; char *host; char *port; if ((uri_dup = alloca(strlen(uri) + 1)) == NULL || !bl_parse_uri(&proto, &user, &host, &port, NULL, NULL, strcpy(uri_dup, uri))) { return NULL; } if (!user && !(user = bl_get_user_name())) { return NULL; } if (proto && strcmp(proto, "ssh") != 0) { return NULL; } if ((pty = calloc(1, sizeof(vt_pty_ssh_t))) == NULL) { return NULL; } if (!(pty->session = ssh_connect(host, port ? port : "22", user, pass, pubkey, privkey)) || !open_channel(pty, cmd_path, cmd_argv, env, cols, rows, width_pix, height_pix)) { free(pty); return NULL; } if (auto_reconnect && ! pty->session->stored && strcmp(host, "localhost") != 0 && strcmp(host, "127.0.0.1") != 0) { save_data_for_reconnect(pty->session, cmd_path, cmd_argv, env, pass, pubkey, privkey, cols, rows, width_pix, height_pix); } return &pty->pty; } void *vt_search_ssh_session(const char *host, const char *port, /* can be NULL */ const char *user /* can be NULL */ ) { int count; if (!user && !(user = bl_get_user_name())) { return NULL; } /* search from newer sessions. */ for (count = num_sessions - 1; count >= 0; count--) { if (strcmp(sessions[count]->host, host) == 0 && (port == NULL || strcmp(sessions[count]->port, port) == 0) && strcmp(sessions[count]->user, user) == 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Find cached session for %s %s %s.\n", host, port, user); #endif return sessions[count]; } } return NULL; } int vt_pty_ssh_set_use_loopback(vt_pty_t *pty, int use) { if (use) { if (((vt_pty_ssh_t *)pty)->session->suspended) { return 0; } else { return use_loopback(pty); } } else { return unuse_loopback(pty); } } int vt_pty_ssh_scp_intern(vt_pty_t *pty, int src_is_remote, char *dst_path, char *src_path, u_int progress_len /* > 0 */) { scp_t *scp; #if LIBSSH2_VERSION_NUM >= 0x010700 libssh2_struct_stat st; #else struct stat st; #endif char *msg; /* Note that session is non-block mode in this context. */ /* Check if pty is vt_pty_ssh_t or not. */ if (pty->final != final) { return 0; } /* 2: Processing scp_thread() (See scp_thread()) */ if (((vt_pty_ssh_t *)pty)->session->suspended == 2) { bl_msg_printf("SCP: Another scp process is working.\n"); return 0; } if (!(scp = malloc(sizeof(scp_t)))) { return 0; } scp->pty_ssh = (vt_pty_ssh_t *)pty; scp->pty_ssh->session->suspended = 1; scp->progress_len = progress_len; if (src_is_remote) { while ( #if LIBSSH2_VERSION_NUM >= 0x010700 !(scp->remote = libssh2_scp_recv2(scp->pty_ssh->session->obj, src_path, &st)) #else !(scp->remote = libssh2_scp_recv(scp->pty_ssh->session->obj, src_path, &st)) #endif && libssh2_session_last_errno(scp->pty_ssh->session->obj) == LIBSSH2_ERROR_EAGAIN) ; if (!scp->remote) { bl_msg_printf("SCP: Failed to open remote:%s.\n", src_path); goto error; } if ((scp->local = open(dst_path, O_WRONLY | O_CREAT | O_TRUNC #ifdef USE_WIN32API | O_BINARY #endif , st.st_mode)) < 0) { bl_msg_printf("SCP: Failed to open local:%s.\n", dst_path); while (libssh2_channel_free(scp->remote) == LIBSSH2_ERROR_EAGAIN) ; goto error; } } else { if ((scp->local = open(src_path, O_RDONLY #ifdef USE_WIN32API | O_BINARY #endif , 0644)) < 0) { bl_msg_printf("SCP: Failed to open local:%s.\n", src_path); goto error; } fstat(scp->local, &st); #if 1 if ((st.st_mode & 0700) == 0) { /* XXX Avoid failure of libssh2_scp_send() */ st.st_mode |= 0400; } #endif while (!(scp->remote = libssh2_scp_send(scp->pty_ssh->session->obj, dst_path, st.st_mode & 0777, (u_long)st.st_size)) && libssh2_session_last_errno(scp->pty_ssh->session->obj) == LIBSSH2_ERROR_EAGAIN) ; if (!scp->remote) { bl_msg_printf("SCP: Failed to open remote:%s.\n", dst_path); close(scp->local); goto error; } } scp->src_is_remote = src_is_remote; scp->src_size = st.st_size; if (!use_loopback(pty)) { while (libssh2_channel_free(scp->remote) == LIBSSH2_ERROR_EAGAIN) ; goto error; } if ((msg = alloca(24 + strlen(src_path) + strlen(dst_path) + 1))) { sprintf(msg, "\r\nSCP: %s%s => %s%s", src_is_remote ? "remote:" : "local:", src_path, src_is_remote ? "local:" : "remote:", dst_path); write_loopback(pty, msg, strlen(msg)); } #if defined(USE_WIN32API) { HANDLE thrd; u_int tid; if ((thrd = _beginthreadex(NULL, 0, scp_thread, scp, 0, &tid))) { CloseHandle(thrd); } } #elif defined(HAVE_PTHREAD) { pthread_t thrd; pthread_create(&thrd, NULL, scp_thread, scp); } #else scp_thread(scp); #endif return 1; error: scp->pty_ssh->session->suspended = 0; free(scp); return 0; } void vt_pty_ssh_set_cipher_list(const char *list) { cipher_list = list; } void vt_pty_ssh_set_keepalive_interval(u_int interval_sec) { keepalive_msec_left = keepalive_msec = interval_sec * 1000; } u_int vt_pty_ssh_keepalive(u_int spent_msec) { if (keepalive_msec_left <= spent_msec) { u_int count; for (count = 0; count < num_sessions; count++) { libssh2_keepalive_send(sessions[count]->obj, NULL); } keepalive_msec_left = keepalive_msec; } else { keepalive_msec_left -= spent_msec; } return keepalive_msec_left; } void vt_pty_ssh_set_use_x11_forwarding(void *session, int use) { if (session) { ((ssh_session_t *)session)->use_x11_forwarding = use; } else { use_x11_forwarding = use; } } int vt_pty_ssh_poll(void *p) { fd_set *fds; int num_fds; u_int count; fds = p; FD_ZERO(fds); num_fds = 0; for (count = 0; count < num_sessions; count++) { u_int idx; if (sessions[count]->suspended) { continue; } for (idx = 0; idx < sessions[count]->num_ptys; idx++) { if (libssh2_poll_channel_read(sessions[count]->pty_channels[idx], 0)) { goto found; } else if (sessions[count]->lo_buf_pending) { sessions[count]->lo_buf_pending = 0; goto found; } } for (idx = 0; idx < sessions[count]->num_x11; idx++) { if (libssh2_poll_channel_read(sessions[count]->x11_channels[idx], 0)) { goto found; } } continue; found: FD_SET(sessions[count]->sock, fds); num_fds++; } return num_fds; } /* * The returned fds can contain -1 which means the failure of x11_callback(). */ u_int vt_pty_ssh_get_x11_fds(int **fds) { static int *x11_fds; static u_int num_x11_fds; u_int count; u_int num; if (num_sessions == 0) { return 0; } num = 0; for (count = 0; count < num_sessions; count++) { num += sessions[count]->num_x11; } if (num_x11_fds < num) { void *p; num_x11_fds = num; if (!(p = realloc(x11_fds, num * sizeof(int)))) { return 0; } x11_fds = p; } num = 0; for (count = 0; count < num_sessions; count++) { memcpy(x11_fds + num, sessions[count]->x11_fds, sessions[count]->num_x11 * sizeof(int)); num += sessions[count]->num_x11; } *fds = x11_fds; return num; } int vt_pty_ssh_send_recv_x11(int idx, int bidirection) { u_int count; ssh_session_t *session; for (count = 0;; count++) { if (count >= num_sessions) { return 0; } if (idx < sessions[count]->num_x11) { break; } idx -= sessions[count]->num_x11; } session = sessions[count]; if (session->suspended) { return 0; } if (session->x11_fds[idx] == -1 || /* Failed to connect X server */ !((!bidirection || xserver_to_ssh(session->x11_channels[idx], session->x11_fds[idx])) && ssh_to_xserver(session->x11_channels[idx], session->x11_fds[idx]))) { close_x11(session, idx); } return 1; } void vt_pty_ssh_set_use_auto_reconnect(int flag) { auto_reconnect = flag; } mlterm-3.8.9/vtemu/libctl004075500017600000144000000000001356600660700140775ustar kenusersmlterm-3.8.9/vtemu/libctl/vt_shape_iscii.c010064400017600000144000000061751356600660700173210ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../vt_shape.h" #include /* alloca */ #include /* bl_msg_printf */ #include "vt_iscii.h" /* --- global functions --- */ u_int vt_shape_iscii(vt_char_t *dst, u_int dst_len, vt_char_t *src, u_int src_len) { int src_pos; u_int dst_filled; u_char *iscii_buf; u_int iscii_filled; u_char *font_buf; u_int font_filled; vt_char_t *ch; vt_char_t *dst_shaped; u_int count; ef_charset_t cs; if ((iscii_buf = alloca(src_len * (MAX_COMB_SIZE + 1))) == NULL) { return 0; } #define DST_LEN (dst_len * (MAX_COMB_SIZE + 1)) if ((font_buf = alloca(DST_LEN)) == NULL) { return 0; } dst_filled = 0; iscii_filled = 0; dst_shaped = NULL; cs = UNKNOWN_CS; for (src_pos = 0; src_pos < src_len; src_pos++) { ch = &src[src_pos]; if (cs != vt_char_cs(ch)) { if (iscii_filled) { iscii_buf[iscii_filled] = '\0'; font_filled = vt_iscii_shape(cs, font_buf, DST_LEN, iscii_buf); /* * If EOL char is a iscii byte which presents two glyphs and * its second glyph is out of screen, 'font_filled' is greater * than 'dst + dst_len - dst_shaped'. */ if (font_filled > dst + dst_len - dst_shaped) { font_filled = dst + dst_len - dst_shaped; } #ifdef __DEBUG { int i; for (i = 0; i < iscii_filled; i++) { bl_msg_printf("%.2x ", iscii_buf[i]); } bl_msg_printf("=>\n"); for (i = 0; i < font_filled; i++) { bl_msg_printf("%.2x ", font_buf[i]); } bl_msg_printf("\n"); } #endif for (count = 0; count < font_filled; count++) { vt_char_set_code(dst_shaped++, font_buf[count]); } iscii_filled = 0; dst_shaped = NULL; } } cs = vt_char_cs(ch); if (IS_ISCII(cs)) { vt_char_t *comb; u_int comb_size; if (dst_shaped == NULL) { dst_shaped = &dst[dst_filled]; } if (!vt_char_is_null(ch)) { iscii_buf[iscii_filled++] = vt_char_code(ch); comb = vt_get_combining_chars(ch, &comb_size); for (count = 0; count < comb_size; count++) { iscii_buf[iscii_filled++] = vt_char_code(&comb[count]); } } vt_char_copy(&dst[dst_filled++], vt_get_base_char(ch)); if (dst_filled >= dst_len) { break; } } else { vt_char_copy(&dst[dst_filled++], ch); if (dst_filled >= dst_len) { return dst_filled; } } } if (iscii_filled) { iscii_buf[iscii_filled] = '\0'; font_filled = vt_iscii_shape(cs, font_buf, DST_LEN, iscii_buf); /* * If EOL char is a iscii byte which presents two glyphs and its second * glyph is out of screen, 'font_filled' is greater then * 'dst + dst_len - dst_shaped'. */ if (font_filled > dst + dst_len - dst_shaped) { font_filled = dst + dst_len - dst_shaped; } for (count = 0; count < font_filled; count++) { vt_char_set_code(dst_shaped + count, font_buf[count]); } } return dst_filled; } mlterm-3.8.9/vtemu/libctl/dexport-sun.map012075500017600000144000000000001356600660700213212dexport.mapustar kenusersmlterm-3.8.9/vtemu/libctl/dexport.map010064400017600000144000000001271356600660700163370ustar kenusersmlterm { global: vt_ctl_bidi_func_table ; vt_ctl_iscii_func_table ; local: * ; } ; mlterm-3.8.9/vtemu/libctl/vt_bidi.c010064400017600000144000000204161356600660700157420ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_bidi.h" #include /* memset */ #include /* isalpha */ #include #include /* alloca/realloc/free */ #include #if 0 #define __DEBUG #endif #define DIR_LTR_MARK 0x200e #define DIR_RTL_MARK 0x200f /* --- global functions --- */ vt_bidi_state_t vt_bidi_new(void) { vt_bidi_state_t state; if ((state = malloc(sizeof(*state))) == NULL) { return NULL; } state->visual_order = NULL; state->size = 0; state->rtl_state = 0; state->bidi_mode = BIDI_NORMAL_MODE; return state; } int vt_bidi_destroy(vt_bidi_state_t state) { free(state->visual_order); free(state); return 1; } /* * Don't call this functions with type_p == FRIBIDI_TYPE_ON and size == cur_pos. */ static void log2vis(FriBidiChar *str, u_int size, FriBidiCharType *type_p, vt_bidi_mode_t bidi_mode, FriBidiStrIndex *order, u_int cur_pos, int append) { FriBidiCharType type; u_int pos; if (size > cur_pos) { if (bidi_mode == BIDI_NORMAL_MODE) { type = FRIBIDI_TYPE_ON; } else if (bidi_mode == BIDI_ALWAYS_RIGHT) { type = FRIBIDI_TYPE_RTL; } else /* if (bidi_mode == BIDI_ALWAYS_LEFT) */ { type = FRIBIDI_TYPE_LTR; } fribidi_log2vis(str + cur_pos, size - cur_pos, &type, NULL, order + cur_pos, NULL, NULL); if (*type_p == FRIBIDI_TYPE_ON) { *type_p = type; } } else { /* * This functions is never called if type_p == FRIBIDI_TYPE_ON and * size == cur_pos. */ type = *type_p; } if (*type_p == FRIBIDI_TYPE_LTR) { if (type == FRIBIDI_TYPE_RTL) { /* * (Logical) "LLL/RRRNNN " ('/' is a separator) * ^-> endsp * => (Visual) "LLL/ NNNRRR" => "LLL/NNNRRR " */ u_int endsp_num; for (pos = size; pos > cur_pos; pos--) { if (str[pos - 1] != ' ') { break; } order[pos - 1] = pos - 1; } endsp_num = size - pos; for (pos = cur_pos; pos < size - endsp_num; pos++) { order[pos] = order[pos] + cur_pos - endsp_num; } } else if (cur_pos > 0) { for (pos = cur_pos; pos < size; pos++) { order[pos] += cur_pos; } } if (append) { order[size] = size; } } else /* if (*type_p == FRIBIDI_TYPE_RTL) */ { if (cur_pos > 0) { for (pos = 0; pos < cur_pos; pos++) { order[pos] += (size - cur_pos); } } if (type == FRIBIDI_TYPE_LTR) { /* * (Logical) "RRRNNN/LLL " ('/' is a separator) * ^-> endsp * => (Visual) "LLL /NNNRRR" => " LLL/NNNRRR" */ u_int endsp_num; for (pos = size; pos > cur_pos; pos--) { if (str[pos - 1] != ' ') { break; } order[pos - 1] = size - pos; } endsp_num = size - pos; for (pos = cur_pos; pos < size - endsp_num; pos++) { order[pos] += endsp_num; } } if (append) { for (pos = 0; pos < size; pos++) { order[pos]++; } order[size] = 0; } } } static void log2log(FriBidiStrIndex *order, u_int cur_pos, u_int size) { u_int pos; for (pos = cur_pos; pos < size; pos++) { order[pos] = pos; } } int vt_bidi(vt_bidi_state_t state, vt_char_t *src, u_int size, vt_bidi_mode_t bidi_mode, const char *separators) { FriBidiChar *fri_src; FriBidiCharType fri_type; FriBidiStrIndex *fri_order; int had_rtl; u_int cur_pos; ef_charset_t cs; u_int32_t code; u_int count; int ret; had_rtl = HAS_RTL(state); state->rtl_state = 0; if (size == 0) { state->size = 0; return 0; } if ((fri_src = alloca(sizeof(FriBidiChar) * size)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " alloca() failed.\n"); #endif return 0; } if ((fri_order = alloca(sizeof(FriBidiStrIndex) * size)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " alloca() failed.\n"); #endif return 0; } fri_type = FRIBIDI_TYPE_ON; if (bidi_mode == BIDI_ALWAYS_RIGHT) { SET_HAS_RTL(state); } for (count = 0, cur_pos = 0; count < size; count++) { cs = vt_char_cs(&src[count]); code = vt_char_code(&src[count]); if (cs == US_ASCII) { if (!isalpha(code)) { if (vt_get_picture_char(&src[count])) { fri_src[count] = 'a'; } else if (separators && strchr(separators, code)) { if (HAS_RTL(state)) { log2vis(fri_src, count, &fri_type, bidi_mode, fri_order, cur_pos, 1); } else { fri_type = FRIBIDI_TYPE_LTR; log2log(fri_order, cur_pos, count + 1); } cur_pos = count + 1; } else { fri_src[count] = code; } } else { fri_src[count] = code; } } else if (cs == ISO10646_UCS4_1) { if (0x2500 <= code && code <= 0x259f) { goto decsp; } else { fri_src[count] = code; if (!HAS_RTL(state) && (fribidi_get_type(fri_src[count]) & FRIBIDI_MASK_RTL)) { SET_HAS_RTL(state); } } } else if (cs == DEC_SPECIAL) { decsp: bidi_mode = BIDI_ALWAYS_LEFT; if (HAS_RTL(state)) { log2vis(fri_src, count, &fri_type, bidi_mode, fri_order, cur_pos, 1); } else { log2log(fri_order, cur_pos, count + 1); } cur_pos = count + 1; } else if (IS_ISCII(cs)) { return -2; /* iscii */ } else { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %x is not ucs.\n", cs); #endif /* * Regarded as NEUTRAL character. */ fri_src[count] = ' '; } } if (HAS_RTL(state)) { log2vis(fri_src, size, &fri_type, bidi_mode, fri_order, cur_pos, 0); count = 0; if (state->size != size) { void *p; if (!(p = realloc(state->visual_order, sizeof(u_int16_t) * size))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc() failed.\n"); #endif state->size = 0; return 0; } state->visual_order = p; state->size = size; ret = 2; /* order is changed */ } else { ret = 1; /* order is not changed */ for (; count < size; count++) { if (state->visual_order[count] != fri_order[count]) { ret = 2; /* order_is_changed */ break; } } } for (; count < size; count++) { state->visual_order[count] = fri_order[count]; } #ifdef __DEBUG bl_msg_printf("utf8 text => \n"); for (count = 0; count < size; count++) { bl_msg_printf("%.4x ", fri_src[count]); } bl_msg_printf("\n"); bl_msg_printf("visual order => "); for (count = 0; count < size; count++) { bl_msg_printf("%.2d ", state->visual_order[count]); } bl_msg_printf("\n"); #endif #ifdef DEBUG for (count = 0; count < size; count++) { if (state->visual_order[count] >= size) { bl_warn_printf(BL_DEBUG_TAG " visual order(%d) of %d is illegal.\n", state->visual_order[count], count); bl_msg_printf("returned order => "); for (count = 0; count < size; count++) { bl_msg_printf("%d ", state->visual_order[count]); } bl_msg_printf("\n"); abort(); } } #endif } else { state->size = 0; return -1; /* ot layout */ } if (fri_type == FRIBIDI_TYPE_RTL) { SET_BASE_RTL(state); } state->bidi_mode = bidi_mode; return ret; } int vt_bidi_copy(vt_bidi_state_t dst, vt_bidi_state_t src, int optimize) { u_int16_t *p; if (optimize && !HAS_RTL(src)) { vt_bidi_destroy(dst); return -1; } else if (src->size == 0) { free(dst->visual_order); p = NULL; } else if ((p = realloc(dst->visual_order, sizeof(u_int16_t) * src->size))) { memcpy(p, src->visual_order, sizeof(u_int16_t) * src->size); } else { return 0; } dst->visual_order = p; dst->size = src->size; dst->rtl_state = src->rtl_state; dst->bidi_mode = src->bidi_mode; return 1; } int vt_bidi_reset(vt_bidi_state_t state) { state->size = 0; return 1; } u_int32_t vt_bidi_get_mirror_char(u_int32_t ch) { FriBidiChar mirror; if (fribidi_get_mirror_char(ch, &mirror)) { return mirror; } else { return 0; } } int vt_is_rtl_char(u_int32_t ch) { return (fribidi_get_bidi_type(ch) & FRIBIDI_MASK_RTL) == FRIBIDI_MASK_RTL; } mlterm-3.8.9/vtemu/libctl/vt_bidi.h010064400017600000144000000020671356600660700157510ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __CTL_VT_BIDI_H__ #define __CTL_VT_BIDI_H__ #include "../vt_bidi.h" #include "../vt_char.h" /* Only used by vt_bidi.c, vt_line_bidi.c */ #define BASE_IS_RTL(state) ((((state)->rtl_state) >> 1) & 0x1) #define SET_BASE_RTL(state) (((state)->rtl_state) |= (0x1 << 1)) #define UNSET_BASE_RTL(state) (((state)->rtl_state) &= ~(0x1 << 1)) #define HAS_RTL(state) (((state)->rtl_state) & 0x1) #define SET_HAS_RTL(state) (((state)->rtl_state) |= 0x1) #define UNSET_HAS_RTL(state) (((state)->rtl_state) &= ~0x1) struct vt_bidi_state { u_int16_t *visual_order; u_int16_t size; int8_t bidi_mode; /* Cache how visual_order is rendered. */ /* * 6bit: Not used for now. * 1bit: base_is_rtl * 1bit: has_rtl */ int8_t rtl_state; }; vt_bidi_state_t vt_bidi_new(void); int vt_bidi_destroy(vt_bidi_state_t state); int vt_bidi(vt_bidi_state_t state, vt_char_t *src, u_int size, vt_bidi_mode_t mode, const char *separators); u_int32_t vt_bidi_get_mirror_char(u_int32_t src); #endif mlterm-3.8.9/vtemu/libctl/vt_functbl_bidi.c010064400017600000144000000020501356600660700174510ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../vt_ctl_loader.h" /* Dummy declaration */ void vt_line_set_use_bidi(void); void vt_line_bidi_convert_logical_char_index_to_visual(void); void vt_line_bidi_convert_visual_char_index_to_logical(void); void vt_line_bidi_copy_logical_str(void); void vt_line_bidi_is_rtl(void); void vt_is_rtl_char(void); void vt_bidi_copy(void); void vt_bidi_reset(void); void vt_line_bidi_need_shape(void); void vt_line_bidi_render(void); void vt_line_bidi_visual(void); void vt_line_bidi_logical(void); /* --- global variables --- */ void *vt_ctl_bidi_func_table[MAX_CTL_BIDI_FUNCS] = { (void*)CTL_API_COMPAT_CHECK_MAGIC, vt_line_set_use_bidi, vt_line_bidi_convert_logical_char_index_to_visual, vt_line_bidi_convert_visual_char_index_to_logical, vt_line_bidi_copy_logical_str, vt_line_bidi_is_rtl, vt_shape_arabic, vt_is_arabic_combining, vt_is_rtl_char, vt_bidi_copy, vt_bidi_reset, vt_line_bidi_need_shape, vt_line_bidi_render, vt_line_bidi_visual, vt_line_bidi_logical, }; mlterm-3.8.9/vtemu/libctl/vt_functbl_iscii.c010064400017600000144000000015201356600660700176430ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../vt_ctl_loader.h" /* Dummy declaration */ void vt_line_set_use_iscii(void); void vt_line_iscii_convert_logical_char_index_to_visual(void); void vt_iscii_copy(void); void vt_iscii_reset(void); void vt_line_iscii_need_shape(void); void vt_line_iscii_render(void); void vt_line_iscii_visual(void); void vt_line_iscii_logical(void); /* --- global variables --- */ void *vt_ctl_iscii_func_table[MAX_CTL_ISCII_FUNCS] = { (void*)CTL_API_COMPAT_CHECK_MAGIC, vt_isciikey_state_new, vt_isciikey_state_destroy, vt_convert_ascii_to_iscii, vt_line_set_use_iscii, vt_line_iscii_convert_logical_char_index_to_visual, vt_shape_iscii, vt_iscii_copy, vt_iscii_reset, vt_line_iscii_need_shape, vt_line_iscii_render, vt_line_iscii_visual, vt_line_iscii_logical, }; mlterm-3.8.9/vtemu/libctl/vt_iscii.c010064400017600000144000000224301356600660700161310ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_iscii.h" #include /* bl_snprintf */ #include #include #include #include /* BL_MAX */ #include #ifndef LIBDIR #define INDLIB_DIR "/usr/local/lib/mlterm/" #else #define INDLIB_DIR LIBDIR "/mlterm/" #endif #define A2IMAXBUFF 30 #if 0 #define __DEBUG #endif struct vt_isciikey_state { /* used for iitkeyb */ char prev_key[A2IMAXBUFF]; int8_t is_inscript; }; #ifdef STATIC_LINK_INDIC_TABLES /* for Android */ #if 0 #include #include
#include
#endif #include
#if 0 #include
#include
#include
#include
#include
#include
#endif /* --- static variables --- */ static struct { struct tabl *tabl; size_t size; } tables[] = { #if 0 { iscii_assamese_table, sizeof(iscii_assamese_table) / sizeof(struct tabl), }, { iscii_bengali_table, sizeof(iscii_bengali_table) / sizeof(struct tabl), }, { iscii_gujarati_table, sizeof(iscii_gujarati_table) / sizeof(struct tabl), }, #else { NULL, 0, }, { NULL, 0, }, { NULL, 0, }, #endif { iscii_hindi_table, sizeof(iscii_hindi_table) / sizeof(struct tabl), }, #if 0 { iscii_kannada_table, sizeof(iscii_kannada_table) / sizeof(struct tabl), }, { iscii_malayalam_table, sizeof(iscii_malayalam_table) / sizeof(struct tabl), }, { iscii_oriya_table, sizeof(iscii_oriya_table) / sizeof(struct tabl), }, { iscii_punjabi_table, sizeof(iscii_punjabi_table) / sizeof(struct tabl), }, { iscii_tamil_table, sizeof(iscii_tamil_table) / sizeof(struct tabl), }, { iscii_telugu_table, sizeof(iscii_telugu_table) / sizeof(struct tabl), }, { iscii_bengali_table, sizeof(iscii_bengali_table) / sizeof(struct tabl), }, { iscii_hindi_table, sizeof(iscii_hindi_table) / sizeof(struct tabl), }, #else { NULL, 0, }, { NULL, 0, }, { NULL, 0, }, { NULL, 0, }, { NULL, 0, }, { NULL, 0, }, { NULL, 0, }, { NULL, 0, }, #endif }; /* --- static functions --- */ static struct tabl *get_iscii_table(int idx, size_t *size) { *size = tables[idx].size; return tables[idx].tabl; } static struct a2i_tabl *get_isciikey_table(int is_inscript, size_t *size) { return NULL; } #else /* STATIC_LINK_INDIC_TABLES */ /* --- static variables --- */ static char *iscii_table_files[] = { "ind_assamese", "ind_bengali", "ind_gujarati", "ind_hindi", "ind_kannada", "ind_malayalam", "ind_oriya", "ind_punjabi", "ind_tamil", "ind_telugu", }; static struct tabl *(*get_iscii_tables[11])(u_int *); static struct a2i_tabl *(*get_inscript_table)(u_int *); static struct a2i_tabl *(*get_iitkeyb_table)(u_int *); /* --- static functions --- */ static void *load_symbol(char *file) { void *handle; void *sym; if (!(handle = bl_dl_open(INDLIB_DIR, file)) && !(handle = bl_dl_open("", file))) { bl_msg_printf("Failed to open %s\n", file); return NULL; } bl_dl_close_at_exit(handle); if (!(sym = bl_dl_func_symbol(handle, "libind_get_table"))) { bl_dl_close(handle); } return sym; } static struct tabl *get_iscii_table(int idx, size_t *size) { if (!get_iscii_tables[idx] && !(get_iscii_tables[idx] = load_symbol(iscii_table_files[idx]))) { return NULL; } return (*get_iscii_tables[idx])(size); } static struct a2i_tabl *get_isciikey_table(int is_inscript, size_t *size) { if (is_inscript) { if (!get_inscript_table && !(get_inscript_table = load_symbol("ind_inscript"))) { return NULL; } return (*get_inscript_table)(size); } else { if (!get_iitkeyb_table && !(get_iitkeyb_table = load_symbol("ind_iitkeyb"))) { return NULL; } return (*get_iitkeyb_table)(size); } } #endif /* STATIC_LINK_INDIC_TABLES */ /* --- global functions --- */ u_int vt_iscii_shape(ef_charset_t cs, u_char *dst, size_t dst_size, u_char *src) { struct tabl *table; size_t size; if (!IS_ISCII(cs)) { return 0; } if ((table = get_iscii_table(cs - ISCII_ASSAMESE, &size)) == NULL) { return 0; } /* * XXX * iscii2font() expects dst to be terminated by zero. * int iscii2font(struct tabl table[MAXLEN], char *input, char *output, int *sz) { * ... * bzero(output,strlen(output)); * ... ^^^^^^^^^^^^^^ * } */ dst[0] = '\0'; return iscii2font(table, src, dst, size); } vt_iscii_state_t vt_iscii_new(void) { return calloc(1, sizeof(struct vt_iscii_state)); } int vt_iscii_destroy(vt_iscii_state_t state) { free(state->num_chars_array); free(state); return 1; } int vt_iscii(vt_iscii_state_t state, vt_char_t *src, u_int src_len) { int dst_pos; int src_pos; u_char *iscii_buf; u_char *font_buf; u_int8_t *num_chars_array; u_int font_buf_len; u_int prev_font_filled; u_int iscii_filled; ef_charset_t cs; ef_charset_t prev_cs; int has_ucs; if ((iscii_buf = alloca(src_len * MAX_COMB_SIZE + 1)) == NULL) { return 0; } font_buf_len = src_len * MAX_COMB_SIZE + 1; if ((font_buf = alloca(font_buf_len)) == NULL) { return 0; } if ((num_chars_array = alloca(font_buf_len * sizeof(u_int8_t))) == NULL) { return 0; } state->has_iscii = 0; dst_pos = -1; prev_cs = cs = UNKNOWN_CS; has_ucs = 0; for (src_pos = 0; src_pos < src_len; src_pos++) { cs = vt_char_cs(src + src_pos); if (prev_cs != cs) { prev_font_filled = iscii_filled = 0; prev_cs = cs; } if (IS_ISCII(cs)) { u_int font_filled; u_int count; vt_char_t *comb; u_int num; iscii_buf[iscii_filled++] = vt_char_code(src + src_pos); comb = vt_get_combining_chars(src + src_pos, &num); for (; num > 0; num--) { iscii_buf[iscii_filled++] = vt_char_code(comb++); } iscii_buf[iscii_filled] = '\0'; font_filled = vt_iscii_shape(cs, font_buf, font_buf_len, iscii_buf); if (font_filled < prev_font_filled) { if (font_filled == 0) { return 0; } count = prev_font_filled - font_filled; dst_pos -= count; for (; count > 0; count--) { num_chars_array[dst_pos] += num_chars_array[dst_pos + count]; } prev_font_filled = font_filled; /* goto to the next if block */ } if (dst_pos >= 0 && font_filled == prev_font_filled) { num_chars_array[dst_pos]++; } else { num_chars_array[++dst_pos] = 1; for (count = font_filled - prev_font_filled; count > 1; count--) { num_chars_array[++dst_pos] = 0; } } prev_font_filled = font_filled; state->has_iscii = 1; } else { if (cs == ISO10646_UCS4_1) { has_ucs = 1; } num_chars_array[++dst_pos] = 1; } } if (state->size != dst_pos + 1) { void *p; if (!(p = realloc(state->num_chars_array, BL_MAX(dst_pos + 1, src_len) * sizeof(*num_chars_array)))) { return 0; } #ifdef __DEBUG if (p != state->num_chars_array) { bl_debug_printf(BL_DEBUG_TAG " REALLOC array %d(%p) -> %d(%p)\n", state->size, state->num_chars_array, dst_pos + 1, p); } #endif state->num_chars_array = p; state->size = dst_pos + 1; } memcpy(state->num_chars_array, num_chars_array, state->size * sizeof(*num_chars_array)); return (!state->has_iscii && has_ucs) ? -1 : 1; } int vt_iscii_copy(vt_iscii_state_t dst, vt_iscii_state_t src, int optimize) { u_int8_t *p; if (optimize && !src->has_iscii) { vt_iscii_destroy(dst); return -1; } else if (src->size == 0) { free(dst->num_chars_array); p = NULL; } else if ((p = realloc(dst->num_chars_array, sizeof(u_int8_t) * src->size))) { memcpy(p, src->num_chars_array, sizeof(u_int8_t) * src->size); } else { return 0; } dst->num_chars_array = p; dst->size = src->size; dst->has_iscii = src->has_iscii; return 1; } int vt_iscii_reset(vt_iscii_state_t state) { state->size = 0; return 1; } vt_isciikey_state_t vt_isciikey_state_new(int is_inscript) { vt_isciikey_state_t state; if ((state = malloc(sizeof(*state))) == NULL) { return NULL; } state->is_inscript = is_inscript; state->prev_key[0] = '\0'; return state; } void vt_isciikey_state_destroy(vt_isciikey_state_t state) { free(state); } size_t vt_convert_ascii_to_iscii(vt_isciikey_state_t state, u_char *iscii, size_t iscii_len, u_char *ascii, size_t ascii_len) { struct a2i_tabl *table; size_t size; u_char *dup; /* * ins2iscii() and iitk2iscii() return 2nd argument variable whose memory * is modified by converted iscii bytes. * So, enough memory (* A2IMAXBUFF) should be allocated here. */ if ((dup = alloca(ascii_len * A2IMAXBUFF)) == NULL) { goto no_conv; } if ((table = get_isciikey_table(state->is_inscript, &size)) == NULL) { goto no_conv; } strncpy(dup, ascii, ascii_len); dup[ascii_len] = '\0'; if (state->is_inscript) { bl_snprintf(iscii, iscii_len, "%s", ins2iscii(table, dup, size)); } else { bl_snprintf(iscii, iscii_len, "%s", iitk2iscii(table, dup, state->prev_key, size)); state->prev_key[0] = ascii[0]; state->prev_key[1] = '\0'; } return strlen(iscii); no_conv: memmove(iscii, ascii, iscii_len); return ascii_len; } mlterm-3.8.9/vtemu/libctl/vt_iscii.h010064400017600000144000000010361356600660700161350ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __CTL_VT_ISCII_H__ #define __CTL_VT_ISCII_H__ #include "../vt_iscii.h" #include #include "../vt_char.h" struct vt_iscii_state { u_int8_t *num_chars_array; u_int16_t size; int8_t has_iscii; }; u_int vt_iscii_shape(ef_charset_t cs, u_char *dst, size_t dst_size, u_char *src); vt_iscii_state_t vt_iscii_new(void); int vt_iscii_destroy(vt_iscii_state_t state); int vt_iscii(vt_iscii_state_t state, vt_char_t *src, u_int src_len); #endif mlterm-3.8.9/vtemu/libctl/vt_line_bidi.c010064400017600000144000000322411356600660700167500ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_line_bidi.h" #include /* memset */ #include #include /* alloca */ #define MSB32 0x80000000 /* --- static functions --- */ static void copy_char_with_mirror_check(vt_char_t *dst, vt_char_t *src, u_int16_t *visual_order, u_int16_t visual_order_size, int pos) { vt_char_copy(dst, src); if (((pos > 0 && visual_order[pos - 1] == visual_order[pos] + 1) || (pos + 1 < visual_order_size && visual_order[pos] == visual_order[pos + 1] + 1))) { /* * Pos is RTL character. * => XXX It is assumed that pos is always US_ASCII or ISO10646_UCS4_1. */ #if 0 ef_charset_t cs; if ((cs = vt_char_cs(dst)) == US_ASCII || cs == ISO10646_UCS4_1) #endif { u_int mirror; if ((mirror = vt_bidi_get_mirror_char(vt_char_code(dst)))) { vt_char_set_code(dst, mirror); } } } } static void set_visual_modified(vt_line_t *line, int logical_mod_beg, int logical_mod_end) { int log_pos; int visual_mod_beg; int visual_mod_end; /* same as 0 <= char_index < size */ if (((u_int)logical_mod_beg) >= line->ctl_info.bidi->size || ((u_int)logical_mod_end) >= line->ctl_info.bidi->size) { vt_line_set_modified_all(line); return; } visual_mod_beg = vt_line_end_char_index(line); visual_mod_end = 0; for (log_pos = logical_mod_beg; log_pos <= logical_mod_end; log_pos++) { int vis_pos = line->ctl_info.bidi->visual_order[log_pos]; if (vis_pos < visual_mod_beg) { visual_mod_beg = vis_pos; } if (vis_pos > visual_mod_end) { visual_mod_end = vis_pos; } } #if 0 bl_debug_printf("%p %d %d -> %d %d\n", line, logical_mod_beg, logical_mod_end, visual_mod_beg, visual_mod_end); #endif vt_line_set_updated(line); vt_line_set_modified(line, visual_mod_beg, visual_mod_end); } /* --- global functions --- */ int vt_line_set_use_bidi(vt_line_t *line, int flag) { if (flag) { if (vt_line_is_using_bidi(line)) { return 1; } else if (line->ctl_info_type != 0) { return 0; } if ((line->ctl_info.bidi = vt_bidi_new()) == NULL) { return 0; } line->ctl_info_type = VINFO_BIDI; } else { if (vt_line_is_using_bidi(line)) { vt_bidi_destroy(line->ctl_info.bidi); line->ctl_info_type = 0; } } return 1; } /* The caller should check vt_line_is_using_bidi() in advance. */ int vt_line_bidi_render(vt_line_t *line, /* is always modified */ vt_bidi_mode_t bidi_mode, const char *separators) { int ret; if (vt_line_is_real_modified(line)) { int base_was_rtl; base_was_rtl = BASE_IS_RTL(line->ctl_info.bidi); if ((ret = vt_bidi(line->ctl_info.bidi, line->chars, line->num_filled_chars, bidi_mode, separators)) <= 0) { if (base_was_rtl) { /* shifting RTL-base to LTR-base (which requires redrawing line all) */ vt_line_set_modified_all(line); } return ret; } /* Conforming line->change_{beg|end}_col to visual mode. */ if (base_was_rtl != BASE_IS_RTL(line->ctl_info.bidi)) { /* * shifting RTL-base to LTR-base or LTR-base to RTL-base. * (which requires redrawing line all) */ vt_line_set_modified_all(line); return 1; } } else { ret = 1; /* order is not changed */ } if (ret == 2) { /* order is changed => force to redraw all */ if (vt_line_get_end_of_modified(line) > vt_line_end_char_index(line)) { vt_line_set_modified_all(line); } else { vt_line_set_modified(line, 0, vt_line_end_char_index(line)); } } else if (HAS_RTL(line->ctl_info.bidi)) { set_visual_modified(line, vt_line_get_beg_of_modified(line), vt_line_get_end_of_modified(line)); } return 1; } /* The caller should check vt_line_is_using_bidi() in advance. */ int vt_line_bidi_visual(vt_line_t *line) { int count; vt_char_t *src; if (line->ctl_info.bidi->size == 0 || !HAS_RTL(line->ctl_info.bidi)) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Not need to visualize.\n"); #endif return 1; } if ((src = vt_str_alloca(line->ctl_info.bidi->size)) == NULL) { return 0; } vt_str_init(src, line->ctl_info.bidi->size); vt_str_copy(src, line->chars, line->ctl_info.bidi->size); for (count = 0; count < line->ctl_info.bidi->size; count++) { copy_char_with_mirror_check(line->chars + line->ctl_info.bidi->visual_order[count], src + count, line->ctl_info.bidi->visual_order, line->ctl_info.bidi->size, count); } vt_str_final(src, line->ctl_info.bidi->size); return 1; } /* The caller should check vt_line_is_using_bidi() in advance. */ int vt_line_bidi_logical(vt_line_t *line) { int count; vt_char_t *src; if (line->ctl_info.bidi->size == 0 || !HAS_RTL(line->ctl_info.bidi)) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Not need to logicalize.\n"); #endif return 0; } if ((src = vt_str_alloca(line->ctl_info.bidi->size)) == NULL) { return 0; } vt_str_init(src, line->ctl_info.bidi->size); vt_str_copy(src, line->chars, line->ctl_info.bidi->size); for (count = 0; count < line->ctl_info.bidi->size; count++) { copy_char_with_mirror_check(line->chars + count, src + line->ctl_info.bidi->visual_order[count], line->ctl_info.bidi->visual_order, line->ctl_info.bidi->size, count); } vt_str_final(src, line->ctl_info.bidi->size); /* * !! Notice !! * is_modified is as it is , which should not be touched here. */ return 1; } /* The caller should check vt_line_is_using_bidi() in advance. */ int vt_line_bidi_convert_logical_char_index_to_visual(vt_line_t *line, int char_index, u_int32_t *meet_pos_info) { if (((u_int)char_index) < line->ctl_info.bidi->size && /* same as 0 <= char_index < size */ HAS_RTL(line->ctl_info.bidi)) { if (meet_pos_info) { int count; *meet_pos_info &= ~MSB32; if (!BASE_IS_RTL(line->ctl_info.bidi) && char_index >= 1) { for (count = char_index - 2; count >= -1; count--) { /* * visual order -> 1 2 4 3 5 * ^ ^ ^- char index * | | * cursor position --+ +-- meet position * * visual order -> 1 2*5*4 3 6 * ^ ^ ^ ^- char index * | | * cursor position --+ +-- meet position * * visual order -> 1 2 3 6 5 4 7 * ^ ^ ^ ^- char index * | | * cursor position --+ +-- meet position */ #if 0 bl_debug_printf(" Normal pos %d - Current pos %d %d %d - Meet position info %d\n", line->ctl_info.bidi->visual_order[char_index], count >= 0 ? line->ctl_info.bidi->visual_order[count] : 0, line->ctl_info.bidi->visual_order[count + 1], line->ctl_info.bidi->visual_order[count + 2], *meet_pos_info); #endif if ((count < 0 || line->ctl_info.bidi->visual_order[count] < line->ctl_info.bidi->visual_order[count + 1]) && line->ctl_info.bidi->visual_order[count + 1] + 1 < line->ctl_info.bidi->visual_order[count + 2]) { /* * If meet position is not changed, text isn't changed * but cursor is moved. In this case cursor position should * not be fixed to visual_order[count + 1]. */ if (((*meet_pos_info) & ~MSB32) != line->ctl_info.bidi->visual_order[count + 1] + line->ctl_info.bidi->visual_order[count + 2]) { *meet_pos_info = line->ctl_info.bidi->visual_order[count + 1] + line->ctl_info.bidi->visual_order[count + 2]; if (line->ctl_info.bidi->visual_order[char_index] == line->ctl_info.bidi->visual_order[count + 2] + 1) { *meet_pos_info |= MSB32; return line->ctl_info.bidi->visual_order[count + 1]; } } break; } } if (count == 0) { *meet_pos_info = 0; } } else if (BASE_IS_RTL(line->ctl_info.bidi) && char_index >= 1) { for (count = char_index - 2; count >= -1; count--) { /* * visual order -> 6 5 4 2 3 1 * ^ ^ ^ ^- char index * | * +-- meet position & cursor position * visual order -> 7 6 5 2 3*4*1 * ^ ^ ^ ^- char index * | * +-- meet position & cursor position * * visual order -> 7 6 4 5 3 2 1 * ^ ^ ^- char index * | | * cursor position --+ +-- meet position * visual order -> 7 6 3 4*5*2 1 * ^ ^ ^- char index * | | * cursor position --+ +-- meet position */ #if 0 bl_debug_printf(" Normal pos %d - Current pos %d %d %d - Meet position info %d\n", line->ctl_info.bidi->visual_order[char_index], count >= 0 ? line->ctl_info.bidi->visual_order[count] : 0, line->ctl_info.bidi->visual_order[count + 1], line->ctl_info.bidi->visual_order[count + 2], *meet_pos_info); #endif if ((count < 0 || line->ctl_info.bidi->visual_order[count] > line->ctl_info.bidi->visual_order[count + 1]) && line->ctl_info.bidi->visual_order[count + 1] > line->ctl_info.bidi->visual_order[count + 2] + 1) { /* * If meet position is not changed, text isn't changed * but cursor is moved. In this case cursor position should * not be fixed to visual_order[count + 1]. */ if (((*meet_pos_info) & ~MSB32) != line->ctl_info.bidi->visual_order[count + 1] + line->ctl_info.bidi->visual_order[count + 2]) { *meet_pos_info = line->ctl_info.bidi->visual_order[count + 1] + line->ctl_info.bidi->visual_order[count + 2]; if (line->ctl_info.bidi->visual_order[char_index] + 1 == line->ctl_info.bidi->visual_order[count + 2]) { *meet_pos_info |= MSB32; return line->ctl_info.bidi->visual_order[count + 1]; } } break; } } if (count == 0) { *meet_pos_info = 0; } } else { *meet_pos_info = 0; } } return line->ctl_info.bidi->visual_order[char_index]; } else { if (meet_pos_info) { *meet_pos_info = 0; } return char_index; } } /* * This function is used only by a loader of this module (not used inside this * module), * so it is assumed that vt_line_is_using_bidi() was already checked (otherwise * this * module can be loaded unnecessarily). */ int vt_line_bidi_convert_visual_char_index_to_logical(vt_line_t *line, int char_index) { u_int count; for (count = 0; count < line->ctl_info.bidi->size; count++) { if (line->ctl_info.bidi->visual_order[count] == char_index) { return count; } } return char_index; } /* * This function is used only by a loader of this module (not used inside this * module), * so it is assumed that vt_line_is_using_bidi() was already checked (otherwise * this * module can be loaded unnecessarily). */ int vt_line_bidi_is_rtl(vt_line_t *line) { return BASE_IS_RTL(line->ctl_info.bidi); } int vt_line_bidi_need_shape(vt_line_t *line) { return HAS_RTL(line->ctl_info.bidi); } /* * This function is used only by a loader of this module (not used inside this * module), * so it is assumed that vt_line_is_using_bidi() was already checked. */ int vt_line_bidi_copy_logical_str(vt_line_t *line, vt_char_t *dst, int beg, /* visual position */ u_int len) { /* * XXX * adhoc implementation. */ int *flags; int bidi_pos; int norm_pos; int dst_pos; if (line->ctl_info.bidi->size == 0) { return 0; } if ((flags = alloca(sizeof(int) * line->ctl_info.bidi->size)) == NULL) { return 0; } memset(flags, 0, sizeof(int) * line->ctl_info.bidi->size); for (bidi_pos = beg; bidi_pos < beg + len; bidi_pos++) { for (norm_pos = 0; norm_pos < line->ctl_info.bidi->size; norm_pos++) { if (line->ctl_info.bidi->visual_order[norm_pos] == bidi_pos) { flags[norm_pos] = 1; } } } for (dst_pos = norm_pos = 0; norm_pos < line->ctl_info.bidi->size; norm_pos++) { if (flags[norm_pos]) { copy_char_with_mirror_check( &dst[dst_pos++], line->chars + line->ctl_info.bidi->visual_order[norm_pos], line->ctl_info.bidi->visual_order, line->ctl_info.bidi->size, norm_pos); } } return 1; } mlterm-3.8.9/vtemu/libctl/vt_line_bidi.h010064400017600000144000000012421356600660700167520ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_LINE_BIDI_H__ #define __VT_LINE_BIDI_H__ #include "../vt_line.h" #include "vt_bidi.h" /* vt_bidi_mode_t */ #define vt_line_is_using_bidi(line) ((line)->ctl_info_type == VINFO_BIDI) int vt_line_set_use_bidi(vt_line_t *line, int flag); int vt_line_bidi_render(vt_line_t *line, vt_bidi_mode_t bidi_mode, const char *separators); int vt_line_bidi_visual(vt_line_t *line); int vt_line_bidi_logical(vt_line_t *line); int vt_line_bidi_convert_logical_char_index_to_visual(vt_line_t *line, int char_index, u_int32_t *meet_pos_info); #endif mlterm-3.8.9/vtemu/libctl/vt_line_iscii.c010064400017600000144000000147361356600660700171520ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_line_iscii.h" #include /* NULL */ #include #include "vt_iscii.h" /* --- global functions --- */ int vt_line_set_use_iscii(vt_line_t *line, int flag) { if (flag) { if (vt_line_is_using_iscii(line)) { return 1; } else if (line->ctl_info_type != 0) { return 0; } if ((line->ctl_info.iscii = vt_iscii_new()) == NULL) { return 0; } line->ctl_info_type = VINFO_ISCII; } else { if (vt_line_is_using_iscii(line)) { vt_iscii_destroy(line->ctl_info.iscii); line->ctl_info_type = 0; } } return 1; } /* The caller should check vt_line_is_using_iscii() in advance. */ int vt_line_iscii_render(vt_line_t *line /* is always visual */ ) { int ret; int visual_mod_beg; /* * Lower case: ASCII * Upper case: ISCII * (Logical) AAA == (Visual) BBBBB * => (Logical) aaa == (Visual) aaa * In this case vt_line_is_cleared_to_end() returns 0, so "BB" remains on * the screen unless following vt_line_set_modified(). */ visual_mod_beg = vt_line_get_beg_of_modified(line); if (line->ctl_info.iscii->has_iscii) { visual_mod_beg = vt_line_iscii_convert_logical_char_index_to_visual(line, visual_mod_beg); } if (vt_line_is_real_modified(line)) { if ((ret = vt_iscii(line->ctl_info.iscii, line->chars, line->num_filled_chars)) <= 0) { return ret; } if (line->ctl_info.iscii->has_iscii) { int beg; if ((beg = vt_line_iscii_convert_logical_char_index_to_visual( line, vt_line_get_beg_of_modified(line))) < visual_mod_beg) { visual_mod_beg = beg; } } /* * Conforming line->change_{beg|end}_col to visual mode. * If this line contains ISCII chars, it should be redrawn to the end of * line. */ vt_line_set_modified(line, visual_mod_beg, line->num_chars); } else { vt_line_set_modified(line, visual_mod_beg, vt_line_iscii_convert_logical_char_index_to_visual( line, vt_line_get_end_of_modified(line))); } return 1; } /* The caller should check vt_line_is_using_iscii() in advance. */ int vt_line_iscii_visual(vt_line_t *line) { vt_char_t *src; u_int src_len; vt_char_t *dst; u_int dst_len; int dst_pos; int src_pos; if (line->ctl_info.iscii->size == 0 || !line->ctl_info.iscii->has_iscii) { #ifdef __DEBUG bl_warn_printf(BL_DEBUG_TAG " Not need to visualize.\n"); #endif return 1; } src_len = line->num_filled_chars; if ((src = vt_str_alloca(src_len)) == NULL) { return 0; } vt_str_init(src, src_len); vt_str_copy(src, line->chars, src_len); dst_len = line->ctl_info.iscii->size; if (line->num_chars < dst_len) { vt_char_t *chars; if ((chars = vt_str_new(dst_len))) { /* XXX => shrunk at vt_screen.c and vt_logical_visual_ctl.c */ vt_str_destroy(line->chars, line->num_chars); line->chars = chars; line->num_chars = dst_len; } else { line->ctl_info.iscii->size = dst_len = line->num_chars; } } dst = line->chars; src_pos = 0; for (dst_pos = 0; dst_pos < dst_len; dst_pos++) { if (line->ctl_info.iscii->num_chars_array[dst_pos] == 0) { vt_char_copy(dst + dst_pos, vt_get_base_char(src + src_pos - 1)); /* NULL */ vt_char_set_code(dst + dst_pos, 0); } else { u_int count; vt_char_copy(dst + dst_pos, src + (src_pos++)); for (count = 1; count < line->ctl_info.iscii->num_chars_array[dst_pos]; count++) { vt_char_t *comb; u_int num; #ifdef DEBUG if (vt_char_is_comb(vt_get_base_char(src + src_pos))) { bl_debug_printf(BL_DEBUG_TAG " illegal iscii\n"); } #endif vt_char_combine_simple(dst + dst_pos, vt_get_base_char(src + src_pos)); comb = vt_get_combining_chars(src + (src_pos++), &num); for (; num > 0; num--) { #ifdef DEBUG if (!vt_char_is_comb(comb)) { bl_debug_printf(BL_DEBUG_TAG " illegal iscii\n"); } #endif vt_char_combine_simple(dst + dst_pos, comb++); } } } } #ifdef DEBUG if (src_pos != src_len) { bl_debug_printf(BL_DEBUG_TAG "vt_line_iscii_visual() failed: %d -> %d\n", src_len, src_pos); } #endif vt_str_final(src, src_len); line->num_filled_chars = dst_pos; return 1; } /* The caller should check vt_line_is_using_iscii() in advance. */ int vt_line_iscii_logical(vt_line_t *line) { vt_char_t *src; u_int src_len; vt_char_t *dst; int src_pos; if (line->ctl_info.iscii->size == 0 || !line->ctl_info.iscii->has_iscii) { #ifdef __DEBUG bl_warn_printf(BL_DEBUG_TAG " Not need to logicalize.\n"); #endif return 1; } src_len = line->num_filled_chars; if ((src = vt_str_alloca(src_len)) == NULL) { return 0; } vt_str_init(src, src_len); vt_str_copy(src, line->chars, src_len); dst = line->chars; for (src_pos = 0; src_pos < line->ctl_info.iscii->size; src_pos++) { vt_char_t *comb; u_int num; if (line->ctl_info.iscii->num_chars_array[src_pos] == 0) { continue; } else if (line->ctl_info.iscii->num_chars_array[src_pos] == 1) { vt_char_copy(dst, src + src_pos); } else { vt_char_copy(dst, vt_get_base_char(src + src_pos)); comb = vt_get_combining_chars(src + src_pos, &num); for (; num > 0; num--, comb++) { if (vt_char_is_comb(comb)) { vt_char_combine_simple(dst, comb); } else { vt_char_copy(++dst, comb); } } } dst++; } vt_str_final(src, src_len); line->num_filled_chars = dst - line->chars; return 1; } /* The caller should check vt_line_is_using_iscii() in advance. */ int vt_line_iscii_convert_logical_char_index_to_visual(vt_line_t *line, int logical_char_index) { int visual_char_index; if (vt_line_is_empty(line)) { return 0; } if (line->ctl_info.iscii->size == 0 || !line->ctl_info.iscii->has_iscii) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " logical char_index is same as visual one.\n"); #endif return logical_char_index; } for (visual_char_index = 0; visual_char_index < line->ctl_info.iscii->size; visual_char_index++) { if (logical_char_index == 0 || (logical_char_index -= line->ctl_info.iscii->num_chars_array[visual_char_index]) < 0) { break; } } return visual_char_index; } int vt_line_iscii_need_shape(vt_line_t *line) { return line->ctl_info.iscii->size > 0 && line->ctl_info.iscii->has_iscii; } mlterm-3.8.9/vtemu/libctl/vt_line_iscii.h010064400017600000144000000010071356600660700171420ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_LINE_ISCII_H__ #define __VT_LINE_ISCII_H__ #include "../vt_line.h" #define vt_line_is_using_iscii(line) ((line)->ctl_info_type == VINFO_ISCII) int vt_line_set_use_iscii(vt_line_t *line, int flag); int vt_line_iscii_render(vt_line_t *line); int vt_line_iscii_visual(vt_line_t *line); int vt_line_iscii_logical(vt_line_t *line); int vt_line_iscii_convert_logical_char_index_to_visual(vt_line_t *line, int logical_char_index); #endif mlterm-3.8.9/vtemu/libctl/vt_shape_bidi.c010064400017600000144000000235071356600660700171260ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../vt_shape.h" #include /* strncpy */ #include /* alloca */ #include /* bl_msg_printf */ typedef struct arabic_present { u_int16_t base_arabic; /* presentations. right or left is visual order's one. */ u_int16_t no_joining_present; u_int16_t right_joining_present; u_int16_t left_joining_present; u_int16_t both_joining_present; } arabic_present_t; typedef struct arabic_comb { /* first or second is logical order's one */ u_int16_t first; u_int16_t second; u_int16_t comb; u_int16_t comb_right; } arabic_comb_t; /* --- static variables --- */ static arabic_present_t arabic_present_table[] = { { 0x0621, 0xFE80, 0x0000, 0x0000, 0x0000, }, { 0x0622, 0xFE81, 0xFE82, 0x0000, 0x0000, }, { 0x0623, 0xFE83, 0xFE84, 0x0000, 0x0000, }, { 0x0624, 0xFE85, 0xFE86, 0x0000, 0x0000, }, { 0x0625, 0xFE87, 0xFE88, 0x0000, 0x0000, }, { 0x0626, 0xFE89, 0xFE8A, 0xFE8B, 0xFE8C, }, { 0x0627, 0xFE8D, 0xFE8E, 0x0000, 0x0000, }, { 0x0628, 0xFE8F, 0xFE90, 0xFE91, 0xFE92, }, { 0x0629, 0xFE93, 0xFE94, 0x0000, 0x0000, }, { 0x062A, 0xFE95, 0xFE96, 0xFE97, 0xFE98, }, { 0x062B, 0xFE99, 0xFE9A, 0xFE9B, 0xFE9C, }, { 0x062C, 0xFE9D, 0xFE9E, 0xFE9F, 0xFEA0, }, { 0x062D, 0xFEA1, 0xFEA2, 0xFEA3, 0xFEA4, }, { 0x062E, 0xFEA5, 0xFEA6, 0xFEA7, 0xFEA8, }, { 0x062F, 0xFEA9, 0xFEAA, 0x0000, 0x0000, }, { 0x0630, 0xFEAB, 0xFEAC, 0x0000, 0x0000, }, { 0x0631, 0xFEAD, 0xFEAE, 0x0000, 0x0000, }, { 0x0632, 0xFEAF, 0xFEB0, 0x0000, 0x0000, }, { 0x0633, 0xFEB1, 0xFEB2, 0xFEB3, 0xFEB4, }, { 0x0634, 0xFEB5, 0xFEB6, 0xFEB7, 0xFEB8, }, { 0x0635, 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC, }, { 0x0636, 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0, }, { 0x0637, 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4, }, { 0x0638, 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8, }, { 0x0639, 0xFEC9, 0xFECA, 0xFECB, 0xFECC, }, { 0x063A, 0xFECD, 0xFECE, 0xFECF, 0xFED0, }, { 0x0640, 0x0640, 0x0640, 0x0640, 0x0640, }, { 0x0641, 0xFED1, 0xFED2, 0xFED3, 0xFED4, }, { 0x0642, 0xFED5, 0xFED6, 0xFED7, 0xFED8, }, { 0x0643, 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC, }, { 0x0644, 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0, }, { 0x0645, 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4, }, { 0x0646, 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8, }, { 0x0647, 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC, }, { 0x0648, 0xFEED, 0xFEEE, 0x0000, 0x0000, }, { 0x0649, 0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9, }, { 0x064A, 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4, }, { 0x0671, 0xFB50, 0xFB51, 0x0000, 0x0000, }, { 0x0679, 0xFB66, 0xFB67, 0xFB68, 0xFB69, }, { 0x067A, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61, }, { 0x067B, 0xFB52, 0xFB53, 0xFB54, 0xFB55, }, { 0x067E, 0xFB56, 0xFB57, 0xFB58, 0xFB59, }, { 0x067F, 0xFB62, 0xFB63, 0xFB64, 0xFB65, }, { 0x0680, 0xFB5A, 0xFB5B, 0xFB5C, 0xFB5D, }, { 0x0683, 0xFB76, 0xFB77, 0xFB78, 0xFB79, }, { 0x0684, 0xFB72, 0xFB73, 0xFB74, 0xFB75, }, { 0x0686, 0xFB7A, 0xFB7B, 0xFB7C, 0xFB7D, }, { 0x0687, 0xFB7E, 0xFB7F, 0xFB80, 0xFB81, }, { 0x0688, 0xFB88, 0xFB89, 0x0000, 0x0000, }, { 0x068C, 0xFB84, 0xFB85, 0x0000, 0x0000, }, { 0x068D, 0xFB82, 0xFB83, 0x0000, 0x0000, }, { 0x068E, 0xFB86, 0xFB87, 0x0000, 0x0000, }, { 0x0691, 0xFB8C, 0xFB8D, 0x0000, 0x0000, }, { 0x0698, 0xFB8A, 0xFB8B, 0x0000, 0x0000, }, { 0x06A4, 0xFB6A, 0xFB6B, 0xFB6C, 0xFB6D, }, { 0x06A6, 0xFB6E, 0xFB6F, 0xFB70, 0xFB71, }, { 0x06A9, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, }, { 0x06AD, 0xFBD3, 0xFBD4, 0xFBD5, 0xFBD6, }, { 0x06AF, 0xFB92, 0xFB93, 0xFB94, 0xFB95, }, { 0x06B1, 0xFB9A, 0xFB9B, 0xFB9C, 0xFB9D, }, { 0x06B3, 0xFB96, 0xFB97, 0xFB98, 0xFB99, }, { 0x06BB, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3, }, { 0x06BE, 0xFBAA, 0xFBAB, 0xFBAC, 0xFBAD, }, { 0x06C0, 0xFBA4, 0xFBA5, 0x0000, 0x0000, }, { 0x06C1, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9, }, { 0x06C5, 0xFBE0, 0xFBE1, 0x0000, 0x0000, }, { 0x06C6, 0xFBD9, 0xFBDA, 0x0000, 0x0000, }, { 0x06C7, 0xFBD7, 0xFBD8, 0x0000, 0x0000, }, { 0x06C8, 0xFBDB, 0xFBDC, 0x0000, 0x0000, }, { 0x06C9, 0xFBE2, 0xFBE3, 0x0000, 0x0000, }, { 0x06CB, 0xFBDE, 0xFBDF, 0x0000, 0x0000, }, { 0x06CC, 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF, }, { 0x06D0, 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7, }, { 0x06D2, 0xFBAE, 0xFBAF, 0x0000, 0x0000, }, { 0x06D3, 0xFBB0, 0xFBB1, 0x0000, 0x0000, }, }; static arabic_comb_t arabic_comb_table[] = { { 0x0644, 0x0622, 0xFEF5, 0xFEF6, }, { 0x0644, 0x0623, 0xFEF7, 0xFEF8, }, { 0x0644, 0x0625, 0xFEF9, 0xFEFA, }, { 0x0644, 0x0627, 0xFEFB, 0xFEFC, }, }; /* --- static functions --- */ static arabic_present_t *get_arabic_present(vt_char_t *ch) { u_int16_t code; int count; if (vt_char_cs(ch) == ISO10646_UCS4_1) { code = vt_char_code(ch); } else { return NULL; } for (count = 0; count < sizeof(arabic_present_table) / sizeof(arabic_present_table[0]); count++) { if (arabic_present_table[count].base_arabic == code) { return &arabic_present_table[count]; } } return NULL; } /* --- global functions --- */ /* * 'src' characters are right to left (visual) order. */ u_int vt_shape_arabic(vt_char_t *dst, u_int dst_len, vt_char_t *src, u_int src_len) { int count; arabic_present_t **list; u_int16_t code; vt_char_t *comb; vt_char_t *cur; vt_char_t *next; /* the same as 'prev' in logical order */ u_int size; if ((list = alloca(sizeof(arabic_present_t*) * (src_len + 2))) == NULL) { return 0; } /* head is NULL */ *(list++) = NULL; for (count = 0; count < src_len; count++) { list[count] = get_arabic_present(&src[count]); } /* tail is NULL */ list[count] = NULL; cur = src; if (src_len <= 1) { next = NULL; } else { next = cur + 1; } for (count = 0; count < src_len && count < dst_len; count++) { comb = vt_get_combining_chars(cur, &size); if (comb && (code = vt_is_arabic_combining(count + 1 >= src_len ? NULL : &src[count + 1], vt_get_base_char(cur), comb))) { vt_char_copy(&dst[count], vt_get_base_char(cur)); vt_char_set_code(&dst[count], code); } else if (list[count]) { #if 0 /* * Tanween characters combining their proceeded characters will * be ignored by vt_get_base_char(cur). */ vt_char_copy(&dst[count], vt_get_base_char(cur)); #else vt_char_copy(&dst[count], cur); #endif if (list[count - 1] && list[count - 1]->right_joining_present) { if ((list[count + 1] && list[count + 1]->left_joining_present) && !(next && (comb = vt_get_combining_chars(next, &size)) && vt_is_arabic_combining(count + 2 >= src_len ? NULL : &src[count + 2], vt_get_base_char(next), comb))) { if (list[count]->both_joining_present) { code = list[count]->both_joining_present; } else if (list[count]->left_joining_present) { code = list[count]->left_joining_present; } else if (list[count]->right_joining_present) { code = list[count]->right_joining_present; } else { code = list[count]->no_joining_present; } } else if (list[count]->left_joining_present) { code = list[count]->left_joining_present; } else { code = list[count]->no_joining_present; } } else if ((list[count + 1] && list[count + 1]->left_joining_present) && !(next && (comb = vt_get_combining_chars(next, &size)) && vt_is_arabic_combining(count + 2 >= src_len ? NULL : &src[count + 2], vt_get_base_char(next), comb))) { if (list[count]->right_joining_present) { code = list[count]->right_joining_present; } else { code = list[count]->no_joining_present; } } else { code = list[count]->no_joining_present; } if (code) { vt_char_set_code(&dst[count], code); } } else { vt_char_copy(&dst[count], cur); } cur = next; next++; } return count; } u_int16_t vt_is_arabic_combining(vt_char_t *prev2, /* can be NULL */ vt_char_t *prev, /* must be ISO10646_UCS4_1 character */ vt_char_t *ch /* must be ISO10646_UCS4_1 character */ ) { vt_char_t *seq[4]; /* reverse order */ u_int16_t ucs_seq[4]; /* reverse order */ int count; int prev2_is_comb; arabic_present_t *prev2_present; seq[0] = ch; seq[1] = prev; seq[2] = prev2; seq[3] = NULL; if (prev2) { vt_char_t *comb; u_int size; prev2_present = get_arabic_present(prev2); if ((comb = vt_get_combining_chars(prev2, &size))) { seq[3] = vt_get_base_char(prev2); seq[2] = comb; } } else { prev2_present = NULL; } for (count = 0; count < 4; count++) { if (seq[count] && vt_char_cs(seq[count]) == ISO10646_UCS4_1) { ucs_seq[count] = vt_char_code(seq[count]); } else if (count < 2) { /* Ignore the previous combinational/two characters */ return 0; } else { ucs_seq[count] = 0; } } prev2_is_comb = 0; if (seq[3] && prev2_present) { /* See if the current character was proceeded by combinational character */ for (count = 0; count < sizeof(arabic_comb_table) / sizeof(arabic_comb_table[0]); count++) { if ((ucs_seq[3] == arabic_comb_table[count].first && ucs_seq[2] == arabic_comb_table[count].second)) { prev2_is_comb = 1; break; } } } /* Shape the current combinational character */ for (count = 0; count < sizeof(arabic_comb_table) / sizeof(arabic_comb_table[0]); count++) { if (ucs_seq[1] == arabic_comb_table[count].first && ucs_seq[0] == arabic_comb_table[count].second) { if (!prev2_is_comb && prev2_present && prev2_present->left_joining_present) { return arabic_comb_table[count].comb_right; } else { return arabic_comb_table[count].comb; } } } return 0; } mlterm-3.8.9/vtemu/libctl/Makefile.in010064400017600000144000000037031356600660700162230ustar kenuserstop_builddir = ../.. top_srcdir = @top_srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ libdir = @libdir@ LIBDIR = $(DESTDIR)$(libdir)/mlterm VPATH = ${top_srcdir}/vtemu/libctl CFLAGS = $(CFLAGS_LOCAL) @DEB_CFLAGS@ @POBL_CFLAGS@ @MEF_CFLAGS@ \ @FRIBIDI_CFLAGS@ @IND_CFLAGS@ @CTL_CFLAGS@ @CFLAGS@ @CPPFLAGS@ \ -I/usr/local/include -DLIBDIR=\"$(libdir)\" \ LIBS = $(LIBS_LOCAL) @LPOBL@ LIBS_BIDI = @FRIBIDI_LIBS@ LIBS_ISCII = ../../libind/indian.lo ../../libind/keyboard.lo ../../libind/lex.split.lo BIDI_OBJ = vt_bidi.o vt_line_bidi.o vt_shape_bidi.o ISCII_OBJ = vt_iscii.o vt_line_iscii.o vt_shape_iscii.o CC = @CC@ INSTALL = @INSTALL@ LIBTOOL = @LIBTOOL@ LIBTOOL_CC = $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) all: @CTL_LIBS@ libctl_bidi.la: $(BIDI_OBJ) vt_functbl_bidi.o $(LIBTOOL_LINK) -o libctl_bidi.la $(BIDI_OBJ:.o=.lo) vt_functbl_bidi.lo \ -rpath $(libdir)/mlterm \ -module -avoid-version @NO_UNDEFINED_FLAG@ @DEXPORT@ ../@LMLTERM_CORE@ \ $(LIBS) $(LIBS_BIDI) libctl_iscii.la: $(ISCII_OBJ) vt_functbl_iscii.o $(LIBTOOL_LINK) -o libctl_iscii.la $(ISCII_OBJ:.o=.lo) vt_functbl_iscii.lo \ -rpath $(libdir)/mlterm \ -module -avoid-version @NO_UNDEFINED_FLAG@ @DEXPORT@ ../@LMLTERM_CORE@ \ $(LIBS) $(LIBS_ISCII) libctl_bidi.a: $(BIDI_OBJ) $(LIBTOOL_LINK) -o libctl_bidi.a $(BIDI_OBJ:.o=.lo) libctl_iscii.a: $(ISCII_OBJ) $(LIBTOOL_LINK) -o libctl_iscii.a $(ISCII_OBJ:.o=.lo) $(LIBS_ISCII) .SUFFIXES: .o .c .c.o: $(LIBTOOL_CC) -c $(CFLAGS) $< $(LIBDIR): mkdir -p $(LIBDIR) install: $(LIBDIR) if test "`echo @CTL_LIBS@|grep .la`" != "" ; then \ $(LIBTOOL_INSTALL) @CTL_LIBS@ $(LIBDIR) ; \ fi uninstall: rm -f $(LIBDIR)/*ctl_bidi.* $(LIBDIR)/*ctl_iscii.* clean: rm -rf $(BIDI_OBJ) $(BIDI_OBJ:.o=.lo) $(ISCII_OBJ) $(ISCII_OBJ:.o=.lo) \ vt_functbl_*.o vt_functbl_*.lo libctl_bidi.* libctl_iscii.* .libs distclean: clean rm -f Makefile mlterm-3.8.9/vtemu/libptymosh004075500017600000144000000000001356600660700150205ustar kenusersmlterm-3.8.9/vtemu/libptymosh/COPYING010064400017600000144000001045131356600660700161330ustar kenusers GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . mlterm-3.8.9/vtemu/libptymosh/Makefile.in010064400017600000144000000050411356600660700171410ustar kenuserstop_builddir = ../.. top_srcdir = @top_srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ libdir = @libdir@ LIBDIR = $(DESTDIR)$(libdir)/mlterm MOSH_DIR = @MOSH_DIR@ VPATH = ${top_srcdir}/vtemu/libptymosh:$(MOSH_DIR)/src/network:$(MOSH_DIR)/src/crypto:$(MOSH_DIR)/src/terminal:$(MOSH_DIR)/src/util:$(MOSH_DIR)/src/statesync:$(MOSH_DIR)/src/protobufs:$(MOSH_DIR)/src/frontend CFLAGS = $(CFLAGS_LOCAL) -D_GNU_SOURCE @DEB_CFLAGS@ @POBL_CFLAGS@ @MEF_CFLAGS@ @CFLAGS@ @CPPFLAGS@ \ -pthread @PROTOBUF_CFLAGS@ -I/usr/local/include -DLIBDIR=\"$(libdir)\" \ -I$(MOSH_DIR) -I$(MOSH_DIR)/src/protobufs -I$(MOSH_DIR)/src/crypto -I$(MOSH_DIR)/src/network \ -I$(MOSH_DIR)/src/util -I$(MOSH_DIR)/src/terminal -I$(MOSH_DIR)/src/statesync \ -I$(MOSH_DIR)/src/frontend LIBS = $(LIBS_LOCAL) @LPOBL@ ../libptyssh/libptyssh.la -pthread @PROTOBUF_LIBS@ -lz -lcrypto PROTO = userinput.pb.cc hostinput.pb.cc transportinstruction.pb.cc OBJ = vt_pty_mosh.o compressor.o network.o transportfragment.o base64.o crypto.o ocb.o \ parser.o parseraction.o parserstate.o terminal.o terminaldispatcher.o terminaldisplay.o \ terminaldisplayinit.o terminalframebuffer.o terminalfunctions.o terminaluserinput.o \ timestamp.o completeterminal.o user.o terminaloverlay.o $(PROTO:.cc=.o) CC = @CXX@ INSTALL = @INSTALL@ LIBTOOL = @LIBTOOL@ LIBTOOL_CC = $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) all: $(PROTO) libptymosh.la userinput.pb.cc: protoc --cpp_out=$(MOSH_DIR)/src/protobufs -I$(MOSH_DIR)/src/protobufs $(MOSH_DIR)/src/protobufs/userinput.proto cp $(MOSH_DIR)/src/protobufs/userinput.pb.* . hostinput.pb.cc: protoc --cpp_out=$(MOSH_DIR)/src/protobufs -I$(MOSH_DIR)/src/protobufs $(MOSH_DIR)/src/protobufs/hostinput.proto cp $(MOSH_DIR)/src/protobufs/hostinput.pb.* . transportinstruction.pb.cc: protoc --cpp_out=$(MOSH_DIR)/src/protobufs -I$(MOSH_DIR)/src/protobufs $(MOSH_DIR)/src/protobufs/transportinstruction.proto cp $(MOSH_DIR)/src/protobufs/transportinstruction.pb.* . libptymosh.la: $(OBJ) $(LIBTOOL_LINK) -pthread -o libptymosh.la $(OBJ:.o=.lo) \ -rpath $(libdir)/mlterm -module -avoid-version @NO_UNDEFINED_FLAG@ \ $(LIBS) .SUFFIXES: .o .cpp .cc .cpp.o: $(LIBTOOL_CC) -c $(CFLAGS) $< .cc.o: $(LIBTOOL_CC) -c $(CFLAGS) $< $(LIBDIR): mkdir -p $(LIBDIR) install: $(LIBDIR) $(LIBTOOL_INSTALL) libptymosh.la $(LIBDIR) uninstall: rm -f $(LIBDIR)/*ptymosh.* clean: rm -rf $(OBJ) $(OBJ:.o=.lo) $(PROTO) $(PROTO:.cc=.h) *ptymosh.* .libs distclean: clean rm -f Makefile mlterm-3.8.9/vtemu/libptymosh/terminaldisplayinit.cc010064400017600000144000000012041356600660700214650ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include using namespace Terminal; bool Display::ti_flag(const char *capname) { return true; } int Display::ti_num(const char *capname) { return 0; } const char *Display::ti_str(const char *capname) { return ""; } Display::Display(bool use_environment) : has_ech(true), has_bce(true) /* XXX */, has_title(true), /* * smcup and rmcup are used in Display::open() and Display::close(). * It is unnecessary for mlterm to use alternate screen for mosh, * so both smcup and rmcup are NULL. */ smcup(NULL), rmcup(NULL) { } mlterm-3.8.9/vtemu/libptymosh/vt_pty_mosh.cpp010064400017600000144000001041331356600660700201550ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ extern "C" { #define USE_LIBSSH2 #define USE_MOSH #include "../vt_pty_intern.h" #include /* sprintf */ #include /* close */ #include /* strchr/memcpy */ #include #include #include #ifdef USE_WIN32API #include /* inet_ntoa (winsock2.h should be included before windows.h) */ #include #else #include #include /* inet_ntoa */ #endif #ifdef __CYGWIN__ #include /* waitpid */ #endif #include #include /* malloc */ #include /* bl_basename */ #include #include #include /* bl_str_replace */ #include #include #ifndef USE_WIN32API #define _XOPEN_SOURCE #include /* wcwidth */ #endif } #include #include #include #include #include #include #include #include #if 0 #define __DEBUG #endif #if 0 #define TEST_BY_SSH #endif /* * Following 3 steps allow you to use original terminaldisplayinit.cc. * 1) Remove terminaldisplayinit.cc here. * 2) #if 0 => #if 1 (define USE_ORIG_TERMINALDISPLAYINIT * 3) Add -lncursesw to Makefile.in */ #if 0 #define USE_ORIG_TERMINALDISPLAYINIT #endif typedef struct vt_pty_mosh { vt_pty_t pty; Terminal::Complete complete; Terminal::Framebuffer framebuffer; Network::Transport *network; Terminal::Display display; Overlay::OverlayManager *overlay; bool initialized; char *buf; size_t buf_len; bool ready; bool quit_sequence_started; bool lf_entered; /* bool escape_requires_lf; */ } vt_pty_mosh_t; /* --- static variables --- */ static vt_pty_mosh_t **ptys; static u_int num_ptys; static Network::Transport *dead_network; #ifdef MOSH_SIXEL /* for establish_tcp_connection */ static Network::Transport *cur_network; #endif #ifdef USE_WIN32API static int full_width_prop = -1; static void (*trigger_pty_read)(void); #else static int event_fds[2]; #endif static int event_in_pipe; static pthread_cond_t event_cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER; static int escape_key = 0x1e; static int escape_pass_key = '^'; static int escape_pass_key2 = '^'; static std::wstring escape_key_help = #ifdef MOSH_SIXEL L"Commands: \".\" quits, \",\" resets, \"^\" gives literal Ctrl-^"; #else L"Commands: \".\" quits, \"^\" gives literal Ctrl-^"; #endif static bool escape_requires_lf = false; /* --- static functions --- */ #ifdef MOSH_SIXEL void establish_tcp_connection(int port) { if (port <= 0 || cur_network->tcp_sock >= 0) { return; } cur_network->tcp_sock = tcp_connect(cur_network->get_remote_addr().sin.sin_addr.s_addr, port); if (cur_network->tcp_sock < 0) { bl_error_printf("Failed to connect to mosh server via tcp to send/recv zmodem packets.\n"); } } #endif #ifdef USE_WIN32API int wcwidth(wchar_t ch) { ef_property_t prop = ef_get_ucs_property(ch); if (full_width_prop == -1) { char *env = getenv("MOSH_AWIDTH"); if (env && *env == '2') { full_width_prop = EF_FULLWIDTH | EF_AWIDTH; } else { full_width_prop = EF_FULLWIDTH; } } if (prop & full_width_prop) { return 2; } else if (prop & EF_COMBINING) { return 0; } else { return 1; } } /* Same as vt_pty_ssh.cpp */ static ssize_t lo_recv_pty(vt_pty_t *pty, u_char *buf, size_t len) { return recv(pty->master, (char*)buf, len, 0); } /* Same as vt_pty_ssh.cpp */ static ssize_t lo_send_to_pty(vt_pty_t *pty, u_char *buf, size_t len) { return send(pty->slave, (char*)buf, len, 0); } /* Same as vt_pty_ssh.cpp */ static int _socketpair(int af, int type, int proto, SOCKET sock[2]) { SOCKET listen_sock; SOCKADDR_IN addr; int addr_len; if ((listen_sock = WSASocket(af, type, proto, NULL, 0, 0)) == INVALID_SOCKET) { return -1; } addr_len = sizeof(addr); memset((void *)&addr, 0, sizeof(addr)); addr.sin_family = af; addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = 0; if (bind(listen_sock, (SOCKADDR *)&addr, addr_len) != 0) { goto error1; } if (getsockname(listen_sock, (SOCKADDR *)&addr, &addr_len) != 0) { goto error1; } if (listen(listen_sock, 1) != 0) { goto error1; } /* select() and receive() can call simultaneously on java. */ if ((sock[0] = WSASocket(af, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { goto error1; } if (connect(sock[0], (SOCKADDR *)&addr, addr_len) != 0) { goto error2; } if ((sock[1] = accept(listen_sock, 0, 0)) == INVALID_SOCKET) { goto error2; } closesocket(listen_sock); return 0; error2: closesocket(sock[0]); error1: closesocket(listen_sock); return -1; } #endif /* USE_WIN32API */ #ifdef __CYGWIN__ static int check_sig_child(pid_t pid) { /* SIGCHLD signal isn't delivered on cygwin even if mlconfig exits. */ int status; if (pid > 0 && waitpid(pid, &status, WNOHANG) == pid) { bl_trigger_sig_child(pid); return 1; } else { return 0; } } #endif static ssize_t lo_read_pty(vt_pty_t *pty, u_char *buf, size_t len) { #ifdef __CYGWIN__ if (check_sig_child(pty->config_menu.pid)) { /* vt_pty_mosh_set_use_loopback(0) is called from sig_child() in vt_config_menu.c. */ return 0; } #endif return read(pty->master, buf, len); } static ssize_t lo_write_to_pty(vt_pty_t *pty, u_char *buf, size_t len) { #ifdef __CYGWIN__ if (check_sig_child(pty->config_menu.pid)) { /* * vt_pty_mosh_set_use_loopback(0) is called from sig_child() * in vt_config_menu.c is called */ return 0; } #endif return write(pty->slave, buf, len); } static int use_loopback(vt_pty_t *pty) { int fds[2]; if (pty->stored) { pty->stored->ref_count++; return 1; } if ((pty->stored = (struct vt_pty::_stored*)malloc(sizeof(*pty->stored))) == NULL) { return 0; } pty->stored->master = pty->master; pty->stored->slave = pty->slave; pty->stored->read = pty->read; pty->stored->write = pty->write; #ifdef USE_WIN32API if (_socketpair(AF_INET, SOCK_STREAM, 0, (SOCKET*)fds) == 0) { u_long val; val = 1; ioctlsocket(fds[0], FIONBIO, &val); val = 1; ioctlsocket(fds[1], FIONBIO, &val); pty->read = lo_recv_pty; pty->write = lo_send_to_pty; } else if (_pipe(fds, 256, O_BINARY) == 0) { pty->read = lo_read_pty; pty->write = lo_write_to_pty; } #else if (pipe(fds) == 0) { fcntl(fds[0], F_SETFL, O_NONBLOCK | fcntl(pty->master, F_GETFL, 0)); fcntl(fds[1], F_SETFL, O_NONBLOCK | fcntl(pty->slave, F_GETFL, 0)); pty->read = lo_read_pty; pty->write = lo_write_to_pty; } #endif else { free(pty->stored); pty->stored = NULL; return 0; } pty->master = fds[0]; pty->slave = fds[1]; pty->stored->ref_count = 1; return 1; } static int unuse_loopback(vt_pty_t *pty) { char buf[128]; ssize_t len; if (!pty->stored || --(pty->stored->ref_count) > 0) { return 0; } while ((len = (*pty->read)(pty, (u_char*)buf, sizeof(buf))) > 0) { char *p; if (!(p = (char*)realloc(((vt_pty_mosh_t *)pty)->buf, ((vt_pty_mosh_t *)pty)->buf_len + len))) { break; } memcpy(p + ((vt_pty_mosh_t *)pty)->buf_len, buf, len); ((vt_pty_mosh_t *)pty)->buf = p; ((vt_pty_mosh_t *)pty)->buf_len += len; } #ifdef USE_WIN32API if (pty->read == lo_recv_pty) { closesocket(pty->slave); closesocket(pty->master); } else #endif { close(pty->slave); close(pty->master); } pty->master = pty->stored->master; pty->slave = pty->stored->slave; pty->read = pty->stored->read; pty->write = pty->stored->write; free(pty->stored); pty->stored = NULL; return 1; } static void give_hint_to_overlay(vt_pty_mosh_t *pty_mosh) { pty_mosh->overlay->get_notification_engine().server_heard( pty_mosh->network->get_latest_remote_state().timestamp); pty_mosh->overlay->get_notification_engine().server_acked( pty_mosh->network->get_sent_state_acked_timestamp()); pty_mosh->overlay->get_prediction_engine().set_local_frame_acked( pty_mosh->network->get_sent_state_acked()); pty_mosh->overlay->get_prediction_engine().set_send_interval(pty_mosh->network->send_interval()); pty_mosh->overlay->get_prediction_engine().set_local_frame_late_acked( pty_mosh->network->get_latest_remote_state().state.get_echo_ack()); } #ifdef MOSH_SIXEL static int zmodem_on_tcp = -2; #endif static void *watch_ptys(void *arg) { pthread_detach(pthread_self()); int total_timeout = 0; while (num_ptys > 0) { int timeout = 100; int maxfd = 0; fd_set fds; FD_ZERO(&fds); pthread_mutex_lock(&event_mutex); u_int count; u_int prev_num_ptys = num_ptys; for (count = 0; count < num_ptys; count++) { #ifdef MOSH_SIXEL if (zmodem_on_tcp != ptys[count]->network->tcp_sock) #endif { std::vector fd_list(ptys[count]->network->fds()); for (std::vector::const_iterator it = fd_list.begin(); it != fd_list.end(); it++) { FD_SET(*it, &fds); if (*it > maxfd) { maxfd = *it; } } int wait = ptys[count]->network->wait_time(); if (timeout > wait) { timeout = wait; } } #ifdef MOSH_SIXEL int fd = ptys[count]->network->tcp_sock; if (fd >= 0 && (zmodem_on_tcp == -2 || zmodem_on_tcp == fd)) { FD_SET(fd, &fds); if (fd > maxfd) { maxfd = fd; } } #endif } pthread_mutex_unlock(&event_mutex); struct timeval tv; tv.tv_usec = timeout * 1000; tv.tv_sec = 0; int sel_result = select(maxfd + 1, &fds, NULL, NULL, &tv); #if 0 if (sel_result < 0 && errno != EINTR) { break; } #else /* Loop continues until num_ptys becomes 0 even if select() returns -1. */ #endif freeze_timestamp(); bool ready = false; pthread_mutex_lock(&event_mutex); if (prev_num_ptys == num_ptys) { for (count = 0; count < num_ptys; count++) { if (sel_result > 0) { std::vector fd_list(ptys[count]->network->fds()); #ifdef MOSH_SIXEL int fd = ptys[count]->network->tcp_sock; if (fd >= 0 && (zmodem_on_tcp == -2 || zmodem_on_tcp == fd)) { if (FD_ISSET(fd, &fds)) { cur_ps = &ptys[count]->network->ps; /* for tcp_recv_from_server() */ bool close_socket = !tcp_recv_from_server(fd); if (zmodem_processing(&ptys[count]->network->ps)) { zmodem_on_tcp = fd; } else if (zmodem_on_tcp >= 0) { zmodem_on_tcp = -2; close_socket = true; } if (close_socket) { closesocket(fd); ptys[count]->network->tcp_sock = -1; } ptys[count]->ready = ready = true; goto skip_udp; } else if (zmodem_on_tcp == fd) { if (!zmodem_processing(&ptys[count]->network->ps)) { zmodem_on_tcp = -2; closesocket(fd); ptys[count]->network->tcp_sock = -1; } goto skip_udp; } } #endif for (std::vector::const_iterator it = fd_list.begin(); it != fd_list.end(); it++) { if (FD_ISSET(*it, &fds)) { #ifdef MOSH_SIXEL /* for establish_tcp_connection() which can be called by network->recv() */ cur_network = ptys[count]->network; /* for network->recv() */ cur_ps = &ptys[count]->network->ps; #endif ptys[count]->network->recv(); give_hint_to_overlay(ptys[count]); ptys[count]->ready = ready = true; break; } } #ifdef MOSH_SIXEL skip_udp: ; #endif } #ifdef MOSH_SIXEL pass_seq_change_buf(&ptys[count]->network->ps, 1, false); #endif ptys[count]->network->tick(); #ifdef MOSH_SIXEL pass_seq_change_buf(&ptys[count]->network->ps, 0, false); #endif } } else if (dead_network) { delete dead_network; dead_network = NULL; } pthread_mutex_unlock(&event_mutex); if (!ready) { total_timeout += timeout; if (total_timeout >= 500) { total_timeout = 0; ready = true; for (count = 0; count < num_ptys; count++) { ptys[count]->ready = true; } } } else { total_timeout = 0; } if (ready) { pthread_mutex_lock(&event_mutex); while (event_in_pipe) { pthread_cond_wait(&event_cond, &event_mutex); } event_in_pipe = true; pthread_mutex_unlock(&event_mutex); #ifdef USE_WIN32API (*trigger_pty_read)(); #else write(event_fds[1], "G", 1); fsync(event_fds[1]); #endif } } if (dead_network) { delete dead_network; dead_network = NULL; } #ifndef USE_WIN32API close(event_fds[0]); close(event_fds[1]); #endif return NULL; } static int final(vt_pty_t *pty) { vt_pty_mosh_t *pty_mosh = (vt_pty_mosh_t*)pty; unuse_loopback(pty); if (pty_mosh->buf_len > 0) { free(pty_mosh->buf); } pthread_mutex_lock(&event_mutex); u_int count; for (count = 0; count < num_ptys; count++) { if (ptys[count] == pty_mosh) { ptys[count] = ptys[--num_ptys]; } } if (dead_network) { delete dead_network; /* XXX */ } /* * If delete pty_mosh->network here, watch_ptys() might fall into infinite loop. * (in select()?) */ dead_network = pty_mosh->network; #ifdef MOSH_SIXEL if (dead_network >= 0) { closesocket(dead_network->tcp_sock); dead_network->tcp_sock = -1; /* for dead_network->tick() not to send via tcp_sock */ } #endif dead_network->start_shutdown(); dead_network->tick(); delete pty_mosh->overlay; pthread_mutex_unlock(&event_mutex); return 1; } static int set_winsize(vt_pty_t *pty, u_int cols, u_int rows, u_int width_pix, u_int height_pix) { vt_pty_mosh_t *pty_mosh = (vt_pty_mosh_t*)pty; pthread_mutex_lock(&event_mutex); pty_mosh->network->get_current_state().push_back(Parser::Resize(cols, rows)); #ifdef MOSH_SIXEL pass_seq_change_buf(&pty_mosh->network->ps, 1, false); #endif pty_mosh->network->tick(); #ifdef MOSH_SIXEL pass_seq_change_buf(&pty_mosh->network->ps, 0, false); #endif pty_mosh->overlay->get_prediction_engine().reset(); pthread_mutex_unlock(&event_mutex); return 1; } static ssize_t write_to_pty(vt_pty_t *pty, u_char *buf, size_t len) { vt_pty_mosh_t *pty_mosh = (vt_pty_mosh_t*)pty; pthread_mutex_lock(&event_mutex); #ifdef MOSH_SIXEL bool zmodem_cancel = (strcmp((char*)buf, "**\x18\x18\x18\x18\x18\x18\x18\x18" "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08") == 0); if (pty_mosh->network->tcp_sock >= 0 && tcp_send(pty_mosh->network->tcp_sock, (char*)buf, len)) { if (zmodem_cancel) { pass_seq_full_reset(&pty_mosh->network->ps); if (zmodem_on_tcp == pty_mosh->network->tcp_sock) { zmodem_on_tcp = -2; } closesocket(pty_mosh->network->tcp_sock); pty_mosh->network->tcp_sock = -1; } pass_seq_change_buf(&pty_mosh->network->ps, 1, false); pty_mosh->network->tick(); pass_seq_change_buf(&pty_mosh->network->ps, 0, false); goto end; } else { if (zmodem_cancel) { pass_seq_full_reset(&pty_mosh->network->ps); } } pass_seq_change_buf(&pty_mosh->network->ps, 1, false); #endif pty_mosh->overlay->get_prediction_engine().set_local_frame_sent( pty_mosh->network->get_sent_state_last()); #ifdef MOSH_SIXEL /* for overlays.get_prediction_engine().new_user_byte() */ cur_ps = &pty_mosh->network->ps; #endif for (size_t count = 0; count < len; count++) { pty_mosh->overlay->get_prediction_engine().new_user_byte(buf[count], pty_mosh->framebuffer); #ifdef MOSH_SIXEL if (pass_seq_has_zmodem(&pty_mosh->network->ps) || zmodem_processing(&pty_mosh->network->ps)) { goto skip; } #endif if (pty_mosh->quit_sequence_started) { if (buf[count] == '.') { /* Quit sequence is Ctrl-^ . */ if (pty_mosh->network->has_remote_addr()) { pty_mosh->overlay->get_notification_engine().set_notification_string( wstring( L"Exiting on user request..." ), true); bl_trigger_sig_child(pty->child_pid); } pthread_mutex_unlock(&event_mutex); return -1; } #ifdef MOSH_SIXEL else if (buf[count] == ',') { /* Reset */ pass_seq_full_reset(&pty_mosh->network->ps); } #endif else if (buf[count] == 0x1a) { /* Suspend sequence is escape_key Ctrl-Z */ } else if ((buf[count] == escape_pass_key) || (buf[count] == escape_pass_key2)) { /* Emulation sequence to type escape_key is escape_key + escape_pass_key (that is escape key without Ctrl) */ pty_mosh->network->get_current_state().push_back(Parser::UserByte(escape_key)); } else { /* Escape key followed by anything other than . and ^ gets sent literally */ pty_mosh->network->get_current_state().push_back(Parser::UserByte(escape_key)); pty_mosh->network->get_current_state().push_back(Parser::UserByte(buf[count])); } pty_mosh->quit_sequence_started = false; if (pty_mosh->overlay->get_notification_engine().get_notification_string() == escape_key_help) { pty_mosh->overlay->get_notification_engine().set_notification_string(L""); } continue; } pty_mosh->quit_sequence_started = (escape_key > 0) && (buf[count] == escape_key) && (pty_mosh->lf_entered || !escape_requires_lf) ; if (pty_mosh->quit_sequence_started) { pty_mosh->lf_entered = false; pty_mosh->overlay->get_notification_engine().set_notification_string(escape_key_help, true, false); continue; } /* LineFeed, Ctrl-J, '\n' or CarriageReturn, Ctrl-M, '\r' */ pty_mosh->lf_entered = (buf[count] == 0x0A || buf[count] == 0x0D); /* XXX */ #if 0 if (buf[count] == 0x0C) { /* Ctrl-L */ /* Repaint is requested */ } #endif skip: pty_mosh->network->get_current_state().push_back(Parser::UserByte(buf[count])); } #ifdef MOSH_SIXEL pass_seq_change_buf(&pty_mosh->network->ps, 0, true /* clear pass seq generated by overlay */); pass_seq_change_buf(&pty_mosh->network->ps, 1, false); #endif pty_mosh->network->tick(); /* send UserByte(buf) above to the server */ #ifdef MOSH_SIXEL pass_seq_change_buf(&pty_mosh->network->ps, 0, false); end: #endif pthread_mutex_unlock(&event_mutex); return len; } static ssize_t read_pty(vt_pty_t *pty, u_char *buf, size_t len) { vt_pty_mosh_t *pty_mosh = (vt_pty_mosh_t*)pty; if (event_in_pipe) { #ifndef USE_WIN32API char dummy[16]; if (read(event_fds[0], dummy, sizeof(dummy)) > 0) #endif { pthread_mutex_lock(&event_mutex); pthread_cond_signal(&event_cond); event_in_pipe = false; pthread_mutex_unlock(&event_mutex); } } if (!pty_mosh->network->has_remote_addr()) { return 0; } else if (((int64_t)pty_mosh->network->get_remote_state_num()) < 0) { bl_trigger_sig_child(pty->child_pid); return 0; } #if 0 bl_debug_printf("REMOTE %d %d %d %d %d\n", pty_mosh->network->has_remote_addr(), pty_mosh->network->shutdown_in_progress(), pty_mosh->network->get_remote_state_num(), pty_mosh->network->get_latest_remote_state().timestamp, pty_mosh->network->get_sent_state_acked_timestamp()); #endif size_t prev_len = min(pty_mosh->buf_len, len); if (pty_mosh->buf_len > 0) { /* * Even if pty_mosh->buf_len > 0, prev_len may be 0 because len may be 0. * In this case, it is necessary to enter this block not to change * pty_mosh->buf_len. */ memcpy(buf, pty_mosh->buf, prev_len); buf += prev_len; len -= prev_len; if ((pty_mosh->buf_len -= prev_len) == 0) { free(pty_mosh->buf); pty_mosh->buf = NULL; } else { memmove(pty_mosh->buf, pty_mosh->buf + prev_len, pty_mosh->buf_len); return prev_len; } } if (!pty_mosh->ready) { return prev_len; } pty_mosh->ready = false; if (!pty_mosh->initialized) { /* Put terminal in application-cursor-key mode */ std::string init_str = pty_mosh->display.open(); if (init_str.length() > len) { memcpy(buf, init_str.c_str(), len); if ((pty_mosh->buf = (char*)malloc(init_str.length() - len))) { pty_mosh->buf_len = init_str.length() - len; memcpy(pty_mosh->buf, init_str.c_str() + len, pty_mosh->buf_len); } return prev_len + len; } else { memcpy(buf, init_str.c_str(), init_str.length()); prev_len += init_str.length(); buf += init_str.length(); len -= init_str.length(); } } #ifdef MOSH_SIXEL /* defined in parser.h */ pthread_mutex_lock(&event_mutex); size_t seq_len; char *seq = pass_seq_get(&pty_mosh->network->ps, &seq_len); if (seq) { /* XXX in case len < 8 */ if (len >= 8) { size_t prepend; if (!pass_seq_has_zmodem(&pty_mosh->network->ps) && memcmp(seq, "\x1bP", 2) == 0) { memcpy(buf, "\x1b[?8800h", 8); /* for DRCS-Sixel */ len -= 8; memcpy(buf + 8, seq, min(seq_len, len)); prepend = 8; } else { memcpy(buf, seq, min(seq_len, len)); prepend = 0; } if (seq_len > len) { if ((pty_mosh->buf = (char*)malloc(seq_len - len))) { pty_mosh->buf_len = seq_len - len; memcpy(pty_mosh->buf, seq + len, pty_mosh->buf_len); } } else { len = seq_len; } pass_seq_reset(&pty_mosh->network->ps); pthread_mutex_unlock(&event_mutex); return len + prepend + prev_len; } } else if (zmodem_processing(&pty_mosh->network->ps)) { pthread_mutex_unlock(&event_mutex); return prev_len; } pthread_mutex_unlock(&event_mutex); #endif pthread_mutex_lock(&event_mutex); Terminal::Framebuffer framebuffer = pty_mosh->network->get_latest_remote_state().state.get_fb(); pty_mosh->overlay->apply(framebuffer); pthread_mutex_unlock(&event_mutex); std::string update = pty_mosh->display.new_frame(pty_mosh->initialized, pty_mosh->framebuffer, framebuffer); pty_mosh->framebuffer = framebuffer; pty_mosh->initialized = true; memcpy(buf, update.c_str(), min(update.length(), len)); if (update.length() > len) { if ((pty_mosh->buf = (char*)malloc(update.length() - len))) { pty_mosh->buf_len = update.length() - len; memcpy(pty_mosh->buf, update.c_str() + len, pty_mosh->buf_len); } } else { len = update.length(); } return len + prev_len; } /* --- global functions --- */ #ifdef USE_WIN32API void vt_pty_mosh_set_pty_read_trigger(void (*func)(void)) { trigger_pty_read = func; } #endif vt_pty_t *vt_pty_mosh_new(const char *cmd_path, /* If NULL, child prcess is not exec'ed. */ char **cmd_argv, /* can be NULL(only if cmd_path is NULL) */ char **env, /* can be NULL */ const char *uri, const char *pass, const char *pubkey, /* can be NULL */ const char *privkey, /* can be NULL */ u_int cols, u_int rows, u_int width_pix, u_int height_pix) { char *uri_dup; char *host; char *ip; if (!(uri_dup = (char*)alloca(strlen(uri) + 1)) || !bl_parse_uri(NULL, NULL, &host, NULL, NULL, NULL, strcpy(uri_dup, uri))) { return NULL; } struct addrinfo hints; struct addrinfo *res; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; if (getaddrinfo(host, NULL, &hints, &res) != 0) { return NULL; } struct in_addr addr; addr.s_addr = ((struct sockaddr_in*)res->ai_addr)->sin_addr.s_addr; freeaddrinfo(res); ip = inet_ntoa(addr); char ip_tmp[strlen(ip) + 1]; ip = strcpy(ip_tmp, ip); if (strcmp(host, ip) != 0) { char *new_uri; if ((new_uri = (char*)alloca(strlen(uri) - strlen(host) + strlen(ip) + 1))) { const char *p = strstr(uri, host); memcpy(new_uri, uri, p - uri); strcpy(new_uri + (p - uri), ip); uri = strcat(new_uri, uri + (p - uri + strlen(host))); } } #ifdef TEST_BY_SSH int fds[2]; if (pipe(fds) == -1) { return NULL; } pid_t pid = fork(); if (pid == 0) { close(fds[0]); bl_file_set_cloexec(fds[1]); dup2(fds[1], STDOUT_FILENO); dup2(fds[1], STDERR_FILENO); char *argv[] = { "ssh", "-n", "-tt", "-Snone", #if 0 /* This proxy command outputs "MOSH IP ..." */ "-oProxyCommand=/usr/bin/mosh --family=prefer-inet --fake-proxy -- %h %p", #else "-oProxyCommand=nc %h %p", #endif ip, "--", "mosh-server", "new", "-c", "256", "-s", "-l", "LANG=en_US.UTF-8", "--", "/bin/bash", NULL}; execv("/usr/bin/ssh", argv); } else if (pid < 0) { close(fds[0]); close(fds[1]); return NULL; } close(fds[1]); #else char *base_argv[] = { "mosh-server", "new", "-c", "256", "-s", "-l", "LANG=en_US.UTF-8", NULL }; char *locale; if ((locale = bl_get_locale())) { #ifdef USE_WIN32API if (strstr(locale, "Japanese")) { locale = "ja_JP.UTF-8"; } else if (strstr(locale, "Taiwan")) { locale = "zh_TW.UTF-8"; } else if (strstr(locale, "Hong Kong")) { locale = "zh_HK.UTF-8"; } else if (strstr(locale, "China")) { locale = "zh_CN.UTF-8"; } else if (strstr(locale, "Korean")) { locale = "ko_KR.UTF-8"; } else { locale = "en_US.UTF-8"; goto end_locale; } end_locale: #endif /* The default locale is C.UTF-8 on cygwin. */ if (strncmp(locale, "C.", 2) != 0) { char *p; if ((p = (char*)alloca(5 + strlen(locale) + 1))) { sprintf(p, "LANG=%s", locale); base_argv[6] = p; } } } char *mosh_server = getenv("MOSH_SERVER"); if (mosh_server) { base_argv[0] = mosh_server; } u_int argv_count = 0; if (cmd_argv) { while (cmd_argv[argv_count++]); } #ifdef MOSH_SIXEL if (getenv("MOSH_NO_TCP")) { argv_count++; } #endif u_int env_count = 0; if (env) { while (env[env_count++]); } char **argv; if (argv_count + env_count > 0 && (argv = (char**)alloca(sizeof(base_argv) + sizeof(char*) * (argv_count + env_count * 2)))) { memcpy(argv, base_argv, sizeof(base_argv)); char **argv_p = argv + sizeof(base_argv) / sizeof(base_argv[0]) - 1; #ifdef MOSH_SIXEL if (getenv("MOSH_NO_TCP")) { *(argv_p++) = "-t"; } #endif for (env_count = 0; env[env_count]; env_count++) { /* "COLORFGBG=default;default" breaks following environmental variables. */ if (!strchr(env[env_count], ';')) { #ifndef USE_ORIG_TERMINALDISPLAYINIT if (strncmp(env[env_count], "TERM=", 5) == 0 && (strcmp(env[env_count] + 5, "mlterm") == 0 || strcmp(env[env_count] + 5, "kterm") == 0)) { bl_msg_printf("mlterm's mosh doesn't support %s which disables bce.\n", env[env_count]); } #endif *(argv_p++) = "-l"; *(argv_p++) = env[env_count]; } } if (cmd_argv) { *(argv_p++) = "--"; memcpy(argv_p, cmd_argv, (argv_count + 1) * sizeof(char*)); } else { *argv_p = NULL; } } else { argv = base_argv; } #ifdef __DEBUG int count; bl_debug_printf("Arguments:\n"); for (count = 0; argv[count]; count++) { bl_debug_printf("=> %s\n", argv[count]); } #endif vt_pty_t *ssh = vt_pty_ssh_new(argv[0], argv, env, uri, pass, pubkey, privkey, cols, rows, width_pix, height_pix); if (!ssh) { return NULL; } #endif char *key = NULL; char *port = NULL; char buf[1024]; size_t filled = 0; ssize_t len; #ifdef TEST_BY_SSH /* blocking */ while ((len = read(fds[0], buf + filled, sizeof(buf) - 1 - filled)) > 0) #else /* non blocking */ while ((len = (*ssh->read)(ssh, (u_char*)buf + filled, sizeof(buf) - 1 - filled)) >= 0) #endif { buf[filled += len] = '\0'; char *line = buf; char *p; while ((p = strchr(line, '\r')) || (p = strchr(line, '\n'))) { *p = '\0'; if (strncmp(line, "MOSH CONNECT ", 13) == 0) { char *port_tmp = (line += 13); while ('0' <= *line && *line <= '9') { line++; } *(line++) = '\0'; if ((port = (char*)alloca(strlen(port_tmp) + 1))) { strcpy(port, port_tmp); } if ((key = (char*)alloca(strlen(line) + 1))) { strcpy(key, line); } #ifdef __DEBUG bl_debug_printf("MOSH_KEY=%s PORT=%s\n", key, port); #endif } else if (strncmp(line, "MOSH IP ", 8) == 0) { if ((ip = (char*)alloca(strlen(line + 8) + 1))) { strcpy(ip, line + 8); } #ifdef __DEBUG bl_debug_printf("IP=%s\n", ip); #endif } #if 1 /* See src/frontend/mosh-server.cc at http://bitbucket.org/arakiken/mosh/branch/winsock */ else if (strncmp(line, "MOSH AWIDTH ", 12) == 0) { #ifdef USE_WIN32API /* * SUSv2 and glibc (>=2.1.3) defines the tyep of the argument of putenv() * as 'char*' (not 'const char*'). */ putenv(line[12] == '2' ? (char*)"MOSH_AWIDTH=2" : (char*)"MOSH_AWIDTH=1"); #else int serv_width = (line[12] == '2') ? 2 : 1; int cli_width = wcwidth(0x25a0); /* See vt_parser_set_pty() in vt_parser.c */ if (serv_width != cli_width) { bl_msg_printf("The number of columns of awidth chars doesn't match.\n" " mosh-server: %d, mosh-client: %d\n", serv_width, cli_width); } #endif } #endif /* * "The locale requested by LANG=... isn't available here." * "Running `locale-gen ...' may be necessary." */ else if (strstr(line, "available here") || strstr(line, "Running")) { bl_msg_printf("mosh-server: %s\n", line); } #ifdef __DEBUG else { bl_debug_printf("%s\n", line); } #endif line = p + (*(p + 1) == '\n' ? 2 : 1); } if (line != buf) { filled = strlen(line); memmove(buf, line, filled); } } #ifdef TEST_BY_SSH close(fds[0]); #else /* See vt_pty_destroy() in vt_pty.c */ free(ssh->cmd_line); (*ssh->final)(ssh); free(ssh); #endif vt_pty_mosh_t *pty; if (key && (pty = (vt_pty_mosh_t*)calloc(1, sizeof(vt_pty_mosh_t)))) { Network::UserStream blank; Terminal::Complete complete(cols, rows); #ifdef __DEBUG bl_debug_printf("URI %s IP %s PORT %s KEY %s\n", uri, ip, port, key); #endif pthread_mutex_lock(&event_mutex); pty->network = new Network::Transport(blank, complete, key, ip, port ? port : "60001"); if (pty->network) { pty->network->set_send_delay(1); /* minimal delay on outgoing keystrokes */ pty->network->get_current_state().push_back(Parser::Resize(cols, rows)); pty->network->set_verbose(0); /* 1 causes abort in init_diff() in transportsender-impl.h */ pthread_mutex_unlock(&event_mutex); #ifdef USE_ORIG_TERMINALDISPLAYINIT /* see Display::Display() in mosh-x.x.x/src/terminal/terminaldisplayinit.cc */ char *term = getenv("TERM"); if (term == NULL || (strncmp(term, "xterm", 5) && strncmp(term, "rxvt", 4) && strncmp(term, "kterm", 5) && strncmp(term, "Eterm", 5) && strncmp(term, "screen", 6))) { putenv((char*)"TERM=xterm"); } #endif pty->display = Terminal::Display(true); pty->initialized = false; pty->framebuffer = Terminal::Framebuffer(cols, rows); /* OverlayManager doesn't support operator= */ pty->overlay = new Overlay::OverlayManager(); char *predict_mode; while ((predict_mode = getenv("MOSH_PREDICTION_DISPLAY"))) { Overlay::PredictionEngine::DisplayPreference pref; if (strcmp(predict_mode, "always") == 0) { pref = Overlay::PredictionEngine::Always; } else if (strcmp(predict_mode, "never") == 0) { pref = Overlay::PredictionEngine::Never; } else if (strcmp(predict_mode, "adaptive") == 0) { pref = Overlay::PredictionEngine::Adaptive; } else if (strcmp(predict_mode, "experimental") == 0) { pref = Overlay::PredictionEngine::Experimental; } else { break; } pty->overlay->get_prediction_engine().set_display_preference(pref); break; } #if 0 if (!getenv("MOSH_TITLE_NOPREFIX")) { pty->overlay->set_title_prefix(wstring(L"[mosh] ")); } #endif pty->pty.mode = PTY_MOSH; pty->pty.final = final; pty->pty.set_winsize = set_winsize; pty->pty.write = write_to_pty; pty->pty.read = read_pty; pty->pty.child_pid = 0; while (*key) { pty->pty.child_pid += *(key++); } u_int count = 0; while (count < num_ptys) { if (ptys[count]->pty.child_pid == pty->pty.child_pid) { pty->pty.child_pid++; count = 0; } else { count++; } } void *p; if ((p = realloc(ptys, sizeof(*ptys) * (num_ptys + 1)))) { ptys = (vt_pty_mosh_t**)p; ptys[num_ptys++] = pty; if (num_ptys == 1) { #ifndef USE_WIN32API pipe(event_fds); #endif pthread_t thrd; pthread_create(&thrd, NULL, watch_ptys, NULL); } } #ifndef USE_WIN32API pty->pty.master = event_fds[0]; #endif pty->pty.slave = -1; return &pty->pty; } else { free(pty); } pthread_mutex_unlock(&event_mutex); } return NULL; } int vt_pty_mosh_set_use_loopback(vt_pty_t *pty, int use) { if (use) { use_loopback(pty); return 1; } else { return unuse_loopback(pty); } } mlterm-3.8.9/vtemu/cygfile.h010064400017600000144000000007031356600660700144750ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __CYGFILE_H__ #define __CYGFILE_H__ #define FILE void #define fopen(path, mode) cygfopen(path, mode) #define fclose(file) cygfclose(file) #define fwrite(ptr, size, nmemb, file) cygfwrite(ptr, size, nmemb, file) void *cygfopen(const char *path, const char *mode); int cygfclose(void *file); size_t cygfwrite(const void *ptr, size_t size, size_t nmemb, void *file); #endif mlterm-3.8.9/vtemu/mlterm.c010064400017600000144000000253051356600660700143530ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include /* HAVE_WINDOWS_H, WORDS_BIGENDIAN */ #ifdef HAVE_WINDOWS_H #include /* In Cygwin is not included and error happens in jni.h. */ #endif #include "mlterm.h" #include /* select */ #include #include #include #include /* alloca */ #include /* bl_str_to_uint */ #include #include #include /* bl_basename */ #include /* _bl_arg_str_to_array */ #include "vt_term_manager.h" #if defined(USE_WIN32API) #define CONFIG_PATH "." #elif defined(SYSCONFDIR) #define CONFIG_PATH SYSCONFDIR #else #define CONFIG_PATH "/etc" #endif #if 0 #define USE_LOCAL_ECHO_BY_DEFAULT #endif #if 0 #define __DEBUG #endif /* --- global functions --- */ vt_term_t *mlterm_open(char *host, char *pass, int cols, int rows, u_int log_size, char *encoding_str, char **argv, vt_xterm_event_listener_t *xterm_listener, vt_config_event_listener_t *config_listener, vt_screen_event_listener_t *screen_listener, vt_pty_event_listener_t *pty_listener, int open_pty) { vt_term_t *term; vt_char_encoding_t encoding; int is_auto_encoding; char *envv[4]; char *cmd_path; static int wsa_inited = 0; static u_int tab_size; static vt_char_encoding_t encoding_default; static int is_auto_encoding_default; static vt_unicode_policy_t unicode_policy; static u_int col_size_a; static int use_char_combining; static int use_multi_col_char; static int use_login_shell; static int logging_vt_seq; static int use_local_echo; static int use_auto_detect; static int use_ansi_colors; static char *term_type; static char *public_key; static char *private_key; static char **default_argv; static char *default_cmd_path; if (!wsa_inited) { bl_conf_t *conf; #if defined(USE_WIN32API) && defined(USE_LIBSSH2) WSADATA wsadata; WSAStartup(MAKEWORD(2, 0), &wsadata); /* * Prevent vt_pty_ssh from spawning a thread to watch pty. * If both vt_pty_ssh and MLTerm.java spawn threads to watch ptys, * problems will happen in reloading (that is, finalizing and * starting simultaneously) an applet page (mltermlet.html) * in a web browser. * * This hack doesn't make sense to vt_pty_pipewin32.c. * In the first place, if vt_pty_pipewin32 is used, * Java_mlterm_MLTermPty_waitForReading() returns JNI_FALSE * and PtyWather thread of MLTerm.java immediately exits. * So threads in vt_pty_pipewin32 should not be prevented. */ CreateEvent(NULL, FALSE, FALSE, "PTY_READ_READY"); #endif bl_init_prog("mlterm", "3.8.9"); bl_set_sys_conf_dir(CONFIG_PATH); bl_locale_init(""); bl_sig_child_start(); vt_term_manager_init(1); vt_color_config_init(); tab_size = 8; encoding_default = vt_get_char_encoding("auto"); is_auto_encoding_default = 1; if (strcmp(bl_get_lang(), "ja") == 0) { col_size_a = 2; } else { col_size_a = 1; } use_char_combining = 1; use_multi_col_char = 1; #ifdef USE_LOCAL_ECHO_BY_DEFAULT use_local_echo = 1; #endif use_ansi_colors = 1; if ((conf = bl_conf_new())) { char *rcpath; char *value; if ((rcpath = bl_get_sys_rc_path("mlterm/main"))) { bl_conf_read(conf, rcpath); free(rcpath); } if ((rcpath = bl_get_user_rc_path("mlterm/main"))) { bl_conf_read(conf, rcpath); free(rcpath); } if ((value = bl_conf_get_value(conf, "logging_msg")) && strcmp(value, "false") == 0) { bl_set_msg_log_file_name(NULL); } else { bl_set_msg_log_file_name("mlterm/msg.log"); } if ((value = bl_conf_get_value(conf, "logging_vt_seq")) && strcmp(value, "true") == 0) { logging_vt_seq = 1; } if ((value = bl_conf_get_value(conf, "tabsize"))) { bl_str_to_uint(&tab_size, value); } if ((value = bl_conf_get_value(conf, "encoding"))) { vt_char_encoding_t e; if ((e = vt_get_char_encoding(value)) != VT_UNKNOWN_ENCODING) { encoding_default = e; if (strcmp(value, "auto") == 0) { is_auto_encoding_default = 1; } else { is_auto_encoding_default = 0; } } } if ((value = bl_conf_get_value(conf, "not_use_unicode_font"))) { if (strcmp(value, "true") == 0) { unicode_policy = NOT_USE_UNICODE_FONT; } } if ((value = bl_conf_get_value(conf, "only_use_unicode_font"))) { if (strcmp(value, "true") == 0) { if (unicode_policy == NOT_USE_UNICODE_FONT) { unicode_policy = 0; } else { unicode_policy = ONLY_USE_UNICODE_FONT; } } } if ((value = bl_conf_get_value(conf, "col_size_of_width_a"))) { bl_str_to_uint(&col_size_a, value); } if ((value = bl_conf_get_value(conf, "use_combining"))) { if (strcmp(value, "false") == 0) { use_char_combining = 0; } } /* use_multi_col_char=false causes corrupt screen on SWT or vim terminal. */ #if 0 if ((value = bl_conf_get_value(conf, "use_muti_col_char"))) { if (strcmp(value, "false") == 0) { use_multi_col_char = 0; } } #endif if ((value = bl_conf_get_value(conf, "use_login_shell"))) { if (strcmp(value, "true") == 0) { use_login_shell = 1; } } if ((value = bl_conf_get_value(conf, "use_local_echo"))) { #ifdef USE_LOCAL_ECHO_BY_DEFAULT if (strcmp(value, "false") == 0) { use_local_echo = 0; } #else if (strcmp(value, "true") == 0) { use_local_echo = 1; } #endif } if ((value = bl_conf_get_value(conf, "use_alt_buffer"))) { if (strcmp(value, "false") == 0) { vt_set_use_alt_buffer(0); } } if ((value = bl_conf_get_value(conf, "use_ansi_colors"))) { if (strcmp(value, "false") == 0) { use_ansi_colors = 0; } } if ((value = bl_conf_get_value(conf, "auto_detect_encodings"))) { vt_set_auto_detect_encodings(value); } if ((value = bl_conf_get_value(conf, "use_auto_detect"))) { if (strcmp(value, "true") == 0) { use_auto_detect = 1; } } if ((value = bl_conf_get_value(conf, "termtype"))) { term_type = strdup(value); } else { term_type = "xterm"; } #ifdef USE_LIBSSH2 if ((value = bl_conf_get_value(conf, "ssh_public_key"))) { public_key = strdup(value); } if ((value = bl_conf_get_value(conf, "ssh_private_key"))) { private_key = strdup(value); } if ((value = bl_conf_get_value(conf, "cipher_list"))) { vt_pty_ssh_set_cipher_list(strdup(value)); } if ((value = bl_conf_get_value(conf, "ssh_keepalive_interval"))) { u_int keepalive_interval; if (bl_str_to_uint(&keepalive_interval, value) && keepalive_interval > 0) { vt_pty_ssh_set_keepalive_interval(keepalive_interval); } } if ((value = bl_conf_get_value(conf, "ssh_x11_forwarding"))) { if (strcmp(value, "true") == 0) { vt_pty_ssh_set_use_x11_forwarding(NULL, 1); } } if ((value = bl_conf_get_value(conf, "allow_scp"))) { if (strcmp(value, "true") == 0) { vt_set_use_scp_full(1); } } #endif #if 0 /* XXX How to get password ? */ if ((value = bl_conf_get_value(conf, "default_server"))) { default_server = strdup(value); } #endif if (((value = bl_conf_get_value(conf, "exec_cmd")) #if defined(USE_WIN32API) && !defined(USE_LIBSSH2) || (value = plink) #endif ) && (default_argv = malloc(sizeof(char *) * bl_count_char_in_str(value, ' ') + 2))) { int argc; bl_arg_str_to_array(default_argv, &argc, strdup(value)); default_cmd_path = default_argv[0]; } bl_conf_destroy(conf); } unicode_policy |= ONLY_USE_UNICODE_BOXDRAW_FONT; wsa_inited = 1; } encoding = encoding_default; is_auto_encoding = is_auto_encoding_default; if (encoding_str) { vt_char_encoding_t e; if ((e = vt_get_char_encoding(encoding_str)) != VT_UNKNOWN_ENCODING) { encoding = e; if (strcmp(encoding_str, "auto") == 0) { is_auto_encoding = 1; } else { is_auto_encoding = 0; } } } if (!(term = vt_create_term(term_type, cols, rows, tab_size, log_size, encoding, is_auto_encoding, use_auto_detect, logging_vt_seq, unicode_policy, col_size_a, use_char_combining, use_multi_col_char, 0 /* use_ctl */, 0 /* bidi_mode */, NULL /* bidi_separators */, 0 /* use_dynamic_comb */, BSM_STATIC, 0 /* vertical_mode */, use_local_echo, NULL, NULL, use_ansi_colors, 0 /* alt_color_mode */, 0 /* use_ot_layout */, 0 /* cursor_style */, 0 /* ignore_broadcasted_chars */))) { goto error; } vt_term_attach(term, xterm_listener, config_listener, screen_listener, pty_listener); if (!open_pty) { return term; } if (!host && !(host = getenv("DISPLAY"))) { host = ":0.0"; } if (argv) { cmd_path = argv[0]; } else if (default_argv) { argv = default_argv; cmd_path = default_cmd_path; } else { #ifndef USE_WIN32API if (pass) #endif { cmd_path = NULL; argv = alloca(sizeof(char *)); argv[0] = NULL; } #ifndef USE_WIN32API else { cmd_path = getenv("SHELL"); argv = alloca(sizeof(char *) * 2); argv[1] = NULL; } #endif } if (cmd_path) { if (use_login_shell) { argv[0] = alloca(strlen(cmd_path) + 2); sprintf(argv[0], "-%s", bl_basename(cmd_path)); } else { argv[0] = bl_basename(cmd_path); } } envv[0] = alloca(8 + strlen(host) + 1); sprintf(envv[0], "DISPLAY=%s", host); envv[1] = "TERM=xterm"; envv[2] = "COLORFGBG=default;default"; envv[3] = NULL; if (vt_term_open_pty(term, cmd_path, argv, envv, host, NULL, pass, public_key, private_key, 0, 0)) { return term; } else { vt_destroy_term(term); } error: #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to open pty.\n"); #endif return NULL; } void mlterm_final(void) { vt_term_manager_final(); vt_color_config_final(); vt_free_word_separators(); bl_sig_child_final(); bl_locale_final(); } mlterm-3.8.9/vtemu/mlterm.h010064400017600000144000000010351356600660700143520ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_term_manager.h" vt_term_t *mlterm_open(char *host, char *pass, int cols, int rows, u_int log_size, char *encoding_str, char **argv, vt_xterm_event_listener_t *xterm_listener, vt_config_event_listener_t *config_listener, vt_screen_event_listener_t *screen_listener, vt_pty_event_listener_t *pty_listener, int open_pty); void mlterm_final(void); mlterm-3.8.9/vtemu/vt_bidi.c010064400017600000144000000014401356600660700144650ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_bidi.h" #include /* strcmp */ #if 0 #define __DEBUG #endif /* --- static variables --- */ /* Order of this table must be same as vt_bidi_mode_t. */ static char *bidi_mode_name_table[] = { "normal", "left", "right", }; /* --- global functions --- */ vt_bidi_mode_t vt_get_bidi_mode(const char *name) { vt_bidi_mode_t mode; for (mode = 0; mode < BIDI_MODE_MAX; mode++) { if (strcmp(bidi_mode_name_table[mode], name) == 0) { return mode; } } /* default value */ return BIDI_NORMAL_MODE; } char *vt_get_bidi_mode_name(vt_bidi_mode_t mode) { if ((u_int)mode >= BIDI_MODE_MAX) { /* default value */ mode = BIDI_NORMAL_MODE; } return bidi_mode_name_table[mode]; } mlterm-3.8.9/vtemu/vt_bidi.h010064400017600000144000000006631356600660700145000ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_BIDI_H__ #define __VT_BIDI_H__ #include /* u_int */ typedef enum { BIDI_NORMAL_MODE = 0, BIDI_ALWAYS_LEFT = 1, BIDI_ALWAYS_RIGHT = 2, BIDI_MODE_MAX, } vt_bidi_mode_t; typedef struct vt_bidi_state *vt_bidi_state_t; vt_bidi_mode_t vt_get_bidi_mode(const char *name); char *vt_get_bidi_mode_name(vt_bidi_mode_t mode); #endif mlterm-3.8.9/vtemu/vt_char.c010064400017600000144000000600651356600660700145030ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_char.h" #include /* memset/memcpy */ #include #include /* malloc */ #define LINE_STYLE(attr) (((attr) >> 19) & 0xf) #define IS_UNICODE_AREA_CS(attr) ((attr) & (0x1 << 17)) /* Combination of IS_ITALIC, IS_BOLD, IS_FULLWIDTH, CS_REVISION_1 and * CHARSET(UNICODE AREA) */ #define VTFONT(attr) \ IS_UNICODE_AREA_CS(attr) \ ? ((((attr) >> 5) & 0xf00) | ISO10646_UCS4_1 | (((attr) << 7) & 0xff000)) \ : (((attr) >> 5) & 0xfff) #define IS_BLINKING(attr) ((attr) & (0x1 << 18)) #define IS_ITALIC(attr) ((attr) & (0x1 << 16)) #define IS_BOLD(attr) ((attr) & (0x1 << 15)) #define IS_FULLWIDTH(attr) ((attr) & (0x1 << 14)) #define COLUMNS(attr) ((((attr) >> 14) & 0x1) + 1); #define CHARSET(attr) \ IS_UNICODE_AREA_CS(attr) ? (ISO10646_UCS4_1 | (((attr) >> 5) & 0x100)) : (((attr) >> 5) & 0x1ff) #define IS_REVERSED(attr) ((attr) & (0x1 << 4)) #define REVERSE_COLOR(attr) ((attr) |= (0x1 << 4)) #define RESTORE_COLOR(attr) ((attr) &= ~(0x1 << 4)) #define IS_PROTECTED(attr) ((attr) & (0x1 << 3)) #define IS_COMB(attr) ((attr) & (0x1 << 2)) #define IS_COMB_TRAILING(attr) ((attr) & (0x1 << 1)) #define SET_COMB_TRAILING(attr) ((attr) |= (0x1 << 1)) #define UNSET_COMB_TRAILING(attr) ((attr) &= 0xfffffd) #define IS_SINGLE_CH(attr) ((attr)&0x1) #define USE_MULTI_CH(attr) ((attr) &= 0xfffffe) #define UNUSE_MULTI_CH(attr) ((attr) |= 0x1) #define COMPOUND_ATTR(charset, is_fullwidth, is_bold, is_italic, is_unicode_area_cs, \ line_style, is_blinking, is_protected, is_comb) \ (((line_style) << 19) | ((is_blinking) << 18) | ((is_unicode_area_cs) << 17) | \ ((is_italic) << 16) | ((is_bold) << 15) | ((is_fullwidth) << 14) | ((charset) << 5) | \ ((is_protected) << 3) | ((is_comb) << 2) | 0x1) #define IS_ZEROWIDTH(c) ((c)->u.ch.attr2) /* --- static variables --- */ static int use_multi_col_char = 1; static struct { u_int32_t min; u_int32_t max; } * unicode_areas; static u_int num_unicode_areas; static u_int unicode_area_min; static u_int unicode_area_max; static int blink_visible = 1; /* --- static functions --- */ inline static u_int get_comb_size(vt_char_t *multi_ch) { u_int size; size = 0; while (IS_COMB_TRAILING(multi_ch->u.ch.attr)) { size++; multi_ch++; } return size; } static vt_char_t *new_comb(vt_char_t *ch, u_int *comb_size_ptr) { vt_char_t *multi_ch; u_int comb_size; if (IS_SINGLE_CH(ch->u.ch.attr)) { if (IS_ZEROWIDTH(ch)) { /* * Zero width characters must not be combined to * show string like U+09b0 + U+200c + U+09cd + U+09af correctly. */ return NULL; } if ((multi_ch = malloc(sizeof(vt_char_t) * 2)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc() failed.\n"); #endif return NULL; } #ifndef __GLIBC__ if (sizeof(multi_ch) >= 8 && ((long)(multi_ch)&0x1UL) != 0) { bl_msg_printf( "Your malloc() doesn't return 2 bits aligned address." "Character combining is not supported.\n"); return NULL; } #endif vt_char_init(multi_ch); vt_char_copy(multi_ch, ch); comb_size = 1; if (comb_size > 10) { abort(); } } else { if (IS_ZEROWIDTH(ch->u.multi_ch)) { /* * Zero width characters must not be combined to * show string like U+09b0 + U+200c + U+09cd + U+09af correctly. */ return NULL; } if ((comb_size = get_comb_size(ch->u.multi_ch)) >= MAX_COMB_SIZE) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " This char is already combined by %d chars, so no more combined.\n", comb_size); #endif return NULL; } if ((multi_ch = realloc(ch->u.multi_ch, sizeof(vt_char_t) * (comb_size + 2))) == NULL) { return NULL; } #ifndef __GLIBC__ if (sizeof(multi_ch) >= 8 && ((long)(multi_ch)&0x1UL) != 0) { bl_msg_printf( "Your malloc() doesn't return 2 bits aligned address." "Character combining is not supported.\n"); return 0; } #endif comb_size++; } SET_COMB_TRAILING((multi_ch[comb_size - 1]).u.ch.attr); ch->u.multi_ch = multi_ch; USE_MULTI_CH(ch->u.ch.attr); /* necessary for 64bit big endian */ *comb_size_ptr = comb_size; return multi_ch + comb_size; } #ifdef USE_NORMALIZE #include int vt_normalize(u_int16_t *str, int num); static void normalize(vt_char_t *ch, u_int comb_size) { u_int16_t *str; if ((str = alloca(sizeof(*str) * (comb_size + 1)))) { vt_char_t *multi_ch; u_int count; multi_ch = ch->u.multi_ch; for (count = 0; count < comb_size + 1; count++) { str[count] = vt_char_code(multi_ch + count); } if (vt_normalize(str, comb_size + 1) == 1) { *ch = *multi_ch; ch->u.ch.code = str[0]; UNSET_COMB_TRAILING(ch->u.ch.attr); free(multi_ch); } } } #endif /* --- global functions --- */ void vt_set_use_multi_col_char(int use_it) { use_multi_col_char = use_it; } int vt_get_unicode_area(vt_font_t font, int *min, int *max) { u_int idx; if (/* FONT_CS(font) == ISO10646_UCS4_1 && */ (idx = UNICODE_AREA(font)) && idx <= num_unicode_areas) { *min = unicode_areas[idx - 1].min; *max = unicode_areas[idx - 1].max; return 1; } else { return 0; } } vt_font_t vt_get_unicode_area_font(u_int32_t min, /* min <= max */ u_int32_t max /* min <= max */) { u_int idx; void *p; for (idx = num_unicode_areas; idx > 0; idx--) { if (min == unicode_areas[idx - 1].min && max == unicode_areas[idx - 1].max) { return ISO10646_UCS4_1 | (idx << 12); } } if (num_unicode_areas == 255 /* Max is 2^8-1 */ || !(p = realloc(unicode_areas, sizeof(*unicode_areas) * (num_unicode_areas + 1)))) { bl_msg_printf("No more unicode areas.\n"); return UNKNOWN_CS; } if (num_unicode_areas == 0) { unicode_area_min = min; unicode_area_max = max; } else { if (unicode_area_min > min) { unicode_area_min = min; } if (unicode_area_max < max) { unicode_area_max = max; } } unicode_areas = p; unicode_areas[num_unicode_areas].min = min; unicode_areas[num_unicode_areas++].max = max; return ISO10646_UCS4_1 | (num_unicode_areas << 12); } void vt_set_blink_chars_visible(int visible) { blink_visible = visible; } /* * character functions */ void vt_char_init(vt_char_t *ch) { if (sizeof(vt_char_t *) != sizeof(vt_char_t)) { /*ILP32*/ memset(ch, 0, sizeof(vt_char_t)); /* set u.ch.is_single_ch */ ch->u.ch.attr = 0x1; } else { /*LP64*/ /* LSB of multi_ch must be "is_single_ch" */ ch->u.multi_ch = (vt_char_t *)0x1; } } void vt_char_final(vt_char_t *ch) { if (!IS_SINGLE_CH(ch->u.ch.attr)) { free(ch->u.multi_ch); } } void vt_char_set(vt_char_t *ch, u_int32_t code, ef_charset_t cs, int is_fullwidth, int is_comb, vt_color_t fg_color, vt_color_t bg_color, int is_bold, int is_italic, int line_style, int is_blinking, int is_protected) { u_int idx; vt_char_final(ch); ch->u.ch.code = code; if (unicode_area_min <= code && cs == ISO10646_UCS4_1 && code <= unicode_area_max) { /* * If code == 0, unicode_area_max == 0 and unicode_area_min == 0, * enter this block unexpectedly, but harmless. */ if ((idx = num_unicode_areas) == 1) { cs = 1; } else { do { if (unicode_areas[idx - 1].min <= code && code <= unicode_areas[idx - 1].max) { cs = idx; break; } } while (--idx > 0); } } else { idx = 0; } #if 1 /* * 0 should be returned for all zero-width characters of Unicode, * but 0 is returned for following characters alone for now. * 200C;ZERO WIDTH NON-JOINER * 200D;ZERO WIDTH JOINER * 200E;LEFT-TO-RIGHT MARK * 200F;RIGHT-TO-LEFT MARK * 202A;LEFT-TO-RIGHT EMBEDDING * 202B;RIGHT-TO-LEFT EMBEDDING * 202C;POP DIRECTIONAL FORMATTING * 202D;LEFT-TO-RIGHT OVERRIDE * 202E;RIGHT-TO-LEFT OVERRIDE * * see is_noconv_unicode() in vt_parser.c */ if ((code & ~0x2f) == 0x2000 /* 0x2000-0x2000f or 0x2020-0x202f */ && cs == ISO10646_UCS4_1 && ((0x200c <= code && code <= 0x200f) || (0x202a <= code && code <= 0x202e))) { ch->u.ch.attr2 = 1; /* is zerowidth */ } else #endif { ch->u.ch.attr2 = 0; } ch->u.ch.attr = COMPOUND_ATTR(cs, is_fullwidth != 0, is_bold != 0, is_italic != 0, idx > 0, line_style, is_blinking != 0, is_protected != 0, is_comb != 0); ch->u.ch.fg_color = fg_color; ch->u.ch.bg_color = bg_color; } void vt_char_change_attr(vt_char_t *ch, int is_bold, /* 0: don't change, 1: set, -1: unset */ int is_italic, /* 0: don't change, 1: set, -1: unset */ int underline_style, /* 0: don't change, 1,2: set, -1: unset */ int is_blinking, /* 0: don't change, 1: set, -1: unset */ int is_reversed, /* 0: don't change, 1: set, -1: unset */ int is_crossed_out, /* 0: don't change, 1: set, -1: unset */ int is_overlined /* 0: don't change, 1: set, -1: unset */) { u_int attr; attr = ch->u.ch.attr; if (IS_SINGLE_CH(attr)) { int line_style = LINE_STYLE(attr); if (is_overlined) { if (is_overlined > 0) { line_style |= LS_OVERLINE; } else { line_style &= ~LS_OVERLINE; } } if (is_crossed_out) { if (is_crossed_out > 0) { line_style |= LS_CROSSED_OUT; } else { line_style &= ~LS_CROSSED_OUT; } } if (underline_style) { line_style &= ~LS_UNDERLINE; if (underline_style > 0) { line_style |= underline_style; } } ch->u.ch.attr = COMPOUND_ATTR(CHARSET(attr), IS_FULLWIDTH(attr) != 0, is_bold ? is_bold > 0 : IS_BOLD(attr) != 0, is_italic ? is_italic > 0 : IS_ITALIC(attr) != 0, IS_UNICODE_AREA_CS(attr) != 0, line_style, is_blinking ? is_blinking > 0 : IS_BLINKING(attr) != 0, IS_PROTECTED(attr) != 0, IS_COMB(attr) != 0) | (is_reversed ? (is_reversed > 0 ? IS_REVERSED(0xffffff) : IS_REVERSED(0)) : IS_REVERSED(attr)); } } void vt_char_reverse_attr(vt_char_t *ch, int bold, int italic, int underline_style, int blinking, int reversed, int crossed_out, int overlined) { u_int attr; attr = ch->u.ch.attr; if (IS_SINGLE_CH(attr)) { int line_style = LINE_STYLE(attr); if (overlined) { if (line_style & LS_OVERLINE) { line_style &= ~LS_OVERLINE; } else { line_style |= LS_OVERLINE; } } if (crossed_out) { if (line_style & LS_CROSSED_OUT) { line_style &= ~LS_CROSSED_OUT; } else { line_style |= LS_CROSSED_OUT; } } if (underline_style) { if (line_style & LS_UNDERLINE) { line_style &= ~LS_UNDERLINE; } else { line_style = (line_style & ~LS_UNDERLINE) | (underline_style > 0 ? underline_style : LS_UNDERLINE_SINGLE); } } ch->u.ch.attr = COMPOUND_ATTR(CHARSET(attr), IS_FULLWIDTH(attr) != 0, bold ? !IS_BOLD(attr) : IS_BOLD(attr) != 0, italic ? !IS_ITALIC(attr) : IS_ITALIC(attr) != 0, IS_UNICODE_AREA_CS(attr) != 0, line_style, blinking ? !IS_BLINKING(attr) : IS_BLINKING(attr) != 0, IS_PROTECTED(attr) != 0, IS_COMB(attr) != 0) | (reversed ? (IS_REVERSED(attr) ? IS_REVERSED(0) : IS_REVERSED(0xffffff)) : IS_REVERSED(attr)); } } vt_char_t *vt_char_combine(vt_char_t *ch, u_int32_t code, ef_charset_t cs, int is_fullwidth, int is_comb, vt_color_t fg_color, vt_color_t bg_color, int is_bold, int is_italic, int line_style, int is_blinking, int is_protected) { vt_char_t *comb; u_int comb_size; /* * This check should be excluded, because characters whose is_comb flag * (combining property of mef) is NULL can be combined * if vt_is_arabic_combining(them) returns non-NULL. */ #if 0 if (!is_comb) { return NULL; } #endif #ifdef DEBUG if (!IS_ISCII(vt_char_cs(ch)) && IS_ISCII(cs)) { bl_debug_printf(BL_DEBUG_TAG " combining iscii char to non-iscii char.\n"); } #endif if (!(comb = new_comb(ch, &comb_size))) { return NULL; } vt_char_init(comb); vt_char_set(comb, code, cs, is_fullwidth, is_comb, fg_color, bg_color, is_bold, is_italic, line_style, is_blinking, is_protected); #ifdef USE_NORMALIZE normalize(ch, comb_size); #endif return comb; } vt_char_t *vt_char_combine_simple(vt_char_t *ch, vt_char_t *src) { vt_char_t *comb; u_int comb_size; /* * This check should be excluded, because characters whose is_comb flag * (combining property of mef) is NULL can be combined * if vt_is_arabic_combining(them) returns non-NULL. */ #if 0 if (!is_comb) { return NULL; } #endif if (!(comb = new_comb(ch, &comb_size))) { return NULL; } *comb = *src; UNSET_COMB_TRAILING(comb->u.ch.attr); #ifdef USE_NORMALIZE normalize(ch, comb_size); #endif return comb; } vt_char_t *vt_get_base_char(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { return ch; } else { return ch->u.multi_ch; } } vt_char_t *vt_get_combining_chars(vt_char_t *ch, u_int *size) { if (IS_SINGLE_CH(ch->u.ch.attr)) { *size = 0; return NULL; } else { *size = get_comb_size(ch->u.multi_ch); return ch->u.multi_ch + 1; } } vt_char_t *vt_get_picture_char(vt_char_t *ch) { if (!IS_SINGLE_CH(ch->u.ch.attr)) { ch = ch->u.multi_ch; if (IS_COMB_TRAILING(ch->u.ch.attr) && CHARSET(ch[1].u.ch.attr) == PICTURE_CHARSET) { return ch + 1; } } return NULL; } /* * Not used for now. */ #if 0 int vt_char_move(vt_char_t *dst, vt_char_t *src) { if (dst == src) { return 0; } vt_char_final(dst); memcpy(dst, src, sizeof(vt_char_t)); #if 0 /* invalidated src */ vt_char_init(src); #endif return 1; } #endif int vt_char_copy(vt_char_t *dst, vt_char_t *src) { if (dst == src) { return 0; } vt_char_final(dst); memcpy(dst, src, sizeof(vt_char_t)); if (!IS_SINGLE_CH(src->u.ch.attr)) { vt_char_t *multi_ch; u_int comb_size; comb_size = get_comb_size(src->u.multi_ch); if ((multi_ch = malloc(sizeof(vt_char_t) * (comb_size + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " failed to malloc.\n"); #endif return 0; } memcpy(multi_ch, src->u.multi_ch, sizeof(vt_char_t) * (comb_size + 1)); dst->u.multi_ch = multi_ch; USE_MULTI_CH(dst->u.ch.attr); /* necessary for 64bit big endian */ } return 1; } u_int32_t vt_char_code(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { return ch->u.ch.code; } else { return vt_char_code(ch->u.multi_ch); } } void vt_char_set_code(vt_char_t *ch, u_int32_t code) { if (IS_SINGLE_CH(ch->u.ch.attr)) { ch->u.ch.code = code; } else { vt_char_set_code(ch->u.multi_ch, code); } } ef_charset_t vt_char_cs(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { return CHARSET(ch->u.ch.attr); } else { return vt_char_cs(ch->u.multi_ch); } } int vt_char_set_cs(vt_char_t *ch, ef_charset_t cs) { if (IS_SINGLE_CH(ch->u.ch.attr)) { if (IS_UNICODE_AREA_CS(ch->u.ch.attr)) { if (cs == ISO10646_UCS4_1_V) { ch->u.ch.attr |= (0x100 << 5); } else /* if( cs == ISO10646_UCS4_1) */ { ch->u.ch.attr &= ~(0x100 << 5); } } else { ch->u.ch.attr &= ~(MAX_CHARSET << 5); /* ~0x1ff (vt_font.h) */ ch->u.ch.attr |= (cs << 5); } } else { vt_char_set_cs(ch->u.multi_ch, cs); } return 1; } vt_font_t vt_char_font(vt_char_t *ch) { u_int attr; attr = ch->u.ch.attr; if (IS_SINGLE_CH(attr)) { return VTFONT(attr); } else { return vt_char_font(ch->u.multi_ch); } } u_int vt_char_cols(vt_char_t *ch) { u_int attr; attr = ch->u.ch.attr; if (IS_SINGLE_CH(attr)) { if (!use_multi_col_char) { return 1; } else { return COLUMNS(attr); } } else { return vt_char_cols(ch->u.multi_ch); } } /* * 'use_multi_col_char' not concerned. */ int vt_char_is_fullwidth(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { return IS_FULLWIDTH(ch->u.ch.attr); } else { return vt_char_is_fullwidth(ch->u.multi_ch); } } /* If true, nothing is shown in the screen. */ int vt_char_is_zerowidth(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { return IS_ZEROWIDTH(ch); } else { return vt_char_is_zerowidth(ch->u.multi_ch); } } int vt_char_is_comb(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { return IS_COMB(ch->u.ch.attr); } else { return vt_char_is_comb(ch->u.multi_ch); } } vt_color_t vt_char_fg_color(vt_char_t *ch) { u_int attr; attr = ch->u.ch.attr; if (IS_SINGLE_CH(attr)) { if (IS_REVERSED(attr)) { return (!IS_BLINKING(attr) || blink_visible) ? ch->u.ch.bg_color : ch->u.ch.fg_color; } else { return (!IS_BLINKING(attr) || blink_visible) ? ch->u.ch.fg_color : ch->u.ch.bg_color; } } else { return vt_char_fg_color(ch->u.multi_ch); } } void vt_char_set_fg_color(vt_char_t *ch, vt_color_t color) { if (IS_SINGLE_CH(ch->u.ch.attr)) { ch->u.ch.fg_color = color; } else { u_int count; u_int comb_size; comb_size = get_comb_size(ch->u.multi_ch); for (count = 0; count < comb_size + 1; count++) { #ifdef DEBUG if (CHARSET(ch->u.multi_ch[count].u.ch.attr) == ISO10646_UCS4_1_V) { bl_debug_printf(BL_DEBUG_TAG " Don't change bg_color" " of ISO10646_UCS4_1_V char after shaped.\n"); } #endif vt_char_set_fg_color(ch->u.multi_ch + count, color); } } } vt_color_t vt_char_bg_color(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { return IS_REVERSED(ch->u.ch.attr) ? ch->u.ch.fg_color : ch->u.ch.bg_color; } else { return vt_char_bg_color(ch->u.multi_ch); } } void vt_char_set_bg_color(vt_char_t *ch, vt_color_t color) { if (IS_SINGLE_CH(ch->u.ch.attr)) { ch->u.ch.bg_color = color; } else { u_int count; u_int comb_size; comb_size = get_comb_size(ch->u.multi_ch); for (count = 0; count < comb_size + 1; count++) { #ifdef DEBUG if (CHARSET(ch->u.multi_ch[count].u.ch.attr) == ISO10646_UCS4_1_V) { bl_debug_printf(BL_DEBUG_TAG " Don't change bg_color" " of ISO10646_UCS4_1_V char after shaped.\n"); } #endif vt_char_set_bg_color(ch->u.multi_ch + count, color); } } } int vt_char_get_offset(vt_char_t *ch) { u_int attr; attr = ch->u.ch.attr; if (IS_SINGLE_CH(attr) && CHARSET(attr) == ISO10646_UCS4_1_V) { int8_t offset; offset = ch->u.ch.bg_color; /* unsigned -> signed */ return offset; } else { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " vt_char_get_position() accepts " "ISO10646_UCS4_1_V char alone, but received %x charset.\n", vt_char_cs(ch)); #endif return 0; } } u_int vt_char_get_width(vt_char_t *ch) { u_int attr; attr = ch->u.ch.attr; if (IS_SINGLE_CH(attr) && CHARSET(attr) == ISO10646_UCS4_1_V) { return ch->u.ch.fg_color; } else { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " vt_char_get_width() accepts " "ISO10646_UCS4_1_V char alone, but received %x charset.\n", vt_char_cs(ch)); #endif return 0; } } int vt_char_set_position(vt_char_t *ch, u_int8_t offset, /* signed -> unsigned */ u_int8_t width) { u_int attr; attr = ch->u.ch.attr; if (IS_SINGLE_CH(attr) && CHARSET(attr) == ISO10646_UCS4_1_V) { ch->u.ch.bg_color = offset; ch->u.ch.fg_color = width; return 1; } else { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " vt_char_set_position() accepts " "ISO10646_UCS4_1_V char alone, but received %x charset.\n", vt_char_cs(ch)); #endif return 0; } } int vt_char_line_style(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { return LINE_STYLE(ch->u.ch.attr); } else { return vt_char_line_style(ch->u.multi_ch); } } int vt_char_is_blinking(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { return IS_BLINKING(ch->u.ch.attr); } else { return vt_char_is_blinking(ch->u.multi_ch); } } int vt_char_is_protected(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { return IS_PROTECTED(ch->u.ch.attr); } else { return vt_char_is_protected(ch->u.multi_ch); } } int vt_char_reverse_color(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { if (IS_REVERSED(ch->u.ch.attr)) { return 0; } REVERSE_COLOR(ch->u.ch.attr); return 1; } else { u_int count; u_int comb_size; comb_size = get_comb_size(ch->u.multi_ch); for (count = 0; count < comb_size + 1; count++) { vt_char_reverse_color(ch->u.multi_ch + count); } return 1; } } int vt_char_restore_color(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { if (!IS_REVERSED(ch->u.ch.attr)) { return 0; } RESTORE_COLOR(ch->u.ch.attr); return 1; } else { u_int count; u_int comb_size; comb_size = get_comb_size(ch->u.multi_ch); for (count = 0; count < comb_size + 1; count++) { vt_char_restore_color(ch->u.multi_ch + count); } return 1; } } int vt_char_is_null(vt_char_t *ch) { if (IS_SINGLE_CH(ch->u.ch.attr)) { return ch->u.ch.code == 0; } else { return vt_char_is_null(ch->u.multi_ch); } } /* * XXX * Returns inaccurate result in dealing with combined characters. * Even if they have the same code, false is returned since * vt_char_t:multi_ch-s never point the same address.) */ int vt_char_equal(vt_char_t *ch1, vt_char_t *ch2) { return memcmp(ch1, ch2, sizeof(vt_char_t)) == 0; } int vt_char_code_is(vt_char_t *ch, u_int32_t code, ef_charset_t cs) { if (IS_SINGLE_CH(ch->u.ch.attr)) { /* * XXX * gcc 4.8.2 output codes to cause unexpected result without * () before and after &&. */ if ((CHARSET(ch->u.ch.attr) == cs) && (ch->u.ch.code == code)) { return 1; } else { return 0; } } else { return vt_char_code_is(ch->u.multi_ch, code, cs); } } int vt_char_code_equal(vt_char_t *ch1, vt_char_t *ch2) { vt_char_t *comb1; vt_char_t *comb2; u_int comb1_size; u_int comb2_size; u_int count; if (vt_char_code(ch1) != vt_char_code(ch2)) { return 0; } comb1 = vt_get_combining_chars(ch1, &comb1_size); comb2 = vt_get_combining_chars(ch2, &comb2_size); if (comb1_size != comb2_size) { return 0; } for (count = 0; count < comb1_size; count++) { if (comb1[count].u.ch.code != comb2[count].u.ch.code) { return 0; } } return 1; } vt_char_t *vt_sp_ch(void) { static vt_char_t sp_ch; if (sp_ch.u.ch.attr == 0) { vt_char_init(&sp_ch); vt_char_set(&sp_ch, ' ', US_ASCII, 0, 0, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0); } return &sp_ch; } vt_char_t *vt_nl_ch(void) { static vt_char_t nl_ch; if (nl_ch.u.ch.attr == 0) { vt_char_init(&nl_ch); vt_char_set(&nl_ch, '\n', US_ASCII, 0, 0, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0); } return &nl_ch; } #ifdef DEBUG #if 0 #define DUMP_HEX #endif /* * for debugging. */ void vt_char_dump(vt_char_t *ch) { u_int comb_size; vt_char_t *comb_chars; #ifdef DUMP_HEX bl_msg_printf("[%.4x]", vt_char_code(ch)); #else if (vt_char_code(ch) >= 0x100) { if (vt_char_cs(ch) == JISX0208_1983) { /* only eucjp */ bl_msg_printf("%c%c", ((vt_char_code(ch) >> 8) & 0xff) | 0x80, (vt_char_code(ch) & 0xff) | 0x80); } else { bl_msg_printf("**"); } } else { bl_msg_printf("%c", vt_char_code(ch)); } #endif comb_chars = vt_get_combining_chars(ch, &comb_size); for (; comb_size > 0; comb_size--) { vt_char_dump(comb_chars++); } } #endif mlterm-3.8.9/vtemu/vt_char.h010064400017600000144000000142101356600660700144770ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_CHAR_H__ #define __VT_CHAR_H__ #include #include /* WORDS_BIGENDIAN */ #include /* ef_charset_t */ #include "vt_font.h" #include "vt_color.h" #define MAX_COMB_SIZE 7 /* Used in vt_shape.c,x_screen.c,vt_screen.c */ #define UTF_MAX_SIZE 6 /* see skk/dict.c */ /* * XXX * char prefixes are max 4 bytes. * additional 3 bytes + cs name len ("viscii1.1-1" is max 11 bytes) = * 14 bytes for iso2022 extension. * char length is max 2 bytes. * (total 20 bytes) */ #define XCT_MAX_SIZE 20 #define VTCHAR_UTF_MAX_SIZE (UTF_MAX_SIZE * (MAX_COMB_SIZE + 1)) #define VTCHAR_XCT_MAX_SIZE (XCT_MAX_SIZE * (MAX_COMB_SIZE + 1)) /* For inline pictures (see x_picture.c) */ #define PICTURE_CHARSET 0x1ff #define PICTURE_ID_BITS 9 /* fg or bg color */ #define PICTURE_POS_BITS 23 /* code (Can be shrunk to 21 bits) */ #define LS_UNDERLINE (LS_UNDERLINE_SINGLE|LS_UNDERLINE_DOUBLE) /* * If a new entry is added, check if the size of vt_storable_states_t::line_style * is sufficient or not. */ typedef enum { LS_NOLINE = 0x0, LS_UNDERLINE_SINGLE = 0x1, LS_UNDERLINE_DOUBLE = 0x2, LS_OVERLINE = 0x4, LS_CROSSED_OUT = 0x8, } vt_line_style_t; /* * This object size should be kept as small as possible. * (ILP32: 64bit) (LP64: 64bit) * * If LSB of vt_char_t.u.ch.attr is 0, * vt_char_t.u.ch is invalid. * vt_char_t.u.multi_ch -> vt_char_t [main char] * -> vt_char_t [first combining char] * -> vt_char_t [second combining char] * ..... */ typedef struct vt_char { union { struct { /* * attr member contents. * Total 23 bit * 4 bit : vt_char_attr_line_style_t * 1 bit : is_blinking(0 or 1) * 1 bit : is unicode area cs(0 or 1) * 1 bit : is_italic(0 or 1) -+ * 1 bit : is_bold(0 or 1) |__\ vt_font_t * 1 bit : is_fullwidth(0 or 1) | * 9 bit : charset(0x0 - 0x1ff) or -+ * 1 bit: CS_REVISION_1(ISO10646_UCS4_1_V(*)) * 8 bit: unicode area id * 1 bit : is_reversed(0 or 1) ... used for X Selection * 1 bit : is_protected(0 or 1) * 1 bit : is_comb(0 or 1) * 1 bit : is_comb_trailing(0 or 1) * --- * 1 bit : is_single_ch(0 or 1) * * (*) ISO10646_UCS4_1_V is set during being shaped. * (See vt_shape.c and vt_char_set_cs()) * * attr2 member contents. * Total 2 bit * 1 bit : unused * 1 bit : is_zerowidth(0 or 1) */ #ifdef WORDS_BIGENDIAN u_int code : 21; u_int attr2 : 2; u_int fg_color : 9; u_int bg_color : 9; u_int attr : 23; #else u_int attr : 23; u_int fg_color : 9; u_int bg_color : 9; u_int attr2 : 2; u_int code : 21; #endif } ch; /* * 32 bits(on ILP32) or 64 bits(on LP64). * LSB(used for is_single_ch) is considered 0. */ struct vt_char *multi_ch; } u; } vt_char_t; void vt_set_use_multi_col_char(int use_it); int vt_get_unicode_area(vt_font_t font, int *min, int *max); vt_font_t vt_get_unicode_area_font(u_int32_t min, u_int32_t max); void vt_set_blink_chars_visible(int visible); void vt_char_init(vt_char_t *ch); void vt_char_final(vt_char_t *ch); void vt_char_set(vt_char_t *ch, u_int32_t code, ef_charset_t cs, int is_fullwidth, int is_comb, vt_color_t fg_color, vt_color_t bg_color, int is_bold, int is_italic, int line_style, int is_blinking, int is_protected); void vt_char_change_attr(vt_char_t *ch, int is_bold, int is_italic, int underline_style, int is_blinking, int is_reversed, int crossed_out, int is_overlined); void vt_char_reverse_attr(vt_char_t *ch, int bold, int italic, int underline_style, int blinking, int reversed, int crossed_out, int overlined); vt_char_t *vt_char_combine(vt_char_t *ch, u_int32_t code, ef_charset_t cs, int is_fullwidth, int is_comb, vt_color_t fg_color, vt_color_t bg_color, int is_bold, int is_italic, int line_style, int is_blinking, int is_protected); /* set both fg and bg colors for reversing. */ #define vt_char_combine_picture(ch, id, pos) \ vt_char_combine(ch, pos, PICTURE_CHARSET, 0, 0, id, id, 0, 0, 0, 0, 0) vt_char_t *vt_char_combine_simple(vt_char_t *ch, vt_char_t *comb); vt_char_t *vt_get_base_char(vt_char_t *ch); vt_char_t *vt_get_combining_chars(vt_char_t *ch, u_int *size); vt_char_t *vt_get_picture_char(vt_char_t *ch); #if 0 /* * Not used for now. */ int vt_char_move(vt_char_t *dst, vt_char_t *src); #endif int vt_char_copy(vt_char_t *dst, vt_char_t *src); u_int32_t vt_char_code(vt_char_t *ch); void vt_char_set_code(vt_char_t *ch, u_int32_t code); ef_charset_t vt_char_cs(vt_char_t *ch); int vt_char_set_cs(vt_char_t *ch, ef_charset_t cs); int vt_char_is_comb(vt_char_t *ch); vt_font_t vt_char_font(vt_char_t *ch); u_int vt_char_cols(vt_char_t *ch); int vt_char_is_fullwidth(vt_char_t *ch); int vt_char_is_zerowidth(vt_char_t *ch); vt_color_t vt_char_fg_color(vt_char_t *ch); void vt_char_set_fg_color(vt_char_t *ch, vt_color_t color); #define vt_char_picture_id(ch) vt_char_fg_color(ch) #define vt_char_set_picture_id(ch, idx) vt_char_set_fg_color(ch, idx) vt_color_t vt_char_bg_color(vt_char_t *ch); void vt_char_set_bg_color(vt_char_t *ch, vt_color_t color); int vt_char_get_offset(vt_char_t *ch); u_int vt_char_get_width(vt_char_t *ch); int vt_char_set_position(vt_char_t *ch, u_int8_t offset, u_int8_t width); int vt_char_line_style(vt_char_t *ch); int vt_char_is_blinking(vt_char_t *ch); int vt_char_is_protected(vt_char_t *ch); int vt_char_reverse_color(vt_char_t *ch); int vt_char_restore_color(vt_char_t *ch); int vt_char_is_null(vt_char_t *ch); int vt_char_equal(vt_char_t *ch1, vt_char_t *ch2); int vt_char_code_is(vt_char_t *ch, u_int32_t code, ef_charset_t cs); int vt_char_code_equal(vt_char_t *ch1, vt_char_t *ch2); vt_char_t *vt_sp_ch(void); vt_char_t *vt_nl_ch(void); #ifdef DEBUG void vt_char_dump(vt_char_t *ch); #endif #endif mlterm-3.8.9/vtemu/vt_char_encoding.c010064400017600000144000000405771356600660700163570ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_char_encoding.h" #include /* sscanf */ #include /* bl_str_sep */ #include #include /* alloca */ #include /* bl_get_codeset */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* ef_iso2022_illegal_char */ #include "vt_drcs.h" typedef struct encoding_table { vt_char_encoding_t encoding; char *name; ef_parser_t *(*parser_new)(void); ef_conv_t *(*conv_new)(void); } encoding_table_t; /* --- static variables --- */ /* * !!! Notice !!! * The order should be the same as vt_char_encoding_t in vt_char_encoding.h * If the order is changed, x_font_manager.c:usascii_font_cs_table should be * also changed. */ static encoding_table_t encoding_table[] = { { VT_ISO8859_1, "ISO88591", ef_iso8859_1_parser_new, ef_iso8859_1_conv_new, }, { VT_ISO8859_2, "ISO88592", ef_iso8859_2_parser_new, ef_iso8859_2_conv_new, }, { VT_ISO8859_3, "ISO88593", ef_iso8859_3_parser_new, ef_iso8859_3_conv_new, }, { VT_ISO8859_4, "ISO88594", ef_iso8859_4_parser_new, ef_iso8859_4_conv_new, }, { VT_ISO8859_5, "ISO88595", ef_iso8859_5_parser_new, ef_iso8859_5_conv_new, }, { VT_ISO8859_6, "ISO88596", ef_iso8859_6_parser_new, ef_iso8859_6_conv_new, }, { VT_ISO8859_7, "ISO88597", ef_iso8859_7_parser_new, ef_iso8859_7_conv_new, }, { VT_ISO8859_8, "ISO88598", ef_iso8859_8_parser_new, ef_iso8859_8_conv_new, }, { VT_ISO8859_9, "ISO88599", ef_iso8859_9_parser_new, ef_iso8859_9_conv_new, }, { VT_ISO8859_10, "ISO885910", ef_iso8859_10_parser_new, ef_iso8859_10_conv_new, }, { VT_TIS620, "ISO885911", ef_tis620_2533_parser_new, ef_tis620_2533_conv_new, }, { VT_ISO8859_13, "ISO885913", ef_iso8859_13_parser_new, ef_iso8859_13_conv_new, }, { VT_ISO8859_14, "ISO885914", ef_iso8859_14_parser_new, ef_iso8859_14_conv_new, }, { VT_ISO8859_15, "ISO885915", ef_iso8859_15_parser_new, ef_iso8859_15_conv_new, }, { VT_ISO8859_16, "ISO885916", ef_iso8859_16_parser_new, ef_iso8859_16_conv_new, }, { VT_TCVN5712, "TCVN5712", ef_tcvn5712_3_1993_parser_new, ef_tcvn5712_3_1993_conv_new, }, { VT_ISCII_ASSAMESE, "ISCIIASSAMESE", ef_iscii_assamese_parser_new, ef_iscii_assamese_conv_new, }, { VT_ISCII_BENGALI, "ISCIIBENGALI", ef_iscii_bengali_parser_new, ef_iscii_bengali_conv_new, }, { VT_ISCII_GUJARATI, "ISCIIGUJARATI", ef_iscii_gujarati_parser_new, ef_iscii_gujarati_conv_new, }, { VT_ISCII_HINDI, "ISCIIHINDI", ef_iscii_hindi_parser_new, ef_iscii_hindi_conv_new, }, { VT_ISCII_KANNADA, "ISCIIKANNADA", ef_iscii_kannada_parser_new, ef_iscii_kannada_conv_new, }, { VT_ISCII_MALAYALAM, "ISCIIMALAYALAM", ef_iscii_malayalam_parser_new, ef_iscii_malayalam_conv_new, }, { VT_ISCII_ORIYA, "ISCIIORIYA", ef_iscii_oriya_parser_new, ef_iscii_oriya_conv_new, }, { VT_ISCII_PUNJABI, "ISCIIPUNJABI", ef_iscii_punjabi_parser_new, ef_iscii_punjabi_conv_new, }, { VT_ISCII_TELUGU, "ISCIITELUGU", ef_iscii_telugu_parser_new, ef_iscii_telugu_conv_new, }, { VT_VISCII, "VISCII", ef_viscii_parser_new, ef_viscii_conv_new, }, { VT_KOI8_R, "KOI8R", ef_koi8_r_parser_new, ef_koi8_r_conv_new, }, { VT_KOI8_U, "KOI8U", ef_koi8_u_parser_new, ef_koi8_u_conv_new, }, { VT_KOI8_T, "KOI8T", ef_koi8_t_parser_new, ef_koi8_t_conv_new, }, { VT_GEORGIAN_PS, "GEORGIANPS", ef_georgian_ps_parser_new, ef_georgian_ps_conv_new, }, { VT_CP1250, "CP1250", ef_cp1250_parser_new, ef_cp1250_conv_new, }, { VT_CP1251, "CP1251", ef_cp1251_parser_new, ef_cp1251_conv_new, }, { VT_CP1252, "CP1252", ef_cp1252_parser_new, ef_cp1252_conv_new, }, { VT_CP1253, "CP1253", ef_cp1253_parser_new, ef_cp1253_conv_new, }, { VT_CP1254, "CP1254", ef_cp1254_parser_new, ef_cp1254_conv_new, }, { VT_CP1255, "CP1255", ef_cp1255_parser_new, ef_cp1255_conv_new, }, { VT_CP1256, "CP1256", ef_cp1256_parser_new, ef_cp1256_conv_new, }, { VT_CP1257, "CP1257", ef_cp1257_parser_new, ef_cp1257_conv_new, }, { VT_CP1258, "CP1258", ef_cp1258_parser_new, ef_cp1258_conv_new, }, { VT_CP874, "CP874", ef_cp874_parser_new, ef_cp874_conv_new, }, { VT_UTF8, "UTF8", ef_utf8_parser_new, ef_utf8_conv_new, }, { VT_EUCJP, "EUCJP", ef_eucjp_parser_new, ef_eucjp_conv_new, }, { VT_EUCJISX0213, "EUCJISX0213", ef_eucjisx0213_parser_new, ef_eucjisx0213_conv_new, }, { VT_ISO2022JP, "ISO2022JP", ef_iso2022jp_7_parser_new, ef_iso2022jp_7_conv_new, }, { VT_ISO2022JP2, "ISO2022JP2", ef_iso2022jp2_parser_new, ef_iso2022jp2_conv_new, }, { VT_ISO2022JP3, "ISO2022JP3", ef_iso2022jp3_parser_new, ef_iso2022jp3_conv_new, }, { VT_SJIS, "SJIS", ef_sjis_parser_new, ef_sjis_conv_new, }, { VT_SJISX0213, "SJISX0213", ef_sjisx0213_parser_new, ef_sjisx0213_conv_new, }, { VT_EUCKR, "EUCKR", ef_euckr_parser_new, ef_euckr_conv_new, }, { VT_UHC, "UHC", ef_uhc_parser_new, ef_uhc_conv_new, }, { VT_JOHAB, "JOHAB", ef_johab_parser_new, ef_johab_conv_new, }, { VT_ISO2022KR, "ISO2022KR", ef_iso2022kr_parser_new, ef_iso2022kr_conv_new, }, { VT_BIG5, "BIG5", ef_big5_parser_new, ef_big5_conv_new, }, { VT_EUCTW, "EUCTW", ef_euctw_parser_new, ef_euctw_conv_new, }, { VT_BIG5HKSCS, "BIG5HKSCS", ef_big5hkscs_parser_new, ef_big5hkscs_conv_new, }, /* not listed in IANA. GB2312 is usually used instead. */ { VT_EUCCN, "EUCCN", ef_euccn_parser_new, ef_euccn_conv_new, }, { VT_GBK, "GBK", ef_gbk_parser_new, ef_gbk_conv_new, }, { VT_GB18030, "GB18030", ef_gb18030_2000_parser_new, ef_gb18030_2000_conv_new, }, { VT_HZ, "HZ", ef_hz_parser_new, ef_hz_conv_new, }, { VT_ISO2022CN, "ISO2022CN", ef_iso2022cn_parser_new, ef_iso2022cn_conv_new, }, /* * alternative names. * these are not used in vt_{parser|conv}_new , so parser_new/parser_conv * members are not necessary. */ { VT_TIS620, "TIS620", }, #if 0 /* XXX necessary ? */ { VT_EUCJP, "EXTENDEDUNIXCODEPACKEDFORMATFORJAPANESE", }, /* MIME */ { VT_EUCJP, "CSEUCPKDFMTJAPANESE", }, /* MIME */ #endif { VT_EUCJP, "UJIS" }, { VT_SJIS, "SHIFTJIS", }, /* MIME */ { VT_EUCKR, "KSC56011987", }, /* for IIS error page(IIS bug?) */ { VT_EUCCN, "GB2312", }, { VT_HZ, "HZGB2312", }, }; /* * MSB of these charsets are not set , but must be set manually for X font. * These charsets are placed in an ascending order. */ static u_int16_t /* ef_charset_t */ msb_set_cs_table[] = { JISX0201_KATA, ISO8859_1_R, ISO8859_2_R, ISO8859_3_R, ISO8859_4_R, ISO8859_5_R, ISO8859_6_R, ISO8859_7_R, ISO8859_8_R, ISO8859_9_R, ISO8859_10_R, TIS620_2533, ISO8859_13_R, ISO8859_14_R, ISO8859_15_R, ISO8859_16_R, TCVN5712_3_1993, }; static struct { u_int16_t ucs; u_char decsp; } ucs_to_decsp_table[] = { {0xa0, '_'}, {0xa3, '}'}, {0xb0, 'f'}, {0xb1, 'g'}, {0xb7, '~'}, {0x3c0, '{'}, {0x2260, '|'}, {0x2264, 'y'}, {0x2265, 'z'}, {0x23ba, 'o'}, {0x23bb, 'p'}, {0x23bc, 'r'}, {0x23bd, 's'}, {0x2409, 'b'}, {0x240a, 'e'}, {0x240b, 'i'}, {0x240c, 'c'}, {0x240d, 'd'}, {0x2424, 'h'}, {0x2500, 'q'}, {0x2502, 'x'}, {0x250c, 'l'}, {0x2510, 'k'}, {0x2514, 'm'}, {0x2518, 'j'}, {0x251c, 't'}, {0x2524, 'u'}, {0x252c, 'w'}, {0x2534, 'v'}, {0x253c, 'n'}, {0x2592, 'a'}, {0x25c6, '`'}, }; static void (*iso2022kr_conv_init)(ef_conv_t *); static void (*iso2022kr_parser_init)(ef_parser_t *); /* --- static functions --- */ static void ovrd_iso2022kr_conv_init(ef_conv_t *conv) { u_char buf[5]; ef_parser_t *parser; (*iso2022kr_conv_init)(conv); if ((parser = ef_iso2022kr_parser_new()) == NULL) { return; } /* designating KSC5601 to G1 */ (*parser->set_str)(parser, "\x1b$)Ca", 5); /* this returns sequence of designating KSC5601 to G1 */ (*conv->convert)(conv, buf, sizeof(buf), parser); (*parser->destroy)(parser); } static void ovrd_iso2022kr_parser_init(ef_parser_t *parser) { u_char buf[5]; ef_conv_t *conv; (*iso2022kr_parser_init)(parser); if ((conv = ef_iso2022kr_conv_new()) == NULL) { return; } /* designating KSC5601 to G1 */ (*parser->set_str)(parser, "\x1b$)Ca", 5); /* this returns sequence of designating KSC5601 to G1 */ (*conv->convert)(conv, buf, sizeof(buf), parser); (*conv->destroy)(conv); } static size_t iso2022_illegal_char(ef_conv_t *conv, u_char *dst, size_t dst_size, int *is_full, ef_char_t *ch) { if (ch->cs == ISO10646_UCS4_1) { vt_convert_unicode_pua_to_drcs(ch); } return ef_iso2022_illegal_char(conv, dst, dst_size, is_full, ch); } static size_t non_iso2022_illegal_char(ef_conv_t *conv, u_char *dst, size_t dst_size, int *is_full, ef_char_t *ch) { *is_full = 0; if (ch->cs == DEC_SPECIAL) { if (dst_size < 7) { *is_full = 1; return 0; } dst[0] = '\x1b'; dst[1] = '('; dst[2] = '0'; dst[3] = ch->ch[0]; dst[4] = '\x1b'; dst[5] = '('; dst[6] = 'B'; return 7; } else { return 0; } } static size_t utf8_illegal_char(ef_conv_t *conv, u_char *dst, size_t dst_size, int *is_full, ef_char_t *ch) { *is_full = 0; if (ch->cs == DEC_SPECIAL) { u_int16_t utf16; if (dst_size < 3) { *is_full = 1; } else if ((utf16 = vt_convert_decsp_to_ucs(ef_char_to_int(ch)))) { dst[0] = ((utf16 >> 12) & 0x0f) | 0xe0; dst[1] = ((utf16 >> 6) & 0x3f) | 0x80; dst[2] = (utf16 & 0x3f) | 0x80; return 3; } } return 0; } /* --- global functions --- */ char *vt_get_char_encoding_name(vt_char_encoding_t encoding) { if (encoding < 0 || MAX_CHAR_ENCODINGS <= encoding) { return "ISO88591"; } else { return encoding_table[encoding].name; } } vt_char_encoding_t vt_get_char_encoding(const char *name /* '_' and '-' are ignored. */ ) { int count; char *_name; char *encoding; char *p; /* * duplicating name so as not to destroy its memory. */ if ((_name = alloca(strlen(name) + 1)) == NULL || (encoding = alloca(strlen(name) + 1)) == NULL) { return VT_UNKNOWN_ENCODING; } strcpy(_name, name); encoding[0] = '\0'; /* * removing '-' and '_' from name. */ while ((p = bl_str_sep(&_name, "-_")) != NULL) { strcat(encoding, p); } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " encoding -> %s.\n", encoding); #endif if (strcasecmp(encoding, "auto") == 0) { /* * XXX * UTF-8 is used by default in cygwin, msys, win32, android and osx. * (On osx, if mlterm.app is started from Finder, * vt_get_char_encoding("auto") returns VT_ISO88591.) * Note that vt_get_char_encoding("auto") is used to set character encoding * of window/icon title string, not only to determine character encoding. * (see vt_parser.c) */ #if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(USE_WIN32API) && \ !defined(__ANDROID__) && !defined(__APPLE__) vt_char_encoding_t e; if ((e = vt_get_char_encoding(bl_get_codeset())) != VT_UNKNOWN_ENCODING) { return e; } #endif return VT_UTF8; } for (count = 0; count < sizeof(encoding_table) / sizeof(encoding_table_t); count++) { if (strcasecmp(encoding, encoding_table[count].name) == 0) { return encoding_table[count].encoding; } } return VT_UNKNOWN_ENCODING; } ef_parser_t *vt_char_encoding_parser_new(vt_char_encoding_t encoding) { ef_parser_t *parser; if (encoding < 0 || MAX_CHAR_ENCODINGS <= encoding || encoding_table[encoding].encoding != encoding) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " %d is illegal encoding.\n", encoding); #endif return NULL; } if ((parser = (*encoding_table[encoding].parser_new)()) == NULL) { return NULL; } if (encoding == VT_ISO2022KR) { /* overriding init method */ iso2022kr_parser_init = parser->init; parser->init = ovrd_iso2022kr_parser_init; (*parser->init)(parser); } return parser; } ef_conv_t *vt_char_encoding_conv_new(vt_char_encoding_t encoding) { ef_conv_t *conv; if (encoding < 0 || MAX_CHAR_ENCODINGS <= encoding || encoding_table[encoding].encoding != encoding) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " %d is illegal encoding.\n", encoding); #endif return NULL; } if ((conv = (*encoding_table[encoding].conv_new)()) == NULL) { return NULL; } if (encoding == VT_UTF8) { conv->illegal_char = utf8_illegal_char; } else if (IS_ENCODING_BASED_ON_ISO2022(encoding)) { if (encoding == VT_ISO2022KR) { /* overriding init method */ iso2022kr_conv_init = conv->init; conv->init = ovrd_iso2022kr_conv_init; (*conv->init)(conv); } } return conv; } int vt_is_msb_set(ef_charset_t cs) { if (msb_set_cs_table[0] <= cs && cs <= msb_set_cs_table[sizeof(msb_set_cs_table) / sizeof(msb_set_cs_table[0]) - 1]) { int count; for (count = 0; count < sizeof(msb_set_cs_table) / sizeof(msb_set_cs_table[0]); count++) { if (msb_set_cs_table[count] == cs) { return 1; } } } return 0; } size_t vt_char_encoding_convert(u_char *dst, size_t dst_len, vt_char_encoding_t dst_encoding, u_char *src, size_t src_len, vt_char_encoding_t src_encoding) { ef_parser_t *parser; size_t filled_len; if ((parser = vt_char_encoding_parser_new(src_encoding)) == NULL) { return 0; } (*parser->init)(parser); (*parser->set_str)(parser, src, src_len); filled_len = vt_char_encoding_convert_with_parser(dst, dst_len, dst_encoding, parser); (*parser->destroy)(parser); return filled_len; } size_t vt_char_encoding_convert_with_parser(u_char *dst, size_t dst_len, vt_char_encoding_t dst_encoding, ef_parser_t *parser) { ef_conv_t *conv; size_t filled_len; if ((conv = vt_char_encoding_conv_new(dst_encoding)) == NULL) { return 0; } (*conv->init)(conv); filled_len = (*conv->convert)(conv, dst, dst_len, parser); (*conv->destroy)(conv); return filled_len; } int vt_parse_unicode_area(const char *str, u_int *min, u_int *max) { if (sscanf(str, "U+%x-%x", min, max) != 2) { if (sscanf(str, "U+%x", min) != 1) { goto error; } else { *max = *min; } } else if (*min > *max) { goto error; } return 1; error: bl_msg_printf("Illegal unicode area format: %s\n", str); return 0; } /* XXX This function should be moved to mef */ u_char vt_convert_ucs_to_decsp(u_int16_t ucs) { int l_idx; int h_idx; int idx; l_idx = 0; h_idx = sizeof(ucs_to_decsp_table) / sizeof(ucs_to_decsp_table[0]) - 1; if (ucs < ucs_to_decsp_table[l_idx].ucs || ucs_to_decsp_table[h_idx].ucs < ucs) { return 0; } while (1) { idx = (l_idx + h_idx) / 2; if (ucs == ucs_to_decsp_table[idx].ucs) { return ucs_to_decsp_table[idx].decsp; } else if (ucs < ucs_to_decsp_table[idx].ucs) { h_idx = idx; } else { l_idx = idx + 1; } if (l_idx >= h_idx) { return 0; } } } /* XXX This function should be moved to mef */ u_int16_t vt_convert_decsp_to_ucs(u_char decsp) { if ('`' <= decsp && decsp <= 'x') { int count; for (count = 0; count < sizeof(ucs_to_decsp_table) / sizeof(ucs_to_decsp_table[0]); count++) { if (ucs_to_decsp_table[count].decsp == decsp) { return ucs_to_decsp_table[count].ucs; } } } return 0; } void vt_char_encoding_conv_set_use_loose_rule(ef_conv_t *conv, vt_char_encoding_t encoding, int flag) { if (flag) { if (IS_ENCODING_BASED_ON_ISO2022(encoding)) { conv->illegal_char = iso2022_illegal_char; } else { conv->illegal_char = non_iso2022_illegal_char; } } else { if (encoding == VT_UTF8) { conv->illegal_char = utf8_illegal_char; } else { conv->illegal_char = NULL; } } } mlterm-3.8.9/vtemu/vt_char_encoding.h010064400017600000144000000070621356600660700163540ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_CHAR_ENCODING_H__ #define __VT_CHAR_ENCODING_H__ #include /* u_char */ #include #include /* * Supported encodings are those which are not conflicted with US_ASCII. * So , UCS-2, UCS-4 etc encodings are not supported. */ typedef enum vt_char_encoding { VT_UNKNOWN_ENCODING = -1, VT_ISO8859_1 = 0, VT_ISO8859_2, VT_ISO8859_3, VT_ISO8859_4, VT_ISO8859_5, VT_ISO8859_6, VT_ISO8859_7, VT_ISO8859_8, VT_ISO8859_9, VT_ISO8859_10, VT_TIS620, VT_ISO8859_13, VT_ISO8859_14, VT_ISO8859_15, VT_ISO8859_16, VT_TCVN5712, VT_ISCII_ASSAMESE, VT_ISCII_BENGALI, VT_ISCII_GUJARATI, VT_ISCII_HINDI, VT_ISCII_KANNADA, VT_ISCII_MALAYALAM, VT_ISCII_ORIYA, VT_ISCII_PUNJABI, VT_ISCII_TELUGU, VT_VISCII, VT_KOI8_R, VT_KOI8_U, VT_KOI8_T, VT_GEORGIAN_PS, VT_CP1250, VT_CP1251, VT_CP1252, VT_CP1253, VT_CP1254, VT_CP1255, VT_CP1256, VT_CP1257, VT_CP1258, VT_CP874, VT_UTF8, VT_EUCJP, VT_EUCJISX0213, VT_ISO2022JP, VT_ISO2022JP2, VT_ISO2022JP3, VT_SJIS, VT_SJISX0213, VT_EUCKR, VT_UHC, VT_JOHAB, VT_ISO2022KR, VT_BIG5, VT_EUCTW, VT_BIG5HKSCS, VT_EUCCN, VT_GBK, VT_GB18030, VT_HZ, VT_ISO2022CN, MAX_CHAR_ENCODINGS } vt_char_encoding_t; #define IS_ISO8859_VARIANT(encoding) (VT_ISO8859_1 <= (encoding) && (encoding) <= VT_TCVN5712) #define IS_8BIT_ENCODING(encoding) (VT_ISO8859_1 <= (encoding) && (encoding) <= VT_CP874) #define IS_ENCODING_BASED_ON_ISO2022(encoding) \ (IS_ISO8859_VARIANT(encoding) || (VT_EUCJP <= (encoding) && (encoding) <= VT_ISO2022JP3) || \ VT_EUCKR == (encoding) || VT_ISO2022KR == (encoding) || VT_EUCTW == (encoding) || \ VT_ISO2022CN == (encoding) || VT_EUCCN == (encoding)) /* ISO2022KR is subset and EUC-TW is not subset */ #define IS_UCS_SUBSET_ENCODING(encoding) \ ((encoding) != VT_ISO2022JP && (encoding) != VT_ISO2022JP2 && (encoding) != VT_ISO2022JP3 && \ (encoding) != VT_ISO2022CN && (encoding) != VT_EUCTW) /* 0x0 - 0x7f is not necessarily US-ASCII */ #define IS_STATEFUL_ENCODING(encoding) \ ((encoding) == VT_ISO2022JP || (encoding) == VT_ISO2022JP2 || (encoding) == VT_ISO2022JP3 || \ (encoding) == VT_ISO2022KR || (encoding) == VT_ISO2022CN || (encoding) == VT_HZ) #define IS_ISCII_ENCODING(encoding) \ (VT_ISCII_ASSAMESE <= (encoding) && (encoding) <= VT_ISCII_TELUGU) char *vt_get_char_encoding_name(vt_char_encoding_t encoding); vt_char_encoding_t vt_get_char_encoding(const char *name); ef_parser_t *vt_char_encoding_parser_new(vt_char_encoding_t encoding); ef_conv_t *vt_char_encoding_conv_new(vt_char_encoding_t encoding); int vt_is_msb_set(ef_charset_t cs); size_t vt_char_encoding_convert(u_char *dst, size_t dst_len, vt_char_encoding_t dst_encoding, u_char *src, size_t src_len, vt_char_encoding_t src_encoding); size_t vt_char_encoding_convert_with_parser(u_char *dst, size_t dst_len, vt_char_encoding_t dst_encoding, ef_parser_t *parser); int vt_parse_unicode_area(const char *str, u_int *min, u_int *max); u_char vt_convert_ucs_to_decsp(u_int16_t ucs); u_int16_t vt_convert_decsp_to_ucs(u_char decsp); void vt_char_encoding_conv_set_use_loose_rule(ef_conv_t *conv, vt_char_encoding_t encoding, int flag); #endif mlterm-3.8.9/vtemu/vt_color.c010064400017600000144000000600411356600660700146760ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_color.h" #include /* sscanf */ #include /* strcmp */ #include #include #include #include #include #include /* strdup */ typedef struct rgb { u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; } rgb_t; BL_MAP_TYPEDEF(color_rgb, vt_color_t, rgb_t); /* --- static variables --- */ static char *color_name_table[] = { "hl_black", "hl_red", "hl_green", "hl_yellow", "hl_blue", "hl_magenta", "hl_cyan", "hl_white", }; static u_int8_t vtsys_color_rgb_table[][3] = { {0x00, 0x00, 0x00}, {0xcd, 0x00, 0x00}, {0x00, 0xcd, 0x00}, {0xcd, 0xcd, 0x00}, {0x00, 0x00, 0xee}, {0xcd, 0x00, 0xcd}, {0x00, 0xcd, 0xcd}, {0xe5, 0xe5, 0xe5}, {0x7f, 0x7f, 0x7f}, {0xff, 0x00, 0x00}, {0x00, 0xff, 0x00}, {0xff, 0xff, 0x00}, {0x5c, 0x5c, 0xff}, {0xff, 0x00, 0xff}, {0x00, 0xff, 0xff}, {0xff, 0xff, 0xff}, }; #if 0 static u_int8_t color256_rgb_table[][3] = { /* CUBE COLOR(0x10-0xe7) */ {0x00, 0x00, 0x00}, {0x00, 0x00, 0x5f}, {0x00, 0x00, 0x87}, {0x00, 0x00, 0xaf}, {0x00, 0x00, 0xd7}, {0x00, 0x00, 0xff}, {0x00, 0x5f, 0x00}, {0x00, 0x5f, 0x5f}, {0x00, 0x5f, 0x87}, {0x00, 0x5f, 0xaf}, {0x00, 0x5f, 0xd7}, {0x00, 0x5f, 0xff}, {0x00, 0x87, 0x00}, {0x00, 0x87, 0x5f}, {0x00, 0x87, 0x87}, {0x00, 0x87, 0xaf}, {0x00, 0x87, 0xd7}, {0x00, 0x87, 0xff}, {0x00, 0xaf, 0x00}, {0x00, 0xaf, 0x5f}, {0x00, 0xaf, 0x87}, {0x00, 0xaf, 0xaf}, {0x00, 0xaf, 0xd7}, {0x00, 0xaf, 0xff}, {0x00, 0xd7, 0x00}, {0x00, 0xd7, 0x5f}, {0x00, 0xd7, 0x87}, {0x00, 0xd7, 0xaf}, {0x00, 0xd7, 0xd7}, {0x00, 0xd7, 0xff}, {0x00, 0xff, 0x00}, {0x00, 0xff, 0x5f}, {0x00, 0xff, 0x87}, {0x00, 0xff, 0xaf}, {0x00, 0xff, 0xd7}, {0x00, 0xff, 0xff}, {0x5f, 0x00, 0x00}, {0x5f, 0x00, 0x5f}, {0x5f, 0x00, 0x87}, {0x5f, 0x00, 0xaf}, {0x5f, 0x00, 0xd7}, {0x5f, 0x00, 0xff}, {0x5f, 0x5f, 0x00}, {0x5f, 0x5f, 0x5f}, {0x5f, 0x5f, 0x87}, {0x5f, 0x5f, 0xaf}, {0x5f, 0x5f, 0xd7}, {0x5f, 0x5f, 0xff}, {0x5f, 0x87, 0x00}, {0x5f, 0x87, 0x5f}, {0x5f, 0x87, 0x87}, {0x5f, 0x87, 0xaf}, {0x5f, 0x87, 0xd7}, {0x5f, 0x87, 0xff}, {0x5f, 0xaf, 0x00}, {0x5f, 0xaf, 0x5f}, {0x5f, 0xaf, 0x87}, {0x5f, 0xaf, 0xaf}, {0x5f, 0xaf, 0xd7}, {0x5f, 0xaf, 0xff}, {0x5f, 0xd7, 0x00}, {0x5f, 0xd7, 0x5f}, {0x5f, 0xd7, 0x87}, {0x5f, 0xd7, 0xaf}, {0x5f, 0xd7, 0xd7}, {0x5f, 0xd7, 0xff}, {0x5f, 0xff, 0x00}, {0x5f, 0xff, 0x5f}, {0x5f, 0xff, 0x87}, {0x5f, 0xff, 0xaf}, {0x5f, 0xff, 0xd7}, {0x5f, 0xff, 0xff}, {0x87, 0x00, 0x00}, {0x87, 0x00, 0x5f}, {0x87, 0x00, 0x87}, {0x87, 0x00, 0xaf}, {0x87, 0x00, 0xd7}, {0x87, 0x00, 0xff}, {0x87, 0x5f, 0x00}, {0x87, 0x5f, 0x5f}, {0x87, 0x5f, 0x87}, {0x87, 0x5f, 0xaf}, {0x87, 0x5f, 0xd7}, {0x87, 0x5f, 0xff}, {0x87, 0x87, 0x00}, {0x87, 0x87, 0x5f}, {0x87, 0x87, 0x87}, {0x87, 0x87, 0xaf}, {0x87, 0x87, 0xd7}, {0x87, 0x87, 0xff}, {0x87, 0xaf, 0x00}, {0x87, 0xaf, 0x5f}, {0x87, 0xaf, 0x87}, {0x87, 0xaf, 0xaf}, {0x87, 0xaf, 0xd7}, {0x87, 0xaf, 0xff}, {0x87, 0xd7, 0x00}, {0x87, 0xd7, 0x5f}, {0x87, 0xd7, 0x87}, {0x87, 0xd7, 0xaf}, {0x87, 0xd7, 0xd7}, {0x87, 0xd7, 0xff}, {0x87, 0xff, 0x00}, {0x87, 0xff, 0x5f}, {0x87, 0xff, 0x87}, {0x87, 0xff, 0xaf}, {0x87, 0xff, 0xd7}, {0x87, 0xff, 0xff}, {0xaf, 0x00, 0x00}, {0xaf, 0x00, 0x5f}, {0xaf, 0x00, 0x87}, {0xaf, 0x00, 0xaf}, {0xaf, 0x00, 0xd7}, {0xaf, 0x00, 0xff}, {0xaf, 0x5f, 0x00}, {0xaf, 0x5f, 0x5f}, {0xaf, 0x5f, 0x87}, {0xaf, 0x5f, 0xaf}, {0xaf, 0x5f, 0xd7}, {0xaf, 0x5f, 0xff}, {0xaf, 0x87, 0x00}, {0xaf, 0x87, 0x5f}, {0xaf, 0x87, 0x87}, {0xaf, 0x87, 0xaf}, {0xaf, 0x87, 0xd7}, {0xaf, 0x87, 0xff}, {0xaf, 0xaf, 0x00}, {0xaf, 0xaf, 0x5f}, {0xaf, 0xaf, 0x87}, {0xaf, 0xaf, 0xaf}, {0xaf, 0xaf, 0xd7}, {0xaf, 0xaf, 0xff}, {0xaf, 0xd7, 0x00}, {0xaf, 0xd7, 0x5f}, {0xaf, 0xd7, 0x87}, {0xaf, 0xd7, 0xaf}, {0xaf, 0xd7, 0xd7}, {0xaf, 0xd7, 0xff}, {0xaf, 0xff, 0x00}, {0xaf, 0xff, 0x5f}, {0xaf, 0xff, 0x87}, {0xaf, 0xff, 0xaf}, {0xaf, 0xff, 0xd7}, {0xaf, 0xff, 0xff}, {0xd7, 0x00, 0x00}, {0xd7, 0x00, 0x5f}, {0xd7, 0x00, 0x87}, {0xd7, 0x00, 0xaf}, {0xd7, 0x00, 0xd7}, {0xd7, 0x00, 0xff}, {0xd7, 0x5f, 0x00}, {0xd7, 0x5f, 0x5f}, {0xd7, 0x5f, 0x87}, {0xd7, 0x5f, 0xaf}, {0xd7, 0x5f, 0xd7}, {0xd7, 0x5f, 0xff}, {0xd7, 0x87, 0x00}, {0xd7, 0x87, 0x5f}, {0xd7, 0x87, 0x87}, {0xd7, 0x87, 0xaf}, {0xd7, 0x87, 0xd7}, {0xd7, 0x87, 0xff}, {0xd7, 0xaf, 0x00}, {0xd7, 0xaf, 0x5f}, {0xd7, 0xaf, 0x87}, {0xd7, 0xaf, 0xaf}, {0xd7, 0xaf, 0xd7}, {0xd7, 0xaf, 0xff}, {0xd7, 0xd7, 0x00}, {0xd7, 0xd7, 0x5f}, {0xd7, 0xd7, 0x87}, {0xd7, 0xd7, 0xaf}, {0xd7, 0xd7, 0xd7}, {0xd7, 0xd7, 0xff}, {0xd7, 0xff, 0x00}, {0xd7, 0xff, 0x5f}, {0xd7, 0xff, 0x87}, {0xd7, 0xff, 0xaf}, {0xd7, 0xff, 0xd7}, {0xd7, 0xff, 0xff}, {0xff, 0x00, 0x00}, {0xff, 0x00, 0x5f}, {0xff, 0x00, 0x87}, {0xff, 0x00, 0xaf}, {0xff, 0x00, 0xd7}, {0xff, 0x00, 0xff}, {0xff, 0x5f, 0x00}, {0xff, 0x5f, 0x5f}, {0xff, 0x5f, 0x87}, {0xff, 0x5f, 0xaf}, {0xff, 0x5f, 0xd7}, {0xff, 0x5f, 0xff}, {0xff, 0x87, 0x00}, {0xff, 0x87, 0x5f}, {0xff, 0x87, 0x87}, {0xff, 0x87, 0xaf}, {0xff, 0x87, 0xd7}, {0xff, 0x87, 0xff}, {0xff, 0xaf, 0x00}, {0xff, 0xaf, 0x5f}, {0xff, 0xaf, 0x87}, {0xff, 0xaf, 0xaf}, {0xff, 0xaf, 0xd7}, {0xff, 0xaf, 0xff}, {0xff, 0xd7, 0x00}, {0xff, 0xd7, 0x5f}, {0xff, 0xd7, 0x87}, {0xff, 0xd7, 0xaf}, {0xff, 0xd7, 0xd7}, {0xff, 0xd7, 0xff}, {0xff, 0xff, 0x00}, {0xff, 0xff, 0x5f}, {0xff, 0xff, 0x87}, {0xff, 0xff, 0xaf}, {0xff, 0xff, 0xd7}, {0xff, 0xff, 0xff}, /* GRAY SCALE COLOR(0xe8-0xff) */ {0x08, 0x08, 0x08}, {0x12, 0x12, 0x12}, {0x1c, 0x1c, 0x1c}, {0x26, 0x26, 0x26}, {0x30, 0x30, 0x30}, {0x3a, 0x3a, 0x3a}, {0x44, 0x44, 0x44}, {0x4e, 0x4e, 0x4e}, {0x58, 0x58, 0x58}, {0x62, 0x62, 0x62}, {0x6c, 0x6c, 0x6c}, {0x76, 0x76, 0x76}, {0x80, 0x80, 0x80}, {0x8a, 0x8a, 0x8a}, {0x94, 0x94, 0x94}, {0x9e, 0x9e, 0x9e}, {0xa8, 0xa8, 0xa8}, {0xb2, 0xb2, 0xb2}, {0xbc, 0xbc, 0xbc}, {0xc6, 0xc6, 0xc6}, {0xd0, 0xd0, 0xd0}, {0xda, 0xda, 0xda}, {0xe4, 0xe4, 0xe4}, {0xee, 0xee, 0xee}, }; #endif static char *color_file = "mlterm/color"; static BL_MAP(color_rgb) color_config; static u_int num_changed_256_colors; static struct { u_int is_changed : 1; u_int mark : 7; u_int8_t red; u_int8_t green; u_int8_t blue; } * ext_color_table; static u_int ext_color_mark = 1; static int color_distance_threshold = COLOR_DISTANCE_THRESHOLD; static int use_pseudo_color = 0; /* --- static functions --- */ static void get_default_rgb(vt_color_t color, /* is 255 or less */ u_int8_t *red, u_int8_t *green, u_int8_t *blue) { if (IS_VTSYS_COLOR(color)) { *red = vtsys_color_rgb_table[color][0]; *green = vtsys_color_rgb_table[color][1]; *blue = vtsys_color_rgb_table[color][2]; } else if (color <= 0xe7) { u_int8_t tmp; tmp = (color - 0x10) % 6; *blue = tmp ? (tmp * 40 + 55) & 0xff : 0; tmp = ((color - 0x10) / 6) % 6; *green = tmp ? (tmp * 40 + 55) & 0xff : 0; tmp = ((color - 0x10) / 36) % 6; *red = tmp ? (tmp * 40 + 55) & 0xff : 0; } else /* if( color >= 0xe8) */ { u_int8_t tmp; tmp = (color - 0xe8) * 10 + 8; *blue = tmp; *green = tmp; *red = tmp; } } static BL_PAIR(color_rgb) get_color_rgb_pair(vt_color_t color) { BL_PAIR(color_rgb) pair; bl_map_get(color_config, color, pair); return pair; } static int color_config_set_rgb(vt_color_t color, /* is 255 or less */ u_int8_t red, u_int8_t green, u_int8_t blue, u_int8_t alpha) { BL_PAIR(color_rgb) pair; int result; rgb_t rgb; rgb.red = red; rgb.green = green; rgb.blue = blue; rgb.alpha = alpha; if ((pair = get_color_rgb_pair(color))) { u_int8_t r; u_int8_t g; u_int8_t b; if (pair->value.red == red && pair->value.green == green && pair->value.blue == blue && pair->value.alpha == alpha) { /* Not changed */ #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " color %d rgb(%02x%02x%02x%02x) not changed.\n", color, red, green, blue, alpha); #endif return 0; } get_default_rgb(color, &r, &g, &b); if (r == red && g == green && b == blue && alpha == 0xff) { if (IS_256_COLOR(color)) { num_changed_256_colors--; } bl_map_erase_simple(result, color_config, color); } else { pair->value = rgb; } return 1; } else { u_int8_t r; u_int8_t g; u_int8_t b; /* * The same rgb as the default is rejected in 256 color. * The same rgb as the default is not rejected in sys color * for backward compatibility with 3.1.5 or before. (If rejected, * mlterm -fg hl_white doesn't work even if hl_white is defined * in ~/.mlterm/color.) */ if (IS_256_COLOR(color)) { if (!vt_get_color_rgba(color, &r, &g, &b, NULL)) { return 0; } if (red == r && green == g && blue == b && alpha == 0xff) { /* Not changed */ #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " color %d rgb(%02x%02x%02x%02x) not changed.\n", color, red, green, blue, alpha); #endif return 0; } #ifdef DEBUG else { bl_debug_printf(BL_DEBUG_TAG " color %d rgb(%02x%02x%02x) changed => %02x%02x%02x.\n", color, r, g, b, red, green, blue); } #endif num_changed_256_colors++; } bl_map_set(result, color_config, color, rgb); return result; } } static int color_config_get_rgb(vt_color_t color, u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_int8_t *alpha /* can be NULL */ ) { BL_PAIR(color_rgb) pair; if ((pair = get_color_rgb_pair(color)) == NULL) { return 0; } *red = pair->value.red; *blue = pair->value.blue; *green = pair->value.green; if (alpha) { *alpha = pair->value.alpha; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %d's rgb => %d %d %d\n", color, *red, *blue, *green); #endif return 1; } static int parse_conf(char *color_name, char *rgb) { u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; vt_color_t color; /* * Illegal color name is rejected. */ if ((color = vt_get_color(color_name)) == VT_UNKNOWN_COLOR) { return 0; } if (*rgb == '\0') { if (!get_color_rgb_pair(color)) { return 0; } else { int result; if (IS_256_COLOR(color)) { num_changed_256_colors--; } bl_map_erase_simple(result, color_config, color); return 1; } } else { /* XXX "red", "green", "blue" and so on are available for rgb */ vt_color_t rgb_color = vt_get_color(rgb); if ((rgb_color != VT_UNKNOWN_COLOR) ? !vt_get_color_rgba(color, &red, &green, &blue, &alpha) : !vt_color_parse_rgb_name(&red, &green, &blue, &alpha, rgb)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " illegal rgblist format (%s,%s)\n", color_name, rgb); #endif return 0; } } #ifdef __DEBUG bl_debug_printf("%s(%d) = red %x green %x blue %x\n", color_name, color, red, green, blue); #endif return color_config_set_rgb(color, red, green, blue, alpha); } static void read_conf(const char *filename) { bl_file_t *from; char *color_name; char *rgb; if (!(from = bl_file_open(filename, "r"))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " %s couldn't be opened.\n", filename); #endif return; } while (bl_conf_io_read(from, &color_name, &rgb)) { parse_conf(color_name, rgb); } bl_file_close(from); } /* --- global functions --- */ void vt_set_color_mode(const char *mode) { if (strcmp(mode, "256") == 0) { color_distance_threshold = COLOR_DISTANCE_THRESHOLD; use_pseudo_color = 1; } else { if (strcmp(mode, "true") == 0) { color_distance_threshold = 40; /* 9 + 30 + 1 */ } else /* if( strcmp( mode , "high") == 0 */ { color_distance_threshold = COLOR_DISTANCE_THRESHOLD; } use_pseudo_color = 0; } } char *vt_get_color_mode(void) { if (use_pseudo_color) { return "256"; } else if (color_distance_threshold == 40) { return "true"; } else { return "high"; } } void vt_color_config_init(void) { char *rcpath; bl_map_new_with_size(vt_color_t, rgb_t, color_config, bl_map_hash_int, bl_map_compare_int, 16); if ((rcpath = bl_get_sys_rc_path(color_file))) { read_conf(rcpath); free(rcpath); } if ((rcpath = bl_get_user_rc_path(color_file))) { read_conf(rcpath); free(rcpath); } } void vt_color_config_final(void) { bl_map_destroy(color_config); color_config = NULL; } /* * Return value 0 means customization failed or not changed. * Return value -1 means saving failed. */ int vt_customize_color_file(char *color, char *rgb, int save) { if (!color_config || !parse_conf(color, rgb)) { return 0; } if (save) { char *path; bl_conf_write_t *conf; if ((path = bl_get_user_rc_path(color_file)) == NULL) { return -1; } conf = bl_conf_write_open(path); free(path); if (conf == NULL) { return -1; } bl_conf_io_write(conf, color, rgb); bl_conf_write_close(conf); } return 1; } char *vt_get_color_name(vt_color_t color) { if (IS_VTSYS_COLOR(color)) { if (color & VT_BOLD_COLOR_MASK) { return color_name_table[color & ~VT_BOLD_COLOR_MASK]; } else { return color_name_table[color] + 3; } } else if (IS_256_COLOR(color)) { /* XXX Not reentrant */ static char color_name_256[4]; snprintf(color_name_256, sizeof(color_name_256), "%d", color); return color_name_256; } else { return NULL; } } vt_color_t vt_get_color(const char *name) { vt_color_t color; if (sscanf(name, "%d", (int*)&color) == 1) { if (IS_VTSYS256_COLOR(color)) { return color; } } for (color = VT_BLACK; color <= VT_WHITE; color++) { if (strcmp(name, color_name_table[color] + 3) == 0) { return color; } else if (strcmp(name, color_name_table[color]) == 0) { return color | VT_BOLD_COLOR_MASK; } } return VT_UNKNOWN_COLOR; } int vt_get_color_rgba(vt_color_t color, u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_int8_t *alpha /* can be NULL */ ) { if (!IS_VALID_COLOR_EXCEPT_SPECIAL_COLORS(color)) { return 0; } if (IS_EXT_COLOR(color)) { if (!ext_color_table || ext_color_table[EXT_COLOR_TO_INDEX(color)].mark == 0) { return 0; } *red = ext_color_table[EXT_COLOR_TO_INDEX(color)].red; *green = ext_color_table[EXT_COLOR_TO_INDEX(color)].green; *blue = ext_color_table[EXT_COLOR_TO_INDEX(color)].blue; } else if (color_config && color_config_get_rgb(color, red, green, blue, alpha)) { return 1; } else { get_default_rgb(color, red, green, blue); } if (alpha) { *alpha = 0xff; } return 1; } int vt_color_parse_rgb_name(u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_int8_t *alpha, const char *name) { int r; int g; int b; int a; size_t name_len; char *format; int has_alpha; int long_color; a = 0xffff; has_alpha = 0; long_color = 0; name_len = strlen(name); if (name_len >= 14) { /* * XXX * "RRRR-GGGG-BBBB" length is 14, but 2.4.0 or before accepts * "RRRR-GGGG-BBBB....."(trailing any characters) format and * what is worse "RRRR-GGGG-BBBB;" appears in etc/color sample file. * So, more than 14 length is also accepted for backward compatiblity. */ if (sscanf(name, "%4x-%4x-%4x", &r, &g, &b) == 3) { goto end; } else if (name_len == 16) { format = "rgba:%2x/%2x/%2x/%2x"; has_alpha = 1; } else if (name_len == 17) { format = "#%4x%4x%4x%4x"; has_alpha = 1; long_color = 1; } else if (name_len == 18) { format = "rgb:%4x/%4x/%4x"; long_color = 1; } else if (name_len == 24) { format = "rgba:%4x/%4x/%4x/%4x"; long_color = 1; has_alpha = 1; } else { goto fail; } } else { if (name_len == 7) { format = "#%2x%2x%2x"; } else if (name_len == 9) { format = "#%2x%2x%2x%2x"; has_alpha = 1; } else if (name_len == 12) { format = "rgb:%2x/%2x/%2x"; } else if (name_len == 13) { format = "#%4x%4x%4x"; long_color = 1; } else { goto fail; } } if (sscanf(name, format, &r, &g, &b, &a) != (3 + has_alpha)) { goto fail; } end: if (long_color) { *red = (r >> 8) & 0xff; *green = (g >> 8) & 0xff; *blue = (b >> 8) & 0xff; *alpha = (a >> 8) & 0xff; } else { *red = r; *green = g; *blue = b; *alpha = a & 0xff; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s => %x %x %x %x\n", name, *red, *green, *blue, *alpha); #endif return 1; fail: #if 1 /* Backward compatibility with mlterm-3.1.5 or before. */ if (color_config) { /* * If 'name' is a color name defined in ~/.mlterm/color, its rgb is returned. * (for ui_load_named_xcolor()) */ vt_color_t color; if ((color = vt_get_color(name)) != VT_UNKNOWN_COLOR && color_config_get_rgb(color, red, green, blue, alpha)) { return 1; } } #endif return 0; } void vt_color_force_linear_search(int flag) { if (flag) { num_changed_256_colors++; } else { num_changed_256_colors--; } } /* * Return the number of colors which should be searched after this function. */ u_int vt_get_closest_256_color(vt_color_t *closest, u_int *min_diff, u_int8_t red, u_int8_t green, u_int8_t blue, int threshold) { int r, g, b; int tmp; vt_color_t color; u_int8_t rgb[3]; u_int diff; int diff_r, diff_g, diff_b; int count; int num; if (num_changed_256_colors > 0) { return 256; } /* * 0 - 47 => 0 * 48 - 114 => 1 * 115 - 154 => 2 * ... */ tmp = (red <= 114 ? (red >= 48) : ((red - 55) + 20) / 40); r = tmp ? (tmp * 40 + 55) & 0xff : 0; color = tmp * 36; tmp = (green <= 114 ? (green >= 48) : ((green - 55) + 20) / 40); g = tmp ? (tmp * 40 + 55) & 0xff : 0; color += tmp * 6; tmp = (blue <= 114 ? (blue >= 48) : ((blue - 55) + 20) / 40); b = tmp ? (tmp * 40 + 55) & 0xff : 0; color += tmp; /* lazy color-space conversion */ diff_r = red - r; diff_g = green - g; diff_b = blue - b; diff = COLOR_DISTANCE(diff_r, diff_g, diff_b); if (diff < *min_diff) { *min_diff = diff; *closest = color + 0x10; if (diff < threshold) { return 0; } } num = 1; rgb[0] = red; if (red != green) { rgb[num++] = green; } if (red != blue && green != blue) { rgb[num++] = blue; } for (count = 0; count < num; count++) { tmp = (rgb[count] >= 233 ? 23 : (rgb[count] <= 12 ? 0 : ((rgb[count] - 8) + 5) / 10)); r = g = b = tmp * 10 + 8; /* lazy color-space conversion */ diff_r = red - r; diff_g = green - g; diff_b = blue - b; diff = COLOR_DISTANCE(diff_r, diff_g, diff_b); if (diff < *min_diff) { *min_diff = diff; *closest = tmp + 0xe8; if (diff < threshold) { return 0; } } } return 16; } vt_color_t vt_get_closest_color(u_int8_t red, u_int8_t green, u_int8_t blue) { vt_color_t closest = VT_UNKNOWN_COLOR; vt_color_t color; u_int linear_search_max; u_int min = 0xffffff; vt_color_t oldest_color; u_int oldest_mark; u_int max = 0; #ifdef __DEBUG vt_color_t hit_closest = VT_UNKNOWN_COLOR; vt_get_closest_256_color(&hit_closest, &min, red, green, blue); min = 0xffffff; for (color = 16; color < 256; color++) #else if ((linear_search_max = vt_get_closest_256_color(&closest, &min, red, green, blue, color_distance_threshold)) == 0) { return closest; } for (color = 0; color < linear_search_max; color++) #endif { u_int8_t r; u_int8_t g; u_int8_t b; u_int8_t a; if (vt_get_color_rgba(color, &r, &g, &b, &a) && a == 0xff) { u_int diff; int diff_r, diff_g, diff_b; /* lazy color-space conversion */ diff_r = red - r; diff_g = green - g; diff_b = blue - b; diff = COLOR_DISTANCE(diff_r, diff_g, diff_b); if (diff < min) { min = diff; closest = color; if (diff < color_distance_threshold) { #ifdef __DEBUG /* * XXX * The result of linear search of boundary values * (115, 195 etc) is different from that of * vt_get_closest_256_color() of it. */ if (closest != hit_closest) { bl_debug_printf("ERROR %x %x %x -> %x<=>%x\n", red, green, blue, closest, hit_closest); } #endif return closest; } } } } #ifdef __DEBUG /* * XXX * The result of linear search of boundary values (115, 195 etc) is * different from that of vt_get_closest_256_color() of it. */ if (closest != hit_closest) { bl_debug_printf("ERROR %x %x %x -> %x<=>%x\n", red, green, blue, closest, hit_closest); } #endif if (use_pseudo_color || (!ext_color_table && !(ext_color_table = calloc(MAX_EXT_COLORS, sizeof(*ext_color_table))))) { return closest; } if ((oldest_mark = ext_color_mark / 2) == MAX_EXT_COLORS / 2) { oldest_mark = 1; } else { oldest_mark++; } if (ext_color_mark == MAX_EXT_COLORS) { ext_color_mark = 2; } else { ext_color_mark++; } color = 0; while (ext_color_table[color].mark) { u_int diff; int diff_r, diff_g, diff_b; /* lazy color-space conversion */ diff_r = red - ext_color_table[color].red; diff_g = green - ext_color_table[color].green; diff_b = blue - ext_color_table[color].blue; diff = COLOR_DISTANCE(diff_r, diff_g, diff_b); if (diff < min) { min = diff; if (diff < color_distance_threshold) { /* Set new mark */ ext_color_table[color].mark = ext_color_mark / 2; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Use cached ext color %x\n", INDEX_TO_EXT_COLOR(color)); #endif return INDEX_TO_EXT_COLOR(color); } } if (max == MAX_EXT_COLORS / 2) { /* do nothing */ } else if (ext_color_table[color].mark == oldest_mark) { max = MAX_EXT_COLORS / 2; oldest_color = color; } else { if (ext_color_table[color].mark < oldest_mark) { diff = oldest_mark - ext_color_table[color].mark; } else /* if( ext_color_table[color].mark > oldest_mark) */ { diff = oldest_mark + (MAX_EXT_COLORS / 2) - ext_color_table[color].mark; } if (diff > max) { max = diff; oldest_color = color; } } if (++color == MAX_EXT_COLORS) { color = oldest_color; ext_color_table[color].is_changed = 1; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Destroy ext color %x mark %x\n", INDEX_TO_EXT_COLOR(color), ext_color_table[color].mark); #endif break; } } ext_color_table[color].mark = ext_color_mark / 2; ext_color_table[color].red = red; ext_color_table[color].green = green; ext_color_table[color].blue = blue; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "New ext color %.2x: r%.2x g%x b%.2x mark %x\n", INDEX_TO_EXT_COLOR(color), red, green, blue, ext_color_table[color].mark); #endif return INDEX_TO_EXT_COLOR(color); } int vt_ext_color_is_changed(vt_color_t color) { if (ext_color_table[EXT_COLOR_TO_INDEX(color)].is_changed) { ext_color_table[EXT_COLOR_TO_INDEX(color)].is_changed = 0; return 1; } else { return 0; } } mlterm-3.8.9/vtemu/vt_color.h010064400017600000144000000057531356600660700147140ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_COLOR_H__ #define __VT_COLOR_H__ #include #define MAX_VTSYS_COLORS 16 #define MAX_BASIC_VTSYS_COLORS 8 #define MAX_256_COLORS 240 #define MAX_EXT_COLORS 240 #define MAX_256EXT_COLORS (MAX_256_COLORS + MAX_EXT_COLORS) /* same as 0 <= color <= 0x7 */ #define IS_VTSYS_BASE_COLOR(color) ((unsigned int)(color) <= 0x7) /* same as 0 <= color <= 0xf */ #define IS_VTSYS_COLOR(color) ((unsigned int)(color) <= 0xf) #define IS_256_COLOR(color) (0x10 <= (color) && (color) <= 0xff) #define IS_VTSYS256_COLOR(color) ((unsigned int)(color) <= 0xff) #define IS_EXT_COLOR(color) (0x100 <= (color) && (color) <= 0x1ef) #define IS_256EXT_COLOR(color) (0x10 <= (color) && (color) <= 0x1ef) #define IS_VALID_COLOR_EXCEPT_SPECIAL_COLORS(color) ((unsigned int)(color) <= 0x1ef) #define IS_FG_BG_COLOR(color) (0x1f0 <= (color) && (color) <= 0x1f1) #define IS_ALT_COLOR(color) (0x1f2 <= (color)) #define EXT_COLOR_TO_INDEX(color) ((color) - MAX_VTSYS_COLORS - MAX_256_COLORS) #define INDEX_TO_EXT_COLOR(color) ((color) + MAX_VTSYS_COLORS + MAX_256_COLORS) #define COLOR_DISTANCE(diff_r, diff_g, diff_b) \ ((diff_r) * (diff_r)*9 + (diff_g) * (diff_g)*30 + (diff_b) * (diff_b)) /* no one may notice the difference (4[2^3/2]*4*9+4*4*30+4*4) */ #define COLOR_DISTANCE_THRESHOLD 640 /* XXX If these members are changed, modify init() in MLTerm.java. */ typedef enum vt_color { VT_UNKNOWN_COLOR = -1, /* * Don't change this order, which vt_parser.c(change_char_attr etc) and * x_color_cache.c etc depend on. */ VT_BLACK = 0x0, VT_RED = 0x1, VT_GREEN = 0x2, VT_YELLOW = 0x3, VT_BLUE = 0x4, VT_MAGENTA = 0x5, VT_CYAN = 0x6, VT_WHITE = 0x7, VT_BOLD_COLOR_MASK = 0x8, /* * 0x8 - 0xf: bold vt colors. */ /* * 0x10 - 0xff: 240 colors. */ /* * 0x100 - 0x1ef: 241-480 colors. */ VT_FG_COLOR = 0x1f0, VT_BG_COLOR = 0x1f1, VT_BOLD_COLOR = 0x1f2, VT_UNDERLINE_COLOR = 0x1f3, VT_BLINKING_COLOR = 0x1f4, VT_REVERSE_COLOR = 0x1f5, VT_ITALIC_COLOR = 0x1f6, VT_CROSSED_OUT_COLOR = 0x1f7, } vt_color_t; void vt_set_color_mode(const char *mode); char *vt_get_color_mode(void); void vt_color_config_init(void); void vt_color_config_final(void); int vt_customize_color_file(char *color, char *rgb, int save); char *vt_get_color_name(vt_color_t color); vt_color_t vt_get_color(const char *name); int vt_get_color_rgba(vt_color_t color, u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_int8_t *alpha); int vt_color_parse_rgb_name(u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_int8_t *alpha, const char *name); void vt_color_force_linear_search(int flag); u_int vt_get_closest_256_color(vt_color_t *closest, u_int *min_diff, u_int8_t red, u_int8_t green, u_int8_t blue, int threshold); vt_color_t vt_get_closest_color(u_int8_t red, u_int8_t green, u_int8_t blue); int vt_ext_color_is_changed(vt_color_t color); #endif mlterm-3.8.9/vtemu/vt_config_menu.c010064400017600000144000000235001356600660700160500ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef NO_TOOLS #include "vt_config_menu.h" #ifdef USE_WIN32API #include #endif #include /* sprintf */ #include /* strchr */ #include /* fork */ #include #include #include /* DIGIT_STR_LEN */ #include /* malloc */ #include /* bl_file_set_cloexec, bl_file_unset_cloexec */ #include /* HAVE_WINDOWS_H */ #include /* BL_LIBEXECDIR */ #include "vt_pty.h" /* --- static functions --- */ #ifdef USE_WIN32API static DWORD WINAPI wait_child_exited(LPVOID thr_param) { vt_config_menu_t *config_menu; DWORD ev; #if 0 bl_debug_printf("wait_child_exited thread.\n"); #endif config_menu = thr_param; while (1) { ev = WaitForSingleObject(config_menu->pid, INFINITE); #if 0 bl_debug_printf("WaitForMultipleObjects %dth event signaled.\n", ev); #endif if (ev == WAIT_OBJECT_0) { CloseHandle(config_menu->fd); CloseHandle(config_menu->pid); config_menu->fd = 0; config_menu->pid = 0; #ifdef USE_LIBSSH2 if (vt_pty_get_mode(config_menu->pty) == PTY_MOSH) { vt_pty_mosh_set_use_loopback(config_menu->pty, 0); } else { vt_pty_ssh_set_use_loopback(config_menu->pty, 0); } config_menu->pty = NULL; #endif break; } } ExitThread(0); return 0; } #else static void sig_child(void *self, pid_t pid) { vt_config_menu_t *config_menu; config_menu = self; if (config_menu->pid == pid) { config_menu->pid = 0; close(config_menu->fd); config_menu->fd = -1; #ifdef USE_LIBSSH2 if (config_menu->pty) { if (vt_pty_get_mode(config_menu->pty) == PTY_MOSH) { vt_pty_mosh_set_use_loopback(config_menu->pty, 0); } else { vt_pty_ssh_set_use_loopback(config_menu->pty, 0); } config_menu->pty = NULL; } #endif } } #endif /* --- global functions --- */ void vt_config_menu_init(vt_config_menu_t *config_menu) { config_menu->pid = 0; #ifdef USE_WIN32API config_menu->fd = 0; #else config_menu->fd = -1; bl_add_sig_child_listener(config_menu, sig_child); #endif #ifdef USE_LIBSSH2 config_menu->pty = NULL; #endif } void vt_config_menu_final(vt_config_menu_t *config_menu) { #ifndef USE_WIN32API bl_remove_sig_child_listener(config_menu, sig_child); #endif } int vt_config_menu_start(vt_config_menu_t *config_menu, char *cmd_path, int x, int y, char *display, vt_pty_ptr_t pty) { #ifdef USE_WIN32API HANDLE input_write_tmp; HANDLE input_read; HANDLE output_write; HANDLE error_write; SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; STARTUPINFO si; char *cmd_line; char geometry[] = "--geometry"; DWORD tid; int pty_fd; if (config_menu->pid > 0) { /* configuration menu is active now */ return 0; } input_read = output_write = error_write = 0; if ((pty_fd = vt_pty_get_slave_fd(pty)) < 0) { #ifdef USE_LIBSSH2 if ((vt_pty_get_mode(pty) == PTY_MOSH) ? vt_pty_mosh_set_use_loopback(pty, 1) : vt_pty_ssh_set_use_loopback(pty, 1)) { pty_fd = vt_pty_get_slave_fd(pty); config_menu->pty = pty; } else #endif { return 0; } } /* * pty_fd is not inheritable(see vt_pty_pipewin32.c), so it is necessary * to duplicate inheritable handle. * It is possible to DuplicateHandle(socket) if pty_fd is socket. */ if (!DuplicateHandle(GetCurrentProcess(), (HANDLE)pty_fd, GetCurrentProcess(), &output_write, 0, TRUE, DUPLICATE_SAME_ACCESS)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " DuplicateHandle() failed.\n"); #endif goto error1; } if (!DuplicateHandle(GetCurrentProcess(), (HANDLE)pty_fd, GetCurrentProcess(), &error_write, 0, TRUE, DUPLICATE_SAME_ACCESS)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " DuplicateHandle() failed.\n"); #endif goto error1; } /* Set up the security attributes struct. */ sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* Create the child input pipe. */ if (!CreatePipe(&input_read, &input_write_tmp, &sa, 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreatePipe() failed.\n"); #endif goto error1; } if (!DuplicateHandle(GetCurrentProcess(), input_write_tmp, GetCurrentProcess(), &config_menu->fd, /* Address of new handle. */ 0, FALSE, /* Make it uninheritable. */ DUPLICATE_SAME_ACCESS)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " DuplicateHandle() failed.\n"); #endif CloseHandle(input_write_tmp); goto error1; } /* * Close inheritable copies of the handles you do not want to be * inherited. */ CloseHandle(input_write_tmp); /* Set up the start up info struct. */ ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES | STARTF_FORCEOFFFEEDBACK; si.hStdOutput = output_write; si.hStdInput = input_read; si.hStdError = error_write; /* * Use this if you want to hide the child: * si.wShowWindow = SW_HIDE; * Note that dwFlags must include STARTF_USESHOWWINDOW if you want to * use the wShowWindow flags. */ if ((cmd_line = alloca(strlen(cmd_path) + 1 + sizeof(geometry) + (1 + DIGIT_STR_LEN(int)) * 2 + 1)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " alloca failed.\n"); #endif goto error1; } sprintf(cmd_line, "%s %s +%d+%d", cmd_path, geometry, x, y); if (!CreateProcess(cmd_path, cmd_line, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreateProcess() failed.\n"); #endif goto error1; } /* Set global child process handle to cause threads to exit. */ config_menu->pid = pi.hProcess; /* Close any unnecessary handles. */ CloseHandle(pi.hThread); /* * Close pipe handles (do not continue to modify the parent). * You need to make sure that no handles to the write end of the * output pipe are maintained in this process or else the pipe will * not close when the child process exits and the ReadFile will hang. */ CloseHandle(output_write); CloseHandle(input_read); CloseHandle(error_write); if (!CreateThread(NULL, 0, wait_child_exited, config_menu, 0, &tid)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreateThread() failed.\n"); #endif goto error2; } return 1; error1: if (input_read) { CloseHandle(input_read); } if (output_write) { CloseHandle(output_write); } if (error_write) { CloseHandle(error_write); } error2: if (config_menu->pid) { /* * TerminateProcess must be called before CloseHandle(fd). */ TerminateProcess(config_menu->pid, 0); config_menu->pid = 0; } if (config_menu->fd) { CloseHandle(config_menu->fd); config_menu->fd = 0; } #ifdef USE_LIBSSH2 if (config_menu->pty) { if (vt_pty_get_mode(config_menu->pty) == PTY_MOSH) { vt_pty_mosh_set_use_loopback(config_menu->pty, 0); } else { vt_pty_ssh_set_use_loopback(config_menu->pty, 0); } config_menu->pty = NULL; } #endif return 0; #else /* USE_WIN32API */ pid_t pid; int fds[2]; int pty_fd; if (config_menu->pid > 0) { /* configuration menu is active now */ return 0; } if ((pty_fd = vt_pty_get_slave_fd(pty)) < 0) { #ifdef USE_LIBSSH2 if ((vt_pty_get_mode(pty) == PTY_MOSH) ? vt_pty_mosh_set_use_loopback(pty, 1) : vt_pty_ssh_set_use_loopback(pty, 1)) { pty_fd = vt_pty_get_slave_fd(pty); config_menu->pty = pty; } else #endif { return 0; } } if (!bl_file_unset_cloexec(pty_fd)) { /* configulators require an inherited pty. */ return 0; } if (pipe(fds) == -1) { return 0; } pid = fork(); if (pid == -1) { return 0; } if (pid == 0) { /* child process */ char *args[6]; char geom[2 + DIGIT_STR_LEN(int)*2 + 1]; args[0] = cmd_path; sprintf(geom, "+%d+%d", x, y); args[1] = "--geometry"; args[2] = geom; if (display) { args[3] = "--display"; args[4] = display; args[5] = NULL; } else { args[3] = NULL; } close(fds[1]); /* for configulators, * STDIN => to read replys from mlterm * STDOUT => to write the "master" side of pty * STDERR => is retained to be the mlterm's STDERR */ if (dup2(fds[0], STDIN_FILENO) == -1 || dup2(pty_fd, STDOUT_FILENO) == -1) { bl_msg_printf("dup2 failed.\n"); exit(1); } #if (defined(__CYGWIN__) || defined(__MSYS__)) && !defined(DEBUG) /* Suppress error message */ close(STDERR_FILENO); #endif execv(cmd_path, args); /* failed */ /* If program name was specified without directory, prepend LIBEXECDIR to it. */ if (strchr(cmd_path, '/') == NULL) { char *p; char dir[] = BL_LIBEXECDIR("mlterm"); if ((p = alloca(sizeof(dir) + strlen(cmd_path) + 1))) { sprintf(p, "%s/%s", dir, cmd_path); args[0] = cmd_path = p; execv(cmd_path, args); } } bl_error_printf("Failed to exec %s.\n", cmd_path); exit(1); } /* parent process */ close(fds[0]); config_menu->fd = fds[1]; config_menu->pid = pid; bl_file_set_cloexec(pty_fd); bl_file_set_cloexec(config_menu->fd); return 1; #endif /* USE_WIN32API */ } int vt_config_menu_write(vt_config_menu_t *config_menu, u_char *buf, size_t len) { ssize_t write_len; #ifdef USE_WIN32API if (config_menu->fd == 0 || !WriteFile(config_menu->fd, buf, len, &write_len, NULL)) #else if (config_menu->fd == -1 || (write_len = write(config_menu->fd, buf, len)) == -1) #endif { return 0; } else { return write_len; } } #endif /* NO_TOOLS */ mlterm-3.8.9/vtemu/vt_config_menu.h010064400017600000144000000020341356600660700160540ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_CONFIG_MENU_H__ #define __VT_CONFIG_MENU_H__ #include /* pid_t */ typedef struct vt_pty *vt_pty_ptr_t; typedef struct vt_config_menu { #ifdef USE_WIN32API void *pid; /* HANDLE */ void *fd; /* HANDLE */ #else pid_t pid; int fd; #endif #ifdef USE_LIBSSH2 vt_pty_ptr_t pty; #endif } vt_config_menu_t; #ifdef NO_TOOLS #define vt_config_menu_init(config_menu) (0) #define vt_config_menu_final(config_menu) (0) #define vt_config_menu_start(config_menu, cmd_path, x, y, display, pty) (0) #define vt_config_menu_write(config_menu, buf, len) (0) #else /* NO_TOOLS */ void vt_config_menu_init(vt_config_menu_t *config_menu); void vt_config_menu_final(vt_config_menu_t *config_menu); int vt_config_menu_start(vt_config_menu_t *config_menu, char *cmd_path, int x, int y, char *display, vt_pty_ptr_t pty); int vt_config_menu_write(vt_config_menu_t *config_menu, u_char *buf, size_t len); #endif /* NO_TOOLS */ #endif mlterm-3.8.9/vtemu/vt_config_proto.c010064400017600000144000000100041356600660700162420ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_config_proto.h" #include #include #include #include /* open/creat */ #include /* close */ #include /* time */ #include #include #include #include #include #if 0 #define __DEBUG #endif /* --- static functions --- */ static char *challenge; static char *path; /* --- static functions --- */ static int read_challenge(void) { FILE *file; struct stat st; if ((file = fopen(path, "r")) == NULL) { return 0; } fstat(fileno(file), &st); if (st.st_size > DIGIT_STR_LEN(int)) { return 0; } free(challenge); if ((challenge = malloc(DIGIT_STR_LEN(int)+1)) == NULL) { return 0; } fread(challenge, st.st_size, 1, file); challenge[st.st_size] = '\0'; fclose(file); return 1; } /* --- global functions --- */ int vt_config_proto_init(void) { if ((path = bl_get_user_rc_path("mlterm/challenge")) == NULL) { return 0; } bl_mkdir_for_file(path, 0700); return vt_gen_proto_challenge(); } void vt_config_proto_final(void) { free(path); free(challenge); } int vt_gen_proto_challenge(void) { int fd; if ((fd = creat(path, 0600)) == -1) { bl_error_printf("Failed to create %s.\n", path); return 0; } free(challenge); if ((challenge = malloc(DIGIT_STR_LEN(int)+1)) == NULL) { return 0; } srand((u_int)(time(NULL) + (int)challenge)); sprintf(challenge, "%d", rand()); write(fd, challenge, strlen(challenge)); close(fd); return 1; } char *vt_get_proto_challenge(void) { return challenge; } /* * Returns 0 if illegal format. * Returns -1 if do_challenge is 1 and challenge failed. */ int vt_parse_proto_prefix(char **dev, /* can be NULL */ char **str, int do_challenge) { char *p; p = *str; while (do_challenge) { char *chal; chal = p; if ((p = strchr(p, ';'))) { *(p++) = '\0'; if ((challenge && strcmp(chal, challenge) == 0) || /* Challenge could have been re-generated. */ (read_challenge() && challenge && strcmp(chal, challenge) == 0)) { /* challenge succeeded. */ break; } } return -1; } *str = p; /* for no_dev */ if (strncmp(p, "/dev/", 5) == 0) { p += 4; while (*(++p) != ':') { /* Don't contain ';' in "/dev/...". */ if (*p == ';' || *p == '\0') { /* Illegal format */ #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " Illegal protocol format.\n"); #endif goto no_dev; } } } else { if (strncmp(p, "color:", 6) == 0) { p += 5; } else { if (*p == 't' || *p == 'v') { p++; } if (*p == 'a' && *(p + 1) == 'a') { p += 2; } if (strncmp(p, "font:", 5) == 0) { p += 4; } else { goto no_dev; } } } if (dev) { *dev = *str; } *(p++) = '\0'; *str = p; return 1; no_dev: if (dev) { *dev = NULL; } return 1; } /* * Returns 0 if illegal format. * Returns -1 if do_challenge is 1 and challenge failed. * If finished parsing str, *str is set NULL(see *str = strchr( p , ';')). */ int vt_parse_proto(char **dev, /* can be NULL */ char **key, /* can be NULL. *key is never NULL. */ char **val, /* can be NULL */ char **str, int do_challenge, int sep_by_semicolon) { char *p; p = *str; if (vt_parse_proto_prefix(dev, &p, do_challenge) < 0) { return -1; } if (sep_by_semicolon) { if ((*str = strchr(p, ';'))) { /* *str points next key=value. */ *((*str)++) = '\0'; } } else { *str = NULL; } if (key) { *key = p; } if ((p = strchr(p, '='))) { *(p++) = '\0'; if (val) { *val = p; } } else { if (val) { *val = NULL; } } #ifdef __DEBUG bl_debug_printf("%s %s %s\n", key ? *key : NULL, val ? *val : NULL, dev ? *dev : NULL); #endif return 1; } mlterm-3.8.9/vtemu/vt_config_proto.h010064400017600000144000000010211356600660700162460ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_CONFIG_PROTO_H__ #define __VT_CONFIG_PROTO_H__ /* * These functions are exported from vt_term.h. */ int vt_config_proto_init(void); void vt_config_proto_final(void); int vt_gen_proto_challenge(void); char *vt_get_proto_challenge(void); int vt_parse_proto_prefix(char **dev, char **str, int do_challenge); int vt_parse_proto(char **dev, char **key, char **val, char **str, int do_challenge, int sep_by_semicolon); #endif mlterm-3.8.9/vtemu/vt_ctl_loader.c010064400017600000144000000040011356600660700156620ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_ctl_loader.h" #ifndef NO_DYNAMIC_LOAD_CTL #include /* NULL */ #include #include #ifndef LIBDIR #define CTLLIB_DIR "/usr/local/lib/mlterm/" #else #define CTLLIB_DIR LIBDIR "/mlterm/" #endif /* --- global functions --- */ void *vt_load_ctl_bidi_func(vt_ctl_bidi_id_t id) { static void **func_table; static int is_tried; if (!is_tried) { bl_dl_handle_t handle; is_tried = 1; if ((!(handle = bl_dl_open(CTLLIB_DIR, "ctl_bidi")) && !(handle = bl_dl_open("", "ctl_bidi")))) { bl_error_printf("BiDi: Could not load.\n"); return NULL; } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Loading libctl_bidi.so\n"); #endif func_table = bl_dl_func_symbol(handle, "vt_ctl_bidi_func_table"); if ((u_int32_t)func_table[CTL_BIDI_API_COMPAT_CHECK] != CTL_API_COMPAT_CHECK_MAGIC) { bl_dl_close(handle); func_table = NULL; bl_error_printf("Incompatible BiDi rendering API.\n"); return NULL; } } if (func_table) { return func_table[id]; } else { return NULL; } } void *vt_load_ctl_iscii_func(vt_ctl_iscii_id_t id) { static void **func_table; static int is_tried; if (!is_tried) { bl_dl_handle_t handle; is_tried = 1; if ((!(handle = bl_dl_open(CTLLIB_DIR, "ctl_iscii")) && !(handle = bl_dl_open("", "ctl_iscii")))) { bl_error_printf("iscii: Could not load.\n"); return NULL; } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Loading libctl_iscii.so\n"); #endif func_table = bl_dl_func_symbol(handle, "vt_ctl_iscii_func_table"); if ((u_int32_t)func_table[CTL_ISCII_API_COMPAT_CHECK] != CTL_API_COMPAT_CHECK_MAGIC) { bl_dl_close(handle); func_table = NULL; bl_error_printf("Incompatible indic rendering API.\n"); return NULL; } } if (func_table) { return func_table[id]; } else { return NULL; } } #endif /* NO_DYNAMIC_LOAD_CTL */ mlterm-3.8.9/vtemu/vt_ctl_loader.h010064400017600000144000000025141356600660700156760ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_CTL_LOADER_H__ #define __VT_CTL_LOADER_H__ #include "vt_line.h" #include "vt_logical_visual.h" #include "vt_shape.h" typedef enum vt_ctl_bidi_id { CTL_BIDI_API_COMPAT_CHECK, VT_LINE_SET_USE_BIDI, VT_LINE_BIDI_CONVERT_LOGICAL_CHAR_INDEX_TO_VISUAL, VT_LINE_BIDI_CONVERT_VISUAL_CHAR_INDEX_TO_LOGICAL, VT_LINE_BIDI_COPY_LOGICAL_STR, VT_LINE_BIDI_IS_RTL, VT_SHAPE_ARABIC, VT_IS_ARABIC_COMBINING, VT_IS_RTL_CHAR, VT_BIDI_COPY, VT_BIDI_RESET, VT_LINE_BIDI_NEED_SHAPE, VT_LINE_BIDI_RENDER, VT_LINE_BIDI_VISUAL, VT_LINE_BIDI_LOGICAL, MAX_CTL_BIDI_FUNCS, } vt_ctl_bidi_id_t; typedef enum vt_ctl_iscii_id { CTL_ISCII_API_COMPAT_CHECK, VT_ISCIIKEY_STATE_NEW, VT_ISCIIKEY_STATE_DESTROY, VT_CONVERT_ASCII_TO_ISCII, VT_LINE_SET_USE_ISCII, VT_LINE_ISCII_CONVERT_LOGICAL_CHAR_INDEX_TO_VISUAL, VT_SHAPE_ISCII, VT_ISCII_COPY, VT_ISCII_RESET, VT_LINE_ISCII_NEED_SHAPE, VT_LINE_ISCII_RENDER, VT_LINE_ISCII_VISUAL, VT_LINE_ISCII_LOGICAL, MAX_CTL_ISCII_FUNCS, } vt_ctl_iscii_id_t; #define CTL_API_VERSION 0x02 #define CTL_API_COMPAT_CHECK_MAGIC \ (((CTL_API_VERSION & 0x0f) << 28) | ((sizeof(vt_line_t) & 0xff) << 20)) void *vt_load_ctl_bidi_func(vt_ctl_bidi_id_t id); void *vt_load_ctl_iscii_func(vt_ctl_iscii_id_t id); #endif mlterm-3.8.9/vtemu/vt_cursor.c010064400017600000144000000102321356600660700150720ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_cursor.h" #include /* memset */ #include /* --- static functions --- */ static int cursor_goto(vt_cursor_t *cursor, int col_or_idx, int row, int is_by_col) { int char_index; u_int cols_rest; vt_line_t *line; if (row > vt_model_end_row(cursor->model)) { /* round row to end of row */ row = vt_model_end_row(cursor->model); } if ((line = vt_model_get_line(cursor->model, row)) == NULL) { return 0; } if (is_by_col) { char_index = vt_convert_col_to_char_index(line, &cols_rest, col_or_idx, BREAK_BOUNDARY); } else { char_index = col_or_idx; cols_rest = 0; } if (!vt_line_assure_boundary(line, char_index)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " cursor cannot goto char index %d(line length is %d)\n", char_index, line->num_filled_chars); #endif char_index = vt_line_end_char_index(line); /* In this case, cols_rest is always 0. */ } cursor->char_index = char_index; cursor->row = row; cursor->col_in_char = cols_rest; cursor->col = vt_convert_char_index_to_col(vt_model_get_line(cursor->model, cursor->row), cursor->char_index, 0) + cursor->col_in_char; return 1; } /* --- global functions --- */ void vt_cursor_init(vt_cursor_t *cursor, vt_model_t *model) { memset(cursor, 0, sizeof(vt_cursor_t)); cursor->model = model; } void vt_cursor_final(vt_cursor_t *cursor) { /* Do nothing for now*/ } int vt_cursor_goto_by_char(vt_cursor_t *cursor, int char_index, int row) { return cursor_goto(cursor, char_index, row, 0); } /* Move horizontally */ int vt_cursor_moveh_by_char(vt_cursor_t *cursor, int char_index) { return cursor_goto(cursor, char_index, cursor->row, 0); } int vt_cursor_goto_by_col(vt_cursor_t *cursor, int col, int row) { return cursor_goto(cursor, col, row, 1); } /* Move horizontally */ int vt_cursor_moveh_by_col(vt_cursor_t *cursor, int col) { return cursor_goto(cursor, col, cursor->row, 1); } void vt_cursor_goto_home(vt_cursor_t *cursor) { cursor->row = 0; cursor->char_index = 0; cursor->col = 0; cursor->col_in_char = 0; } void vt_cursor_goto_beg_of_line(vt_cursor_t *cursor) { cursor->char_index = 0; cursor->col = 0; cursor->col_in_char = 0; } int vt_cursor_go_forward(vt_cursor_t *cursor) { /* full width char check. */ if (cursor->col_in_char + 1 < vt_char_cols(vt_get_cursor_char(cursor))) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " cursor is at 2nd byte of multi byte char.\n"); #endif cursor->col++; cursor->col_in_char++; return 1; } else if (cursor->char_index < vt_line_end_char_index(vt_get_cursor_line(cursor))) { cursor->col = vt_convert_char_index_to_col(vt_get_cursor_line(cursor), ++cursor->char_index, 0); cursor->col_in_char = 0; return 1; } else { /* Can't go forward in this line anymore. */ return 0; } } int vt_cursor_cr_lf(vt_cursor_t *cursor) { if (cursor->model->num_rows <= cursor->row + 1) { return 0; } cursor->row++; cursor->char_index = 0; cursor->col = 0; if (!vt_line_assure_boundary(vt_get_cursor_line(cursor), 0)) { bl_error_printf("Could cause unexpected behavior.\n"); return 0; } return 1; } vt_line_t *vt_get_cursor_line(vt_cursor_t *cursor) { return vt_model_get_line(cursor->model, cursor->row); } vt_char_t *vt_get_cursor_char(vt_cursor_t *cursor) { return vt_model_get_line(cursor->model, cursor->row)->chars + cursor->char_index; } void vt_cursor_char_is_cleared(vt_cursor_t *cursor) { cursor->char_index += cursor->col_in_char; cursor->col_in_char = 0; } void vt_cursor_left_chars_in_line_are_cleared(vt_cursor_t *cursor) { cursor->char_index = cursor->col; cursor->col_in_char = 0; } void vt_cursor_save(vt_cursor_t *cursor) { cursor->saved_col = cursor->col; cursor->saved_char_index = cursor->char_index; cursor->saved_row = cursor->row; } #ifdef DEBUG void vt_cursor_dump(vt_cursor_t *cursor) { bl_msg_printf("Cursor position => CH_IDX %d COL %d(+%d) ROW %d.\n", cursor->char_index, cursor->col, cursor->col_in_char, cursor->row); } #endif mlterm-3.8.9/vtemu/API010064400017600000144000000014431356600660700132400ustar kenusers[vt_term] (All functions declared in vt_term.h) [vt_line] ('get' family functions only) * vt_line_end_char_index * vt_line_is_rtl * vt_line_shape * vt_line_unshape * vt_line_is_empty * vt_line_get_beg_of_modified * vt_line_get_end_of_modified * vt_line_get_num_of_redrawn_chars * vt_line_is_cleared_to_end * vt_line_is_modified [vt_char] * vt_char_code * vt_char_size * vt_char_cs * vt_char_font * vt_char_fg_color * vt_char_bg_color * vt_char_is_underlined * vt_char_init * vt_char_copy * vt_char_final * vt_char_code_is * vt_char_set_code * vt_char_dump [vt_str] * vt_str_alloca * vt_str_new * vt_str_delete [vt_char_encoding] (All functions declared in vt_char_encoding.h) [vt_font] (All functions declared in vt_font.h) [vt_color] (All functions declared in vt_color.h) mlterm-3.8.9/vtemu/vt_cursor.h010064400017600000144000000033271356600660700151060ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_CURSOR_H__ #define __VT_CURSOR_H__ #include "vt_model.h" typedef struct vt_cursor { /* * XXX * Following members are modified directly in vt_logical_visual.c * without vt_cursor_xxx() functions. */ /* * public (readonly) */ int row; int char_index; int col; int col_in_char; /* * private */ int saved_row; int saved_char_index; int saved_col; vt_model_t *model; } vt_cursor_t; void vt_cursor_init(vt_cursor_t *cursor, vt_model_t *model); void vt_cursor_final(vt_cursor_t *cursor); int vt_cursor_goto_by_char(vt_cursor_t *cursor, int char_index, int row); int vt_cursor_moveh_by_char(vt_cursor_t *cursor, int char_index); int vt_cursor_goto_by_col(vt_cursor_t *cursor, int col, int row); int vt_cursor_moveh_by_col(vt_cursor_t *cursor, int col); void vt_cursor_goto_home(vt_cursor_t *cursor); void vt_cursor_goto_beg_of_line(vt_cursor_t *cursor); int vt_cursor_go_forward(vt_cursor_t *cursor); int vt_cursor_cr_lf(vt_cursor_t *cursor); vt_line_t *vt_get_cursor_line(vt_cursor_t *cursor); vt_char_t *vt_get_cursor_char(vt_cursor_t *cursor); void vt_cursor_char_is_cleared(vt_cursor_t *cursor); void vt_cursor_left_chars_in_line_are_cleared(vt_cursor_t *cursor); void vt_cursor_save(vt_cursor_t *cursor); #define vt_saved_cursor_to_home(cursor) \ ((cursor)->saved_col = (cursor)->saved_char_index = (cursor)->saved_row = 0) /* If vt_cursor_restore() is called before vt_cursor_save(), the cursor goes to col=0 row=0. */ #define vt_cursor_restore(cursor) \ vt_cursor_goto_by_col(cursor, (cursor)->saved_col, (cursor)->saved_row) #ifdef DEBUG void vt_cursor_dump(vt_cursor_t *cursor); #endif #endif mlterm-3.8.9/vtemu/vt_drcs.c010064400017600000144000000112501356600660700145110ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_drcs.h" #include /* memset */ #include /* UINT_MAX */ #include #include /* strdup */ #include #ifndef UINT16_MAX #define UINT16_MAX ((1 << 16) - 1) #endif /* --- static variables --- */ static vt_drcs_t *cur_drcs; /* --- global functions --- */ void vt_drcs_select(vt_drcs_t *drcs) { cur_drcs = drcs; } char *vt_drcs_get_glyph(ef_charset_t cs, u_char idx) { vt_drcs_font_t *font; /* msb can be set in vt_parser.c (e.g. ESC(I (JISX0201 kana)) */ if ((font = vt_drcs_get_font(cur_drcs, cs, 0)) && 0x20 <= (idx & 0x7f)) { #if 0 /* * See https://vt100.net/docs/vt510-rm/DECDLD.html * * Pcss: Defines the character set as a 94- or 96- character graphic set. * 0 = 94-character set. (default) * 1 = 96-character set. * The value of Pcss changes the meaning of the Pcn (starting character) parameter above. * If Pcss = 0 (94-character set) * The terminal ignores any attempt to load characters into the 2/0 or 7/15 table positions. * Pcn Specifies * 1 column 2/row 1 * ... * 94 column 7/row 14 * * If Pcss = 1 (96-character set) * Pcn Specifies * 0 column 2/row 0 * ... * 95 column 7/row 15 */ if (IS_CS94SB(cs) && (idx == 0x20 | idx == 0x7f)) { return NULL; } #endif return font->glyphs[(idx & 0x7f) - 0x20]; } else { return NULL; } } vt_drcs_font_t *vt_drcs_get_font(vt_drcs_t *drcs, ef_charset_t cs, int create) { if (!drcs) { return NULL; } /* CS94SB(0x30)-CS94SB(0x7e) (=0x00-0x4e), CS96SB(0x30)-CS96SB(0x7e) (0x50-0x9e) */ if (cs > CS96SB_ID(0x7e)) { return NULL; } if (!drcs->fonts[cs]) { if (!create || !(drcs->fonts[cs] = calloc(1, sizeof(vt_drcs_font_t)))) { return NULL; } } return drcs->fonts[cs]; } void vt_drcs_final(vt_drcs_t *drcs, ef_charset_t cs) { if (drcs) { if (drcs->fonts[cs]) { int idx; for (idx = 0; idx <= 0x5f; idx++) { free(drcs->fonts[cs]->glyphs[idx]); } free(drcs->fonts[cs]); drcs->fonts[cs] = NULL; } } } void vt_drcs_final_full(vt_drcs_t *drcs) { ef_charset_t cs; for (cs = CS94SB_ID(0x30); cs <= CS96SB_ID(0x7e); cs++) { vt_drcs_final(drcs, cs); } } void vt_drcs_add_glyph(vt_drcs_font_t *font, int idx, const char *seq, u_int width, u_int height) { if (font) { free(font->glyphs[idx]); if ((font->glyphs[idx] = malloc(2 + strlen(seq) + 1))) { font->glyphs[idx][0] = width; font->glyphs[idx][1] = height; strcpy(font->glyphs[idx] + 2, seq); } } } void vt_drcs_add_picture(vt_drcs_font_t *font, int id, u_int offset, int beg_idx, u_int num_cols, u_int num_rows, u_int num_cols_small, u_int num_rows_small) { /* 'offset > UINT32_MAX' is not necessary to check. */ if (num_cols > UINT16_MAX || num_rows > UINT16_MAX) { return; } if (font) { font->pic_id = id; font->pic_offset = offset; font->pic_beg_idx = beg_idx; font->pic_num_rows = num_rows; font->pic_num_cols = num_cols; font->pic_num_cols_small = num_cols_small; font->pic_num_rows_small = num_rows_small; } } int vt_drcs_get_picture(vt_drcs_font_t *font, int *id, int *pos, u_int ch) { if (font->pic_num_rows > 0) { ch &= 0x7f; if (ch >= 0x20 && (ch -= 0x20) >= font->pic_beg_idx) { ch += font->pic_offset; /* See MAKE_INLINEPIC_POS() in ui_picture.h */ *pos = (ch % font->pic_num_cols_small) * font->pic_num_rows + (ch / font->pic_num_cols_small); *id = font->pic_id; return 1; } } return 0; } int vt_convert_drcs_to_unicode_pua(ef_char_t *ch) { if (vt_drcs_get_glyph(ch->cs, ch->ch[0])) { if (IS_CS94SB(ch->cs)) { ch->ch[2] = CS94SB_FT(ch->cs); ch->ch[3] = ch->ch[0] & 0x7f; } else { ch->ch[2] = CS96SB_FT(ch->cs); ch->ch[3] = ch->ch[0] | 0x80; } ch->ch[1] = 0x10; ch->ch[0] = 0x00; ch->cs = ISO10646_UCS4_1; ch->size = 4; ch->property = 0; return 1; } else { return 0; } } int vt_convert_unicode_pua_to_drcs(ef_char_t *ch) { u_char *c; c = ch->ch; if (c[1] == 0x10 && 0x30 <= c[2] && c[2] <= 0x7e && c[0] == 0x00) { if (0x20 <= c[3] && c[3] <= 0x7f) { ch->cs = CS94SB_ID(c[2]); } else if (0xa0 <= c[3] && c[3] <= 0xff) { ch->cs = CS96SB_ID(c[2]); } else { return 0; } c[0] = c[3]; ch->size = 1; ch->property = 0; /* Ignore EF_AWIDTH */ return 1; } return 0; } mlterm-3.8.9/vtemu/vt_drcs.h010064400017600000144000000033011356600660700145140ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_DRCS_H__ #define __VT_DRCS_H__ #include #include typedef struct vt_drcs_font { /*ef_charset_t cs;*/ /* 0x40-0x7e */ char *glyphs[0x60]; u_int16_t pic_id; /* MAX_INLINE_PICTURES in ui_picture.h */ u_int16_t pic_beg_idx; /* 0x0-0x59 */ u_int16_t pic_num_cols; u_int16_t pic_num_rows; u_int16_t pic_num_cols_small; u_int16_t pic_num_rows_small; u_int32_t pic_offset; /* offset from the begining of the picture */ } vt_drcs_font_t; typedef struct vt_drcs { vt_drcs_font_t *fonts[CS96SB_ID(0x7e)+1]; } vt_drcs_t; #define vt_drcs_new() calloc(1, sizeof(vt_drcs_t)) #define vt_drcs_destroy(drcs) \ vt_drcs_final_full(drcs); \ free(drcs); void vt_drcs_select(vt_drcs_t *drcs); char *vt_drcs_get_glyph(ef_charset_t cs, u_char idx); vt_drcs_font_t *vt_drcs_get_font(vt_drcs_t *drcs, ef_charset_t cs, int create); void vt_drcs_final(vt_drcs_t *drcs, ef_charset_t cs); void vt_drcs_final_full(vt_drcs_t *drcs); void vt_drcs_add_glyph(vt_drcs_font_t *font, int idx, const char *seq, u_int width, u_int height); void vt_drcs_add_picture(vt_drcs_font_t *font, int id, u_int offset, int beg_inx, u_int num_cols, u_int num_rows, u_int num_cols_small, u_int num_rows_small); int vt_drcs_get_picture(vt_drcs_font_t *font, int *id, int *pos, u_int ch); #define vt_drcs_has_picture(font) ((font)->pic_num_rows > 0) #define vt_drcs_is_picture(font, ch) \ (vt_drcs_has_picture(font) && (font)->pic_beg_idx + 0x20 <= ((ch) & 0x7f)) int vt_convert_drcs_to_unicode_pua(ef_char_t *ch); int vt_convert_unicode_pua_to_drcs(ef_char_t *ch); #endif mlterm-3.8.9/vtemu/vt_edit.c010064400017600000144000001525151356600660700145150ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_edit.h" #include /* memmove/memset */ #include /* alloca */ #include #include #include /* ef_charset_t */ #include "vt_edit_util.h" #include "vt_edit_scroll.h" #if 0 #define __DEBUG #endif #if 0 #define CURSOR_DEBUG #endif #if 0 #define COMPAT_XTERM #endif /* * vt_edit_t::tab_stops * e.g.) * 1 line = 40 columns * => tab_stops = u_int8_t * 5 (40bits) * => Check tab_stops bits if you want to know whether a column is set tab stop * or not. */ #define TAB_STOPS_SIZE(edit) (((edit)->model.num_cols - 1) / 8 + 1) #define reset_wraparound_checker(edit) ((edit)->wraparound_ready_line = NULL) #define MARGIN_IS_ENABLED(edit) \ ((edit)->use_margin && \ (0 < (edit)->hmargin_beg || (edit)->hmargin_end + 1 < (edit)->model.num_cols)) #define CURSOR_IS_INSIDE_HMARGIN(edit) \ ((edit)->hmargin_beg <= (edit)->cursor.col && (edit)->cursor.col <= (edit)->hmargin_end) #define CURSOR_IS_INSIDE_VMARGIN(edit) \ ((edit)->vmargin_beg <= (edit)->cursor.row && (edit)->cursor.row <= (edit)->vmargin_end) /* --- static variables --- */ static int scroll_on_resizing; /* --- static functions --- */ /* * Insert chars within a line. * The cursor must be inside the left and right margins. (The caller of this * function must check it in advance.) */ static int insert_chars(vt_edit_t *edit, vt_char_t *ins_chars, u_int num_ins_chars, int do_move_cursor) { vt_char_t *buffer; u_int buf_len; u_int num_cols; u_int filled_len; u_int filled_cols; u_int last_index; u_int cols_after; u_int cols; int cursor_col; int count; vt_line_t *cursor_line; #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif cursor_line = CURSOR_LINE(edit); buf_len = edit->model.num_cols; #ifndef COMPAT_XTERM if (edit->cursor.col > edit->hmargin_end) { num_cols = edit->model.num_cols; } else #endif { num_cols = edit->hmargin_end + 1; } if ((buffer = vt_str_alloca(buf_len)) == NULL) { return 0; } vt_str_init(buffer, buf_len); filled_len = 0; filled_cols = 0; cursor_col = edit->cursor.col; /* * before cursor(excluding cursor) */ if (edit->cursor.col_in_char) { #ifdef DEBUG if (vt_char_cols(CURSOR_CHAR(edit)) <= edit->cursor.col_in_char) { bl_warn_printf(BL_DEBUG_TAG " illegal col_in_char.\n"); } #endif /* * padding spaces for former half of cursor. */ for (count = 0; count < edit->cursor.col_in_char; count++) { vt_char_copy(&buffer[filled_len++], vt_sp_ch()); } filled_cols += count; cols_after = vt_char_cols(CURSOR_CHAR(edit)) - count; cursor_col -= count; } else { cols_after = 0; } /* * chars are appended one by one below since the line may be full. */ /* * inserted chars */ for (count = 0; count < num_ins_chars; count++) { cols = vt_char_cols(&ins_chars[count]); if (cursor_col + filled_cols + cols > num_cols) { /* * ---+ ---+ * | | * abcde => abe| */ if (filled_len > 0) { vt_char_copy(&buffer[filled_len - 1], &ins_chars[num_ins_chars - 1]); } break; } vt_char_copy(&buffer[filled_len++], &ins_chars[count]); filled_cols += cols; } if (edit->cursor.char_index + filled_len == num_cols) { /* cursor position doesn't proceed. */ last_index = filled_len - 1; } else { last_index = filled_len; } /* * cursor char */ if (cols_after) { /* * padding spaces for latter half of cursor. */ for (count = 0; count < cols_after; count++) { /* + 1 is for vt_sp_ch() */ if (cursor_col + filled_cols + 1 > num_cols) { goto line_full; } vt_char_copy(&buffer[filled_len++], vt_sp_ch()); } filled_cols += count; } else { cols = vt_char_cols(CURSOR_CHAR(edit)); if (cursor_col + filled_cols + cols > num_cols) { goto line_full; } vt_char_copy(&buffer[filled_len++], CURSOR_CHAR(edit)); filled_cols += cols; } /* * after cursor(excluding cursor) */ for (count = edit->cursor.char_index + 1; count < cursor_line->num_filled_chars; count++) { cols = vt_char_cols(vt_char_at(cursor_line, count)); if (cursor_col + filled_cols + cols > num_cols) { break; } vt_char_copy(&buffer[filled_len++], vt_char_at(cursor_line, count)); filled_cols += cols; } line_full: /* * Updating current line and cursor. */ vt_line_overwrite(cursor_line, edit->cursor.char_index, buffer, filled_len, filled_cols); vt_str_final(buffer, buf_len); if (do_move_cursor) { vt_cursor_moveh_by_char(&edit->cursor, edit->cursor.char_index + last_index); } else if (edit->cursor.col_in_char) { vt_cursor_moveh_by_char(&edit->cursor, edit->cursor.char_index + edit->cursor.col_in_char); } #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif return 1; } static int horizontal_tabs(vt_edit_t *edit, u_int num, int is_forward) { int col; u_int count; if (edit->wraparound_ready_line) { vt_edit_go_downward(edit, SCROLL); vt_edit_goto_beg_of_line(edit); } /* * Compatible with rlogin 2.23.1. * * To be compatible with xterm-332, enclose by #if 0 ... #endif. * (esctest: DECSETTests.test_DECSET_DECAWM_NoLineWrapOnTabWithLeftRightMargin) */ #if 1 if (edit->cursor.col < edit->hmargin_beg) { vt_cursor_goto_by_col(&edit->cursor, edit->hmargin_beg, edit->cursor.row); } else if (edit->cursor.col > edit->hmargin_end) { vt_cursor_goto_by_col(&edit->cursor, edit->hmargin_end, edit->cursor.row); } #endif col = edit->cursor.col; for (count = 0; count < num; count++) { while (1) { if (is_forward) { if (col >= edit->hmargin_end) { return 1; } col++; vt_edit_go_forward(edit, WRAPAROUND); } else { if (col <= edit->hmargin_beg) { return 1; } col--; vt_edit_go_back(edit, WRAPAROUND); } if (vt_edit_is_tab_stop(edit, col)) { break; } } } return 1; } static void copy_area(vt_edit_t *src_edit, int src_col, int src_row, u_int num_copy_cols, u_int num_copy_rows, vt_edit_t *dst_edit, int dst_col, int dst_row) { u_int count; vt_line_t *src_line; vt_line_t *dst_line; int src_char_index; int dst_char_index; u_int src_cols_rest; u_int src_cols_after; u_int dst_cols_rest; u_int num_src_chars; u_int num_src_cols; for (count = 0; count < num_copy_rows; count++) { int srow; int drow; if (src_row < dst_row) { srow = src_row + num_copy_rows - count - 1; drow = dst_row + num_copy_rows - count - 1; } else { srow = src_row + count; drow = dst_row + count; } if (!(src_line = vt_edit_get_line(src_edit, srow)) || !(dst_line = vt_edit_get_line(dst_edit, drow))) { continue; } /* Beginning of src line */ src_char_index = vt_convert_col_to_char_index(src_line, &src_cols_rest, src_col, BREAK_BOUNDARY); if (src_char_index >= src_line->num_filled_chars) { src_cols_after = num_copy_cols; } else if (src_cols_rest > 0) { src_cols_after = vt_char_cols(src_line->chars + src_char_index) - src_cols_rest; src_char_index++; } else { src_cols_after = 0; } /* Beginning of dst line */ dst_char_index = vt_convert_col_to_char_index(dst_line, &dst_cols_rest, dst_col, 0); /* Fill rest at the beginning */ if (dst_cols_rest + src_cols_after > 0) { vt_line_fill(dst_line, vt_sp_ch(), dst_char_index, dst_cols_rest + src_cols_after); if (src_char_index >= src_line->num_filled_chars) { continue; } dst_char_index += (dst_cols_rest + src_cols_after); } /* End of src line */ num_src_chars = vt_convert_col_to_char_index(src_line, &src_cols_rest, /* original value is replaced. */ src_col + num_copy_cols - 1, 0) + 1 - src_char_index; if (src_cols_rest == 0) { if ((src_cols_rest = vt_char_cols(src_line->chars + src_char_index + num_src_chars - 1) - 1) > 0) { num_src_chars--; } } else { src_cols_rest = 0; } num_src_cols = num_copy_cols - src_cols_after - src_cols_rest; /* Copy src to dst */ if (num_src_cols > 0) { vt_line_overwrite(dst_line, dst_char_index, src_line->chars + src_char_index, num_src_chars, num_src_cols); } /* Fill rest at the end */ if (src_cols_rest > 0) { vt_line_fill(dst_line, vt_sp_ch(), dst_char_index + num_src_chars, src_cols_rest); } } } static void erase_area(vt_edit_t *edit, int col, int row, u_int num_cols, u_int num_rows) { u_int count; vt_line_t *line; int char_index; u_int cols_rest; for (count = 0; count < num_rows; count++) { if (!(line = vt_edit_get_line(edit, row + count))) { continue; } char_index = vt_convert_col_to_char_index(line, &cols_rest, col, BREAK_BOUNDARY); if (char_index >= line->num_filled_chars && !edit->use_bce) { continue; } if (cols_rest > 0) { vt_line_fill(line, edit->use_bce ? &edit->bce_ch : vt_sp_ch(), char_index, cols_rest); char_index += cols_rest; } vt_line_fill(line, edit->use_bce ? &edit->bce_ch : vt_sp_ch(), char_index, num_cols); } } static int scroll_downward_region(vt_edit_t *edit, u_int size, int is_cursor_beg, int ignore_cursor_pos) { int vmargin_beg; if (is_cursor_beg) { if (edit->cursor.row < edit->vmargin_beg) { return 0; } vmargin_beg = edit->cursor.row; } else { vmargin_beg = edit->vmargin_beg; } /* * XXX * CURSOR_IS_INSIDE_HMARGIN(edit) disables vim to scroll the right side of * vertically splitted window. */ if (ignore_cursor_pos || (/* CURSOR_IS_INSIDE_HMARGIN(edit) && */ edit->cursor.row >= vmargin_beg && edit->cursor.row <= edit->vmargin_end)) { if (size > edit->vmargin_end - vmargin_beg + 1) { size = edit->vmargin_end - vmargin_beg + 1; } else { copy_area(edit, edit->hmargin_beg, vmargin_beg, edit->hmargin_end - edit->hmargin_beg + 1, edit->vmargin_end - vmargin_beg + 1 - size, edit, edit->hmargin_beg, vmargin_beg + size); } erase_area(edit, edit->hmargin_beg, vmargin_beg, edit->hmargin_end - edit->hmargin_beg + 1, size); return 1; } else { return 0; } } static int scroll_upward_region(vt_edit_t *edit, u_int size, int is_cursor_beg, int ignore_cursor_pos) { int vmargin_beg; if (is_cursor_beg) { if (edit->cursor.row < edit->vmargin_beg) { return 0; } vmargin_beg = edit->cursor.row; } else { vmargin_beg = edit->vmargin_beg; } if (ignore_cursor_pos || (CURSOR_IS_INSIDE_HMARGIN(edit) && edit->cursor.row >= vmargin_beg && edit->cursor.row <= edit->vmargin_end)) { if (size > edit->vmargin_end - vmargin_beg + 1) { size = edit->vmargin_end - vmargin_beg + 1; } else { copy_area(edit, edit->hmargin_beg, vmargin_beg + size, edit->hmargin_end - edit->hmargin_beg + 1, edit->vmargin_end - vmargin_beg + 1 - size, edit, edit->hmargin_beg, vmargin_beg); } erase_area(edit, edit->hmargin_beg, edit->vmargin_end + 1 - size, edit->hmargin_end - edit->hmargin_beg + 1, size); return 1; } else { return 0; } } static int apply_relative_origin(vt_edit_t *edit, int *col, int *row, u_int *num_cols, u_int *num_rows) { if (edit->is_relative_origin) { if (((*row) += edit->vmargin_beg) > edit->vmargin_end || ((*col) += edit->hmargin_beg) > edit->hmargin_end) { return 0; } if ((*row) + (*num_rows) > edit->vmargin_end + 1) { (*num_rows) = edit->vmargin_end + 1 - (*row); } if ((*col) + (*num_cols) > edit->hmargin_end + 1) { (*num_cols) = edit->hmargin_end + 1 - (*col); } } else { if ((*row) >= edit->model.num_rows || (*col) >= edit->model.num_cols) { return 0; } if ((*row) + (*num_rows) > edit->model.num_rows) { (*num_rows) = edit->model.num_rows - (*row); } if ((*col) + (*num_cols) > edit->model.num_cols) { (*num_cols) = edit->model.num_cols - (*col); } } return 1; } /* --- global functions --- */ void vt_set_scroll_on_resizing(int flag) { scroll_on_resizing = flag; } int vt_edit_init(vt_edit_t *edit, vt_edit_scroll_event_listener_t *scroll_listener, u_int num_cols, u_int num_rows, u_int tab_size, int is_logging, int use_bce) { if (!vt_model_init(&edit->model, num_cols, num_rows)) { return 0; } vt_cursor_init(&edit->cursor, &edit->model); vt_line_assure_boundary(CURSOR_LINE(edit), 0); vt_char_init(&edit->bce_ch); vt_char_copy(&edit->bce_ch, vt_sp_ch()); edit->use_bce = use_bce; edit->is_logging = is_logging; reset_wraparound_checker(edit); edit->vmargin_beg = 0; edit->vmargin_end = vt_model_end_row(&edit->model); edit->scroll_listener = scroll_listener; edit->use_margin = 0; edit->hmargin_beg = 0; edit->hmargin_end = num_cols - 1; if ((edit->tab_stops = malloc(TAB_STOPS_SIZE(edit))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc failed.\n"); #endif return 0; } vt_edit_set_tab_size(edit, tab_size); edit->is_relative_origin = 0; edit->is_auto_wrap = 1; return 1; } void vt_edit_final(vt_edit_t *edit) { vt_model_final(&edit->model); free(edit->tab_stops); vt_char_final(&edit->bce_ch); } int vt_edit_clone(vt_edit_t *dst_edit, vt_edit_t *src_edit) { u_int row; u_int num_rows; vt_line_t *src_line; vt_line_t *dst_line; memcpy(((char*)dst_edit) + sizeof(vt_model_t), ((char*)src_edit) + sizeof(vt_model_t), sizeof(vt_edit_t) - sizeof(vt_model_t)); if (!(dst_edit->tab_stops = malloc(TAB_STOPS_SIZE(src_edit)))) { return 0; } memcpy(dst_edit->tab_stops, src_edit->tab_stops, TAB_STOPS_SIZE(src_edit)); dst_edit->cursor.model = &dst_edit->model; num_rows = vt_edit_get_rows(src_edit); if (!vt_model_init(&dst_edit->model, vt_edit_get_cols(src_edit), num_rows)) { free(dst_edit->tab_stops); return 0; } for (row = 0; row < num_rows; row++) { dst_line = vt_edit_get_line(dst_edit, row); if ((src_line = vt_edit_get_line(src_edit, row)) == src_edit->wraparound_ready_line) { dst_edit->wraparound_ready_line = dst_line; } vt_line_copy(dst_line, src_line); } return 1; } int vt_edit_resize(vt_edit_t *edit, u_int num_cols, u_int num_rows) { u_int old_cols; u_int slide; #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif if (edit->is_logging && edit->scroll_listener->receive_scrolled_out_line) { u_int count; u_int old_filled_rows = vt_model_get_num_filled_rows(&edit->model); int scroll_all = 0; if (scroll_on_resizing) { for (count = 0; count < old_filled_rows; count++) { vt_line_t *line = vt_model_get_line(&edit->model, count); if (vt_str_cols(line->chars, vt_line_get_num_filled_chars_except_sp(line)) > num_cols) { scroll_all = 1; break; } } } if (scroll_all) { for (count = 0; count < old_filled_rows; count++) { (*edit->scroll_listener->receive_scrolled_out_line)(edit->scroll_listener->self, vt_model_get_line(&edit->model, count)); } vt_edit_goto_home(edit); vt_edit_clear_below(edit); } else if (old_filled_rows > num_rows) { for (count = 0; count < old_filled_rows - num_rows; count++) { (*edit->scroll_listener->receive_scrolled_out_line)(edit->scroll_listener->self, vt_model_get_line(&edit->model, count)); } } } old_cols = edit->model.num_cols; if (!vt_model_resize(&edit->model, &slide, num_cols, num_rows)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_model_resize() failed.\n"); #endif return 0; } if (slide > edit->cursor.row) { vt_cursor_goto_home(&edit->cursor); vt_line_assure_boundary(CURSOR_LINE(edit), 0); } else { edit->cursor.row -= slide; if (edit->cursor.row >= num_rows) { /* Forcibly move cursor to the bottom line. */ edit->cursor.row = num_rows - 1; edit->cursor.col = edit->cursor.char_index = 0; } if (num_cols < old_cols) { if (edit->cursor.col >= num_cols) { edit->cursor.col = num_cols - 1; edit->cursor.char_index = vt_convert_col_to_char_index( CURSOR_LINE(edit), &edit->cursor.col_in_char, edit->cursor.col, 0); } } } reset_wraparound_checker(edit); edit->vmargin_beg = 0; edit->vmargin_end = vt_model_end_row(&edit->model); edit->use_margin = 0; edit->hmargin_beg = 0; edit->hmargin_end = num_cols - 1; free(edit->tab_stops); if ((edit->tab_stops = malloc(TAB_STOPS_SIZE(edit))) == NULL) { return 0; } vt_edit_set_tab_size(edit, edit->tab_size); #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif return 1; } int vt_edit_insert_chars(vt_edit_t *edit, vt_char_t *ins_chars, u_int num_ins_chars) { /* * edit->wraparound_ready_line is ignored. * esctest: SMTests.test_SM_IRM_DoesNotWrapUnlessCursorAtMargin fails by this. * * XXX * xterm-332, TeraTerm-4.95: Wraparound works if IRM is set. * rlogin-2.23.1: Wraparound is disabled if IRM is set. */ reset_wraparound_checker(edit); #ifdef COMPAT_XTERM if (!CURSOR_IS_INSIDE_HMARGIN(edit)) { return vt_edit_overwrite_chars(edit, ins_chars, num_ins_chars); } else #endif { return insert_chars(edit, ins_chars, num_ins_chars, 1); } } int vt_edit_insert_blank_chars(vt_edit_t *edit, u_int num_blank_chars) { int count; vt_char_t *blank_chars; vt_char_t *sp_ch; if (!CURSOR_IS_INSIDE_HMARGIN(edit)) { return 0; } reset_wraparound_checker(edit); if ((blank_chars = vt_str_alloca(num_blank_chars)) == NULL) { return 0; } vt_str_init(blank_chars, num_blank_chars); if (edit->use_bce) { /* * If bce_ch is not used here, vttest 11.4.5 "If your terminal * has the ANSI 'Insert Character' function..." will fail. */ sp_ch = &edit->bce_ch; } else { sp_ch = vt_sp_ch(); } for (count = 0; count < num_blank_chars; count++) { vt_char_copy(&blank_chars[count], sp_ch); } vt_str_final(blank_chars, num_blank_chars); /* cursor will not moved. */ return insert_chars(edit, blank_chars, num_blank_chars, 0); } int vt_edit_overwrite_chars(vt_edit_t *edit, vt_char_t *ow_chars, u_int num_ow_chars) { int count; vt_char_t *buffer; u_int buf_len; u_int num_cols; u_int filled_len; vt_line_t *line; int beg; u_int cols; int new_char_index; #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif buf_len = num_ow_chars + edit->model.num_cols; if (edit->cursor.col > edit->hmargin_end) { num_cols = edit->model.num_cols; } else { num_cols = edit->hmargin_end + 1; } if ((buffer = vt_str_alloca(buf_len)) == NULL) { return 0; } vt_str_init(buffer, buf_len); line = CURSOR_LINE(edit); filled_len = 0; /* before cursor(excluding cursor) */ if (edit->cursor.col_in_char) { int count; /* * padding spaces before cursor. */ for (count = 0; count < edit->cursor.col_in_char; count++) { vt_char_copy(&buffer[filled_len++], vt_sp_ch()); } } /* appending overwriting chars */ vt_str_copy(&buffer[filled_len], ow_chars, num_ow_chars); filled_len += num_ow_chars; /* * overwriting */ beg = 0; count = 0; cols = 0; while (1) { u_int _cols; _cols = vt_char_cols(&buffer[count]); if (edit->cursor.col + cols + _cols > num_cols || (edit->wraparound_ready_line && edit->cursor.col + cols + _cols == num_cols)) { vt_line_overwrite(line, edit->cursor.char_index, &buffer[beg], count - beg, cols); if (!edit->is_auto_wrap) { /* * ---+ ---+ * | | * abcde => abe| * (esctest: DECSET_DECAWM_OffRespectsLeftRightMargin) */ if (count > 0) { vt_char_copy(&buffer[count - 1], &buffer[filled_len - 1]); } break; } vt_line_set_continued_to_next(line, 1); if (edit->cursor.row + 1 > edit->vmargin_end) { if (MARGIN_IS_ENABLED(edit) ? !scroll_upward_region(edit, 1, 0, 0) : !vt_edsl_scroll_upward(edit, 1)) { return 0; } /* * If edit->cursor.row == edit->vmargin_end in this situation, * vmargin_beg == vmargin_end. */ if (edit->cursor.row + 1 <= edit->vmargin_end) { edit->cursor.row++; } } else { edit->cursor.row++; } if (edit->hmargin_beg > 0) { vt_cursor_goto_by_col(&edit->cursor, edit->hmargin_beg, edit->cursor.row); } else { edit->cursor.char_index = edit->cursor.col = 0; } /* Reset edit->wraparound_ready_line because it is not cursor line now. */ reset_wraparound_checker(edit); beg = count; cols = _cols; line = CURSOR_LINE(edit); } else { cols += _cols; } if (++count >= filled_len) { break; } } new_char_index = edit->cursor.char_index + count - beg; if (edit->cursor.col + cols >= num_cols && edit->wraparound_ready_line != line) { /* * Don't use vt_line_end_char_index() instead of * new_char_index --, because num_cols is not * vt_model::num_cols but is vt_edit_t::hmargin_end + 1. */ new_char_index--; edit->wraparound_ready_line = line; } else { reset_wraparound_checker(edit); } vt_line_overwrite(line, edit->cursor.char_index, &buffer[beg], count - beg, cols); vt_line_set_continued_to_next(line, 0); vt_cursor_moveh_by_char(&edit->cursor, new_char_index); vt_str_final(buffer, buf_len); #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif return 1; } /* * deleting cols within a line. */ int vt_edit_delete_cols(vt_edit_t *edit, u_int del_cols) { int char_index; vt_char_t *buffer; u_int buf_len; u_int filled_len; vt_line_t *cursor_line; u_int num_filled_cols; #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif reset_wraparound_checker(edit); cursor_line = CURSOR_LINE(edit); num_filled_cols = vt_line_get_num_filled_cols(cursor_line); if (!MARGIN_IS_ENABLED(edit) && edit->cursor.col + del_cols >= num_filled_cols) { /* no need to overwrite */ vt_edit_clear_line_to_right(edit); /* Considering BCE */ return 1; } /* * collecting chars after cursor line. */ buf_len = cursor_line->num_chars - edit->cursor.col; if ((buffer = vt_str_alloca(buf_len)) == NULL) { return 0; } vt_str_init(buffer, buf_len); filled_len = 0; /* before cursor(including cursor) */ if (edit->cursor.col_in_char) { int cols_after; int count; #ifdef DEBUG if (vt_char_cols(CURSOR_CHAR(edit)) <= edit->cursor.col_in_char) { bl_warn_printf(BL_DEBUG_TAG " illegal col_in_char.\n"); } #endif cols_after = vt_char_cols(CURSOR_CHAR(edit)) - edit->cursor.col_in_char; /* * padding spaces before cursor. */ for (count = 0; count < edit->cursor.col_in_char; count++) { vt_char_copy(&buffer[filled_len++], vt_sp_ch()); } if (del_cols >= cols_after) { del_cols -= cols_after; } else { del_cols = 0; /* * padding spaces after cursor. */ for (count = 0; count < cols_after - del_cols; count++) { vt_char_copy(&buffer[filled_len++], vt_sp_ch()); } } char_index = edit->cursor.char_index + 1; } else { char_index = edit->cursor.char_index; } /* after cursor(excluding cursor) + del_cols */ if (del_cols) { u_int cols; cols = vt_char_cols(vt_char_at(cursor_line, char_index++)); if (MARGIN_IS_ENABLED(edit)) { if (!CURSOR_IS_INSIDE_HMARGIN(edit)) { return 0; } if (num_filled_cols > edit->hmargin_end + 1) { u_int count; u_int copy_len; while (cols < del_cols && edit->cursor.col + cols <= edit->hmargin_end) { cols += vt_char_cols(vt_char_at(cursor_line, char_index++)); } del_cols = cols; while (edit->cursor.col + (cols++) <= edit->hmargin_end) { vt_char_copy(buffer + filled_len++, vt_char_at(cursor_line, char_index++)); } for (count = 0; count < del_cols; count++) { vt_char_copy(buffer + (filled_len++), edit->use_bce ? &edit->bce_ch : vt_sp_ch()); } copy_len = 0; while (char_index + copy_len < cursor_line->num_filled_chars) { vt_char_cols(vt_char_at(cursor_line, char_index + (copy_len++))); } vt_str_copy(buffer + filled_len, vt_char_at(cursor_line, char_index), copy_len); filled_len += copy_len; } } else { while (cols < del_cols && char_index < cursor_line->num_filled_chars) { cols += vt_char_cols(vt_char_at(cursor_line, char_index++)); } vt_str_copy(buffer + filled_len, vt_char_at(cursor_line, char_index), cursor_line->num_filled_chars - char_index); filled_len += (cursor_line->num_filled_chars - char_index); } } if (filled_len > 0) { /* * overwriting. */ vt_edit_clear_line_to_right(edit); /* Considering BCE */ vt_line_overwrite(cursor_line, edit->cursor.char_index, buffer, filled_len, vt_str_cols(buffer, filled_len)); } else { vt_line_reset(cursor_line); } vt_str_final(buffer, buf_len); if (edit->cursor.col_in_char) { vt_cursor_moveh_by_char(&edit->cursor, edit->cursor.char_index + edit->cursor.col_in_char); } #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif return 1; } int vt_edit_clear_cols(vt_edit_t *edit, u_int cols) { vt_line_t *cursor_line; reset_wraparound_checker(edit); if (edit->cursor.col + cols >= edit->model.num_cols) { return vt_edit_clear_line_to_right(edit); } cursor_line = CURSOR_LINE(edit); if (edit->cursor.col_in_char) { vt_line_fill(cursor_line, edit->use_bce ? &edit->bce_ch : vt_sp_ch(), edit->cursor.char_index, edit->cursor.col_in_char); vt_cursor_char_is_cleared(&edit->cursor); } vt_line_fill(cursor_line, edit->use_bce ? &edit->bce_ch : vt_sp_ch(), edit->cursor.char_index, cols); return 1; } int vt_edit_insert_new_line(vt_edit_t *edit) { reset_wraparound_checker(edit); if (MARGIN_IS_ENABLED(edit)) { return scroll_downward_region(edit, 1, 1, 0); } else { return vt_edsl_insert_new_line(edit); } } int vt_edit_delete_line(vt_edit_t *edit) { reset_wraparound_checker(edit); if (MARGIN_IS_ENABLED(edit)) { return scroll_upward_region(edit, 1, 1, 0); } else { return vt_edsl_delete_line(edit); } } int vt_edit_clear_line_to_right(vt_edit_t *edit) { vt_line_t *cursor_line; reset_wraparound_checker(edit); cursor_line = CURSOR_LINE(edit); if (edit->cursor.col_in_char) { vt_line_fill(cursor_line, edit->use_bce ? &edit->bce_ch : vt_sp_ch(), edit->cursor.char_index, edit->cursor.col_in_char); vt_cursor_char_is_cleared(&edit->cursor); } if (edit->use_bce) { vt_line_clear_with(cursor_line, edit->cursor.char_index, &edit->bce_ch); } else { vt_line_clear(CURSOR_LINE(edit), edit->cursor.char_index); } return 1; } int vt_edit_clear_line_to_left(vt_edit_t *edit) { vt_line_t *cursor_line; reset_wraparound_checker(edit); cursor_line = CURSOR_LINE(edit); vt_line_fill(cursor_line, edit->use_bce ? &edit->bce_ch : vt_sp_ch(), 0, edit->cursor.col + 1); vt_cursor_left_chars_in_line_are_cleared(&edit->cursor); return 1; } int vt_edit_clear_below(vt_edit_t *edit) { reset_wraparound_checker(edit); if (!vt_edit_clear_line_to_right(edit)) { return 0; } if (edit->use_bce) { int row; for (row = edit->cursor.row + 1; row < edit->model.num_rows; row++) { vt_line_clear_with(vt_model_get_line(&edit->model, row), 0, &edit->bce_ch); } return 1; } else { return vt_edit_clear_lines(edit, edit->cursor.row + 1, edit->model.num_rows - edit->cursor.row - 1); } } int vt_edit_clear_above(vt_edit_t *edit) { reset_wraparound_checker(edit); if (!vt_edit_clear_line_to_left(edit)) { return 0; } if (edit->use_bce) { int row; for (row = 0; row < edit->cursor.row; row++) { vt_line_clear_with(vt_model_get_line(&edit->model, row), 0, &edit->bce_ch); } return 1; } else { return vt_edit_clear_lines(edit, 0, edit->cursor.row); } } vt_protect_store_t *vt_edit_save_protected_chars(vt_edit_t *edit, int beg_row, /* -1: cursor row (unless relative) */ int end_row, /* -1: cursor row (unless relative) */ int relative) { vt_protect_store_t *save = NULL; vt_char_t *dst; vt_char_t *src; int row; vt_line_t *line; if (relative) { if (edit->is_relative_origin) { if ((beg_row += edit->vmargin_beg) > edit->vmargin_end) { return NULL; } if ((end_row += edit->vmargin_beg) > edit->vmargin_end) { end_row = edit->vmargin_end; } } } else { if (beg_row == -1) { beg_row = vt_cursor_row(edit); } if (end_row == -1) { end_row = vt_cursor_row(edit); } } for (row = beg_row; row <= end_row; row++) { if ((line = vt_edit_get_line(edit, row))) { u_int num = vt_line_get_num_filled_chars_except_sp(line); u_int count; src = line->chars; for (count = 0; count < num; count++, src++) { if (vt_char_is_protected(src)) { if (!save) { if (!(save = malloc(sizeof(vt_protect_store_t) + sizeof(vt_char_t) * (vt_edit_get_cols(edit) + 1) * (end_row - row + 1)))) { return NULL; } dst = save->chars = save + 1; vt_str_init(dst, (vt_edit_get_cols(edit) + 1) * (end_row - row + 1)); dst += count; save->beg_row = row; save->end_row = end_row; } vt_char_copy(dst++, src); } else if (save) { dst += vt_char_cols(src); } } } if (save) { vt_char_copy(dst++, vt_nl_ch()); } } return save; } void vt_edit_restore_protected_chars(vt_edit_t *edit, vt_protect_store_t *save) { int row; int col; u_int cols; vt_line_t *line; vt_char_t *src_p; if (save == NULL) { return; } src_p = save->chars; for (row = save->beg_row; row <= save->end_row; row++) { if ((line = vt_edit_get_line(edit, row))) { for (col = 0; !vt_char_equal(src_p, vt_nl_ch()); src_p++) { if (vt_char_is_protected(src_p)) { cols = vt_char_cols(src_p); vt_line_overwrite(line, /* cols_rest must be always 0, so pass NULL. */ vt_convert_col_to_char_index(line, NULL, col, BREAK_BOUNDARY), src_p, 1, cols); } else { cols = 1; } col += cols; } src_p++; } } vt_str_final(save->chars, (vt_edit_get_cols(edit) + 1) * (save->end_row - save->beg_row + 1)); free(save); } int vt_edit_set_vmargin(vt_edit_t *edit, int beg, int end) { /* * If beg and end is -1, use default(full size of window). * (see vt_parser.c) * * For compatibility with xterm: * 1. if beg and end are smaller than 0, ignore the sequence. * 2. if end is not larger than beg, ignore the sequence. * 3. if beg and end are out of window, ignore the sequence. */ if (beg < 0) { if (beg == -1) { beg = 0; } else { return 0; } } if (end < 0) { if (end == -1) { end = vt_model_end_row(&edit->model); } else { return 0; } } if (beg >= end) { return 0; } if (beg >= edit->model.num_rows) { return 0; } if (end >= edit->model.num_rows) { end = vt_model_end_row(&edit->model); } edit->vmargin_beg = beg; edit->vmargin_end = end; return 1; } void vt_edit_scroll_leftward(vt_edit_t *edit, u_int size) { copy_area(edit, edit->hmargin_beg + size, edit->vmargin_beg, edit->hmargin_end - edit->hmargin_beg + 1 - size, edit->vmargin_end - edit->vmargin_beg + 1, edit, edit->hmargin_beg, edit->vmargin_beg); erase_area(edit, edit->hmargin_end + 1 - size, edit->vmargin_beg, size, edit->vmargin_end - edit->vmargin_beg + 1); } void vt_edit_scroll_rightward(vt_edit_t *edit, u_int size) { copy_area(edit, edit->hmargin_beg, edit->vmargin_beg, edit->hmargin_end - edit->hmargin_beg + 1 - size, edit->vmargin_end - edit->vmargin_beg + 1, edit, edit->hmargin_beg + size, edit->vmargin_beg); erase_area(edit, edit->hmargin_beg, edit->vmargin_beg, size, edit->vmargin_end - edit->vmargin_beg + 1); } int vt_edit_scroll_leftward_from_cursor(vt_edit_t *edit, u_int width) { int src; u_int height; if (!CURSOR_IS_INSIDE_HMARGIN(edit) || !CURSOR_IS_INSIDE_VMARGIN(edit)) { return 0; } height = edit->vmargin_end - edit->vmargin_beg + 1; if ((src = edit->cursor.col + width) <= edit->hmargin_end) { copy_area(edit, src, edit->vmargin_beg, edit->hmargin_end - src + 1, height, edit, edit->cursor.col, edit->vmargin_beg); } else { width = edit->hmargin_end - edit->cursor.col + 1; } erase_area(edit, edit->hmargin_end - width + 1, edit->vmargin_beg, width, height); return 1; } int vt_edit_scroll_rightward_from_cursor(vt_edit_t *edit, u_int width) { int dst; u_int height; if (!CURSOR_IS_INSIDE_HMARGIN(edit) || !CURSOR_IS_INSIDE_VMARGIN(edit)) { return 0; } height = edit->vmargin_end - edit->vmargin_beg + 1; if ((dst = edit->cursor.col + width) <= edit->hmargin_end) { copy_area(edit, edit->cursor.col, edit->vmargin_beg, edit->hmargin_end - dst + 1, height, edit, dst, edit->vmargin_beg); } else { width = edit->hmargin_end - edit->cursor.col + 1; } erase_area(edit, edit->cursor.col, edit->vmargin_beg, width, height); return 1; } int vt_edit_scroll_upward(vt_edit_t *edit, u_int size) { int cursor_row; int cursor_col; cursor_row = edit->cursor.row; cursor_col = edit->cursor.col; if (MARGIN_IS_ENABLED(edit)) { scroll_upward_region(edit, size, 0, 1); } else { vt_edsl_scroll_upward(edit, size); } vt_cursor_goto_by_col(&edit->cursor, cursor_col, cursor_row); return 1; } int vt_edit_scroll_downward(vt_edit_t *edit, u_int size) { int cursor_row; int cursor_col; cursor_row = edit->cursor.row; cursor_col = edit->cursor.col; if (MARGIN_IS_ENABLED(edit)) { scroll_downward_region(edit, size, 0, 1); } else { vt_edsl_scroll_downward(edit, size); } vt_cursor_goto_by_col(&edit->cursor, cursor_col, cursor_row); return 1; } void vt_edit_set_use_hmargin(vt_edit_t *edit, int use) { if (!use) { edit->use_margin = 0; edit->hmargin_beg = 0; edit->hmargin_end = edit->model.num_cols - 1; } else { edit->use_margin = 1; } } int vt_edit_set_hmargin(vt_edit_t *edit, int beg, int end) { if (!edit->use_margin) { /* * The terminal only recognizes DECSLRM if vertical split screen mode (DECLRMM) is set. * (see https://www.vt100.net/docs/vt510-rm/DECSLRM.html) */ return 0; } /* * If beg and end is -1, use default(full size of window). * (see vt_parser.c) * * For compatibility with xterm: * 1. if beg and end are smaller than 0, ignore the sequence. * 2. if end is not larger than beg, ignore the sequence. * 3. if beg and end are out of window, ignore the sequence. */ if (beg < 0) { if (beg == -1) { beg = 0; } else { return 0; } } if (end < 0) { if (end == -1) { end = edit->model.num_cols - 1; } else { return 0; } } if (beg >= end) { return 0; } if (beg >= edit->model.num_cols) { return 0; } if (end >= edit->model.num_cols) { end = edit->model.num_cols - 1; } edit->hmargin_beg = beg; edit->hmargin_end = end; return 1; } int vt_edit_forward_tabs(vt_edit_t *edit, u_int num) { return horizontal_tabs(edit, num, 1); } int vt_edit_backward_tabs(vt_edit_t *edit, u_int num) { #if 0 /* compat with xterm 332 CBT behavior (esctest: CHATests.test_CHA_IgnoresScrollRegion) */ int orig_hmargin_beg = edit->hmargin_beg; int ret; edit->hmargin_beg = 0; ret = horizontal_tabs(edit, num, 0); edit->hmargin_beg = orig_hmargin_beg; return ret; #else /* compat with RLogin 2.23.1 / Teraterm 4.95 */ return horizontal_tabs(edit, num, 0); #endif } void vt_edit_set_tab_size(vt_edit_t *edit, u_int tab_size) { int col; u_int8_t *tab_stops; if (tab_size == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " tab size 0 is not acceptable.\n"); #endif return; } vt_edit_clear_all_tab_stops(edit); col = 0; tab_stops = edit->tab_stops; while (1) { if (col % tab_size == 0) { (*tab_stops) |= (1 << (col % 8)); } col++; if (col >= edit->model.num_cols) { tab_stops++; break; } else if (col % 8 == 7) { tab_stops++; } } #ifdef __DEBUG { int i; bl_debug_printf(BL_DEBUG_TAG " tab stops =>\n"); for (i = 0; i < edit->model.num_cols; i++) { if (vt_edit_is_tab_stop(edit, i)) { bl_msg_printf("*"); } else { bl_msg_printf(" "); } } bl_msg_printf("\n"); } #endif edit->tab_size = tab_size; } void vt_edit_set_tab_stop(vt_edit_t *edit) { edit->tab_stops[edit->cursor.col / 8] |= (1 << (edit->cursor.col % 8)); } void vt_edit_clear_tab_stop(vt_edit_t *edit) { edit->tab_stops[edit->cursor.col / 8] &= ~(1 << (edit->cursor.col % 8)); } void vt_edit_clear_all_tab_stops(vt_edit_t *edit) { memset(edit->tab_stops, 0, TAB_STOPS_SIZE(edit)); } void vt_edit_set_modified_all(vt_edit_t *edit) { u_int count; for (count = 0; count < edit->model.num_rows; count++) { vt_line_set_modified_all(vt_model_get_line(&edit->model, count)); } } void vt_edit_goto_beg_of_line(vt_edit_t *edit) { reset_wraparound_checker(edit); if (edit->hmargin_beg > 0 && edit->cursor.col >= edit->hmargin_beg) { vt_cursor_goto_by_col(&edit->cursor, edit->hmargin_beg, edit->cursor.row); } else { vt_cursor_goto_beg_of_line(&edit->cursor); } } /* * Note that this function ignores edit->is_relative_origin. */ void vt_edit_goto_home(vt_edit_t *edit) { reset_wraparound_checker(edit); vt_cursor_goto_home(&edit->cursor); } int vt_edit_go_forward(vt_edit_t *edit, int flag /* WARPAROUND | SCROLL */ ) { u_int num_cols; #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif if (CURSOR_IS_INSIDE_HMARGIN(edit)) { num_cols = edit->hmargin_end + 1; } else { num_cols = edit->model.num_cols; } reset_wraparound_checker(edit); if (edit->cursor.col + 1 >= num_cols) { if (!(flag & WRAPAROUND)) { return 0; } if (vt_is_scroll_lowerlimit(edit, edit->cursor.row)) { if (!(flag & SCROLL) || (MARGIN_IS_ENABLED(edit) ? !scroll_upward_region(edit, 1, 0, 0) : !vt_edsl_scroll_upward(edit, 1))) { return 0; } } vt_cursor_cr_lf(&edit->cursor); } else if (!vt_cursor_go_forward(&edit->cursor)) { vt_line_break_boundary(CURSOR_LINE(edit), 1); vt_cursor_go_forward(&edit->cursor); } #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif return 1; } int vt_edit_go_back(vt_edit_t *edit, int flag /* WRAPAROUND | SCROLL */ ) { #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif reset_wraparound_checker(edit); /* * full width char check. */ if (edit->cursor.col_in_char) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " cursor is at 2nd byte of multi byte char.\n"); #endif edit->cursor.col--; edit->cursor.col_in_char--; return 1; } /* * moving backward. */ if (edit->cursor.char_index == 0 || edit->cursor.char_index == edit->hmargin_beg) { if (!(flag & WRAPAROUND)) { return 0; } if (vt_is_scroll_upperlimit(edit, edit->cursor.row)) { if (!(flag & SCROLL) || (MARGIN_IS_ENABLED(edit) ? !scroll_downward_region(edit, 1, 0, 0) : !vt_edsl_scroll_downward(edit, 1))) { return 0; } } if (edit->cursor.row == 0) { return 0; } edit->cursor.row--; edit->cursor.char_index = vt_line_end_char_index(CURSOR_LINE(edit)); } else { edit->cursor.char_index--; } edit->cursor.col_in_char = vt_char_cols(CURSOR_CHAR(edit)) - 1; edit->cursor.col = vt_convert_char_index_to_col(CURSOR_LINE(edit), edit->cursor.char_index, 0) + edit->cursor.col_in_char; #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif return 1; } int vt_edit_go_upward(vt_edit_t *edit, int flag /* SCROLL */ ) { #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif reset_wraparound_checker(edit); if (vt_is_scroll_upperlimit(edit, edit->cursor.row)) { if (!(flag & SCROLL) || (MARGIN_IS_ENABLED(edit) ? !scroll_downward_region(edit, 1, 0, 0) : !vt_edit_scroll_downward(edit, 1))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " cursor cannot go upward(reaches scroll lower limit).\n"); #endif return 0; } } else { if (!vt_cursor_goto_by_col(&edit->cursor, edit->cursor.col, edit->cursor.row - 1)) { return 0; } } #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif return 1; } int vt_edit_go_downward(vt_edit_t *edit, int flag /* SCROLL */ ) { #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif reset_wraparound_checker(edit); if (vt_is_scroll_lowerlimit(edit, edit->cursor.row)) { if (!(flag & SCROLL) || (MARGIN_IS_ENABLED(edit) ? !scroll_upward_region(edit, 1, 0, 0) : !vt_edit_scroll_upward(edit, 1))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " cursor cannot go downward(reaches scroll lower limit).\n"); #endif return 0; } } else { if (!vt_cursor_goto_by_col(&edit->cursor, edit->cursor.col, edit->cursor.row + 1)) { return 0; } } #ifdef CURSOR_DEBUG vt_cursor_dump(&edit->cursor); #endif return 1; } int vt_edit_goto(vt_edit_t *edit, int col, int row) { reset_wraparound_checker(edit); if (edit->is_relative_origin) { if ((row += edit->vmargin_beg) > edit->vmargin_end) { row = edit->vmargin_end; } if ((col += edit->hmargin_beg) > edit->hmargin_end) { col = edit->hmargin_end; } } return vt_cursor_goto_by_col(&edit->cursor, col, row); } void vt_edit_set_last_column_flag(vt_edit_t *edit, int flag) { if (flag) { edit->wraparound_ready_line = CURSOR_LINE(edit); } else { reset_wraparound_checker(edit); } } int vt_edit_restore_cursor(vt_edit_t *edit) { if (vt_cursor_restore(&edit->cursor)) { reset_wraparound_checker(edit); return 1; } else { return 0; } } void vt_edit_fill_area(vt_edit_t *edit, int code /* Unicode */, int is_protected, int col, int row, u_int num_cols, u_int num_rows) { int char_index; u_int cols_rest; vt_line_t *line; vt_char_t ch; if (!apply_relative_origin(edit, &col, &row, &num_cols, &num_rows)) { return; } vt_char_init(&ch); vt_char_set(&ch, code, code <= 0x7f ? US_ASCII : ISO10646_UCS4_1, /* XXX biwidth is not supported. */ 0, 0, /* * xterm-332 and Tera Term 4.95 don't use BCE for DECALN(ESC#8), but use for DECFRA. * rlogin-2.23.1 use BCE for both of them. * * (Test) * echo -e "\x1b[0;33;44m\x1b[60;1;1;10;10\$x" * echo -e "\x1b[0;33;44m\x1b#8" */ edit->use_bce ? vt_char_fg_color(&edit->bce_ch) : VT_FG_COLOR, edit->use_bce ? vt_char_bg_color(&edit->bce_ch) : VT_BG_COLOR, 0, 0, 0, 0, is_protected); for (; num_rows > 0; num_rows--) { line = vt_model_get_line(&edit->model, row++); char_index = vt_convert_col_to_char_index(line, &cols_rest, col, BREAK_BOUNDARY); if (cols_rest > 0) { vt_line_fill(line, edit->use_bce ? &edit->bce_ch : vt_sp_ch(), char_index, cols_rest); char_index += cols_rest; } vt_line_fill(line, &ch, char_index, num_cols); } vt_char_final(&ch); } void vt_edit_copy_area(vt_edit_t *src_edit, int src_col, int src_row, u_int num_copy_cols, u_int num_copy_rows, vt_edit_t *dst_edit, int dst_col, int dst_row) { if (src_edit->is_relative_origin) { if ((src_row += src_edit->vmargin_beg) > src_edit->vmargin_end || (dst_row += dst_edit->vmargin_beg) > dst_edit->vmargin_end || (src_col += src_edit->hmargin_beg) > src_edit->hmargin_end || (dst_col += dst_edit->hmargin_beg) > dst_edit->hmargin_end) { return; } if (src_row + num_copy_rows > src_edit->vmargin_end + 1) { num_copy_rows = src_edit->vmargin_end + 1 - src_row; } if (dst_row + num_copy_rows > dst_edit->vmargin_end + 1) { num_copy_rows = dst_edit->vmargin_end + 1 - dst_row; } if (src_col + num_copy_cols > src_edit->hmargin_end + 1) { num_copy_cols = src_edit->hmargin_end + 1 - src_col; } if (dst_col + num_copy_cols > dst_edit->hmargin_end + 1) { num_copy_cols = dst_edit->hmargin_end + 1 - dst_col; } } else { if (src_row >= src_edit->model.num_rows || dst_row >= dst_edit->model.num_rows || src_col >= src_edit->model.num_cols || dst_col >= dst_edit->model.num_cols) { return; } if (src_row + num_copy_rows > src_edit->model.num_rows) { num_copy_rows = src_edit->model.num_rows - src_row; } if (dst_row + num_copy_rows > dst_edit->model.num_rows) { num_copy_rows = dst_edit->model.num_rows - dst_row; } if (src_col + num_copy_cols > src_edit->model.num_cols) { num_copy_cols = src_edit->model.num_cols - src_col; } if (dst_col + num_copy_cols > dst_edit->model.num_cols) { num_copy_cols = dst_edit->model.num_cols - dst_col; } } copy_area(src_edit, src_col, src_row, num_copy_cols, num_copy_rows, dst_edit, dst_col, dst_row); } void vt_edit_erase_area(vt_edit_t *edit, int col, int row, u_int num_cols, u_int num_rows) { if (!apply_relative_origin(edit, &col, &row, &num_cols, &num_rows)) { return; } erase_area(edit, col, row, num_cols, num_rows); } void vt_edit_change_attr_area(vt_edit_t *edit, int col, int row, u_int num_cols, u_int num_rows, void (*func)(vt_char_t*, int, int, int, int, int, int, int), int attr) { u_int count; vt_line_t *line; int char_index; int end_char_index; u_int cols_rest; int bold; int italic; int underline_style; int blinking; int reversed; int crossed_out; int overlined; if (attr == 0) { bold = italic = underline_style = blinking = reversed = crossed_out = overlined = -1; } else { bold = italic = underline_style = blinking = reversed = crossed_out = overlined = 0; if (attr == 1) { bold = 1; } else if (attr == 3) { italic = 1; } else if (attr == 4) { underline_style = LS_UNDERLINE_SINGLE; } else if (attr == 5 || attr == 6) { blinking = 1; } else if (attr == 7) { reversed = 1; } else if (attr == 9) { crossed_out = 1; } else if (attr == 21) { underline_style = LS_UNDERLINE_DOUBLE; } else if (attr == 22) { bold = -1; } else if (attr == 23) { italic = -1; } else if (attr == 24) { underline_style = -1; } else if (attr == 25) { blinking = -1; } else if (attr == 27) { reversed = -1; } else if (attr == 29) { crossed_out = -1; } else if (attr == 53) { overlined = 1; } else if (attr == 55) { overlined = -1; } else { return; } } /* * XXX * apply_relative_origin() adjusts arguments regarding edit->use_rect_attr_select as true * all the time. */ if (!apply_relative_origin(edit, &col, &row, &num_cols, &num_rows)) { return; } for (count = 0; count < num_rows; count++) { if (count == 1 && !edit->use_rect_attr_select) { int old_col; old_col = col; col = edit->is_relative_origin ? edit->hmargin_beg : 0; num_cols += (old_col - col); } if (!(line = vt_edit_get_line(edit, row + count))) { continue; } char_index = vt_convert_col_to_char_index(line, &cols_rest, col, BREAK_BOUNDARY); if (char_index >= line->num_filled_chars && attr > 7) { continue; } if (cols_rest > 0) { char_index++; } if (edit->use_rect_attr_select || count + 1 == num_rows) { end_char_index = vt_convert_col_to_char_index(line, NULL, col + num_cols - 1, BREAK_BOUNDARY); } else { end_char_index = vt_convert_col_to_char_index( line, NULL, edit->is_relative_origin ? edit->hmargin_end : vt_edit_get_cols(edit) - 1, BREAK_BOUNDARY); } vt_line_assure_boundary(line, end_char_index); vt_line_set_modified(line, char_index, end_char_index); for (; char_index <= end_char_index; char_index++) { (*func)(vt_char_at(line, char_index), bold, italic, underline_style, blinking, reversed, crossed_out, overlined); } } } u_int16_t vt_edit_get_checksum(vt_edit_t *edit, int col, int row, u_int num_cols, u_int num_rows) { int count; u_int16_t checksum; vt_line_t *line; int char_index; u_int cols_rest; if (!apply_relative_origin(edit, &col, &row, &num_cols, &num_rows)) { return 0; } checksum = 0; for (count = 0; count < num_rows; count++) { if ((line = vt_edit_get_line(edit, row + count))) { int end_char_index; vt_char_t *ch; if ((char_index = vt_convert_col_to_char_index(line, &cols_rest, col, BREAK_BOUNDARY)) >= line->num_filled_chars) { continue; } if (cols_rest > 0) { char_index ++; checksum --; /* 2nd column of full width character is 0xFFFF (compat with xterm) */ } if ((end_char_index = vt_convert_col_to_char_index(line, &cols_rest, col + num_cols, BREAK_BOUNDARY)) > #if 0 line->num_filled_chars #else vt_line_get_num_filled_chars_except_sp(line) /* compat with xterm */ #endif ) { #if 0 end_char_index = line->num_filled_chars; #else end_char_index = vt_line_get_num_filled_chars_except_sp(line); /* compat with xterm */ #endif } if (cols_rest > 0) { end_char_index++; checksum ++; /* col + num_cols - 1 is 1st column of full width character */ } for(; char_index < end_char_index; char_index++) { ch = vt_char_at(line, char_index); checksum += vt_char_code(ch); if (vt_char_cols(ch) == 2) { checksum --; /* 2nd column of full width character is 0xFFFF (compat with xterm) */ } } } } return checksum; } void vt_edit_clear_size_attr(vt_edit_t *edit) { u_int count; for (count = 0; count < edit->model.num_rows; count++) { vt_line_set_size_attr(vt_edit_get_line(edit, count), 0); } } int vt_edit_cursor_logical_col(vt_edit_t *edit) { if (edit->is_relative_origin) { if (edit->cursor.col > edit->hmargin_beg) { return edit->cursor.col - edit->hmargin_beg; } else { return 0; } } return edit->cursor.col; } int vt_edit_cursor_logical_row(vt_edit_t *edit) { if (edit->is_relative_origin) { if (edit->cursor.row > edit->vmargin_beg) { return edit->cursor.row - edit->vmargin_beg; } else { return 0; } } return edit->cursor.row; } /* * for debugging. */ #ifdef DEBUG void vt_edit_dump(vt_edit_t *edit) { int row; vt_line_t *line; bl_debug_printf(BL_DEBUG_TAG " ===> dumping edit...[cursor(index)%d (col)%d (row)%d]\n", edit->cursor.char_index, edit->cursor.col, edit->cursor.row); for (row = 0; row < edit->model.num_rows; row++) { int char_index; line = vt_model_get_line(&edit->model, row); if (vt_line_is_modified(line)) { if (vt_line_is_cleared_to_end(line)) { bl_msg_printf("!%.2d-END", vt_line_get_beg_of_modified(line)); } else { bl_msg_printf("!%.2d-%.2d", vt_line_get_beg_of_modified(line), vt_line_get_end_of_modified(line)); } } else { bl_msg_printf(" "); } bl_msg_printf("[%.2d %.2d]", line->num_filled_chars, vt_line_get_num_filled_cols(line)); if (line->num_filled_chars > 0) { for (char_index = 0; char_index < line->num_filled_chars; char_index++) { if (edit->cursor.row == row && edit->cursor.char_index == char_index) { bl_msg_printf("**"); } vt_char_dump(vt_char_at(line, char_index)); if (edit->cursor.row == row && edit->cursor.char_index == char_index) { bl_msg_printf("**"); } } } bl_msg_printf("\n"); } bl_debug_printf(BL_DEBUG_TAG " <=== end of edit.\n\n"); } void vt_edit_dump_updated(vt_edit_t *edit) { int row; for (row = 0; row < edit->model.num_rows; row++) { bl_msg_printf("(%.2d)%d ", row, vt_line_is_modified(vt_model_get_line(&edit->model, row))); } bl_msg_printf("\n"); } #endif mlterm-3.8.9/vtemu/vt_edit.h010064400017600000144000000143761356600660700145240ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_EDIT_H__ #define __VT_EDIT_H__ #include #include "vt_str.h" #include "vt_line.h" #include "vt_model.h" #include "vt_cursor.h" typedef struct vt_edit_scroll_event_listener { void *self; void (*receive_scrolled_out_line)(void *, vt_line_t *); void (*scrolled_out_lines_finished)(void *); int (*window_scroll_upward_region)(void *, int, int, u_int); int (*window_scroll_downward_region)(void *, int, int, u_int); } vt_edit_scroll_event_listener_t; typedef struct vt_protect_store { vt_char_t *chars; int beg_row; int end_row; } vt_protect_store_t; typedef struct vt_edit { vt_model_t model; vt_cursor_t cursor; u_int tab_size; u_int8_t *tab_stops; vt_char_t bce_ch; /* used for line overlapping */ vt_line_t *wraparound_ready_line; int16_t vmargin_beg; int16_t vmargin_end; vt_edit_scroll_event_listener_t *scroll_listener; int16_t hmargin_beg; int16_t hmargin_end; int8_t use_margin; int8_t is_logging; int8_t is_relative_origin; int8_t is_auto_wrap; int8_t use_bce; int8_t use_rect_attr_select; } vt_edit_t; void vt_set_scroll_on_resizing(int flag); int vt_edit_init(vt_edit_t *edit, vt_edit_scroll_event_listener_t *scroll_listener, u_int num_cols, u_int num_rows, u_int tab_size, int is_logging, int use_bce); void vt_edit_final(vt_edit_t *edit); int vt_edit_clone(vt_edit_t *dst_edit, vt_edit_t *src_edit); int vt_edit_resize(vt_edit_t *edit, u_int num_cols, u_int num_rows); int vt_edit_insert_chars(vt_edit_t *edit, vt_char_t *chars, u_int num_chars); int vt_edit_insert_blank_chars(vt_edit_t *edit, u_int num_blank_chars); int vt_edit_overwrite_chars(vt_edit_t *edit, vt_char_t *chars, u_int num_chars); int vt_edit_delete_cols(vt_edit_t *edit, u_int delete_cols); int vt_edit_clear_cols(vt_edit_t *edit, u_int cols); int vt_edit_insert_new_line(vt_edit_t *edit); int vt_edit_delete_line(vt_edit_t *edit); int vt_edit_clear_line_to_right(vt_edit_t *edit); int vt_edit_clear_line_to_left(vt_edit_t *edit); int vt_edit_clear_below(vt_edit_t *edit); int vt_edit_clear_above(vt_edit_t *edit); vt_protect_store_t *vt_edit_save_protected_chars(vt_edit_t *edit, int beg_row, int end_row, int relative); void vt_edit_restore_protected_chars(vt_edit_t *edit, vt_protect_store_t *save); int vt_edit_set_vmargin(vt_edit_t *edit, int beg, int end); int vt_edit_scroll_upward(vt_edit_t *edit, u_int size); int vt_edit_scroll_downward(vt_edit_t *edit, u_int size); void vt_edit_scroll_leftward(vt_edit_t *edit, u_int size); void vt_edit_scroll_rightward(vt_edit_t *edit, u_int size); int vt_edit_scroll_leftward_from_cursor(vt_edit_t *edit, u_int size); int vt_edit_scroll_rightward_from_cursor(vt_edit_t *edit, u_int size); void vt_edit_set_use_hmargin(vt_edit_t *edit, int use); int vt_edit_set_hmargin(vt_edit_t *edit, int beg, int end); int vt_edit_forward_tabs(vt_edit_t *edit, u_int num); int vt_edit_backward_tabs(vt_edit_t *edit, u_int num); #define vt_edit_get_tab_size(edit) ((edit)->tab_size) void vt_edit_set_tab_size(vt_edit_t *edit, u_int tab_size); void vt_edit_set_tab_stop(vt_edit_t *edit); #define vt_edit_is_tab_stop(edit, col) ((edit)->tab_stops[(col) / 8] & (1 << ((col) % 8))) void vt_edit_clear_tab_stop(vt_edit_t *edit); void vt_edit_clear_all_tab_stops(vt_edit_t *edit); #define vt_edit_get_line(edit, row) (vt_model_get_line(&(edit)->model, row)) void vt_edit_set_modified_all(vt_edit_t *edit); #define vt_edit_get_cols(edit) ((edit)->model.num_cols) #define vt_edit_get_rows(edit) ((edit)->model.num_rows) int vt_edit_go_forward(vt_edit_t *edit, int flag); int vt_edit_go_back(vt_edit_t *edit, int flag); int vt_edit_go_upward(vt_edit_t *edit, int flag); int vt_edit_go_downward(vt_edit_t *edit, int flag); void vt_edit_goto_beg_of_line(vt_edit_t *edit); void vt_edit_goto_home(vt_edit_t *edit); int vt_edit_goto(vt_edit_t *edit, int col, int row); #define vt_edit_set_relative_origin(edit, flag) ((edit)->is_relative_origin = (flag)) #define vt_edit_is_relative_origin(edit) ((edit)->is_relative_origin) #define vt_edit_set_auto_wrap(edit, flag) ((edit)->is_auto_wrap = (flag)) #define vt_edit_is_auto_wrap(edit) ((edit)->is_auto_wrap) void vt_edit_set_last_column_flag(vt_edit_t *edit, int flag); #define vt_edit_get_last_column_flag(edit) ((edit)->wraparound_ready_line ? 1 : 0) #define vt_edit_set_use_bce(edit, use) ((edit)->use_bce = (use)) #define vt_edit_is_using_bce(edit) ((edit)->use_bce) #define vt_edit_set_bce_fg_color(edit, fg_color) vt_char_set_fg_color(&(edit)->bce_ch, fg_color) #define vt_edit_set_bce_bg_color(edit, bg_color) vt_char_set_bg_color(&(edit)->bce_ch, bg_color) #define vt_edit_get_bce_ch(edit) (&(edit)->bce_ch) #define vt_edit_save_cursor(edit) vt_cursor_save(&(edit)->cursor) #define vt_edit_saved_cursor_to_home(edit) vt_saved_cursor_to_home(&(edit)->cursor) int vt_edit_restore_cursor(vt_edit_t *edit); void vt_edit_fill_area(vt_edit_t *edit, int code, int is_protected, int col, int row, u_int num_cols, u_int num_rows); void vt_edit_copy_area(vt_edit_t *src_edit, int src_col, int src_row, u_int num_copy_cols, u_int num_copy_rows, vt_edit_t *dst_edit, int dst_col, int dst_row); void vt_edit_erase_area(vt_edit_t *edit, int col, int row, u_int num_cols, u_int num_rows); void vt_edit_change_attr_area(vt_edit_t *edit, int col, int row, u_int num_cols, u_int num_rows, void (*func)(vt_char_t *, int, int, int, int, int, int, int), int attr); u_int16_t vt_edit_get_checksum(vt_edit_t *edit, int col, int row, u_int num_cols, u_int num_rows); void vt_edit_clear_size_attr(vt_edit_t *edit); #define vt_edit_set_use_rect_attr_select(edit, use) ((edit)->use_rect_attr_select = (use)) #define vt_edit_is_using_rect_attr_select(edit) ((edit)->use_rect_attr_select) #define vt_cursor_char_index(edit) ((edit)->cursor.char_index) #define vt_cursor_col(edit) ((edit)->cursor.col) #define vt_cursor_row(edit) ((edit)->cursor.row) int vt_edit_cursor_logical_col(vt_edit_t *edit); int vt_edit_cursor_logical_row(vt_edit_t *edit); #ifdef DEBUG void vt_edit_dump(vt_edit_t *edit); void vt_edit_dump_updated(vt_edit_t *edit); #endif #endif mlterm-3.8.9/vtemu/vt_edit_scroll.c010064400017600000144000000215461356600660700160720ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_edit_scroll.h" #include #include "vt_edit_util.h" /* --- static functions --- */ /* * src and dst may overlap */ static int copy_lines(vt_edit_t *edit, int dst_row, int src_row, u_int size, int mark_changed) { int count; vt_line_t *src_line; vt_line_t *dst_line; if (size == 0 || dst_row == src_row) { return 1; } if (src_row + size > edit->model.num_rows) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " copying %d lines from %d row is over edit->model.num_rows(%d)", size, src_row, edit->model.num_rows); #endif size = edit->model.num_rows - src_row; #ifdef DEBUG bl_msg_printf(" ... size modified -> %d.\n", size); #endif } if (dst_row + size > edit->model.num_rows) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " copying %d lines to %d row is over edit->model.num_rows(%d)", size, dst_row, edit->model.num_rows); #endif size = edit->model.num_rows - dst_row; #ifdef DEBUG bl_msg_printf(" ... size modified -> %d.\n", size); #endif } if (dst_row < src_row) { for (count = 0; count < size; count++) { dst_line = vt_model_get_line(&edit->model, dst_row + count); src_line = vt_model_get_line(&edit->model, src_row + count); vt_line_swap(dst_line, src_line); if (mark_changed) { vt_line_set_modified_all(dst_line); } } } else { for (count = size - 1; count >= 0; count--) { dst_line = vt_model_get_line(&edit->model, dst_row + count); src_line = vt_model_get_line(&edit->model, src_row + count); vt_line_swap(dst_line, src_line); if (mark_changed) { vt_line_set_modified_all(dst_line); } } } return 1; } static int clear_lines_to_eol(vt_edit_t *edit, int beg_row, u_int size) { int count; vt_edit_clear_lines(edit, beg_row, size); for (count = 0; count < size; count++) { vt_line_set_modified_all(vt_model_get_line(&edit->model, beg_row + count)); } return 1; } static int scroll_upward_region(vt_edit_t *edit, int boundary_beg, int boundary_end, u_int size) { int count; int window_is_scrolled; if (boundary_beg + size > boundary_end) { /* * all lines within boundary are scrolled out. */ if (edit->is_logging && edit->scroll_listener->receive_scrolled_out_line) { for (count = boundary_beg; count < boundary_end; count++) { (*edit->scroll_listener->receive_scrolled_out_line)(edit->scroll_listener->self, vt_model_get_line(&edit->model, count)); } } edit->cursor.row = boundary_beg; edit->cursor.col = 0; edit->cursor.char_index = 0; (*edit->scroll_listener->scrolled_out_lines_finished)(edit->scroll_listener->self); return clear_lines_to_eol(edit, boundary_beg, boundary_end - boundary_beg + 1); } /* * scrolling up in window. * * !! Notice !! * This should be done before vt_edit_t data structure is chanegd * for the listener object to clear existing cache. */ #if 0 bl_debug_printf(" SCROLL UP region %d %d size %d\n", boundary_beg, boundary_end, size); #endif window_is_scrolled = (*edit->scroll_listener->window_scroll_upward_region)( edit->scroll_listener->self, boundary_beg, boundary_end, size); /* * handing over scrolled out lines , and calculating scrolling beg/end y * positions. */ if (edit->is_logging && edit->scroll_listener->receive_scrolled_out_line) { for (count = boundary_beg; count < boundary_beg + size; count++) { (*edit->scroll_listener->receive_scrolled_out_line)(edit->scroll_listener->self, vt_model_get_line(&edit->model, count)); } } /* * resetting cursor position. */ if (boundary_beg <= edit->cursor.row && edit->cursor.row <= boundary_end) { if (edit->cursor.row < boundary_beg + size) { edit->cursor.row = boundary_beg; edit->cursor.char_index = 0; edit->cursor.col = 0; } else { edit->cursor.row -= size; } } /* * scrolling up in edit. */ if (boundary_beg == 0 && boundary_end == vt_model_end_row(&edit->model)) { vt_model_scroll_upward(&edit->model, size); } else { copy_lines(edit, boundary_beg, boundary_beg + size, boundary_end - (boundary_beg + size) + 1, 0); } if (!window_is_scrolled) { int count; vt_edit_clear_lines(edit, boundary_end - size + 1, size); for (count = boundary_beg; count <= boundary_end; count++) { vt_line_set_modified_all(vt_model_get_line(&edit->model, count)); } } else { clear_lines_to_eol(edit, boundary_end - size + 1, size); } /* * This must be called after vt_model_scroll_upward() because * scrolled_out_lines_finished() * can change vt_model_t. */ (*edit->scroll_listener->scrolled_out_lines_finished)(edit->scroll_listener->self); return 1; } static int scroll_downward_region(vt_edit_t *edit, int boundary_beg, int boundary_end, u_int size) { int window_is_scrolled; if (boundary_beg + size > boundary_end) { /* * all lines within boundary are scrolled out. */ edit->cursor.row = boundary_end; edit->cursor.col = 0; edit->cursor.char_index = 0; return clear_lines_to_eol(edit, boundary_beg, boundary_end - boundary_beg + 1); } /* * scrolling down in window. * * !! Notice !! * This should be done before vt_edit_t data structure is chanegd * for the listener object to clear existing cache. */ #if 0 bl_debug_printf(" SCROLL DOWN region %d %d size %d\n", boundary_beg, boundary_end, size); #endif window_is_scrolled = (*edit->scroll_listener->window_scroll_downward_region)( edit->scroll_listener->self, boundary_beg, boundary_end, size); /* * resetting cursor position. */ if (boundary_beg <= edit->cursor.row && edit->cursor.row <= boundary_end) { if (edit->cursor.row + size >= boundary_end + 1) { edit->cursor.row = boundary_end; edit->cursor.char_index = 0; edit->cursor.col = 0; } else { edit->cursor.row += size; } } /* * scrolling down in edit. */ if (boundary_beg == 0 && boundary_end == vt_model_end_row(&edit->model)) { vt_model_scroll_downward(&edit->model, size); } else { copy_lines(edit, boundary_beg + size, boundary_beg, (boundary_end - size) - boundary_beg + 1, 0); } if (!window_is_scrolled) { int count; vt_edit_clear_lines(edit, boundary_beg, size); for (count = boundary_beg; count <= boundary_end; count++) { vt_line_set_modified_all(vt_model_get_line(&edit->model, count)); } } else { clear_lines_to_eol(edit, boundary_beg, size); } return 1; } /* --- global functions --- */ int vt_edsl_scroll_upward(vt_edit_t *edit, u_int size) { #if 0 /* * XXX * Can this cause unexpected result ? */ if (edit->vmargin_beg > edit->cursor.row || edit->cursor.row > edit->vmargin_end) { return 0; } #endif return scroll_upward_region(edit, edit->vmargin_beg, edit->vmargin_end, size); } int vt_edsl_scroll_downward(vt_edit_t *edit, u_int size) { #if 0 /* * XXX * Can this cause unexpected result ? */ if (edit->vmargin_beg > edit->cursor.row || edit->cursor.row > edit->vmargin_end) { return 0; } #endif return scroll_downward_region(edit, edit->vmargin_beg, edit->vmargin_end, size); } /* * XXX * not used for now. */ #if 0 int vt_edsl_scroll_upward_in_all(vt_edit_t *edit, u_int size) { return scroll_upward_region(edit, 0, edit->model.num_rows - 1, size); } int vt_edsl_scroll_downward_in_all(vt_edit_t *edit, u_int size) { return scroll_downward_region(edit, 0, edit->model.num_rows - 1, size); } #endif int vt_is_scroll_upperlimit(vt_edit_t *edit, int row) { return (row == edit->vmargin_beg); } int vt_is_scroll_lowerlimit(vt_edit_t *edit, int row) { return (row == edit->vmargin_end); } int vt_edsl_insert_new_line(vt_edit_t *edit) { int start_row; int start_col; int end_row; if (edit->cursor.row < edit->vmargin_beg || edit->vmargin_end < edit->cursor.row) { return 0; } start_row = edit->cursor.row; start_col = edit->cursor.col; end_row = edit->vmargin_end; scroll_downward_region(edit, start_row, end_row, 1); vt_cursor_goto_by_col(&edit->cursor, start_col, start_row); vt_edit_clear_line_to_right(edit); return 1; } int vt_edsl_delete_line(vt_edit_t *edit) { int start_row; int start_col; int end_row; int is_logging; if (edit->cursor.row < edit->vmargin_beg || edit->vmargin_end < edit->cursor.row) { return 0; } is_logging = edit->is_logging; edit->is_logging = 0; start_row = edit->cursor.row; start_col = edit->cursor.col; end_row = edit->vmargin_end; scroll_upward_region(edit, start_row, end_row, 1); vt_edit_clear_lines(edit, end_row, 1); vt_cursor_goto_by_col(&edit->cursor, start_col, start_row); edit->is_logging = is_logging; return 1; } mlterm-3.8.9/vtemu/vt_edit_scroll.h010064400017600000144000000011501356600660700160640ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_EDIT_SCROLL_H__ #define __VT_EDIT_SCROLL_H__ #include "vt_edit.h" int vt_edsl_scroll_upward(vt_edit_t *edit, u_int size); int vt_edsl_scroll_downward(vt_edit_t *edit, u_int size); #if 0 int vt_edsl_scroll_upward_in_all(vt_edit_t *edit, u_int size); int vt_edsl_scroll_downward_in_all(vt_edit_t *edit, u_int size); #endif int vt_is_scroll_upperlimit(vt_edit_t *edit, int row); int vt_is_scroll_lowerlimit(vt_edit_t *edit, int row); int vt_edsl_delete_line(vt_edit_t *edit); int vt_edsl_insert_new_line(vt_edit_t *edit); #endif mlterm-3.8.9/vtemu/vt_edit_util.c010064400017600000144000000023401356600660700155400ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_edit_util.h" #include /* --- global functions --- */ /* * used in vt_edit/vt_edit_scroll */ int vt_edit_clear_lines(vt_edit_t *edit, int beg_row, u_int size) { int count; if (size == 0) { return 0; } if (beg_row > vt_model_end_row(&edit->model)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " line %d is already empty.\n", beg_row); #endif return 0; } if (edit->use_bce) { for (count = 0; count < size; count++) { vt_line_clear_with(vt_model_get_line(&edit->model, beg_row + count), 0, &edit->bce_ch); } } else { for (count = 0; count < size; count++) { vt_line_reset(vt_model_get_line(&edit->model, beg_row + count)); } } if (beg_row <= edit->cursor.row && edit->cursor.row <= beg_row + size - 1) { u_int brk_size; if ((brk_size = vt_line_break_boundary(CURSOR_LINE(edit), edit->cursor.col + 1)) == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " critical error.\n"); #endif edit->cursor.char_index = edit->cursor.col = 0; } else { edit->cursor.char_index = edit->cursor.col = brk_size - 1; } edit->cursor.col_in_char = 0; } return 1; } mlterm-3.8.9/vtemu/vt_edit_util.h010064400017600000144000000007241356600660700155510ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_EDIT_UTIL_H__ #define __VT_EDIT_UTIL_H__ #include #include "vt_edit.h" #define CURSOR_LINE(edit) vt_get_cursor_line(&(edit)->cursor) #define CURSOR_CHAR(edit) vt_get_cursor_char(&(edit)->cursor) int vt_edit_clear_lines(vt_edit_t *edit, int start, u_int size); int vt_edit_copy_lines(vt_edit_t *edit, int dst_row, int src_row, u_int size, int mark_changed); #endif mlterm-3.8.9/vtemu/vt_font.h010064400017600000144000000027151356600660700145370ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_FONT_H__ #define __VT_FONT_H__ #include #undef MAX_CHARSET #define MAX_CHARSET 0x1ff #define FONT_CS(font) ((font) & MAX_CHARSET) #define FONT_STYLES (FONT_BOLD | FONT_ITALIC) #define FONT_STYLE_INDEX(font) ((((font) & FONT_STYLES) >> 10) - 1) #define UNICODE_AREA(font) (((font) >> 12) & 0xff) #define NORMAL_FONT_OF(cs) (IS_FULLWIDTH_CS(cs) ? (cs) | FONT_FULLWIDTH : (cs)) #define SIZE_ATTR_FONT(font, size_attr) ((font) | (((int)(size_attr)) << 21)) #define SIZE_ATTR_OF(font) (((font) >> 21) & 0x3) #define NO_SIZE_ATTR(font) ((font) & ~(0x3 << 21)) enum { DOUBLE_WIDTH = 0x1, DOUBLE_HEIGHT_TOP = 0x2, DOUBLE_HEIGHT_BOTTOM = 0x3, }; typedef enum vt_font { /* 0x00 - MAX_CHARSET(0x1ff) is reserved for ef_charset_t */ /* for unicode half or full width tag */ FONT_FULLWIDTH = 0x200u, /* (default) half width */ /* for font thickness */ FONT_BOLD = 0x400u, /* (default) medium */ /* for font slant */ FONT_ITALIC = 0x800u, /* (default) roman */ /* * Note that FONT_ROTATED is defined in fb/ui_font.c as (FONT_ITALIC << 1), * so be careful to add new entries after FONT_ITALIC. */ #if 0 /* font width */ FONT_SEMICONDENSED /* (default) normal */ #endif /* * 0x1000 - 0xff000 is used for Unicode range mark (see vt_get_unicode_area_font) * 0x200000 - 0x700000 is used for size_attr (see ui_font_manager.c) */ } vt_font_t; #endif mlterm-3.8.9/vtemu/vt_iscii.c010064400017600000144000000033201356600660700146550ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_iscii.h" #include /* memcpy */ #include "vt_ctl_loader.h" /* --- global functions --- */ #ifndef NO_DYNAMIC_LOAD_CTL #ifdef __APPLE__ vt_isciikey_state_t vt_isciikey_state_new(int) __attribute__((weak)); void vt_isciikey_state_destroy(vt_isciikey_state_t) __attribute__((weak)); size_t vt_convert_ascii_to_iscii(vt_isciikey_state_t, u_char*, size_t, u_char*, size_t) __attribute__((weak)); #endif vt_isciikey_state_t vt_isciikey_state_new(int is_inscript) { vt_isciikey_state_t (*func)(int); if (!(func = vt_load_ctl_iscii_func(VT_ISCIIKEY_STATE_NEW))) { return NULL; } return (*func)(is_inscript); } void vt_isciikey_state_destroy(vt_isciikey_state_t state) { void (*func)(vt_isciikey_state_t); if (!(func = vt_load_ctl_iscii_func(VT_ISCIIKEY_STATE_DESTROY))) { return; } (*func)(state); } size_t vt_convert_ascii_to_iscii(vt_isciikey_state_t state, u_char *iscii, size_t iscii_len, u_char *ascii, size_t ascii_len) { int (*func)(vt_isciikey_state_t, u_char*, size_t, u_char*, size_t); if (!(func = vt_load_ctl_iscii_func(VT_CONVERT_ASCII_TO_ISCII))) { return 0; } return (*func)(state, iscii, iscii_len, ascii, ascii_len); } #else #ifdef USE_IND #include "libctl/vt_iscii.c" #else /* * Dummy functions are necessary for x_im.c */ vt_isciikey_state_t vt_isciikey_state_new(int is_inscript) { return NULL; } void vt_isciikey_state_destroy(vt_isciikey_state_t state) {} size_t vt_convert_ascii_to_iscii(vt_isciikey_state_t state, u_char *iscii, size_t iscii_len, u_char *ascii, size_t ascii_len) { return 0; } #endif #endif mlterm-3.8.9/vtemu/vt_iscii.h010064400017600000144000000010541356600660700146640ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_ISCII_H__ #define __VT_ISCII_H__ #include /* u_int/u_char */ typedef struct vt_isciikey_state *vt_isciikey_state_t; typedef struct vt_iscii_state *vt_iscii_state_t; vt_isciikey_state_t vt_isciikey_state_new(int is_inscript); void vt_isciikey_state_destroy(vt_isciikey_state_t state); size_t vt_convert_ascii_to_iscii(vt_isciikey_state_t state, u_char *iscii, size_t iscii_len, u_char *ascii, size_t ascii_len); #endif mlterm-3.8.9/vtemu/vt_line.c010064400017600000144000001240521356600660700145120ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_line.h" #include /* memset */ #include #include /* BL_MIN */ #include /* alloca */ #include "vt_ctl_loader.h" #include "vt_ot_layout.h" #if 0 #define __DEBUG #endif #ifdef __DEBUG #define END_CHAR_INDEX(line) \ ((line)->num_filled_chars == 0 && \ bl_debug_printf("END_CHAR_INDEX()" BL_DEBUG_TAG " num_filled_chars is 0.\n") \ ? 0 \ : (line)->num_filled_chars - 1) #else #define END_CHAR_INDEX(line) \ ((line)->num_filled_chars == 0 ? 0 : (line)->num_filled_chars - 1) #endif #define IS_EMPTY(line) ((line)->num_filled_chars == 0) #define vt_line_is_using_bidi(line) ((line)->ctl_info_type == VINFO_BIDI) #define vt_line_is_using_iscii(line) ((line)->ctl_info_type == VINFO_ISCII) #define vt_line_is_using_ot_layout(line) ((line)->ctl_info_type == VINFO_OT_LAYOUT) /* You can specify this macro by configure script option. */ #if 0 #define OPTIMIZE_REDRAWING #endif /* --- static functions --- */ #ifndef NO_DYNAMIC_LOAD_CTL static int vt_line_set_use_bidi(vt_line_t *line, int flag) { int (*func)(vt_line_t *, int); if (!(func = vt_load_ctl_bidi_func(VT_LINE_SET_USE_BIDI))) { return 0; } return (*func)(line, flag); } static int vt_line_bidi_convert_visual_char_index_to_logical(vt_line_t *line, int char_index) { int (*func)(vt_line_t *, int); if (!(func = vt_load_ctl_bidi_func(VT_LINE_BIDI_CONVERT_VISUAL_CHAR_INDEX_TO_LOGICAL))) { return char_index; } return (*func)(line, char_index); } static int vt_line_bidi_copy_logical_str(vt_line_t *line, vt_char_t *dst, int beg, /* visual position */ u_int len) { int (*func)(vt_line_t *, vt_char_t *, int, u_int); if (!(func = vt_load_ctl_bidi_func(VT_LINE_BIDI_COPY_LOGICAL_STR))) { return 0; } return (*func)(line, dst, beg, len); } static int vt_line_bidi_is_rtl(vt_line_t *line) { int (*func)(vt_line_t *); if (!(func = vt_load_ctl_bidi_func(VT_LINE_BIDI_IS_RTL))) { return 0; } return (*func)(line); } static int vt_bidi_copy(vt_bidi_state_t dst, vt_bidi_state_t src, int optimize_ctl_info) { int (*func)(vt_bidi_state_t, vt_bidi_state_t, int); if (!(func = vt_load_ctl_bidi_func(VT_BIDI_COPY))) { return 0; } return (*func)(dst, src, optimize_ctl_info); } static int vt_bidi_reset(vt_bidi_state_t state) { int (*func)(vt_bidi_state_t); if (!(func = vt_load_ctl_bidi_func(VT_BIDI_RESET))) { return 0; } return (*func)(state); } static int vt_line_bidi_render(vt_line_t *line, vt_bidi_mode_t bidi_mode, const char *separators) { int (*func)(vt_line_t *, vt_bidi_mode_t, const char *); if (!(func = vt_load_ctl_bidi_func(VT_LINE_BIDI_RENDER))) { return 0; } return (*func)(line, bidi_mode, separators); } static int vt_line_bidi_visual(vt_line_t *line) { int (*func)(vt_line_t *); if (!(func = vt_load_ctl_bidi_func(VT_LINE_BIDI_VISUAL))) { return 0; } return (*func)(line); } static int vt_line_bidi_logical(vt_line_t *line) { int (*func)(vt_line_t *); if (!(func = vt_load_ctl_bidi_func(VT_LINE_BIDI_LOGICAL))) { return 0; } return (*func)(line); } static int vt_line_set_use_iscii(vt_line_t *line, int flag) { int (*func)(vt_line_t *, int); if (!(func = vt_load_ctl_iscii_func(VT_LINE_SET_USE_ISCII))) { return 0; } return (*func)(line, flag); } static int vt_iscii_copy(vt_iscii_state_t dst, vt_iscii_state_t src, int optimize_ctl_info) { int (*func)(vt_iscii_state_t, vt_iscii_state_t, int); if (!(func = vt_load_ctl_iscii_func(VT_ISCII_COPY))) { return 0; } return (*func)(dst, src, optimize_ctl_info); } static int vt_iscii_reset(vt_iscii_state_t state) { int (*func)(vt_iscii_state_t); if (!(func = vt_load_ctl_iscii_func(VT_ISCII_RESET))) { return 0; } return (*func)(state); } static int vt_line_iscii_render(vt_line_t *line) { int (*func)(vt_line_t *); if (!(func = vt_load_ctl_iscii_func(VT_LINE_ISCII_RENDER))) { return 0; } return (*func)(line); } static int vt_line_iscii_visual(vt_line_t *line) { int (*func)(vt_line_t *); if (!(func = vt_load_ctl_iscii_func(VT_LINE_ISCII_VISUAL))) { return 0; } return (*func)(line); } static int vt_line_iscii_logical(vt_line_t *line) { int (*func)(vt_line_t *); if (!(func = vt_load_ctl_iscii_func(VT_LINE_ISCII_LOGICAL))) { return 0; } return (*func)(line); } #else /* NO_DYNAMIC_LOAD_CTL */ #ifndef USE_FRIBIDI #define vt_line_set_use_bidi(line, flag) (0) #define vt_line_bidi_convert_visual_char_index_to_logical(line, char_index) (char_index) #define vt_line_bidi_copy_logical_str(line, dst, beg, len) (0) #define vt_line_bidi_is_rtl(line) (0) #define vt_bidi_copy(dst, src, optimize) (0) #define vt_bidi_reset(state) (0) #define vt_line_bidi_render(line, bidi_mode, separators) (0) #define vt_line_bidi_visual(line) (0) #define vt_line_bidi_logical(line) (0) #else /* Link functions in libctl/vt_*bidi.c */ int vt_line_set_use_bidi(vt_line_t *line, int flag); int vt_line_bidi_convert_visual_char_index_to_logical(vt_line_t *line, int char_index); int vt_line_bidi_copy_logical_str(vt_line_t *line, vt_char_t *dst, int beg, u_int len); int vt_line_bidi_is_rtl(vt_line_t *line); int vt_bidi_copy(vt_bidi_state_t dst, vt_bidi_state_t src, int optimize); int vt_bidi_reset(vt_bidi_state_t state); int vt_line_bidi_convert_logical_char_index_to_visual(vt_line_t *line, int char_index, u_int32_t *meet_pos_info); int vt_line_bidi_render(vt_line_t *line, vt_bidi_mode_t bidi_mode, const char *separators); int vt_line_bidi_visual(vt_line_t *line); int vt_line_bidi_logical(vt_line_t *line); #endif /* USE_FRIBIDI */ #ifndef USE_IND #define vt_line_set_use_iscii(line, flag) (0) #define vt_iscii_copy(dst, src, optimize) (0) #define vt_iscii_reset(state) (0) #define vt_line_iscii_render(line) (0) #define vt_line_iscii_visual(line) (0) #define vt_line_iscii_logical(line) (0) #else /* Link functions in libctl/vt_*iscii.c */ int vt_line_set_use_iscii(vt_line_t *line, int flag); int vt_iscii_copy(vt_iscii_state_t dst, vt_iscii_state_t src, int optimize); int vt_iscii_reset(vt_iscii_state_t state); int vt_line_iscii_convert_logical_char_index_to_visual(vt_line_t *line, int logical_char_index); int vt_line_iscii_render(vt_line_t *line); int vt_line_iscii_visual(vt_line_t *line); int vt_line_iscii_logical(vt_line_t *line); #endif /* USE_IND */ #endif /* NO_DYNAMIC_LOAD_CTL */ #ifdef USE_OT_LAYOUT static int vt_line_set_use_ot_layout(vt_line_t *line, int flag) { if (flag) { if (vt_line_is_using_ot_layout(line)) { return 1; } else if (line->ctl_info_type != 0) { return 0; } if ((line->ctl_info.ot_layout = vt_ot_layout_new()) == NULL) { return 0; } line->ctl_info_type = VINFO_OT_LAYOUT; } else { if (vt_line_is_using_ot_layout(line)) { vt_ot_layout_destroy(line->ctl_info.ot_layout); line->ctl_info_type = 0; } } return 1; } /* The caller should check vt_line_is_using_ot_layout() in advance. */ static int vt_line_ot_layout_visual(vt_line_t *line) { vt_char_t *src; u_int src_len; vt_char_t *dst; u_int dst_len; int dst_pos; int src_pos; if (line->ctl_info.ot_layout->size == 0 || !line->ctl_info.ot_layout->substituted) { #ifdef __DEBUG bl_warn_printf(BL_DEBUG_TAG " Not need to visualize.\n"); #endif return 1; } src_len = line->num_filled_chars; if ((src = vt_str_alloca(src_len)) == NULL) { return 0; } vt_str_init(src, src_len); vt_str_copy(src, line->chars, src_len); dst_len = line->ctl_info.ot_layout->size; if (line->num_chars < dst_len) { vt_char_t *chars; if ((chars = vt_str_new(dst_len))) { /* XXX => shrunk at vt_screen.c and vt_logical_visual_ctl.c */ vt_str_destroy(line->chars, line->num_chars); line->chars = chars; line->num_chars = dst_len; } else { line->ctl_info.ot_layout->size = dst_len = line->num_chars; } } dst = line->chars; src_pos = 0; for (dst_pos = 0; dst_pos < dst_len; dst_pos++) { if (line->ctl_info.ot_layout->num_chars_array[dst_pos] == 0) { /* * (logical)ACD -> (visual)A0CD -> (shaped)abcd * B B * (B is combining char) */ vt_char_copy(dst + dst_pos, vt_get_base_char(src + src_pos - 1)); vt_char_set_code(dst + dst_pos, 0); } else { u_int count; vt_char_copy(dst + dst_pos, src + (src_pos++)); for (count = 1; count < line->ctl_info.ot_layout->num_chars_array[dst_pos]; count++) { vt_char_t *comb; u_int num; #ifdef DEBUG if (vt_char_is_comb(vt_get_base_char(src + src_pos))) { bl_debug_printf(BL_DEBUG_TAG " illegal ot_layout\n"); } #endif vt_char_combine_simple(dst + dst_pos, vt_get_base_char(src + src_pos)); comb = vt_get_combining_chars(src + (src_pos++), &num); for (; num > 0; num--) { #ifdef DEBUG if (!vt_char_is_comb(comb)) { bl_debug_printf(BL_DEBUG_TAG " illegal ot_layout\n"); } #endif vt_char_combine_simple(dst + dst_pos, comb++); } } } } #ifdef DEBUG if (src_pos != src_len) { bl_debug_printf(BL_DEBUG_TAG "vt_line_ot_layout_visual() failed: %d -> %d\n", src_len, src_pos); } #endif vt_str_final(src, src_len); line->num_filled_chars = dst_pos; return 1; } /* The caller should check vt_line_is_using_ot_layout() in advance. */ static int vt_line_ot_layout_logical(vt_line_t *line) { vt_char_t *src; u_int src_len; vt_char_t *dst; int src_pos; if (line->ctl_info.ot_layout->size == 0 || !line->ctl_info.ot_layout->substituted) { #ifdef __DEBUG bl_warn_printf(BL_DEBUG_TAG " Not need to logicalize.\n"); #endif return 1; } src_len = line->num_filled_chars; if ((src = vt_str_alloca(src_len)) == NULL) { return 0; } vt_str_init(src, src_len); vt_str_copy(src, line->chars, src_len); dst = line->chars; for (src_pos = 0; src_pos < line->ctl_info.ot_layout->size; src_pos++) { vt_char_t *comb; u_int num; if (line->ctl_info.ot_layout->num_chars_array[src_pos] == 0) { continue; } if (vt_char_cs(src + src_pos) == ISO10646_UCS4_1_V) { vt_char_set_cs(src + src_pos, ISO10646_UCS4_1); } if (line->ctl_info.ot_layout->num_chars_array[src_pos] == 1) { vt_char_copy(dst, src + src_pos); } else { vt_char_copy(dst, vt_get_base_char(src + src_pos)); comb = vt_get_combining_chars(src + src_pos, &num); for (; num > 0; num--, comb++) { if (vt_char_cs(comb) == ISO10646_UCS4_1_V) { vt_char_set_cs(comb, ISO10646_UCS4_1); } if (vt_char_is_comb(comb)) { vt_char_combine_simple(dst, comb); } else { vt_char_copy(++dst, comb); } } } dst++; } vt_str_final(src, src_len); line->num_filled_chars = dst - line->chars; return 1; } /* The caller should check vt_line_is_using_ot_layout() in advance. */ static int vt_line_ot_layout_convert_logical_char_index_to_visual(vt_line_t *line, int logical_char_index) { int visual_char_index; if (vt_line_is_empty(line)) { return 0; } if (line->ctl_info.ot_layout->size == 0 || !line->ctl_info.ot_layout->substituted) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " logical char_index is same as visual one.\n"); #endif return logical_char_index; } for (visual_char_index = 0; visual_char_index < line->ctl_info.ot_layout->size; visual_char_index++) { if (logical_char_index == 0 || (logical_char_index -= line->ctl_info.ot_layout->num_chars_array[visual_char_index]) < 0) { break; } } return visual_char_index; } /* The caller should check vt_line_is_using_ot_layout() in advance. */ static int vt_line_ot_layout_render(vt_line_t *line, /* is always modified */ void *term) { int ret; int visual_mod_beg; int visual_mod_end; /* * Lower case: ASCII * Upper case: GLYPH INDEX * (Logical) AAA == (Visual) BBBBB * => (Logical) aaa == (Visual) aaa * In this case vt_line_is_cleared_to_end() returns 0, so "BB" remains on * the screen unless following vt_line_set_modified(). */ visual_mod_beg = vt_line_get_beg_of_modified(line); if (line->ctl_info.ot_layout->substituted) { visual_mod_beg = vt_line_ot_layout_convert_logical_char_index_to_visual(line, visual_mod_beg); } if (vt_line_is_real_modified(line)) { int char_index; int complex_shape = line->ctl_info.ot_layout->complex_shape; int has_var_width_char = line->ctl_info.ot_layout->has_var_width_char; int count; line->ctl_info.ot_layout->term = term; if ((ret = vt_ot_layout(line->ctl_info.ot_layout, line->chars, line->num_filled_chars)) <= 0) { return ret; } complex_shape |= line->ctl_info.ot_layout->complex_shape; has_var_width_char |= line->ctl_info.ot_layout->has_var_width_char; if (line->ctl_info.ot_layout->substituted) { int beg; if ((beg = vt_line_ot_layout_convert_logical_char_index_to_visual( line, vt_line_get_beg_of_modified(line))) < visual_mod_beg) { visual_mod_beg = beg; } } if (has_var_width_char) { visual_mod_end = line->num_chars; } else { visual_mod_end = vt_line_ot_layout_convert_logical_char_index_to_visual(line, vt_line_get_end_of_modified(line)); } if (complex_shape) { /* * XXX * * Input Logical Visual * ! => ! => ! * ^ ^ * = => != => =/= * ^ ^^^ * ('=' after '!' should be redrawn in logical, but the first '!' should * be also redrawn in visual.) */ for (count = 0; visual_mod_beg > 0 && count < 4; count++, visual_mod_beg--) { if (vt_char_code(line->chars + visual_mod_beg - 1) == 0x20 /* SP */) { break; } } /* If trailing characters in this line are all spaces, visual_mod_end is not modified. */ for (char_index = visual_mod_end + 1; char_index < line->num_filled_chars; char_index++) { if (vt_char_code(line->chars + char_index) != 0x20 /* SP */) { visual_mod_end = line->num_chars; break; } } } } else { visual_mod_end = vt_line_ot_layout_convert_logical_char_index_to_visual(line, vt_line_get_end_of_modified(line)); } vt_line_set_modified(line, visual_mod_beg, visual_mod_end); return 1; } #endif /* USE_OT_LAYOUT */ static void copy_line(vt_line_t *dst, vt_line_t *src, int optimize_ctl_info) { u_int copy_len; copy_len = BL_MIN(src->num_filled_chars, dst->num_chars); vt_str_copy(dst->chars, src->chars, copy_len); dst->num_filled_chars = copy_len; dst->change_beg_col = BL_MIN(src->change_beg_col, dst->num_chars); dst->change_end_col = BL_MIN(src->change_end_col, dst->num_chars); dst->is_modified = src->is_modified; dst->is_continued_to_next = src->is_continued_to_next; dst->size_attr = src->size_attr; #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_FRIBIDI) if (vt_line_is_using_bidi(src)) { if (vt_line_is_using_bidi(dst) || vt_line_set_use_bidi(dst, 1)) { /* * Don't use vt_line_bidi_render() here, * or it is impossible to call this function in visual context. */ if (dst->num_chars < src->num_filled_chars) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Not copy vt_bidi.\n"); #endif } else if (vt_bidi_copy(dst->ctl_info.bidi, src->ctl_info.bidi, optimize_ctl_info) == -1) { dst->ctl_info_type = 0; dst->ctl_info.bidi = NULL; } } } else if (vt_line_is_using_bidi(dst)) { vt_line_set_use_bidi(dst, 0); } #endif #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_IND) if (vt_line_is_using_iscii(src)) { if (vt_line_is_using_iscii(dst) || vt_line_set_use_iscii(dst, 1)) { /* * Don't use vt_line_iscii_render() here, * or it is impossible to call this function in visual context. */ if (dst->num_chars < src->num_filled_chars) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Not copy vt_iscii.\n"); #endif } else if (vt_iscii_copy(dst->ctl_info.iscii, src->ctl_info.iscii, optimize_ctl_info) == -1) { dst->ctl_info_type = 0; dst->ctl_info.iscii = NULL; } } } else if (vt_line_is_using_iscii(dst)) { vt_line_set_use_iscii(dst, 0); } #endif #ifdef USE_OT_LAYOUT if (vt_line_is_using_ot_layout(src)) { if (vt_line_is_using_ot_layout(dst) || vt_line_set_use_ot_layout(dst, 1)) { /* * Don't use vt_line_ot_layout_render() here, * or it is impossible to call this function in visual context. */ if (dst->num_chars < src->num_filled_chars) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Not copy vt_ot_layout.\n"); #endif } else if (vt_ot_layout_copy(dst->ctl_info.ot_layout, src->ctl_info.ot_layout, optimize_ctl_info) == -1) { dst->ctl_info_type = 0; dst->ctl_info.ot_layout = NULL; } } } else if (vt_line_is_using_ot_layout(dst)) { vt_line_set_use_ot_layout(dst, 0); } #endif } static void set_real_modified(vt_line_t *line, int beg_char_index, int end_char_index) { vt_line_set_modified(line, beg_char_index, end_char_index); line->is_modified = 2; } /* --- global functions --- */ /* * Functions which doesn't have to care about visual order. */ int vt_line_init(vt_line_t *line, u_int num_chars) { memset(line, 0, sizeof(vt_line_t)); if ((line->chars = vt_str_new(num_chars)) == NULL) { return 0; } line->num_chars = num_chars; return 1; } int vt_line_clone(vt_line_t *clone, vt_line_t *orig, u_int num_chars) { if (vt_line_init(clone, num_chars)) { copy_line(clone, orig, 1 /* clone->ctl_info can be uncopied. */); return 1; } else { return 0; } } void vt_line_final(vt_line_t *line) { if (vt_line_is_using_bidi(line)) { vt_line_set_use_bidi(line, 0); } else if (vt_line_is_using_iscii(line)) { vt_line_set_use_iscii(line, 0); } #ifdef USE_OT_LAYOUT else if (vt_line_is_using_ot_layout(line)) { vt_line_set_use_ot_layout(line, 0); } #endif if (line->chars) { vt_str_destroy(line->chars, line->num_chars); } } /* * return: actually broken chars. */ u_int vt_line_break_boundary(vt_line_t *line, u_int size) { int count; if (line->num_filled_chars + size > line->num_chars) { /* over line length */ #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " breaking from col %d by size %d failed.", line->num_filled_chars, size); #endif size = line->num_chars - line->num_filled_chars; #ifdef DEBUG bl_msg_printf(" ... size modified -> %d\n", size); #endif } if (size == 0) { /* nothing is done */ return 0; } /* padding spaces */ for (count = line->num_filled_chars; count < line->num_filled_chars + size; count++) { vt_char_copy(line->chars + count, vt_sp_ch()); } #if 0 set_real_modified(line, END_CHAR_INDEX(line) + 1, END_CHAR_INDEX(line) + size); #else if (vt_line_is_using_ctl(line) && !vt_line_is_real_modified(line)) { /* ctl_render_line() should be called in ctl_render() in * vt_logical_visual.c. */ set_real_modified(line, END_CHAR_INDEX(line) + size, END_CHAR_INDEX(line) + size); } #endif line->num_filled_chars += size; return size; } int vt_line_assure_boundary(vt_line_t *line, int char_index) { if (char_index >= line->num_filled_chars) { u_int brk_size; brk_size = char_index - line->num_filled_chars + 1; if (vt_line_break_boundary(line, brk_size) < brk_size) { return 0; } } return 1; } void vt_line_reset(vt_line_t *line) { if (IS_EMPTY(line)) { /* already reset */ return; } #ifdef OPTIMIZE_REDRAWING { int count; count = END_CHAR_INDEX(line); while (1) { if (!vt_char_equal(line->chars + count, vt_sp_ch())) { set_real_modified(line, 0, count); break; } else if (--count < 0) { break; } } } #else set_real_modified(line, 0, END_CHAR_INDEX(line)); #endif line->num_filled_chars = 0; if (vt_line_is_using_bidi(line)) { vt_bidi_reset(line->ctl_info.bidi); } else if (vt_line_is_using_iscii(line)) { vt_iscii_reset(line->ctl_info.iscii); } #ifdef USE_OT_LAYOUT else if (vt_line_is_using_ot_layout(line)) { vt_ot_layout_reset(line->ctl_info.ot_layout); } #endif line->is_continued_to_next = 0; line->size_attr = 0; } void vt_line_clear(vt_line_t *line, int char_index) { if (char_index >= line->num_filled_chars) { return; } #ifdef OPTIMIZE_REDRAWING { int count; count = END_CHAR_INDEX(line); while (1) { if (!vt_char_equal(line->chars + count, vt_sp_ch())) { set_real_modified(line, char_index, count); break; } else if (--count < char_index) { break; } } } #else set_real_modified(line, char_index, END_CHAR_INDEX(line)); #endif vt_char_copy(line->chars + char_index, vt_sp_ch()); line->num_filled_chars = char_index + 1; line->is_continued_to_next = 0; line->size_attr = 0; } int vt_line_clear_with(vt_line_t *line, int char_index, vt_char_t *ch) { line->is_continued_to_next = 0; return vt_line_fill( line, ch, char_index, (line->num_chars - vt_str_cols(line->chars, char_index)) / vt_char_cols(ch)); } int vt_line_overwrite(vt_line_t *line, int beg_char_index, /* >= line->num_filled_chars is OK */ vt_char_t *chars, u_int len, u_int cols) { int count; u_int cols_to_beg; u_int cols_rest; u_int padding; u_int new_len; u_int copy_len; vt_char_t *copy_src; if (len == 0) { return 1; } if (beg_char_index + len > line->num_chars) { if (beg_char_index >= line->num_chars) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " beg[%d] is over num_chars[%d].\n", beg_char_index, line->num_chars); #endif return 0; } #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " beg_char_index[%d] + len[%d] is over num_chars[%d].\n", beg_char_index, len, line->num_chars); #endif len = line->num_chars - beg_char_index; } if (beg_char_index > 0) { vt_line_assure_boundary(line, beg_char_index - 1); } #ifdef OPTIMIZE_REDRAWING if (len <= line->num_filled_chars - beg_char_index) { if (vt_str_equal(line->chars + beg_char_index, chars, len)) { return 1; } } else { if (vt_str_equal(line->chars + beg_char_index, chars, line->num_filled_chars - beg_char_index)) { chars += (line->num_filled_chars - beg_char_index); len -= (line->num_filled_chars - beg_char_index); beg_char_index = line->num_filled_chars; count = 0; while (1) { if (!vt_char_equal(chars + count, vt_sp_ch())) { break; } else if (++count >= len) { vt_str_copy(line->chars + beg_char_index, chars, len); line->num_filled_chars = beg_char_index + len; /* Not necessary vt_line_set_modified() */ return 1; } } } } #endif cols_to_beg = vt_str_cols(line->chars, beg_char_index); if (cols_to_beg + cols < line->num_chars) { int char_index; char_index = vt_convert_col_to_char_index(line, &cols_rest, cols_to_beg + cols, 0); if (0 < cols_rest && cols_rest < vt_char_cols(line->chars + char_index)) { padding = vt_char_cols(line->chars + char_index) - cols_rest; char_index++; } else { padding = 0; } if (line->num_filled_chars > char_index) { copy_len = line->num_filled_chars - char_index; } else { copy_len = 0; } copy_src = line->chars + char_index; } else { padding = 0; copy_len = 0; copy_src = NULL; } new_len = beg_char_index + len + padding + copy_len; if (new_len > line->num_chars) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " new line len %d(beg %d ow %d padding %d copy %d) is overflowed\n", new_len, beg_char_index, len, padding, copy_len); #endif new_len = line->num_chars; if (new_len > padding + beg_char_index + len) { copy_len = new_len - padding - beg_char_index - len; } else { copy_len = 0; padding = new_len - beg_char_index - len; } #ifdef DEBUG bl_msg_printf(" ... modified -> new_len %d , copy_len %d\n", new_len, copy_len); #endif } if (copy_len > 0) { /* making space */ vt_str_copy(line->chars + beg_char_index + len + padding, copy_src, copy_len); } for (count = 0; count < padding; count++) { vt_char_copy(line->chars + beg_char_index + len + count, vt_sp_ch()); } vt_str_copy(line->chars + beg_char_index, chars, len); line->num_filled_chars = new_len; set_real_modified(line, beg_char_index, beg_char_index + len + padding - 1); return 1; } /* * Not used for now. */ #if 0 int vt_line_overwrite_all(vt_line_t *line, vt_char_t *chars, int len) { set_real_modified(line, 0, END_CHAR_INDEX(line)); vt_str_copy(line->chars, chars, len); line->num_filled_chars = len; set_real_modified(line, 0, END_CHAR_INDEX(line)); return 1; } #endif int vt_line_fill(vt_line_t *line, vt_char_t *ch, int beg, /* >= line->num_filled_chars is OK */ u_int num) { int count; int char_index; u_int left_cols; u_int copy_len; if (num == 0) { return 1; } if (beg >= line->num_chars) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " beg[%d] is over num_chars[%d].\n", beg, line->num_chars); #endif return 0; } if (beg > 0) { vt_line_assure_boundary(line, beg - 1); } #ifdef OPTIMIZE_REDRAWING count = 0; while (1) { if (!vt_char_equal(line->chars + beg + count, ch)) { beg += count; num -= count; if (beg + num <= line->num_filled_chars) { count = 0; while (1) { if (!vt_char_equal(line->chars + beg + num - 1 - count, ch)) { num -= count; break; } else if (count++ == num) { /* Never happens */ return 1; } } } break; } else if (++count >= num) { return 1; } else if (beg + count == line->num_filled_chars) { beg += count; num -= count; break; } } #endif num = BL_MIN(num, line->num_chars - beg); char_index = beg; left_cols = num * vt_char_cols(ch); while (1) { if (char_index >= line->num_filled_chars) { left_cols = 0; copy_len = 0; break; } else if (left_cols < vt_char_cols(line->chars + char_index)) { if (beg + num + left_cols > line->num_chars) { left_cols = line->num_chars - beg - num; copy_len = 0; } else { copy_len = line->num_filled_chars - char_index - left_cols; if (beg + num + left_cols + copy_len > line->num_chars) { /* * line->num_chars is equal to or larger than * beg + num + left_cols since * 'if( beg + num + left_cols > line->num_chars)' * is already passed here. */ copy_len = line->num_chars - beg - num - left_cols; } } char_index += (left_cols / vt_char_cols(ch)); break; } else { left_cols -= vt_char_cols(line->chars + char_index); char_index++; } } if (copy_len > 0) { /* making space */ vt_str_copy(line->chars + beg + num + left_cols, line->chars + char_index, copy_len); } char_index = beg; for (count = 0; count < num; count++) { vt_char_copy(&line->chars[char_index++], ch); } /* padding */ for (count = 0; count < left_cols; count++) { vt_char_copy(&line->chars[char_index++], vt_sp_ch()); } line->num_filled_chars = char_index + copy_len; set_real_modified(line, beg, beg + num + left_cols); return 1; } vt_char_t *vt_char_at(vt_line_t *line, int at) { if (at >= line->num_filled_chars) { return NULL; } else { return line->chars + at; } } int vt_line_set_modified(vt_line_t *line, int beg_char_index, int end_char_index) { int count; int beg_col; int end_col; if (beg_char_index > end_char_index) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " beg_char_index %d > end_char_index %d\n", beg_char_index, end_char_index); #endif return 0; } if (beg_char_index >= line->num_filled_chars) { beg_char_index = END_CHAR_INDEX(line); } beg_col = 0; for (count = 0; count < beg_char_index; count++) { beg_col += vt_char_cols(line->chars + count); } if (end_char_index >= line->num_filled_chars) { /* * '* 2' assures change_end_col should point over the end of line. * If triple width(or wider) characters(!) were to exist, this hack would * make * no sense... */ end_col = line->num_chars * 2; } else { end_col = beg_col; for (; count <= end_char_index; count++) { /* * This will be executed at least once, because beg_char_index is never * greater than end_char_index. */ end_col += vt_char_cols(line->chars + count); } /* * If vt_char_cols() returns 0, beg_col can be equals to end_col here. * If beg_col is equals to end_col, don't minus end_col. */ if (beg_col < end_col) { end_col--; } } if (line->is_modified) { if (beg_col < line->change_beg_col) { line->change_beg_col = beg_col; } if (end_col > line->change_end_col) { line->change_end_col = end_col; } } else { line->change_beg_col = beg_col; line->change_end_col = end_col; line->is_modified = 1; } return 1; } int vt_line_set_modified_all(vt_line_t *line) { line->change_beg_col = 0; /* * '* 2' assures change_end_col should point over the end of line. * If triple width(or wider) characters(!) were to exist, this hack would make * no sense... */ line->change_end_col = line->num_chars * 2; /* Don't overwrite if line->is_modified == 2 (real modified) */ if (!line->is_modified) { line->is_modified = 1; } return 1; } int vt_line_is_cleared_to_end(vt_line_t *line) { if (vt_line_get_num_filled_cols(line) < line->change_end_col + 1) { return 1; } else { return 0; } } int vt_line_is_modified(vt_line_t *line) { return line->is_modified; } int vt_line_get_beg_of_modified(vt_line_t *line) { if (IS_EMPTY(line)) { return 0; } else { return vt_convert_col_to_char_index(line, NULL, line->change_beg_col, 0); } } int vt_line_get_end_of_modified(vt_line_t *line) { if (IS_EMPTY(line)) { return 0; } else { return vt_convert_col_to_char_index(line, NULL, line->change_end_col, 0); } } u_int vt_line_get_num_redrawn_chars(vt_line_t *line, int to_end) { if (IS_EMPTY(line)) { return 0; } else if (to_end) { return line->num_filled_chars - vt_line_get_beg_of_modified(line); } else { return vt_line_get_end_of_modified(line) - vt_line_get_beg_of_modified(line) + 1; } } void vt_line_set_updated(vt_line_t *line) { line->is_modified = 0; line->change_beg_col = 0; line->change_end_col = 0; } int vt_line_is_continued_to_next(vt_line_t *line) { return line->is_continued_to_next; } void vt_line_set_continued_to_next(vt_line_t *line, int flag) { line->is_continued_to_next = flag; } int vt_convert_char_index_to_col(vt_line_t *line, int char_index, int flag /* BREAK_BOUNDARY */ ) { int count; int col; if (char_index >= line->num_chars) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " char index %d is larger than num_chars(%d) ... modified -> %d.\n", char_index, line->num_chars, line->num_chars - 1); #endif char_index = line->num_chars - 1; } col = 0; if ((flag & BREAK_BOUNDARY) && line->num_filled_chars <= char_index) { for (count = 0; count < line->num_filled_chars; count++) { col += vt_char_cols(line->chars + count); } col += (char_index - count); } else if (line->num_filled_chars > 0) { /* * excluding the width of the last char. */ int end = BL_MIN(char_index, END_CHAR_INDEX(line)); for (count = 0; count < end; count++) { col += vt_char_cols(line->chars + count); } } return col; } int vt_convert_col_to_char_index(vt_line_t *line, u_int *cols_rest, int col, int flag /* BREAK_BOUNDARY */ ) { int char_index; #ifdef DEBUG if (col >= line->num_chars * 2 && cols_rest) { bl_warn_printf(BL_DEBUG_TAG " Since col [%d] is over line->num_chars * 2 [%d]," " cols_rest will be corrupt...\n", col, line->num_chars * 2); } #endif for (char_index = 0; char_index + 1 < line->num_filled_chars; char_index++) { int cols; cols = vt_char_cols(line->chars + char_index); if (col < cols) { goto end; } col -= cols; } if (flag & BREAK_BOUNDARY) { char_index += col; col = 0; } end: if (cols_rest != NULL) { *cols_rest = col; } return char_index; } int vt_line_reverse_color(vt_line_t *line, int char_index) { if (char_index >= line->num_filled_chars) { return 0; } if (vt_char_reverse_color(line->chars + char_index)) { vt_line_set_modified(line, char_index, char_index); } return 1; } int vt_line_restore_color(vt_line_t *line, int char_index) { if (char_index >= line->num_filled_chars) { return 0; } if (vt_char_restore_color(line->chars + char_index)) { vt_line_set_modified(line, char_index, char_index); } return 1; } /* * This copys a line as it is and doesn't care about visual order. * But bidi parameters are also copyed as it is. */ int vt_line_copy(vt_line_t *dst, /* should be initialized ahead */ vt_line_t *src) { copy_line(dst, src, 0); return 1; } int vt_line_swap(vt_line_t *line1, vt_line_t *line2) { vt_line_t tmp; tmp = *line1; *line1 = *line2; *line2 = tmp; return 1; } int vt_line_share(vt_line_t *dst, vt_line_t *src) { memcpy(dst, src, sizeof(vt_line_t)); return 1; } int vt_line_is_empty(vt_line_t *line) { return IS_EMPTY(line); } int vt_line_beg_char_index_regarding_rtl(vt_line_t *line) { int char_index; if (vt_line_is_rtl(line)) { for (char_index = 0; char_index < line->num_filled_chars; char_index++) { if (!vt_char_equal(line->chars + char_index, vt_sp_ch())) { return char_index; } } } return 0; } int vt_line_end_char_index(vt_line_t *line) { if (IS_EMPTY(line)) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " num_filled_chars is 0.\n"); #endif return 0; } else { return line->num_filled_chars - 1; } } u_int vt_line_get_num_filled_cols(vt_line_t *line) { return vt_str_cols(line->chars, line->num_filled_chars); } u_int vt_line_get_num_filled_chars_except_sp_with_func(vt_line_t *line, int (*func)(vt_char_t *, vt_char_t *)) { if (IS_EMPTY(line)) { return 0; } else if (vt_line_is_rtl(line) || line->is_continued_to_next) { return line->num_filled_chars; } else { int char_index; for (char_index = END_CHAR_INDEX(line); char_index >= 0; char_index--) { #if 1 /* >= 3.0.6 */ if (!(*func)(line->chars + char_index, vt_sp_ch())) #else /* <= 3.0.5 */ if (!vt_char_equal(line->chars + char_index, vt_sp_ch())) #endif { return char_index + 1; } } return 0; } } void vt_line_set_size_attr(vt_line_t *line, int size_attr) { if (line->size_attr != size_attr) { line->size_attr = size_attr; vt_line_set_modified_all(line); } } int vt_line_convert_visual_char_index_to_logical(vt_line_t *line, int char_index) { if (vt_line_is_using_bidi(line)) { return vt_line_bidi_convert_visual_char_index_to_logical(line, char_index); } else { return char_index; } } int vt_line_is_rtl(vt_line_t *line) { if (vt_line_is_using_bidi(line)) { return vt_line_bidi_is_rtl(line); } else { return 0; } } /* * It is assumed that this function is called in *visual* context. */ int vt_line_copy_logical_str(vt_line_t *line, vt_char_t *dst, int beg, /* visual position */ u_int len) { if (vt_line_is_using_bidi(line)) { if (vt_line_bidi_copy_logical_str(line, dst, beg, len)) { return 1; } } return vt_str_copy(dst, line->chars + beg, len); } int vt_line_convert_logical_char_index_to_visual(vt_line_t *line, int char_index, u_int32_t *meet_pos_info) { #ifdef NO_DYNAMIC_LOAD_CTL if (line->ctl_info_type) { #ifdef USE_OT_LAYOUT if (vt_line_is_using_ot_layout(line)) { char_index = vt_line_ot_layout_convert_logical_char_index_to_visual(line, char_index); } else #endif if (vt_line_is_using_bidi(line)) { #ifdef USE_FRIBIDI char_index = vt_line_bidi_convert_logical_char_index_to_visual(line, char_index, meet_pos_info); #endif } else /* if( vt_line_is_using_iscii( line)) */ { #ifdef USE_IND char_index = vt_line_iscii_convert_logical_char_index_to_visual(line, char_index); #endif } } return char_index; #else if (line->ctl_info_type) { #ifdef USE_OT_LAYOUT if (vt_line_is_using_ot_layout(line)) { char_index = vt_line_ot_layout_convert_logical_char_index_to_visual(line, char_index); } else #endif if (vt_line_is_using_bidi(line)) { int (*bidi_func)(vt_line_t *, int, int *); if ((bidi_func = vt_load_ctl_bidi_func(VT_LINE_BIDI_CONVERT_LOGICAL_CHAR_INDEX_TO_VISUAL))) { char_index = (*bidi_func)(line, char_index, meet_pos_info); } } else /* if( vt_line_is_using_iscii( line)) */ { int (*iscii_func)(vt_line_t *, int); if ((iscii_func = vt_load_ctl_iscii_func(VT_LINE_ISCII_CONVERT_LOGICAL_CHAR_INDEX_TO_VISUAL))) { char_index = (*iscii_func)(line, char_index); } } } return char_index; #endif } int vt_line_unuse_ctl(vt_line_t *line) { if (line->ctl_info_type) { /* *_render() which may be called later works only if vt_line_t is really modified. */ set_real_modified(line, 0, END_CHAR_INDEX(line)); #ifdef USE_OT_LAYOUT if (vt_line_is_using_ot_layout(line)) { return vt_line_set_use_ot_layout(line, 0); } else #endif if (vt_line_is_using_bidi(line)) { return vt_line_set_use_bidi(line, 0); } else /* if( vt_line_is_using_iscii( line)) */ { return vt_line_set_use_iscii(line, 0); } } return 0; } int vt_line_ctl_render(vt_line_t *line, vt_bidi_mode_t bidi_mode, const char *separators, void *term) { int ret; int (*set_use_ctl)(vt_line_t *, int); if (!vt_line_is_using_ctl(line)) { if ( #ifdef USE_OT_LAYOUT (!term || !vt_line_set_use_ot_layout(line, 1)) && #endif !vt_line_set_use_bidi(line, 1) && !vt_line_set_use_iscii(line, 1)) { return 0; } } if (line->ctl_info_type) { #ifdef USE_OT_LAYOUT if (vt_line_is_using_ot_layout(line)) { if (!term) { ret = -1; } else if ((ret = vt_line_ot_layout_render(line, term)) >= 0) { return ret; } set_use_ctl = vt_line_set_use_ot_layout; if (ret == -1) { goto render_bidi; } else /* if( ret == -2) */ { goto render_iscii; } } else #endif if (vt_line_is_using_bidi(line)) { if ((ret = vt_line_bidi_render(line, bidi_mode, separators)) >= 0) { return ret; } #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_FRIBIDI) set_use_ctl = vt_line_set_use_bidi; #else /* Never enter here */ #endif if (ret == -1) { #ifdef USE_OT_LAYOUT if (!term) { return 1; } goto render_ot_layout; #else return 1; #endif } else /* if( ret == -2) */ { goto render_iscii; } } else /* if( vt_line_is_using_iscii( line)) */ { if ((ret = vt_line_iscii_render(line)) >= 0) { return ret; } #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_IND) set_use_ctl = vt_line_set_use_iscii; #else /* Never enter here */ #endif #ifdef USE_OT_LAYOUT if (term) { goto render_ot_layout; } else #endif { goto render_bidi; } } } return 0; #ifdef USE_OT_LAYOUT render_ot_layout: (*set_use_ctl)(line, 0); vt_line_set_use_ot_layout(line, 1); if ((ret = vt_line_ot_layout_render(line, term) != -1)) { return ret; } /* Fall through */ #endif render_bidi: if ( #if !defined(NO_DYNAMIC_LOAD_CTL) vt_load_ctl_bidi_func(VT_LINE_SET_USE_BIDI) #elif defined(USE_FRIBIDI) 1 #else 0 #endif ) { (*set_use_ctl)(line, 0); vt_line_set_use_bidi(line, 1); return vt_line_bidi_render(line, bidi_mode, separators); } else { return 0; } render_iscii: if ( #if !defined(NO_DYNAMIC_LOAD_CTL) vt_load_ctl_iscii_func(VT_LINE_SET_USE_ISCII) #elif defined(USE_ISCII) 1 #else 0 #endif ) { (*set_use_ctl)(line, 0); vt_line_set_use_iscii(line, 1); return vt_line_iscii_render(line); } else { return 0; } } int vt_line_ctl_visual(vt_line_t *line) { if (line->ctl_info_type) { #ifdef USE_OT_LAYOUT if (vt_line_is_using_ot_layout(line)) { return vt_line_ot_layout_visual(line); } else #endif if (vt_line_is_using_bidi(line)) { return vt_line_bidi_visual(line); } else /* if( vt_line_is_using_iscii( line)) */ { return vt_line_iscii_visual(line); } } return 0; } int vt_line_ctl_logical(vt_line_t *line) { if (line->ctl_info_type) { #ifdef USE_OT_LAYOUT if (vt_line_is_using_ot_layout(line)) { return vt_line_ot_layout_logical(line); } else #endif if (vt_line_is_using_bidi(line)) { return vt_line_bidi_logical(line); } else /* if( vt_line_is_using_iscii( line)) */ { return vt_line_iscii_logical(line); } } return 0; } #ifdef DEBUG void vt_line_dump(vt_line_t *line) { int count; for (count = 0; count < line->num_filled_chars; count++) { vt_char_dump(line->chars + count); } bl_msg_printf("\n"); } #endif mlterm-3.8.9/vtemu/vt_line.h010064400017600000144000000120561356600660700145170ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_LINE_H__ #define __VT_LINE_H__ #include "vt_str.h" #include "vt_bidi.h" /* vt_bidi_state_t */ #include "vt_iscii.h" /* vt_iscii_state_t */ #include "vt_ot_layout.h" /* vt_ot_layout_state_t */ enum { WRAPAROUND = 0x01, BREAK_BOUNDARY = 0x02, SCROLL = 0x04 }; enum { VINFO_BIDI = 0x01, VINFO_ISCII = 0x02, VINFO_OT_LAYOUT = 0x03, }; typedef union ctl_info { vt_bidi_state_t bidi; vt_iscii_state_t iscii; vt_ot_layout_state_t ot_layout; } ctl_info_t; /* * This object size should be kept as small as possible. * (160bit ILP32) (224bit ILP64) */ typedef struct vt_line { /* public(readonly) -- If you access &chars[at], use vt_char_at(). */ vt_char_t *chars; /* public(readonly) */ u_int16_t num_chars; /* 0 - 65535 */ u_int16_t num_filled_chars; /* 0 - 65535 */ /* private */ /* * Type of col should be int, but u_int16_t is used here to shrink memory * because it is appropriate to assume that change_{beg|end}_col never * becomes minus value. */ u_int16_t change_beg_col; /* 0 - 65535 */ u_int16_t change_end_col; /* 0 - 65535 */ #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_IND) || defined(USE_FRIBIDI) || \ defined(USE_OT_LAYOUT) /* Don't touch from vt_line.c. ctl_info is used by vt_line_bidi.c and * vt_line_iscii.c. */ ctl_info_t ctl_info; #endif u_int8_t ctl_info_type; int8_t is_modified; /* 1: need to redraw. 2: was really changed. */ int8_t is_continued_to_next; /* public */ int8_t size_attr; } vt_line_t; int vt_line_init(vt_line_t *line, u_int num_chars); int vt_line_clone(vt_line_t *clone, vt_line_t *orig, u_int num_chars); void vt_line_final(vt_line_t *line); u_int vt_line_break_boundary(vt_line_t *line, u_int size); int vt_line_assure_boundary(vt_line_t *line, int char_index); void vt_line_reset(vt_line_t *line); void vt_line_clear(vt_line_t *line, int char_index); int vt_line_clear_with(vt_line_t *line, int char_index, vt_char_t *ch); int vt_line_overwrite(vt_line_t *line, int beg_char_index, vt_char_t *chars, u_int len, u_int cols); #if 0 int vt_line_overwrite_all(vt_line_t *line, vt_char_t *chars, int len); #endif int vt_line_fill(vt_line_t *line, vt_char_t *ch, int beg, u_int num); vt_char_t *vt_char_at(vt_line_t *line, int at); int vt_line_set_modified(vt_line_t *line, int beg_char_index, int end_char_index); int vt_line_set_modified_all(vt_line_t *line); int vt_line_is_cleared_to_end(vt_line_t *line); int vt_line_is_modified(vt_line_t *line); /* XXX Private api for vt_line.c and vt_line_{iscii|bidi}.c */ #define vt_line_is_real_modified(line) (vt_line_is_modified(line) == 2) int vt_line_get_beg_of_modified(vt_line_t *line); int vt_line_get_end_of_modified(vt_line_t *line); u_int vt_line_get_num_redrawn_chars(vt_line_t *line, int to_end); void vt_line_set_updated(vt_line_t *line); int vt_line_is_continued_to_next(vt_line_t *line); void vt_line_set_continued_to_next(vt_line_t *line, int flag); int vt_convert_char_index_to_col(vt_line_t *line, int char_index, int flag); int vt_convert_col_to_char_index(vt_line_t *line, u_int *cols_rest, int col, int flag); int vt_line_reverse_color(vt_line_t *line, int char_index); int vt_line_restore_color(vt_line_t *line, int char_index); int vt_line_copy(vt_line_t *dst, vt_line_t *src); int vt_line_swap(vt_line_t *line1, vt_line_t *line2); int vt_line_share(vt_line_t *dst, vt_line_t *src); int vt_line_is_empty(vt_line_t *line); u_int vt_line_get_num_filled_cols(vt_line_t *line); int vt_line_end_char_index(vt_line_t *line); int vt_line_beg_char_index_regarding_rtl(vt_line_t *line); u_int vt_line_get_num_filled_chars_except_sp_with_func(vt_line_t *line, int (*func)(vt_char_t *, vt_char_t *)); #define vt_line_get_num_filled_chars_except_sp(line) \ vt_line_get_num_filled_chars_except_sp_with_func((line), vt_char_code_equal) void vt_line_set_size_attr(vt_line_t *line, int size_attr); #define vt_line_is_using_ctl(line) ((line)->ctl_info_type) #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_OT_LAYOUT) #define vt_line_has_ot_substitute_glyphs(line) \ ((line)->ctl_info_type == VINFO_OT_LAYOUT && (line)->ctl_info.ot_layout->substituted) #else #define vt_line_has_ot_substitute_glyphs(line) (0) #endif int vt_line_convert_visual_char_index_to_logical(vt_line_t *line, int char_index); int vt_line_is_rtl(vt_line_t *line); int vt_line_copy_logical_str(vt_line_t *line, vt_char_t *dst, int beg, u_int len); int vt_line_convert_logical_char_index_to_visual(vt_line_t *line, int logical_char_index, u_int32_t *meet_pos_info); vt_line_t *vt_line_shape(vt_line_t *line); int vt_line_unshape(vt_line_t *line, vt_line_t *orig); int vt_line_unuse_ctl(vt_line_t *line); int vt_line_ctl_render(vt_line_t *line, vt_bidi_mode_t bidi_mode, const char *separators, void *term); int vt_line_ctl_visual(vt_line_t *line); int vt_line_ctl_logical(vt_line_t *line); #ifdef DEBUG void vt_line_dump(vt_line_t *line); #endif #endif mlterm-3.8.9/vtemu/vt_line_shape.c010064400017600000144000000055571356600660700157020ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_line.h" #include /* NULL */ #include #include "vt_shape.h" #include "vt_ctl_loader.h" #define vt_line_is_using_bidi(line) ((line)->ctl_info_type == VINFO_BIDI) #define vt_line_is_using_iscii(line) ((line)->ctl_info_type == VINFO_ISCII) #define vt_line_is_using_ot_layout(line) ((line)->ctl_info_type == VINFO_OT_LAYOUT) /* --- static functions --- */ #ifndef NO_DYNAMIC_LOAD_CTL static int vt_line_bidi_need_shape(vt_line_t *line) { int (*func)(vt_line_t *); if (!(func = vt_load_ctl_bidi_func(VT_LINE_BIDI_NEED_SHAPE))) { return 0; } return (*func)(line); } static int vt_line_iscii_need_shape(vt_line_t *line) { int (*func)(vt_line_t *); if (!(func = vt_load_ctl_iscii_func(VT_LINE_ISCII_NEED_SHAPE))) { return 0; } return (*func)(line); } #else #ifndef USE_FRIBIDI #define vt_line_bidi_need_shape(line) (0) #else /* Link functions in libctl/vt_*bidi.c */ int vt_line_bidi_need_shape(vt_line_t *line); #endif /* USE_FRIBIDI */ #ifndef USE_IND #define vt_line_iscii_need_shape(line) (0) #else /* Link functions in libctl/vt_*iscii.c */ int vt_line_iscii_need_shape(vt_line_t *line); #endif /* USE_IND */ #endif #ifdef USE_OT_LAYOUT static int vt_line_ot_layout_need_shape(vt_line_t *line) { return line->ctl_info.ot_layout->size > 0 && line->ctl_info.ot_layout->substituted; } #endif /* --- global functions --- */ vt_line_t *vt_line_shape(vt_line_t *line) { vt_line_t *orig; vt_char_t *shaped; u_int (*func)(vt_char_t *, u_int, vt_char_t *, u_int, ctl_info_t); if (line->ctl_info_type) { #ifdef USE_OT_LAYOUT if (vt_line_is_using_ot_layout(line)) { if (!vt_line_ot_layout_need_shape(line)) { return NULL; } func = vt_shape_ot_layout; } else #endif if (vt_line_is_using_bidi(line)) { if (!vt_line_bidi_need_shape(line)) { return NULL; } func = vt_shape_arabic; } else /* if( vt_line_is_using_iscii( line)) */ { if (!vt_line_iscii_need_shape(line)) { return NULL; } func = vt_shape_iscii; } if ((orig = malloc(sizeof(vt_line_t))) == NULL) { return NULL; } vt_line_share(orig, line); if ((shaped = vt_str_new(line->num_chars)) == NULL) { free(orig); return NULL; } #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_IND) || defined(USE_FRIBIDI) || \ defined(USE_OT_LAYOUT) line->num_filled_chars = (*func)(shaped, line->num_chars, line->chars, line->num_filled_chars, line->ctl_info); #else /* Never enter here */ #endif line->chars = shaped; return orig; } return NULL; } int vt_line_unshape(vt_line_t *line, vt_line_t *orig) { vt_str_destroy(line->chars, line->num_chars); line->chars = orig->chars; line->num_filled_chars = orig->num_filled_chars; free(orig); return 1; } mlterm-3.8.9/vtemu/vt_logical_visual.c010064400017600000144000000665051356600660700165700ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_logical_visual.h" #include /* realloc/free */ #include /* bl_msg_printf */ #include /* strcmp */ #include "vt_ctl_loader.h" #include "vt_shape.h" /* vt_is_arabic_combining */ #define CURSOR_LINE(logvis) (vt_model_get_line((logvis)->model, (logvis)->cursor->row)) #define MSB32 0x80000000 #if 0 #define __DEBUG #endif #if 0 #define CURSOR_DEBUG #endif typedef struct container_logical_visual { vt_logical_visual_t logvis; /* * visual : children[0] => children[1] => ... => children[n] * logical: children[n] => ... => children[1] => children[0] */ vt_logical_visual_t **children; u_int num_children; } container_logical_visual_t; typedef struct comb_logical_visual { vt_logical_visual_t logvis; int cursor_logical_char_index; int cursor_logical_col; } comb_logical_visual_t; typedef struct vert_logical_visual { vt_logical_visual_t logvis; vt_model_t logical_model; vt_model_t visual_model; int cursor_logical_char_index; int cursor_logical_col; int cursor_logical_row; int8_t is_init; } vert_logical_visual_t; typedef struct ctl_logical_visual { vt_logical_visual_t logvis; int cursor_logical_char_index; int cursor_logical_col; u_int32_t cursor_meet_pos_info; vt_bidi_mode_t bidi_mode; const char *separators; void *term; } ctl_logical_visual_t; /* --- static variables --- */ /* Order of this table must be same as x_vertical_mode_t. */ static char *vertical_mode_name_table[] = { "none", "mongol", "cjk", }; /* --- static functions --- */ static int container_destroy(vt_logical_visual_t *logvis) { container_logical_visual_t *container; int count; container = (container_logical_visual_t*)logvis; if (container->num_children) { for (count = container->num_children - 1; count >= 0; count--) { (*container->children[count]->destroy)(container->children[count]); } } free(container->children); free(logvis); return 1; } static int container_init(vt_logical_visual_t *logvis, vt_model_t *model, vt_cursor_t *cursor) { container_logical_visual_t *container; u_int count; logvis->model = model; logvis->cursor = cursor; container = (container_logical_visual_t*)logvis; for (count = 0; count < container->num_children; count++) { (*container->children[count]->init)(container->children[count], model, cursor); } return 1; } static u_int container_logical_cols(vt_logical_visual_t *logvis) { container_logical_visual_t *container; container = (container_logical_visual_t*)logvis; if (container->num_children > 0) { return (*container->children[container->num_children - 1]->logical_cols)( container->children[container->num_children - 1]); } else { return logvis->model->num_cols; } } static u_int container_logical_rows(vt_logical_visual_t *logvis) { container_logical_visual_t *container; container = (container_logical_visual_t*)logvis; if (container->num_children > 0) { return (*container->children[container->num_children - 1]->logical_rows)( container->children[container->num_children - 1]); } else { return logvis->model->num_rows; } } static int container_render(vt_logical_visual_t *logvis) { container_logical_visual_t *container; u_int count; container = (container_logical_visual_t*)logvis; /* * XXX * only the first children can render correctly. */ for (count = 0; count < container->num_children; count++) { (*container->children[count]->render)(container->children[count]); } return 1; } static int container_visual(vt_logical_visual_t *logvis) { container_logical_visual_t *container; u_int count; if (logvis->is_visual) { return 0; } container = (container_logical_visual_t*)logvis; for (count = 0; count < container->num_children; count++) { (*container->children[count]->visual)(container->children[count]); } logvis->is_visual = 1; return 1; } static int container_logical(vt_logical_visual_t *logvis) { container_logical_visual_t *container; int count; if (!logvis->is_visual) { return 0; } container = (container_logical_visual_t*)logvis; if (container->num_children == 0) { return 1; } for (count = container->num_children - 1; count >= 0; count--) { (*container->children[count]->logical)(container->children[count]); } logvis->is_visual = 0; return 1; } static int container_visual_line(vt_logical_visual_t *logvis, vt_line_t *line) { container_logical_visual_t *container; u_int count; container = (container_logical_visual_t*)logvis; for (count = 0; count < container->num_children; count++) { (*container->children[count]->visual_line)(container->children[count], line); } return 1; } /* * dynamic combining */ static int comb_destroy(vt_logical_visual_t *logvis) { free(logvis); return 1; } static int comb_init(vt_logical_visual_t *logvis, vt_model_t *model, vt_cursor_t *cursor) { logvis->model = model; logvis->cursor = cursor; return 1; } static u_int comb_logical_cols(vt_logical_visual_t *logvis) { return logvis->model->num_cols; } static u_int comb_logical_rows(vt_logical_visual_t *logvis) { return logvis->model->num_rows; } static int comb_render(vt_logical_visual_t *logvis) { return (*logvis->visual)(logvis); } static int comb_visual(vt_logical_visual_t *logvis) { int row; if (logvis->is_visual) { return 0; } ((comb_logical_visual_t*)logvis)->cursor_logical_char_index = logvis->cursor->char_index; ((comb_logical_visual_t*)logvis)->cursor_logical_col = logvis->cursor->col; for (row = 0; row < logvis->model->num_rows; row++) { vt_line_t *line; int dst_pos; int src_pos; vt_char_t *cur; line = vt_model_get_line(logvis->model, row); dst_pos = 0; cur = line->chars; for (src_pos = 0; src_pos < line->num_filled_chars; src_pos++) { if (dst_pos > 0 && (vt_char_is_comb(cur) || vt_is_arabic_combining(dst_pos >= 2 ? vt_char_at(line, dst_pos - 2) : NULL, vt_char_at(line, dst_pos - 1), cur))) { vt_char_combine_simple(vt_char_at(line, dst_pos - 1), cur); #if 0 /* * This doesn't work as expected, for example, when * one of combined two characters is destroyed. */ if (vt_line_is_modified(line)) { int beg; int end; beg = vt_line_get_beg_of_modified(line); end = vt_line_get_end_of_modified(line); if (beg > dst_pos - 1) { beg--; } if (end > dst_pos - 1) { end--; } vt_line_set_updated(line); vt_line_set_modified(line, beg, end); } #endif } else { vt_char_copy(vt_char_at(line, dst_pos++), cur); } if (row == logvis->cursor->row && src_pos == logvis->cursor->char_index) { logvis->cursor->char_index = dst_pos - 1; logvis->cursor->col = vt_convert_char_index_to_col(CURSOR_LINE(logvis), logvis->cursor->char_index, 0) + logvis->cursor->col_in_char; } cur++; } #if 1 if (vt_line_is_modified(line)) { /* * (Logical) AbcdEfgHij (bcdfg are combining characters) * => (Visual) AEH * => (Logical) AbcEfgHij * ^^^^^^^ (^ means redrawn characters) * => (Visual) AE * ^^^^^^^ * ^^^^^^^^^^ <= vt_line_set_modified( line , 0 , ...) * => (Logical) AkcEfgHij * ^ * => (Visual) AEH * ^ * ^^ <= vt_line_set_modified( line , 0 , ...) */ vt_line_set_modified(line, 0, vt_line_get_end_of_modified(line)); } #endif line->num_filled_chars = dst_pos; } logvis->is_visual = 1; return 1; } static int comb_logical(vt_logical_visual_t *logvis) { vt_char_t *buf; int row; if (!logvis->is_visual) { return 0; } if ((buf = vt_str_alloca(logvis->model->num_cols)) == NULL) { return 0; } vt_str_init(buf, logvis->model->num_cols); for (row = 0; row < logvis->model->num_rows; row++) { vt_line_t *line; int src_pos; u_int src_len; vt_char_t *c; line = vt_model_get_line(logvis->model, row); vt_str_copy(buf, line->chars, line->num_filled_chars); src_len = line->num_filled_chars; line->num_filled_chars = 0; c = buf; for (src_pos = 0; src_pos < src_len && line->num_filled_chars < line->num_chars; src_pos++) { vt_char_t *comb; u_int size; if ((comb = vt_get_combining_chars(c, &size)) #if 1 /* XXX Hack for inline pictures (see x_picture.c) */ && vt_char_cs(comb) != PICTURE_CHARSET #endif ) { int count; vt_char_copy(vt_char_at(line, line->num_filled_chars++), vt_get_base_char(c)); for (count = 0; count < size; count++) { if (line->num_filled_chars >= line->num_chars) { break; } #if 0 /* * This doesn't work as expected, for example, when * one of combined two characters is destroyed. */ if (vt_line_is_modified(line)) { int beg; int end; int is_cleared_to_end; beg = vt_line_get_beg_of_modified(line); end = vt_line_get_end_of_modified(line); if (beg > src_pos) { beg++; } if (end > src_pos) { end++; } vt_line_set_updated(line); vt_line_set_modified(line, beg, end); } #endif vt_char_copy(vt_char_at(line, line->num_filled_chars++), comb); comb++; } } else { vt_char_copy(vt_char_at(line, line->num_filled_chars++), c); } c++; } } vt_str_final(buf, logvis->model->num_cols); logvis->cursor->char_index = ((comb_logical_visual_t*)logvis)->cursor_logical_char_index; logvis->cursor->col = ((comb_logical_visual_t*)logvis)->cursor_logical_col; logvis->is_visual = 0; return 1; } static int comb_visual_line(vt_logical_visual_t *logvis, vt_line_t *line) { int dst_pos; int src_pos; vt_char_t *cur; dst_pos = 0; cur = line->chars; for (src_pos = 0; src_pos < line->num_filled_chars; src_pos++) { if (dst_pos > 0 && (vt_char_is_comb(cur) || vt_is_arabic_combining(dst_pos >= 2 ? vt_char_at(line, dst_pos - 2) : NULL, vt_char_at(line, dst_pos - 1), cur))) { vt_char_combine_simple(vt_char_at(line, dst_pos - 1), cur); } else { vt_char_copy(vt_char_at(line, dst_pos++), cur); } cur++; } line->num_filled_chars = dst_pos; return 1; } /* * vertical view logical <=> visual methods */ static int vert_destroy(vt_logical_visual_t *logvis) { vert_logical_visual_t *vert_logvis; if (logvis->model) { vert_logvis = (vert_logical_visual_t*)logvis; vt_model_final(&vert_logvis->visual_model); } free(logvis); return 1; } static int vert_init(vt_logical_visual_t *logvis, vt_model_t *model, vt_cursor_t *cursor) { vert_logical_visual_t *vert_logvis; vert_logvis = (vert_logical_visual_t*)logvis; if (vert_logvis->is_init) { vt_model_resize(&vert_logvis->visual_model, NULL, model->num_rows, model->num_cols); } else { vt_model_init(&vert_logvis->visual_model, model->num_rows, model->num_cols); vert_logvis->is_init = 1; } vert_logvis->logical_model = *model; logvis->model = model; logvis->cursor = cursor; return 1; } static u_int vert_logical_cols(vt_logical_visual_t *logvis) { if (logvis->is_visual) { return ((vert_logical_visual_t*)logvis)->logical_model.num_cols; } else { return logvis->model->num_cols; } } static u_int vert_logical_rows(vt_logical_visual_t *logvis) { if (logvis->is_visual) { return ((vert_logical_visual_t*)logvis)->logical_model.num_rows; } else { return logvis->model->num_rows; } } static int vert_render(vt_logical_visual_t *logvis) { return 1; } static void vert_set_modified(vt_line_t *vis_line, vt_line_t *log_line, int log_char_index) { /* * a:hankaku AA:zenkaku * * 012 3 0 1 * 012345 0123 * abAABB => AABB : change_beg_col=0, change_end_col=3, beg_of_modified=0, end_of_modified=1 * * 0 aa => AA : should be redraw from 0 column to 3 column * 1 bb BB * 2 AA * 3 BB * * || * * call vt_line_set_modified() from vt_line_get_beg_of_modified(log_line) to * log_line->change_end_col. */ if (vt_line_is_modified(log_line) && vt_line_get_beg_of_modified(log_line) <= log_char_index && (vt_line_is_cleared_to_end(log_line) || log_char_index <= log_line->change_end_col)) { vt_line_set_modified(vis_line, vis_line->num_filled_chars - 1, vis_line->num_filled_chars - 1); } } static int vert_visual_intern(vt_logical_visual_t *logvis, vt_vertical_mode_t mode) { vert_logical_visual_t *vert_logvis; vt_line_t *log_line; vt_line_t *vis_line; int row; int count; if (logvis->is_visual) { return 0; } #ifdef CURSOR_DEBUG bl_debug_printf(BL_DEBUG_TAG " logical cursor [col %d index %d row %d]\n", logvis->cursor->col, logvis->cursor->char_index, logvis->cursor->row); #endif vert_logvis = (vert_logical_visual_t*)logvis; if (vert_logvis->logical_model.num_rows != logvis->model->num_rows || vert_logvis->logical_model.num_cols != logvis->model->num_cols) { /* vt_model_t is resized */ vt_model_resize(&vert_logvis->visual_model, NULL, logvis->model->num_rows, logvis->model->num_cols); } vt_model_reset(&vert_logvis->visual_model); if (mode & VERT_LTR) { /* Mongol */ count = -1; } else { /* CJK */ count = logvis->model->num_rows; } while (1) { if (mode & VERT_LTR) { /* Mongol */ if (++count >= logvis->model->num_rows) { break; } } else { /* CJK */ if (--count < 0) { break; } } log_line = vt_model_get_line(logvis->model, count); for (row = 0; row < log_line->num_filled_chars; row++) { vis_line = vt_model_get_line(&vert_logvis->visual_model, row); if (vis_line == NULL || vis_line->num_filled_chars >= vis_line->num_chars) { continue; } vt_char_copy(vt_char_at(vis_line, vis_line->num_filled_chars++), vt_char_at(log_line, row)); vert_set_modified(vis_line, log_line, row); } for (; row < vert_logvis->visual_model.num_rows; row++) { vis_line = vt_model_get_line(&vert_logvis->visual_model, row); if (vis_line == NULL || vis_line->num_filled_chars >= vis_line->num_chars) { continue; } vt_char_copy(vt_char_at(vis_line, vis_line->num_filled_chars++), vt_sp_ch()); vert_set_modified(vis_line, log_line, row); } } vert_logvis->logical_model = *logvis->model; *logvis->model = vert_logvis->visual_model; vert_logvis->cursor_logical_char_index = logvis->cursor->char_index; vert_logvis->cursor_logical_col = logvis->cursor->col; vert_logvis->cursor_logical_row = logvis->cursor->row; logvis->cursor->row = vert_logvis->cursor_logical_char_index; logvis->cursor->char_index = logvis->cursor->col = 0; if (mode & VERT_LTR) { /* Mongol */ logvis->cursor->col = logvis->cursor->char_index = vert_logvis->cursor_logical_row; } else { /* CJK */ logvis->cursor->col = logvis->cursor->char_index = vert_logvis->logical_model.num_rows - vert_logvis->cursor_logical_row - 1; } #ifdef CURSOR_DEBUG bl_debug_printf(BL_DEBUG_TAG " visual cursor [col %d index %d row %d]\n", logvis->cursor->col, logvis->cursor->char_index, logvis->cursor->row); #endif logvis->is_visual = 1; return 1; } static int cjk_vert_visual(vt_logical_visual_t *logvis) { return vert_visual_intern(logvis, VERT_RTL); } static int mongol_vert_visual(vt_logical_visual_t *logvis) { return vert_visual_intern(logvis, VERT_LTR); } static int vert_logical(vt_logical_visual_t *logvis) { vert_logical_visual_t *vert_logvis; if (!logvis->is_visual) { return 0; } vert_logvis = (vert_logical_visual_t*)logvis; *logvis->model = vert_logvis->logical_model; logvis->cursor->char_index = vert_logvis->cursor_logical_char_index; logvis->cursor->col = vert_logvis->cursor_logical_col; logvis->cursor->row = vert_logvis->cursor_logical_row; #ifdef CURSOR_DEBUG bl_debug_printf(BL_DEBUG_TAG " logical cursor [col %d index %d row %d]\n", logvis->cursor->col, logvis->cursor->char_index, logvis->cursor->row); #endif logvis->is_visual = 0; return 1; } static int vert_visual_line(vt_logical_visual_t *logvis, vt_line_t *line) { return 1; } #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_FRIBIDI) || defined(USE_IND) || \ defined(USE_OT_LAYOUT) /* * Ctl logical <=> visual methods */ static int ctl_destroy(vt_logical_visual_t *logvis) { int row; if (logvis->model) { for (row = 0; row < logvis->model->num_rows; row++) { vt_line_unuse_ctl(&logvis->model->lines[row]); } } free(logvis); return 1; } static int ctl_init(vt_logical_visual_t *logvis, vt_model_t *model, vt_cursor_t *cursor) { int row; if (logvis->model) { for (row = 0; row < logvis->model->num_rows; row++) { vt_line_unuse_ctl(&logvis->model->lines[row]); } } logvis->model = model; logvis->cursor = cursor; return 1; } static u_int ctl_logical_cols(vt_logical_visual_t *logvis) { return logvis->model->num_cols; } static u_int ctl_logical_rows(vt_logical_visual_t *logvis) { return logvis->model->num_rows; } static void ctl_render_line(vt_logical_visual_t *logvis, vt_line_t *line) { if (!vt_line_is_empty(line) && vt_line_is_modified(line)) { vt_line_ctl_render(line, ((ctl_logical_visual_t*)logvis)->bidi_mode, ((ctl_logical_visual_t*)logvis)->separators, ((ctl_logical_visual_t*)logvis)->term); } } static int ctl_render(vt_logical_visual_t *logvis) { if (!logvis->is_visual) { int row; /* * all lines(not only filled lines) should be rendered. */ for (row = 0; row < logvis->model->num_rows; row++) { ctl_render_line(logvis, vt_model_get_line(logvis->model, row)); } } return 1; } static int ctl_visual(vt_logical_visual_t *logvis) { int row; if (logvis->is_visual) { return 0; } #ifdef CURSOR_DEBUG bl_debug_printf(BL_DEBUG_TAG " [cursor(index)%d (col)%d (row)%d (ltrmeet)%d] ->", logvis->cursor->char_index, logvis->cursor->col, logvis->cursor->row, ((ctl_logical_visual_t*)logvis)->cursor_meet_pos_info); #endif for (row = 0; row < logvis->model->num_rows; row++) { if (!vt_line_ctl_visual(vt_model_get_line(logvis->model, row))) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " visualize row %d failed.\n", row); #endif } } ((ctl_logical_visual_t*)logvis)->cursor_logical_char_index = logvis->cursor->char_index; ((ctl_logical_visual_t*)logvis)->cursor_logical_col = logvis->cursor->col; logvis->cursor->char_index = vt_line_convert_logical_char_index_to_visual( CURSOR_LINE(logvis), logvis->cursor->char_index, &((ctl_logical_visual_t*)logvis)->cursor_meet_pos_info); /* * XXX * col_in_char should not be plused to col, because the character pointed by * vt_line_bidi_convert_logical_char_index_to_visual() is not the same as the * one * in logical order. */ logvis->cursor->col = vt_convert_char_index_to_col(CURSOR_LINE(logvis), logvis->cursor->char_index, 0) + logvis->cursor->col_in_char; #ifdef CURSOR_DEBUG bl_msg_printf("-> [cursor(index)%d (col)%d (row)%d (ltrmeet)%d]\n", logvis->cursor->char_index, logvis->cursor->col, logvis->cursor->row, ((bidi_logical_visual_t*)logvis)->cursor_meet_pos_info); #endif logvis->is_visual = 1; return 1; } static int ctl_logical(vt_logical_visual_t *logvis) { int row; if (!logvis->is_visual) { return 0; } #ifdef CURSOR_DEBUG bl_debug_printf(BL_DEBUG_TAG " [cursor(index)%d (col)%d (row)%d] ->", logvis->cursor->char_index, logvis->cursor->col, logvis->cursor->row); #endif for (row = 0; row < logvis->model->num_rows; row++) { vt_line_t *line; line = vt_model_get_line(logvis->model, row); if (!vt_line_ctl_logical(line)) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " logicalize row %d failed.\n", row); #endif } #if 1 /* XXX See vt_iscii_visual */ if (line->num_chars > logvis->model->num_cols) { vt_str_final(line->chars + logvis->model->num_cols, line->num_chars - logvis->model->num_cols); line->num_chars = logvis->model->num_cols; /* * line->num_filled_chars is equal or less than line->num_chars * because line is logicalized. */ } #endif } if (((ctl_logical_visual_t*)logvis)->cursor_meet_pos_info & MSB32) { /* cursor position is adjusted */ vt_line_t *line = vt_model_get_line(logvis->model, logvis->cursor->row); int idx = vt_line_convert_visual_char_index_to_logical(line, logvis->cursor->char_index); vt_line_set_modified(line, idx, idx); } logvis->cursor->char_index = ((ctl_logical_visual_t*)logvis)->cursor_logical_char_index; logvis->cursor->col = ((ctl_logical_visual_t*)logvis)->cursor_logical_col; #ifdef CURSOR_DEBUG bl_msg_printf("-> [cursor(index)%d (col)%d (row)%d]\n", logvis->cursor->char_index, logvis->cursor->col, logvis->cursor->row); #endif logvis->is_visual = 0; return 1; } static int ctl_visual_line(vt_logical_visual_t *logvis, vt_line_t *line) { ctl_render_line(logvis, line); vt_line_ctl_visual(line); return 1; } #endif /* --- global functions --- */ vt_logical_visual_t *vt_logvis_container_new(void) { container_logical_visual_t *container; if ((container = calloc(1, sizeof(container_logical_visual_t))) == NULL) { return NULL; } container->logvis.destroy = container_destroy; container->logvis.init = container_init; container->logvis.logical_cols = container_logical_cols; container->logvis.logical_rows = container_logical_rows; container->logvis.render = container_render; container->logvis.visual = container_visual; container->logvis.logical = container_logical; container->logvis.visual_line = container_visual_line; container->logvis.is_reversible = 1; return (vt_logical_visual_t*)container; } /* * logvis_comb can coexist with another logvise, but must be added to * logvis_container first of all. * vert_logvis, ctl_logvis and iscii_logvis can't coexist with each other * for now. */ int vt_logvis_container_add(vt_logical_visual_t *logvis, vt_logical_visual_t *child) { void *p; container_logical_visual_t *container; container = (container_logical_visual_t*)logvis; if ((p = realloc(container->children, (container->num_children + 1) * sizeof(vt_logical_visual_t))) == NULL) { return 0; } container->children = p; container->children[container->num_children++] = child; if (!child->is_reversible) { container->logvis.is_reversible = 0; } return 1; } vt_logical_visual_t *vt_logvis_comb_new(void) { comb_logical_visual_t *comb_logvis; if ((comb_logvis = calloc(1, sizeof(comb_logical_visual_t))) == NULL) { return NULL; } comb_logvis->logvis.destroy = comb_destroy; comb_logvis->logvis.init = comb_init; comb_logvis->logvis.logical_cols = comb_logical_cols; comb_logvis->logvis.logical_rows = comb_logical_rows; comb_logvis->logvis.render = comb_render; comb_logvis->logvis.visual = comb_visual; comb_logvis->logvis.logical = comb_logical; comb_logvis->logvis.visual_line = comb_visual_line; comb_logvis->logvis.is_reversible = 1; return (vt_logical_visual_t*)comb_logvis; } vt_logical_visual_t *vt_logvis_vert_new(vt_vertical_mode_t vertical_mode) { vert_logical_visual_t *vert_logvis; if (vertical_mode != VERT_RTL && vertical_mode != VERT_LTR) { return NULL; } if ((vert_logvis = calloc(1, sizeof(vert_logical_visual_t))) == NULL) { return NULL; } vert_logvis->logvis.destroy = vert_destroy; vert_logvis->logvis.init = vert_init; vert_logvis->logvis.logical_cols = vert_logical_cols; vert_logvis->logvis.logical_rows = vert_logical_rows; vert_logvis->logvis.render = vert_render; vert_logvis->logvis.logical = vert_logical; vert_logvis->logvis.visual_line = vert_visual_line; if (vertical_mode == VERT_RTL) { /* * CJK type vertical view */ vert_logvis->logvis.visual = cjk_vert_visual; } else /* if( vertical_mode == VERT_LTR) */ { /* * mongol type vertical view */ vert_logvis->logvis.visual = mongol_vert_visual; } return (vt_logical_visual_t*)vert_logvis; } vt_vertical_mode_t vt_get_vertical_mode(char *name) { vt_vertical_mode_t mode; for (mode = 0; mode < VERT_MODE_MAX; mode++) { if (strcmp(vertical_mode_name_table[mode], name) == 0) { return mode; } } /* default value */ return 0; } char *vt_get_vertical_mode_name(vt_vertical_mode_t mode) { if (mode < 0 || VERT_MODE_MAX <= mode) { /* default value */ mode = 0; } return vertical_mode_name_table[mode]; } #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_FRIBIDI) || defined(USE_IND) || \ defined(USE_OT_LAYOUT) vt_logical_visual_t *vt_logvis_ctl_new(vt_bidi_mode_t bidi_mode, const char *separators, void *term) { ctl_logical_visual_t *ctl_logvis; #ifndef USE_OT_LAYOUT #ifndef NO_DYNAMIC_LOAD_CTL if (!vt_load_ctl_bidi_func(VT_LINE_SET_USE_BIDI) && !vt_load_ctl_iscii_func(VT_LINE_SET_USE_ISCII)) { return NULL; } #endif #endif if ((ctl_logvis = calloc(1, sizeof(ctl_logical_visual_t))) == NULL) { return NULL; } ctl_logvis->bidi_mode = bidi_mode; ctl_logvis->separators = separators; ctl_logvis->term = term; ctl_logvis->logvis.destroy = ctl_destroy; ctl_logvis->logvis.init = ctl_init; ctl_logvis->logvis.logical_cols = ctl_logical_cols; ctl_logvis->logvis.logical_rows = ctl_logical_rows; ctl_logvis->logvis.render = ctl_render; ctl_logvis->logvis.visual = ctl_visual; ctl_logvis->logvis.logical = ctl_logical; ctl_logvis->logvis.visual_line = ctl_visual_line; ctl_logvis->logvis.is_reversible = 1; return (vt_logical_visual_t*)ctl_logvis; } int vt_logical_visual_cursor_is_rtl(vt_logical_visual_t *logvis) { if (logvis->init == ctl_init) { vt_line_t *line; int ret = 0; if ((line = vt_model_get_line(logvis->model, logvis->cursor->row))) { int lidx = ((ctl_logical_visual_t*)logvis)->cursor_logical_char_index; int vidx1 = vt_line_convert_logical_char_index_to_visual(line, lidx > 0 ? lidx - 1 : 0, NULL); int vidx2 = vt_line_convert_logical_char_index_to_visual(line, lidx, NULL); int vidx3 = vt_line_convert_logical_char_index_to_visual(line, lidx + 1, NULL); if (vt_line_is_rtl(line) ? (vidx1 >= vidx2 && vidx2 >= vidx3) : (vidx1 > vidx2 || vidx2 > vidx3)) { ret = 1; } } if (((ctl_logical_visual_t*)logvis)->cursor_meet_pos_info & MSB32) { ret = !ret; } return ret; } else if (logvis->init == container_init) { u_int count; container_logical_visual_t *container = (container_logical_visual_t*)logvis; for (count = 0; count < container->num_children; count++) { if (vt_logical_visual_cursor_is_rtl(container->children[count])) { return 1; } } } return 0; } #endif mlterm-3.8.9/vtemu/vt_logical_visual.h010064400017600000144000000041611356600660700165630ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_LOGICAL_VISUAL_H__ #define __VT_LOGICAL_VISUAL_H__ #include "vt_model.h" #include "vt_cursor.h" #include "vt_bidi.h" /* vt_bidi_mode_t */ /* * LTR ... e.g. Mongolian * RTL ... e.g. CJK */ typedef enum vt_vertical_mode { VERT_LTR = 0x1, VERT_RTL = 0x2, VERT_MODE_MAX } vt_vertical_mode_t; typedef struct vt_logical_visual { /* Private */ vt_model_t *model; vt_cursor_t *cursor; int8_t is_visual; /* Public */ /* * Whether logical <=> visual is reversible. * * XXX This flag is used to determine if logvis is vertical mode or not in vt_screen.c * (vt_screen_set_use_status_line()) */ int8_t is_reversible; int (*init)(struct vt_logical_visual *, vt_model_t *, vt_cursor_t *); int (*destroy)(struct vt_logical_visual *); u_int (*logical_cols)(struct vt_logical_visual *); u_int (*logical_rows)(struct vt_logical_visual *); /* * !! Notice !! * vt_model_t should not be modified from render/viaul until logical. * Any modification is done from logical until render/visual. */ int (*render)(struct vt_logical_visual *); int (*visual)(struct vt_logical_visual *); int (*logical)(struct vt_logical_visual *); int (*visual_line)(struct vt_logical_visual *, vt_line_t *line); } vt_logical_visual_t; vt_logical_visual_t *vt_logvis_container_new(void); int vt_logvis_container_add(vt_logical_visual_t *logvis, vt_logical_visual_t *child); vt_logical_visual_t *vt_logvis_comb_new(void); vt_logical_visual_t *vt_logvis_vert_new(vt_vertical_mode_t vertical_mode); vt_vertical_mode_t vt_get_vertical_mode(char *name); char *vt_get_vertical_mode_name(vt_vertical_mode_t mode); #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_FRIBIDI) || defined(USE_IND) || \ defined(USE_OT_LAYOUT) vt_logical_visual_t *vt_logvis_ctl_new(vt_bidi_mode_t mode, const char *separators, void *term); int vt_logical_visual_cursor_is_rtl(vt_logical_visual_t *logvis); #else #define vt_logvis_ctl_new(mode, separators, term) (0) #define vt_logical_visual_cursor_is_rtl(logvis) (0) #endif #endif /* __VT_LOGICAL_VISUAL_H__ */ mlterm-3.8.9/vtemu/vt_logs.c010064400017600000144000000130621356600660700145250ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_logs.h" #include /* memmove/memset */ #include /* malloc */ #include #include #if 0 #define __DEBUG #endif /* --- global functions --- */ int vt_log_init(vt_logs_t *logs, u_int num_rows) { logs->lines = NULL; logs->index = NULL; logs->num_rows = 0; /* Over 65535 is regarded as unlimited. */ if (num_rows > 0xffff) { vt_unlimit_log_size(logs); num_rows = VT_LOG_SIZE_UNIT; } else if (num_rows == 0) { return 1; } if ((logs->lines = calloc(sizeof(vt_line_t), num_rows)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " calloc() failed.\n"); #endif return 0; } if ((logs->index = bl_cycle_index_new(num_rows)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " bl_cycle_index_new() failed.\n"); #endif free(logs->lines); logs->lines = NULL; return 0; } logs->num_rows = num_rows; return 1; } void vt_log_final(vt_logs_t *logs) { u_int count; if (logs->num_rows == 0) { return; } for (count = 0; count < logs->num_rows; count++) { vt_line_final(&logs->lines[count]); } bl_cycle_index_destroy(logs->index); free(logs->lines); } int vt_change_log_size(vt_logs_t *logs, u_int new_num_rows) { u_int num_filled_rows; /* Over 65535 is regarded as unlimited. */ if (new_num_rows > 0xffff) { vt_unlimit_log_size(logs); return 1; } logs->unlimited = 0; num_filled_rows = vt_get_num_logged_lines(logs); if (new_num_rows == logs->num_rows) { return 1; } else if (new_num_rows == 0) { free(logs->lines); logs->lines = NULL; bl_cycle_index_destroy(logs->index); logs->index = NULL; logs->num_rows = 0; return 1; } else if (new_num_rows > logs->num_rows && bl_cycle_index_of(logs->index, 0) == 0) { vt_line_t *new_lines; if (sizeof(vt_line_t) * new_num_rows < sizeof(vt_line_t) * logs->num_rows) { /* integer overflow */ return 0; } if ((new_lines = realloc(logs->lines, sizeof(vt_line_t) * new_num_rows)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc() failed.\n"); #endif return 0; } memset(&new_lines[logs->num_rows], 0, sizeof(vt_line_t) * (new_num_rows - logs->num_rows)); logs->lines = new_lines; } else { vt_line_t *new_lines; vt_line_t *line; int count; int start; if ((new_lines = calloc(sizeof(vt_line_t), new_num_rows)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " calloc() failed.\n"); #endif return 0; } num_filled_rows = vt_get_num_logged_lines(logs); if (new_num_rows >= num_filled_rows) { start = 0; } else { start = num_filled_rows - new_num_rows; } /* * freeing excess lines. */ for (count = 0; count < start; count++) { if ((line = vt_log_get(logs, count)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " this is impossible.\n"); #endif return 0; } vt_line_final(line); } /* * copying to new lines. */ for (count = 0; count < new_num_rows; count++) { if ((line = vt_log_get(logs, count + start)) == NULL) { break; } vt_line_init(&new_lines[count], line->num_filled_chars); vt_line_share(&new_lines[count], line); } free(logs->lines); logs->lines = new_lines; } if (logs->index) { bl_cycle_index_change_size(logs->index, new_num_rows); } else { if ((logs->index = bl_cycle_index_new(new_num_rows)) == NULL) { free(logs->lines); logs->lines = NULL; logs->num_rows = 0; return 0; } } logs->num_rows = new_num_rows; return 1; } int vt_log_add(vt_logs_t *logs, vt_line_t *line) { int at; if (logs->num_rows == 0) { return 1; } if (logs->unlimited && bl_get_filled_cycle_index(logs->index) == bl_get_cycle_index_size(logs->index)) { if (logs->num_rows + VT_LOG_SIZE_UNIT > logs->num_rows) { vt_change_log_size(logs, logs->num_rows + VT_LOG_SIZE_UNIT); logs->unlimited = 1; } } at = bl_next_cycle_index(logs->index); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %d len line logged to index %d.\n", line->num_filled_chars, at); #endif vt_line_final(&logs->lines[at]); /* logs->lines[at] becomes completely the same one as line */ vt_line_clone(&logs->lines[at], line, line->num_filled_chars); vt_line_set_updated(&logs->lines[at]); return 1; } vt_line_t *vt_log_get(vt_logs_t *logs, int at) { int _at; if (at < 0 || vt_get_num_logged_lines(logs) <= at) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " row %d is overflowed in logs.\n", at); #endif return NULL; } if ((_at = bl_cycle_index_of(logs->index, at)) == -1) { return NULL; } return &logs->lines[_at]; } u_int vt_get_num_logged_lines(vt_logs_t *logs) { if (logs->num_rows == 0) { return 0; } else { return bl_get_filled_cycle_index(logs->index); } } #if 0 int vt_log_reverse_color(vt_logs_t *logs, int char_index, int row) { vt_line_t *line; if ((line = vt_log_get(logs, row)) == NULL) { return 0; } vt_char_reverse_color(vt_char_at(line, char_index)); vt_line_set_modified(line, char_index, vt_line_end_char_index(line)); return 1; } int vt_log_restore_color(vt_logs_t *logs, int char_index, int row) { vt_line_t *line; if ((line = vt_log_get(logs, row)) == NULL) { return 0; } vt_char_restore_color(vt_char_at(line, char_index)); vt_line_set_modified(line, char_index, vt_line_end_char_index(line)); return 1; } #endif mlterm-3.8.9/vtemu/vt_logs.h010064400017600000144000000016021356600660700145270ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_LOGS_H__ #define __VT_LOGS_H__ #include #include "vt_char.h" #include "vt_edit.h" #define VT_LOG_SIZE_UNIT 128 typedef struct vt_logs { vt_line_t *lines; bl_cycle_index_t *index; u_int num_rows; int unlimited; } vt_logs_t; int vt_log_init(vt_logs_t *logs, u_int num_rows); void vt_log_final(vt_logs_t *logs); int vt_change_log_size(vt_logs_t *logs, u_int num_rows); #define vt_unlimit_log_size(logs) ((logs)->unlimited = 1) #define vt_log_size_is_unlimited(logs) ((logs)->unlimited) int vt_log_add(vt_logs_t *logs, vt_line_t *line); vt_line_t *vt_log_get(vt_logs_t *logs, int at); u_int vt_get_num_logged_lines(vt_logs_t *logs); #define vt_log_rollback_index(logs, num) bl_cycle_index_rollback((logs)->index, num) #define vt_get_log_size(logs) ((logs)->num_rows) #endif mlterm-3.8.9/vtemu/vt_model.c010064400017600000144000000113361356600660700146630ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_model.h" #include /* malloc/free */ #include #include /* --- global functions --- */ int vt_model_init(vt_model_t *model, u_int num_cols, u_int num_rows) { u_int count; if (num_rows == 0 || num_cols == 0) { return 0; } model->num_rows = num_rows; model->num_cols = num_cols; if ((model->lines = calloc(sizeof(vt_line_t), model->num_rows)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG "calloc() failed.\n"); #endif return 0; } for (count = 0; count < model->num_rows; count++) { if (!vt_line_init(&model->lines[count], model->num_cols)) { return 0; } } model->beg_row = 0; return 1; } void vt_model_final(vt_model_t *model) { u_int count; for (count = 0; count < model->num_rows; count++) { vt_line_final(&model->lines[count]); } free(model->lines); } void vt_model_reset(vt_model_t *model) { u_int count; for (count = 0; count < model->num_rows; count++) { vt_line_reset(&model->lines[count]); vt_line_set_updated(&model->lines[count]); } } int vt_model_resize(vt_model_t *model, u_int *slide, u_int num_cols, u_int num_rows) { int old_row; int new_row; u_int count; u_int copy_rows; vt_line_t *lines_p; u_int filled_rows; if (num_cols == 0 || num_rows == 0) { return 0; } if (num_cols == model->num_cols && num_rows == model->num_rows) { /* not resized */ return 0; } if ((lines_p = calloc(sizeof(vt_line_t), num_rows)) == NULL) { return 0; } filled_rows = vt_model_get_num_filled_rows(model); if (num_rows >= filled_rows) { old_row = 0; copy_rows = filled_rows; } else { old_row = filled_rows - num_rows; copy_rows = num_rows; } if (slide) { *slide = old_row; } /* updating existing lines. */ for (new_row = 0; new_row < copy_rows; new_row++) { vt_line_init(&lines_p[new_row], num_cols); vt_line_copy(&lines_p[new_row], vt_model_get_line(model, old_row)); old_row++; vt_line_set_modified_all(&lines_p[new_row]); lines_p[new_row].is_modified = 2; /* XXX See set_real_modified() in vt_line.c */ } /* freeing old data. */ for (count = 0; count < model->num_rows; count++) { vt_line_final(&model->lines[count]); } free(model->lines); model->lines = lines_p; /* update empty lines. */ for (; new_row < num_rows; new_row++) { vt_line_init(&lines_p[new_row], num_cols); vt_line_set_modified_all(&lines_p[new_row]); } model->num_rows = num_rows; model->num_cols = num_cols; model->beg_row = 0; return 1; } u_int vt_model_get_num_filled_rows(vt_model_t *model) { u_int filled_rows; for (filled_rows = model->num_rows; filled_rows > 0; filled_rows--) { #if 1 /* * This is problematic, since the value of 'slide' can be incorrect when * cursor is located at the line which contains white spaces alone. */ if (vt_line_get_num_filled_chars_except_sp(vt_model_get_line(model, filled_rows - 1)) > 0) #else if (!vt_line_is_empty(vt_model_get_line(model, filled_rows - 1))) #endif { return filled_rows; } } return 0; } int vt_model_end_row(vt_model_t *model) { return model->num_rows - 1; } vt_line_t *vt_model_get_line(vt_model_t *model, int row) { if (row < 0 || model->num_rows <= row) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " row %d is out of range.\n", row); #endif return NULL; } if (model->beg_row + row < model->num_rows) { return &model->lines[model->beg_row + row]; } else { return &model->lines[model->beg_row + row - model->num_rows]; } } int vt_model_scroll_upward(vt_model_t *model, u_int size) { if (size > model->num_rows) { size = model->num_rows; } if (model->beg_row + size >= model->num_rows) { model->beg_row = model->beg_row + size - model->num_rows; } else { model->beg_row += size; } return 1; } int vt_model_scroll_downward(vt_model_t *model, u_int size) { if (size > model->num_rows) { size = model->num_rows; } if (model->beg_row < size) { model->beg_row = model->num_rows - (size - model->beg_row); } else { model->beg_row -= size; } return 1; } #ifdef DEBUG void vt_model_dump(vt_model_t *model) { int row; vt_line_t *line; for (row = 0; row < model->num_rows; row++) { line = vt_model_get_line(model, row); if (vt_line_is_modified(line)) { bl_msg_printf("!%.2d-%.2d", vt_line_get_beg_of_modified(line), vt_line_get_end_of_modified(line)); } else { bl_msg_printf(" "); } bl_msg_printf("[%.2d %.2d]", line->num_filled_chars, vt_line_get_num_filled_cols(line)); vt_str_dump(line->chars, line->num_filled_chars); } } #endif mlterm-3.8.9/vtemu/vt_model.h010064400017600000144000000017611356600660700146710ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_MODEL_H__ #define __VT_MODEL_H__ #include #include "vt_str.h" #include "vt_line.h" typedef struct vt_model { /* private */ vt_line_t *lines; /* public(readonly) */ u_int16_t num_cols; /* 0 - 65536 */ u_int16_t num_rows; /* 0 - 65536 */ /* private */ int beg_row; /* used for scrolling */ } vt_model_t; int vt_model_init(vt_model_t *model, u_int num_cols, u_int num_rows); void vt_model_final(vt_model_t *model); void vt_model_reset(vt_model_t *model); int vt_model_resize(vt_model_t *model, u_int *slide, u_int num_cols, u_int num_rows); u_int vt_model_get_num_filled_rows(vt_model_t *model); int vt_model_end_row(vt_model_t *model); vt_line_t *vt_model_get_line(vt_model_t *model, int row); int vt_model_scroll_upward(vt_model_t *model, u_int size); int vt_model_scroll_downward(vt_model_t *model, u_int size); #ifdef DEBUG void vt_model_dump(vt_model_t *model); #endif #endif mlterm-3.8.9/vtemu/vt_normalize.m010064400017600000144000000012401356600660700155660ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifdef __APPLE__ #include /* --- global functions --- */ int vt_normalize(UniChar* str, int num) { static CFMutableStringRef mutable_str; if (!mutable_str) { mutable_str = CFStringCreateMutable(kCFAllocatorDefault, 0); } CFStringAppendCharacters(mutable_str, str, num); CFStringNormalize(mutable_str, kCFStringNormalizationFormC); if ((num = CFStringGetLength(mutable_str)) == 1) { /* Normalized */ CFStringGetCharacters(mutable_str, CFRangeMake(0, 1), str); } CFStringDelete(mutable_str, CFRangeMake(0, num)); return num; } #endif mlterm-3.8.9/vtemu/vt_ot_layout.c010064400017600000144000000227701356600660700156060ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_ot_layout.h" #ifdef USE_OT_LAYOUT #include /* bl_snprintf */ #include #include #include #include /* BL_MAX */ #include "vt_ctl_loader.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static u_int (*shape_func)(void *, u_int32_t *, u_int, int8_t *, u_int8_t *, u_int32_t *, u_int32_t *, u_int, const char *, const char *); static void *(*get_font_func)(void *, vt_font_t); static char *ot_layout_attrs[] = {"latn", "liga,clig,dlig,hlig,rlig"}; static int8_t ot_layout_attr_changed[2]; /* --- static functions --- */ #ifndef NO_DYNAMIC_LOAD_CTL static int vt_is_rtl_char(u_int32_t code) { int (*func)(u_int32_t); if (!(func = vt_load_ctl_bidi_func(VT_IS_RTL_CHAR))) { return 0; } return (*func)(code); } #elif defined(USE_FRIBIDI) /* Defined in libctl/vt_bidi.c */ int vt_is_rtl_char(u_int32_t code); #else #define vt_is_rtl_char(code) (0) #endif /* --- global functions --- */ void vt_set_ot_layout_attr(char *value, vt_ot_layout_attr_t attr) { if (0 <= attr && attr < MAX_OT_ATTRS) { if (ot_layout_attr_changed[attr]) { free(ot_layout_attrs[attr]); } else { ot_layout_attr_changed[attr] = 1; } if (!value || (attr == OT_SCRIPT && strlen(value) != 4) || !(ot_layout_attrs[attr] = strdup(value))) { ot_layout_attrs[attr] = (attr == OT_SCRIPT) ? "latn" : "liga,clig,dlig,hlig,rlig"; } } } char *vt_get_ot_layout_attr(vt_ot_layout_attr_t attr) { if (0 <= attr && attr < MAX_OT_ATTRS) { return ot_layout_attrs[attr]; } else { return ""; } } void vt_ot_layout_set_shape_func(u_int (*func1)(void *, u_int32_t *, u_int, int8_t *, u_int8_t *, u_int32_t *, u_int32_t *, u_int, const char *, const char *), void *(*func2)(void *, vt_font_t)) { shape_func = func1; get_font_func = func2; } u_int vt_ot_layout_shape(void *font, u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len) { if (!shape_func) { return 0; } return (*shape_func)(font, shaped, shaped_len, offsets, widths, cmapped, src, src_len, ot_layout_attrs[OT_SCRIPT], ot_layout_attrs[OT_FEATURES]); } void *vt_ot_layout_get_font(void *term, vt_font_t font) { if (!get_font_func) { return NULL; } return (*get_font_func)(term, font); } vt_ot_layout_state_t vt_ot_layout_new(void) { return calloc(1, sizeof(struct vt_ot_layout_state)); } void vt_ot_layout_destroy(vt_ot_layout_state_t state) { free(state->num_chars_array); free(state); } int vt_ot_layout(vt_ot_layout_state_t state, vt_char_t *src, u_int src_len) { int dst_pos; int src_pos; u_int32_t *ucs_buf; u_int32_t *shaped_buf; u_int8_t *num_chars_array; u_int shaped_buf_len; u_int prev_shaped_filled; u_int ucs_filled; u_int32_t prev_shaped; vt_font_t font; vt_font_t prev_font; void *xfont; u_int32_t code; u_int32_t prev_code; u_int usascii_repeat_count; if ((ucs_buf = alloca((src_len * MAX_COMB_SIZE + 1) * sizeof(*ucs_buf))) == NULL) { return 0; } shaped_buf_len = src_len * MAX_COMB_SIZE + 1; if ((shaped_buf = alloca(shaped_buf_len * sizeof(*shaped_buf))) == NULL) { return 0; } if ((num_chars_array = alloca(shaped_buf_len * sizeof(*num_chars_array))) == NULL) { return 0; } state->substituted = 0; state->complex_shape = 0; state->has_var_width_char = 0; dst_pos = -1; prev_font = font = UNKNOWN_CS; xfont = NULL; prev_shaped = 0; prev_code = -1; usascii_repeat_count = 0; for (src_pos = 0; src_pos < src_len; src_pos++) { font = vt_char_font(src + src_pos); code = vt_char_code(src + src_pos); if (FONT_CS(font) == US_ASCII && code != ' ') { if (code == prev_code) { if (++usascii_repeat_count == 5 && (num_chars_array[dst_pos] != 1 || num_chars_array[dst_pos - 1] != 1 || num_chars_array[dst_pos - 2] != 1 || num_chars_array[dst_pos - 3] != 1 || num_chars_array[dst_pos - 4] != 1)) { usascii_repeat_count = 1; } } else { usascii_repeat_count = 1; } prev_code = code; if (usascii_repeat_count >= 5) { /* * If 5 or more same US-ASCII characters are repeated, regard them as * characters which doesn't need complex shape to improve performance. * (e.g. repeating '-' for separator or decoration (emacs)) */ } else { font &= ~US_ASCII; font |= ISO10646_UCS4_1; } } else { prev_code = -1; usascii_repeat_count = 0; } if (prev_font != font) { if (!state->substituted && xfont && (prev_shaped_filled != ucs_filled || memcmp(shaped_buf, ucs_buf, prev_shaped_filled * sizeof(*shaped_buf)) != 0)) { /* * state->substituted is useful for libotf (ucs -> glyph index -> shaped glyph index) * while useless for libharfbuzz (ucs -> ucs -> shaped glyph index) * If glyph index and shaped glyph index are the same, state->substituted is 0. */ state->substituted = 1; } prev_shaped_filled = ucs_filled = 0; prev_font = font; if (FONT_CS(font) == ISO10646_UCS4_1) { xfont = vt_ot_layout_get_font(state->term, font); } else { xfont = NULL; } } if (xfont) { u_int shaped_filled; u_int count; vt_char_t *comb; u_int num; ucs_buf[ucs_filled] = code; if (vt_is_rtl_char(ucs_buf[ucs_filled])) { return -1; /* bidi */ } else if (IS_VAR_WIDTH_CHAR(ucs_buf[ucs_filled])) { state->has_var_width_char = 1; } /* Don't do it in vt_is_rtl_char() which may be replaced by (0). */ ucs_filled++; comb = vt_get_combining_chars(src + src_pos, &num); for (count = 0; count < num; count++) { ucs_buf[ucs_filled] = vt_char_code(comb++); if (vt_is_rtl_char(ucs_buf[ucs_filled])) { return -1; /* bidi */ } /* Don't do it in vt_is_rtl_char() which may be replaced by (0). */ ucs_filled++; } /* store glyph index in ucs_buf. */ vt_ot_layout_shape(xfont, NULL, 0, NULL, NULL, ucs_buf + ucs_filled - num - 1, ucs_buf + ucs_filled - num - 1, num + 1); /* apply ot_layout to glyph indeces in ucs_buf. */ shaped_filled = vt_ot_layout_shape(xfont, shaped_buf, shaped_buf_len, NULL, NULL, ucs_buf, NULL, ucs_filled); if (shaped_filled < prev_shaped_filled) { if (shaped_filled == 0) { return 0; } count = prev_shaped_filled - shaped_filled; dst_pos -= count; for (; count > 0; count--) { num_chars_array[dst_pos] += num_chars_array[dst_pos + count]; } prev_shaped_filled = shaped_filled; /* goto to the next if block */ state->complex_shape = 1; } if (dst_pos >= 0 && shaped_filled == prev_shaped_filled) { num_chars_array[dst_pos]++; state->complex_shape = 1; } else { num_chars_array[++dst_pos] = 1; if ((count = shaped_filled - prev_shaped_filled) > 1) { do { num_chars_array[++dst_pos] = 0; } while (--count > 1); state->complex_shape = 1; } else if (!state->complex_shape) { if (shaped_filled >= 2 && shaped_buf[shaped_filled - 2] != prev_shaped) { /* * This line contains glyphs which are changeable according to the context * before and after. */ state->complex_shape = 1; } prev_shaped = shaped_buf[shaped_filled - 1]; } } prev_shaped_filled = shaped_filled; } else if (IS_ISCII(FONT_CS(font))) { return -2; /* iscii */ } else { num_chars_array[++dst_pos] = 1; } } if (!state->substituted && xfont && (prev_shaped_filled != ucs_filled || memcmp(shaped_buf, ucs_buf, prev_shaped_filled * sizeof(*shaped_buf)) != 0)) { state->substituted = 1; } if (state->size != dst_pos + 1) { void *p; if (!(p = realloc(state->num_chars_array, BL_MAX(dst_pos + 1, src_len) * sizeof(*num_chars_array)))) { return 0; } #ifdef __DEBUG if (p != state->num_chars_array) { bl_debug_printf(BL_DEBUG_TAG " REALLOC array %d(%p) -> %d(%p)\n", state->size, state->num_chars_array, dst_pos + 1, p); } #endif state->num_chars_array = p; state->size = dst_pos + 1; } memcpy(state->num_chars_array, num_chars_array, state->size * sizeof(*num_chars_array)); return 1; } int vt_ot_layout_copy(vt_ot_layout_state_t dst, vt_ot_layout_state_t src, int optimize) { u_int8_t *p; if (optimize && !src->substituted) { vt_ot_layout_destroy(dst); return -1; } else if (src->size == 0) { free(dst->num_chars_array); p = NULL; } else if ((p = realloc(dst->num_chars_array, sizeof(u_int8_t) * src->size))) { memcpy(p, src->num_chars_array, sizeof(u_int8_t) * src->size); } else { return 0; } dst->num_chars_array = p; dst->term = src->term; dst->size = src->size; dst->substituted = src->substituted; return 1; } void vt_ot_layout_reset(vt_ot_layout_state_t state) { state->size = 0; } #endif mlterm-3.8.9/vtemu/vt_ot_layout.h010064400017600000144000000030341356600660700156030ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_OT_LAYOUT_H__ #define __VT_OT_LAYOUT_H__ #include /* u_int/u_char */ #include "vt_font.h" #include "vt_char.h" typedef enum vt_ot_layout_attr { OT_SCRIPT = 0, OT_FEATURES = 1, MAX_OT_ATTRS = 2, } vt_ot_layout_attr_t; typedef struct vt_ot_layout_state { void *term; u_int8_t *num_chars_array; u_int16_t size; int substituted : 2; int complex_shape : 2; int has_var_width_char : 2; } * vt_ot_layout_state_t; void vt_set_ot_layout_attr(char *value, vt_ot_layout_attr_t attr); char *vt_get_ot_layout_attr(vt_ot_layout_attr_t attr); void vt_ot_layout_set_shape_func(u_int (*func1)(void *, u_int32_t *, u_int, int8_t *, u_int8_t *, u_int32_t *, u_int32_t *, u_int, const char *, const char *), void *(*func2)(void *, vt_font_t)); u_int vt_ot_layout_shape(void *font, u_int32_t *shaped, u_int32_t shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int32_t src_len); void *vt_ot_layout_get_font(void *term, vt_font_t font); vt_ot_layout_state_t vt_ot_layout_new(void); void vt_ot_layout_destroy(vt_ot_layout_state_t state); int vt_ot_layout(vt_ot_layout_state_t state, vt_char_t *src, u_int src_len); void vt_ot_layout_reset(vt_ot_layout_state_t state); int vt_ot_layout_copy(vt_ot_layout_state_t dst, vt_ot_layout_state_t src, int optimize); #endif mlterm-3.8.9/vtemu/vt_parser.c010064400017600000144000007040131356600660700150600ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_parser.h" #include /* sprintf */ #include /* memmove */ #include /* atoi */ #include /* open */ #include /* write/getcwd */ #include /* gettimeofday */ #include /* clock */ #include /* iscntrl */ #ifdef DEBUG #include /* va_list */ #endif #include #include /* malloc/free */ #include /* DIGIT_STR_LEN */ #include /* bl_get_user_rc_path */ #include /* strdup */ #include #include /* bl_usleep */ #include /* bl_get_locale */ #include /* ef_map_to_ucs4 */ #include #include #include #include "vt_iscii.h" #include "vt_str_parser.h" #include "vt_shape.h" /* vt_is_arabic_combining */ #include "vt_transfer.h" #if defined(__CYGWIN__) || defined(__MSYS__) #include "cygfile.h" #endif #if defined(USE_LIBSSH2) && !defined(USE_WIN32API) #define _XOPEN_SOURCE #include /* wcwidth */ #endif /* * kterm BUF_SIZE in ptyx.h is 4096. */ #define PTY_RD_BUFFER_SIZE 3072 #define CTL_BEL 0x07 #define CTL_BS 0x08 #define CTL_TAB 0x09 #define CTL_LF 0x0a #define CTL_VT 0x0b #define CTL_FF 0x0c #define CTL_CR 0x0d #define CTL_SO 0x0e #define CTL_SI 0x0f #define CTL_ESC 0x1b #define CURRENT_STR_P(vt_parser) \ ((vt_parser)->r_buf.chars + (vt_parser)->r_buf.filled_len - (vt_parser)->r_buf.left) #define HAS_XTERM_LISTENER(vt_parser, method) \ ((vt_parser)->xterm_listener && ((vt_parser)->xterm_listener->method)) #define HAS_CONFIG_LISTENER(vt_parser, method) \ ((vt_parser)->config_listener && ((vt_parser)->config_listener->method)) #if 1 #define MAX_PS_DIGIT 0xffff #endif #if 0 #define EDIT_DEBUG #endif #if 0 #define EDIT_ROUGH_DEBUG #endif #if 0 #define INPUT_DEBUG #endif #if 0 #define ESCSEQ_DEBUG #endif #if 0 #define OUTPUT_DEBUG #endif #if 0 #define DUMP_HEX #endif #if 0 #define SUPPORT_VTE_CJK_WIDTH #endif #ifndef NO_IMAGE #define SUPPORT_ITERM2_OSC1337 #endif /* If u_int64_t is defined as 32 bit (unsigned long), 1 << (32 or larger) is ignored. */ static u_int64_t true64 = 1; #define SHIFT_FLAG64(mode) ((sizeof(true64) < 8 && (mode) >= 32) ? 0 : (true64 << (mode))) /* * The default of DECMODE_1010 is 'set' (scroll to bottom on tty output) on xterm, * but is 'reset' on mlterm ("exit_backscroll_by_pty" option). */ #define INITIAL_VTMODE_FLAGS \ SHIFT_FLAG64(DECMODE_2) | /* is_vt52_mode == 0 */ \ SHIFT_FLAG64(DECMODE_7) | /* auto_wrap == 1 (compatible with xterm, not with VT220) */ \ SHIFT_FLAG64(DECMODE_25) | /* is_visible_cursor == 1 */ \ SHIFT_FLAG64(DECMODE_1034) | /* mod_meta_mode = 8bit (compatible with xterm) */ \ SHIFT_FLAG64(VTMODE_12); /* local echo is false */ #define VTMODE(mode) ((mode) + 10000) #define destroy_drcs(drcs) \ vt_drcs_destroy(drcs); \ (drcs) = NULL; /* * If VTMODE_NUM >= 64, enlarge the size of vt_parser_t::vtmode_flags. * See get_initial_vtmode_flags() to check initial values of these modes. */ typedef enum { /* DECSET/DECRST */ DECMODE_1 = 0, DECMODE_2, DECMODE_3, DECMODE_5, DECMODE_6, DECMODE_7, DECMODE_25, DECMODE_40, DECMODE_47, DECMODE_66, DECMODE_67, DECMODE_69, DECMODE_80, DECMODE_95, DECMODE_116, DECMODE_117, DECMODE_1000, DECMODE_1002, /* Don't add an entry between 1000 and 1002 (see set_vtmode() idx - DECMODE_1000) */ DECMODE_1003, DECMODE_1004, DECMODE_1005, DECMODE_1006, DECMODE_1015, /* Don't add an entry between 1005 and 1015 (see set_vtmode() idx - DECMODE_1005) */ DECMODE_1010, DECMODE_1034, DECMODE_1036, DECMODE_1042, DECMODE_1047, DECMODE_1048, DECMODE_1049, DECMODE_2004, DECMODE_7727, DECMODE_8428, DECMODE_8452, DECMODE_8800, /* SM/RM */ VTMODE_2, VTMODE_4, VTMODE_12, VTMODE_20, VTMODE_33, VTMODE_34, VTMODE_NUM, } vtmode_t; typedef struct area { u_int32_t min; u_int32_t max; } area_t; /* --- static variables --- */ static u_int16_t vtmodes[] = { /* DECSET/DECRST */ 1, 2, 3, 5, 6, 7, 25, 40, 47, 66, 67, 69, 80, 95, 116, 117, 1000, 1002, /* Don't add an entry between 1000 and 1002 (see set_vtmode()) */ 1003, 1004, 1005, 1006, 1015, /* Don't add an entry between 1005 and 1015 (see set_vtmode()) */ 1010, 1034, 1036, 1042, 1047, 1048, 1049, 2004, 7727, 8428, 8452, 8800, /* SM/RM */ VTMODE(2), VTMODE(4), VTMODE(12), VTMODE(20), VTMODE(33), VTMODE(34), }; static int use_alt_buffer = 1; static area_t *unicode_noconv_areas; static u_int num_unicode_noconv_areas; static area_t *full_width_areas; static u_int num_full_width_areas; static area_t *half_width_areas; static u_int num_half_width_areas; static char *auto_detect_encodings; static struct { vt_char_encoding_t encoding; ef_parser_t *parser; } * auto_detect; static u_int num_auto_detect_encodings; static int use_ttyrec_format; static clock_t timeout_read_pty = CLOCKS_PER_SEC / 100; /* 0.01 sec */ static char *primary_da; static char *secondary_da; static int is_broadcasting; static int old_drcs_sixel; /* Compatible behavior with RLogin 2.23.0 or before */ static u_int local_echo_wait_msec = 250; #ifdef USE_LIBSSH2 static int use_scp_full; #endif static u_int8_t alt_color_idxs[] = { 0, 1, 2, 4, 8, 3, 5, 9, 6, 10, 12, 7, 11, 13, 14, 15, } ; static char *send_file; static char *recv_dir; /* --- static functions --- */ #ifdef DEBUG #if 0 #define debug_print_unknown bl_debug_printf #else static void debug_print_unknown(const char *format, ...) { va_list arg_list; va_start(arg_list, format); fprintf(stderr, BL_DEBUG_TAG " received unknown sequence "); vfprintf(stderr, format, arg_list); } #endif #endif /* XXX This function should be moved to pobl */ static void str_replace(char *str, int c1, int c2) { while (*str) { if (*str == c1) { *str = c2; } str++; } } static area_t *set_area_to_table(area_t *area_table, u_int *num, char *areas) { char *area; #ifdef __DEBUG if (area_table == unicode_noconv_areas) { bl_debug_printf("Unicode noconv area:"); } else if (area_table == full_width_areas) { bl_debug_printf("Unicode full width area:"); } else { bl_debug_printf("Unicode half width area:"); } bl_msg_printf(" parsing %s\n", areas); #endif if (areas == NULL || *areas == '\0') { free(area_table); *num = 0; return NULL; } else { void *p; if (!(p = realloc(area_table, sizeof(*area_table) * (bl_count_char_in_str(areas, ',') + 2)))) { return area_table; } area_table = p; } *num = 0; while ((area = bl_str_sep(&areas, ","))) { u_int min; u_int max; if (vt_parse_unicode_area(area, &min, &max)) { u_int count = 0; while (1) { if (count == *num) { area_table[*num].min = min; area_table[(*num)++].max = max; break; } if (area_table[count].min <= min) { if (area_table[count].max + 1 >= min) { if (area_table[count].max < max) { area_table[count].max = max; } break; } } else { if (area_table[count].min <= max + 1) { if (area_table[count].min > min) { area_table[count].min = min; } if (area_table[count].max < max) { area_table[count].max = max; } } else { memmove(area_table + count + 1, area_table + count, (*num - count) * sizeof(*area_table)); area_table[count].max = max; area_table[count].min = min; (*num)++; } break; } count++; } } } #ifdef __DEBUG { u_int count; for (count = 0; count < *num; count++) { bl_debug_printf("AREA %x-%x\n", area_table[count].min, area_table[count].max); } } #endif return area_table; } static void response_area_table(vt_pty_t *pty, u_char *key, area_t *area_table, u_int num, int to_menu) { u_char *value; /* 20: U+FFFFFFFF-FFFFFFFF, */ if (num > 0 && (value = alloca(20 * num))) { u_int count; u_char *p; p = value; count = 0; while (1) { sprintf(p, area_table[count].min == area_table[count].max ? "U+%x" : "U+%x-%x", area_table[count].min, area_table[count].max); p += strlen(p); if (++count < num) { *(p++) = ','; } else { break; } } } else { value = ""; } vt_response_config(pty, key, value, to_menu); } static inline int hit_area(area_t *areas, u_int num, u_int code) { if (num > 0 && areas[0].min <= code && code <= areas[num - 1].max) { u_int count; if (num == 1) { return 1; } count = 0; do { if (areas[count].min <= code && code <= areas[count].max) { return 1; } } while (++count < num); } return 0; } static inline int is_noconv_unicode(u_char *ch) { if (unicode_noconv_areas || ch[2] == 0x20) { u_int32_t code = ef_bytes_to_int(ch, 4); if (hit_area(unicode_noconv_areas, num_unicode_noconv_areas, code)) { return 1; } /* * Don't convert these characters in order not to show them. * see vt_char_cols(). */ if ((0x200c <= code && code <= 0x200f) || (0x202a <= code && code <= 0x202e)) { return 1; } } return 0; } static inline ef_property_t modify_ucs_property(u_int32_t code, int col_size_of_width_a, ef_property_t prop) { if (prop & EF_AWIDTH) { #ifdef SUPPORT_VTE_CJK_WIDTH char *env; #endif prop &= ~EF_AWIDTH; if (col_size_of_width_a == 2) { prop |= EF_FULLWIDTH; } #ifdef SUPPORT_VTE_CJK_WIDTH else if ((env = getenv("VTE_CJK_WIDTH")) && (strcmp(env, "wide") == 0 || strcmp(env, "1") == 0)) { prop |= EF_FULLWIDTH; } #endif } if (prop & EF_FULLWIDTH) { if (half_width_areas && hit_area(half_width_areas, num_half_width_areas, code)) { return prop & ~EF_FULLWIDTH; } } else { if (full_width_areas && hit_area(full_width_areas, num_full_width_areas, code)) { return prop | EF_FULLWIDTH; } } return prop; } static void start_vt100_cmd(vt_parser_t *vt_parser, int trigger_xterm_event /* dispatch to x_screen or not. */ ) { vt_set_use_multi_col_char(vt_parser->use_multi_col_char); if (trigger_xterm_event && HAS_XTERM_LISTENER(vt_parser, start)) { /* * XXX Adhoc implementation. * Converting visual -> logical in xterm_listener->start. */ (*vt_parser->xterm_listener->start)(vt_parser->xterm_listener->self); } else { vt_screen_logical(vt_parser->screen); } } static void stop_vt100_cmd(vt_parser_t *vt_parser, int trigger_xterm_event /* dispatch to x_screen or not. */ ) { vt_screen_render(vt_parser->screen); vt_screen_visual(vt_parser->screen); if (trigger_xterm_event && HAS_XTERM_LISTENER(vt_parser, stop)) { (*vt_parser->xterm_listener->stop)(vt_parser->xterm_listener->self); } } static void interrupt_vt100_cmd(vt_parser_t *vt_parser) { if (HAS_XTERM_LISTENER(vt_parser, interrupt)) { vt_screen_render(vt_parser->screen); vt_screen_visual(vt_parser->screen); (*vt_parser->xterm_listener->interrupt)(vt_parser->xterm_listener->self); vt_screen_logical(vt_parser->screen); } } static int change_read_buffer_size(vt_read_buffer_t *r_buf, size_t len) { void *p; if (!(p = realloc(r_buf->chars, len))) { return 0; } r_buf->chars = p; r_buf->len = len; /* * Not check if r_buf->left and r_buf->filled_len is larger than r_buf->len. * It should be checked before calling this function. */ return 1; } static char* get_now_suffix(char *now /* 16 bytes */) { time_t t; struct tm *tm; time(&t); tm = localtime(&t); sprintf(now, "-%04d%02d%02d%02d%02d%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return now; } static char *get_home_file_path(const char *prefix, const char *name, const char *suffix) { char *file_name; if (!(file_name = alloca(7 + strlen(prefix) + 1 + strlen(name) + 1 + strlen(suffix) + 1))) { return NULL; } sprintf(file_name, "mlterm/%s%s.%s", prefix, name, suffix); str_replace(file_name + 7, '/', '_'); return bl_get_user_rc_path(file_name); } /* * 0: Error * 1: No error * >=2: Probable */ static int parse_string(ef_parser_t *cc_parser, u_char *str, size_t len) { ef_char_t ch; int ret; u_int nfull; u_int nkana; ret = 1; nfull = 0; nkana = 0; (*cc_parser->init)(cc_parser); (*cc_parser->set_str)(cc_parser, str, len); while (1) { if (!(*cc_parser->next_char)(cc_parser, &ch)) { if (cc_parser->is_eos) { if (nkana * 8 > nfull) { /* kana is over 12.5%. */ ret = 2; } return ret; } else { if (((str[len - cc_parser->left]) & 0x7f) <= 0x1f) { /* skip C0 or C1 */ ef_parser_increment(cc_parser); } else { return 0; } } } else if (ch.size > 1) { if (ch.cs == ISO10646_UCS4_1) { if (ret == 1 && ch.property == EF_FULLWIDTH) { ret = 2; } } else { if (IS_CS94MB(ch.cs)) { if (ch.ch[0] <= 0x20 || ch.ch[0] == 0x7f || ch.ch[1] <= 0x20 || ch.ch[1] == 0x7f) { /* mef can return illegal character code. */ return 0; } else if (ret == 1 && (ch.cs == JISX0208_1983 || ch.cs == JISC6226_1978 || ch.cs == JISX0213_2000_1) && (ch.ch[0] == 0x24 || ch.ch[0] == 0x25) && 0x21 <= ch.ch[1] && ch.ch[1] <= 0x73) { /* Hiragana/Katakana */ nkana++; } } nfull++; } } } } /* Check num_auto_detect_encodings > 0 before calling this function. */ static void detect_encoding(vt_parser_t *vt_parser) { u_char *str; size_t len; size_t count; u_int idx; int cur_idx; int cand_idx; int threshold; str = vt_parser->r_buf.chars; len = vt_parser->r_buf.filled_len; for (count = 0; count < len - 1; count++) { if (str[count] >= 0x80 && str[count + 1] >= 0x80) { goto detect; } } return; detect: cur_idx = -1; threshold = 0; for (idx = 0; idx < num_auto_detect_encodings; idx++) { if (auto_detect[idx].encoding == vt_parser->encoding) { if ((threshold = parse_string(auto_detect[idx].parser, str, len)) > 1) { return; } cur_idx = idx; break; } } cand_idx = -1; for (idx = 0; idx < num_auto_detect_encodings; idx++) { int ret; if (idx != cur_idx && (ret = parse_string(auto_detect[idx].parser, str, len)) > threshold) { cand_idx = idx; if (ret > 1) { break; } } } if (cand_idx >= 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Character encoding is changed to %s.\n", vt_get_char_encoding_name(auto_detect[cand_idx].encoding)); #endif vt_parser_change_encoding(vt_parser, auto_detect[cand_idx].encoding); } } inline static int is_dcs_or_osc(u_char *str /* The length should be 2 or more. */ ) { return *str == 0x90 || memcmp(str, "\x1bP", 2) == 0 || memcmp(str, "\x1b]", 2) == 0; } static void write_ttyrec_header(int fd, size_t len, int keep_time) { u_int32_t buf[3]; #ifdef HAVE_GETTIMEOFDAY if (!keep_time) { struct timeval tval; gettimeofday(&tval, NULL); #ifdef WORDS_BIGENDIAN buf[0] = LE32DEC(((u_char *)&tval.tv_sec)); buf[1] = LE32DEC(((u_char *)&tval.tv_usec)); buf[2] = LE32DEC(((u_char *)&len)); #else buf[0] = tval.tv_sec; buf[1] = tval.tv_usec; buf[2] = len; #endif #if __DEBUG bl_debug_printf("write len %d at %d\n", len, lseek(fd, 0, SEEK_CUR)); #endif write(fd, buf, 12); } else #endif { lseek(fd, 8, SEEK_CUR); #ifdef WORDS_BIGENDIAN buf[0] = LE32DEC(((u_char *)&len)); #else buf[0] = len; #endif write(fd, buf, 4); } } static int receive_bytes(vt_parser_t *vt_parser) { size_t len; if (vt_parser->r_buf.left == vt_parser->r_buf.len) { /* Buffer is full => Expand buffer */ len = vt_parser->r_buf.len >= PTY_RD_BUFFER_SIZE * 5 ? PTY_RD_BUFFER_SIZE * 10 : PTY_RD_BUFFER_SIZE; if (!change_read_buffer_size(&vt_parser->r_buf, vt_parser->r_buf.len + len)) { return 0; } } else { if (0 < vt_parser->r_buf.left && vt_parser->r_buf.left < vt_parser->r_buf.filled_len) { memmove(vt_parser->r_buf.chars, CURRENT_STR_P(vt_parser), vt_parser->r_buf.left * sizeof(u_char)); } /* vt_parser->r_buf.left must be always less than vt_parser->r_buf.len */ if ((len = vt_parser->r_buf.len - vt_parser->r_buf.left) > PTY_RD_BUFFER_SIZE && !is_dcs_or_osc(vt_parser->r_buf.chars)) { len = PTY_RD_BUFFER_SIZE; } } if ((vt_parser->r_buf.new_len = vt_read_pty( vt_parser->pty, vt_parser->r_buf.chars + vt_parser->r_buf.left, len)) == 0) { vt_parser->r_buf.filled_len = vt_parser->r_buf.left; return 0; } if (vt_parser->logging_vt_seq) { if (vt_parser->log_file == -1) { char *path; char buf[16]; if (!(path = get_home_file_path(vt_pty_get_slave_name(vt_parser->pty) + 5, get_now_suffix(buf), "log"))) { goto end; } if ((vt_parser->log_file = open(path, O_CREAT | O_WRONLY, 0600)) == -1) { free(path); goto end; } free(path); /* * O_APPEND in open() forces lseek(0,SEEK_END) in write() * and disables lseek(pos,SEEK_SET) before calling write(). * So don't specify O_APPEND in open() and call lseek(0,SEEK_END) * manually after open(). */ lseek(vt_parser->log_file, 0, SEEK_END); bl_file_set_cloexec(vt_parser->log_file); if (use_ttyrec_format) { char seq[6 + DIGIT_STR_LEN(int)*2 + 1]; /* The height of "CSI 8 t" doesn't include status line. */ sprintf(seq, "\x1b[8;%d;%dt", vt_screen_get_logical_rows(vt_parser->screen), vt_screen_get_logical_cols(vt_parser->screen)); write_ttyrec_header(vt_parser->log_file, strlen(seq), 0); write(vt_parser->log_file, seq, strlen(seq)); } } if (use_ttyrec_format) { if (vt_parser->r_buf.left > 0) { lseek(vt_parser->log_file, lseek(vt_parser->log_file, 0, SEEK_CUR) - vt_parser->r_buf.filled_len - 12, SEEK_SET); if (vt_parser->r_buf.left < vt_parser->r_buf.filled_len) { write_ttyrec_header(vt_parser->log_file, vt_parser->r_buf.filled_len - vt_parser->r_buf.left, 1); lseek(vt_parser->log_file, lseek(vt_parser->log_file, 0, SEEK_CUR) + vt_parser->r_buf.filled_len - vt_parser->r_buf.left, SEEK_SET); } } write_ttyrec_header(vt_parser->log_file, vt_parser->r_buf.left + vt_parser->r_buf.new_len, 0); write(vt_parser->log_file, vt_parser->r_buf.chars, vt_parser->r_buf.left + vt_parser->r_buf.new_len); } else { write(vt_parser->log_file, vt_parser->r_buf.chars + vt_parser->r_buf.left, vt_parser->r_buf.new_len); } #ifndef USE_WIN32API fsync(vt_parser->log_file); #endif } else { if (vt_parser->log_file != -1) { close(vt_parser->log_file); vt_parser->log_file = -1; } } end: vt_parser->r_buf.filled_len = (vt_parser->r_buf.left += vt_parser->r_buf.new_len); if (vt_parser->r_buf.filled_len <= PTY_RD_BUFFER_SIZE && vt_parser->r_buf.len > PTY_RD_BUFFER_SIZE) { /* Shrink buffer */ change_read_buffer_size(&vt_parser->r_buf, PTY_RD_BUFFER_SIZE); } if (vt_parser->use_auto_detect && num_auto_detect_encodings > 0) { detect_encoding(vt_parser); } #ifdef INPUT_DEBUG { size_t count; bl_debug_printf(BL_DEBUG_TAG " pty msg (len %d) is received:", vt_parser->r_buf.left); for (count = 0; count < vt_parser->r_buf.left; count++) { #ifdef DUMP_HEX if (isprint(vt_parser->r_buf.chars[count])) { bl_msg_printf("%c ", vt_parser->r_buf.chars[count]); } else { bl_msg_printf("%.2x ", vt_parser->r_buf.chars[count]); } #else bl_msg_printf("%c", vt_parser->r_buf.chars[count]); #endif } bl_msg_printf("[END]\n"); } #endif return 1; } /* * If buffer exists, vt_parser->w_buf.last_ch is cached. * If buffer doesn't exist, vt_parser->w_buf.last_ch is cleared. */ static int flush_buffer(vt_parser_t *vt_parser) { vt_write_buffer_t *buffer; buffer = &vt_parser->w_buf; if (buffer->filled_len == 0) { return 0; } #ifdef OUTPUT_DEBUG { u_int count; bl_msg_printf("\nflushing chars(%d)...==>", buffer->filled_len); for (count = 0; count < buffer->filled_len; count++) { u_int code = vt_char_code(&buffer->chars[count]); #ifdef DUMP_HEX bl_msg_printf("%x", code); #else bl_msg_printf("%c", code); #endif } bl_msg_printf("<===\n"); } #endif (*buffer->output_func)(vt_parser->screen, buffer->chars, buffer->filled_len); /* last_ch which will be used & cleared in REP sequence is cached. */ buffer->last_ch = &buffer->chars[buffer->filled_len - 1]; /* buffer is cleared. */ buffer->filled_len = 0; #ifdef EDIT_DEBUG vt_edit_dump(vt_parser->screen->edit); #endif return 1; } static void put_char(vt_parser_t *vt_parser, u_int32_t ch, ef_charset_t cs, ef_property_t prop) { vt_color_t fg_color; vt_color_t bg_color; int is_fullwidth; int is_comb; int is_bold; int is_italic; int line_style; int is_blinking; int is_protected; int is_reversed; if (vt_parser->w_buf.filled_len == PTY_WR_BUFFER_SIZE) { flush_buffer(vt_parser); } /* * checking width property of the char. */ if (prop & EF_FULLWIDTH) { is_fullwidth = 1; } else { is_fullwidth = 0; } #ifdef __DEBUG bl_debug_printf("%x %d %x => %s\n", ch, len, cs, is_fullwidth ? "Fullwidth" : "Single"); #endif if ((prop & EF_COMBINING) #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_IND) || (ch == '\xe9' && IS_ISCII(cs)) /* nukta is always combined. */ #endif ) { is_comb = 1; } else { is_comb = 0; } fg_color = vt_parser->fg_color; bg_color = vt_parser->bg_color; is_italic = vt_parser->is_italic ? 1 : 0; is_blinking = vt_parser->is_blinking ? 1 : 0; is_protected = vt_parser->is_protected ? 1 : 0; is_reversed = vt_parser->is_reversed ? 1 : 0; line_style = vt_parser->line_style; if (cs == ISO10646_UCS4_1 && 0x2580 <= ch && ch <= 0x259f) { /* prevent these block characters from being drawn doubly. */ is_bold = 0; } else { is_bold = vt_parser->is_bold ? 1 : 0; } if (fg_color == VT_FG_COLOR) { if (is_italic && (vt_parser->alt_color_mode & ALT_COLOR_ITALIC)) { is_italic = 0; fg_color = VT_ITALIC_COLOR; } if ((line_style & LS_CROSSED_OUT) && (vt_parser->alt_color_mode & ALT_COLOR_CROSSED_OUT)) { line_style &= ~LS_CROSSED_OUT; fg_color = VT_CROSSED_OUT_COLOR; } if (is_blinking && (vt_parser->alt_color_mode & ALT_COLOR_BLINKING)) { is_blinking = 0; fg_color = VT_BLINKING_COLOR; } if ((line_style & LS_UNDERLINE) && (vt_parser->alt_color_mode & ALT_COLOR_UNDERLINE)) { line_style &= ~LS_UNDERLINE; fg_color = VT_UNDERLINE_COLOR; } if (is_bold && (vt_parser->alt_color_mode & ALT_COLOR_BOLD)) { is_bold = 0; fg_color = VT_BOLD_COLOR; } if (is_reversed && (vt_parser->alt_color_mode & ALT_COLOR_REVERSE)) { is_reversed = 0; fg_color = VT_REVERSE_COLOR; } } else { if (is_bold) { if (IS_VTSYS_BASE_COLOR(fg_color)) { fg_color |= VT_BOLD_COLOR_MASK; } if (vt_parser->bold_affects_bg && IS_VTSYS_BASE_COLOR(bg_color)) { bg_color |= VT_BOLD_COLOR_MASK; } } } if (is_reversed) { vt_color_t tmp = bg_color; bg_color = fg_color; fg_color = tmp; } if (vt_parser->alt_colors.flags) { int idx = is_bold | ((vt_parser->is_reversed ? 1 : 0) << 1) | ((line_style & LS_UNDERLINE) ? 4 : 0) | (is_blinking << 3); if (/* idx < 16 && */ (vt_parser->alt_colors.flags & (1 << idx))) { fg_color = vt_parser->alt_colors.fg[idx]; bg_color = vt_parser->alt_colors.bg[idx]; } } /* * 2.9.2 Alternate Text Colors in VT520-VT525ProgrammerInformation.pdf * "The foreground color of text with the invisible attribute becomes the background color." */ if (vt_parser->is_invisible) { fg_color = bg_color; } if (vt_parser->use_char_combining && is_comb) { if (vt_parser->w_buf.filled_len == 0) { /* * vt_line_set_modified() is done in vt_screen_combine_with_prev_char() * internally. */ if (vt_screen_combine_with_prev_char(vt_parser->screen, ch, cs, is_fullwidth, is_comb, fg_color, bg_color, is_bold, is_italic, line_style, is_blinking, is_protected)) { return; } } else { if (vt_char_combine(&vt_parser->w_buf.chars[vt_parser->w_buf.filled_len - 1], ch, cs, is_fullwidth, is_comb, fg_color, bg_color, is_bold, is_italic, line_style, is_blinking, is_protected)) { return; } } /* * if combining failed , char is normally appended. */ } #ifndef NO_IMAGE { vt_drcs_font_t *font; int pic_id; int pic_pos; if (cs != US_ASCII && (font = vt_drcs_get_font(vt_parser->drcs, cs == CS_REVISION_1(US_ASCII) ? US_ASCII : cs, 0)) && /* XXX The width of pua is always regarded as 1. (is_fullwidth is ignored) */ vt_drcs_get_picture(font, &pic_id, &pic_pos, ch)) { vt_char_copy(&vt_parser->w_buf.chars[vt_parser->w_buf.filled_len], vt_screen_get_bce_ch(vt_parser->screen)); vt_char_combine_picture(&vt_parser->w_buf.chars[vt_parser->w_buf.filled_len++], pic_id, pic_pos); return; } } #endif vt_char_set(&vt_parser->w_buf.chars[vt_parser->w_buf.filled_len++], ch, cs, is_fullwidth, is_comb, fg_color, bg_color, is_bold, is_italic, line_style, is_blinking, is_protected); if (cs != ISO10646_UCS4_1) { return; } if (0x1f000 <= ch && ch <= 0x1f9ff && (ch <= 0x1f6ff || 0x1f900 <= ch) && HAS_XTERM_LISTENER(vt_parser, get_emoji_data)) { /* * Emoji pictures (mostly U+1F000-1F6FF) provided by * http://github.com/githuub/gemoji */ vt_char_t *emoji1; vt_char_t *emoji2; emoji1 = &vt_parser->w_buf.chars[vt_parser->w_buf.filled_len - 1]; emoji2 = NULL; if (0x1f1e6 <= ch && ch <= 0x1f1ff) { vt_char_t *prev_ch; if (vt_parser->w_buf.filled_len <= 1) { prev_ch = vt_screen_get_n_prev_char(vt_parser->screen, 1); } else { prev_ch = emoji1 - 1; } if (prev_ch) { if (0x1f1e6 <= vt_char_code(prev_ch) && vt_char_code(prev_ch) <= 0x1f1ff) { emoji2 = emoji1; emoji1 = prev_ch; } } } if ((*vt_parser->xterm_listener->get_emoji_data)(vt_parser->xterm_listener->self, emoji1, emoji2)) { if (emoji2) { /* Base char: emoji1, Comb1: picture, Comb2: emoji2 */ if (emoji2 == emoji1 + 1) { vt_char_combine(emoji1, ch, cs, is_fullwidth, is_comb, fg_color, bg_color, is_bold, is_italic, line_style, is_blinking, is_protected); } else { /* * vt_line_set_modified() is done in * vt_screen_combine_with_prev_char() internally. */ vt_screen_combine_with_prev_char(vt_parser->screen, ch, cs, is_fullwidth, is_comb, fg_color, bg_color, is_bold, is_italic, line_style, is_blinking, is_protected); } vt_parser->w_buf.filled_len--; } /* * Flush buffer before searching and deleting unused pictures * in x_picture.c. */ flush_buffer(vt_parser); } } else if (vt_parser->use_char_combining) { /* * Arabic combining */ vt_char_t *prev2; vt_char_t *prev; vt_char_t *cur; int n; cur = &vt_parser->w_buf.chars[vt_parser->w_buf.filled_len - 1]; n = 0; if (vt_parser->w_buf.filled_len >= 2) { prev = cur - 1; } else { if (!(prev = vt_screen_get_n_prev_char(vt_parser->screen, ++n))) { return; } } if (vt_parser->w_buf.filled_len >= 3) { prev2 = cur - 2; } else { /* possibly NULL */ prev2 = vt_screen_get_n_prev_char(vt_parser->screen, ++n); } if (IS_ARABIC_CHAR(ch) && vt_is_arabic_combining(prev2, prev, cur)) { if (vt_parser->w_buf.filled_len >= 2) { if (vt_char_combine(prev, ch, cs, is_fullwidth, is_comb, fg_color, bg_color, is_bold, is_italic, line_style, is_blinking, is_protected)) { vt_parser->w_buf.filled_len--; } } else { /* * vt_line_set_modified() is done in * vt_screen_combine_with_prev_char() internally. */ if (vt_screen_combine_with_prev_char(vt_parser->screen, ch, cs, is_fullwidth, is_comb, fg_color, bg_color, is_bold, is_italic, line_style, is_blinking, is_protected)) { vt_parser->w_buf.filled_len--; } } } } } static void push_to_saved_names(vt_saved_names_t *saved, char *name) { void *p; if (!(p = realloc(saved->names, (saved->num + 1) * sizeof(name)))) { return; } saved->names = p; saved->names[saved->num++] = name ? strdup(name) : NULL; } static char *pop_from_saved_names(vt_saved_names_t *saved) { char *name; name = saved->names[--saved->num]; if (saved->num == 0) { free(saved->names); saved->names = NULL; } return name; } /* * VT100_PARSER Escape Sequence Commands. */ static void save_cursor(vt_parser_t *vt_parser) { vt_storable_states_t *dest; dest = (vt_screen_is_alternative_edit(vt_parser->screen)) ? &(vt_parser->saved_alternate) : &(vt_parser->saved_normal); dest->is_saved = 1; dest->fg_color = vt_parser->fg_color; dest->bg_color = vt_parser->bg_color; dest->is_bold = vt_parser->is_bold; dest->is_italic = vt_parser->is_italic; dest->line_style = vt_parser->line_style; dest->is_reversed = vt_parser->is_reversed; dest->is_blinking = vt_parser->is_blinking; dest->is_invisible = vt_parser->is_invisible; dest->is_protected = vt_parser->is_protected; dest->is_relative_origin = vt_screen_is_relative_origin(vt_parser->screen); dest->last_column_flag = vt_screen_get_last_column_flag(vt_parser->screen); dest->cs = vt_parser->cs; vt_screen_save_cursor(vt_parser->screen); } static void set_vtmode(vt_parser_t *vt_parser, int mode, int flag); static void change_char_attr(vt_parser_t *vt_parser, int flag); static void restore_cursor(vt_parser_t *vt_parser) { vt_storable_states_t *src; src = (vt_screen_is_alternative_edit(vt_parser->screen)) ? &(vt_parser->saved_alternate) : &(vt_parser->saved_normal); if (src->is_saved) { vt_parser->fg_color = src->fg_color; vt_screen_set_bce_fg_color(vt_parser->screen, src->fg_color); vt_parser->bg_color = src->bg_color; vt_screen_set_bce_bg_color(vt_parser->screen, src->bg_color); vt_parser->is_bold = src->is_bold; vt_parser->is_italic = src->is_italic; vt_parser->line_style = src->line_style; vt_parser->is_reversed = src->is_reversed; vt_parser->is_blinking = src->is_blinking; vt_parser->is_invisible = src->is_invisible; vt_parser->is_protected = src->is_protected; vt_screen_set_relative_origin(vt_parser->screen, src->is_relative_origin ? 1 : 0); /* See "Last Column Flag specifics" at https://github.com/mattiase/wraptest */ vt_screen_set_last_column_flag(vt_parser->screen, src->last_column_flag ? 1 : 0); if (IS_ENCODING_BASED_ON_ISO2022(vt_parser->encoding)) { if ((src->cs == DEC_SPECIAL) && (src->cs != vt_parser->cs)) { /* force grapchics mode by sending \E(0 to current parser*/ u_char DEC_SEQ[] = {CTL_ESC, '(', '0'}; ef_char_t ch; ef_parser_t *parser; vt_init_encoding_parser(vt_parser); parser = vt_parser->cc_parser; (*parser->set_str)(parser, DEC_SEQ, sizeof(DEC_SEQ)); (*parser->next_char)(parser, &ch); } } else { /* XXX: what to do for g0/g1? */ if (src->cs == DEC_SPECIAL) { vt_parser->gl = DEC_SPECIAL; } else { vt_parser->gl = US_ASCII; } } vt_screen_restore_cursor(vt_parser->screen); } else { /* * Moves the cursor to the home position (upper left of screen). * Resets origin mode (DECOM). * Turns all character attributes off (normal setting). * Maps the ASCII character set into GL, and the DEC Supplemental Graphic set into GR. * (see https://www.vt100.net/docs/vt510-rm/DECRC.html) */ change_char_attr(vt_parser, 0); set_vtmode(vt_parser, 6, 0); /* goto(0, 0) internally */ } } static void set_maximize(vt_parser_t *vt_parser, int flag) { if (HAS_XTERM_LISTENER(vt_parser, resize)) { stop_vt100_cmd(vt_parser, 0); (*vt_parser->xterm_listener->resize)(vt_parser->xterm_listener->self, 0, 0, flag); start_vt100_cmd(vt_parser, 0); } } static int get_cell_size(vt_parser_t *vt_parser, u_int *col_width, u_int *line_height) { if (HAS_XTERM_LISTENER(vt_parser, get_window_size)) { u_int width; u_int height; (*vt_parser->xterm_listener->get_window_size)(vt_parser->xterm_listener->self, &width, &height); /* XXX This doesn't work on vertical mode. */ if ((*col_width = width / vt_screen_get_logical_cols(vt_parser->screen)) == 0 || (*line_height = height / vt_screen_get_logical_rows(vt_parser->screen)) == 0) { return 0; } return 1; } else { return 0; } } /* * width|height == 0: maximize * width|height == -1: current value */ static void resize(vt_parser_t *vt_parser, int width, int height, int by_char) { if (HAS_XTERM_LISTENER(vt_parser, resize)) { if (by_char) { if (width == 0 || height == 0) { u_int col_width; u_int line_height; if (!HAS_XTERM_LISTENER(vt_parser, get_display_size) || !get_cell_size(vt_parser, &col_width, &line_height)) { if (width == 0) { width = -1; } if (height == 0) { height = -1; } } else { u_int w; u_int h; (*vt_parser->xterm_listener->get_display_size)(vt_parser->xterm_listener->self, &w, &h); if (width == 0) { width = w / col_width; } if (height == 0) { height = h / line_height; goto do_resize; } } } if (width == -1) { width = vt_screen_get_logical_cols(vt_parser->screen); } if (height == -1) { height = vt_screen_get_logical_rows(vt_parser->screen); } /* * 'height' argument of this function should includes status line according to * the following document, but teraterm (4.95) excludes status line by CSI 8 t. * mlterm considers height of "CSI t", "OSC 5379;geometry", DECSNLS and DECSLPP * to be excluding status line. * * https://vt100.net/docs/vt510-rm/DECSNLS.html * The terminal supports three different font heights, which allows 26, 42, or 53 data * lines to be displayed on the screen or 25, 41, or 52 data lines to be displayed on * the screen, plus a status line. */ if (vt_screen_has_status_line(vt_parser->screen)) { height ++; } do_resize: vt_screen_resize(vt_parser->screen, width, height, 0); /* * xterm_listener::resize(0,0) means that screen should be * resized according to the size of pty. */ width = 0; height = 0; } else { if ((width == 0 || height == 0) && HAS_XTERM_LISTENER(vt_parser, get_display_size)) { u_int w; u_int h; (*vt_parser->xterm_listener->get_display_size)(vt_parser->xterm_listener->self, &w, &h); if (width == 0) { width = w; } if (height == 0) { height = h; } } if (width == -1) { width = 0; /* xterm_listener->resize() doesn't resize width if width == 0. */ } if (height == -1) { height = 0; /* xterm_listener->resize() doesn't resize height if height == 0. */ } } stop_vt100_cmd(vt_parser, 0); (*vt_parser->xterm_listener->resize)(vt_parser->xterm_listener->self, width, height, 0); start_vt100_cmd(vt_parser, 0); } } static void reverse_video(vt_parser_t *vt_parser, int flag) { if (HAS_XTERM_LISTENER(vt_parser, reverse_video)) { stop_vt100_cmd(vt_parser, 0); (*vt_parser->xterm_listener->reverse_video)(vt_parser->xterm_listener->self, flag); start_vt100_cmd(vt_parser, 0); } } static void set_mouse_report(vt_parser_t *vt_parser, vt_mouse_report_mode_t mode) { if (HAS_XTERM_LISTENER(vt_parser, set_mouse_report)) { /* * If xterm_set_mouse_report() calls x_stop_selecting() etc, * remove #if 0 - #end. * * If #if 0 - #end is removed, ctl_render() is at least twice * in one sequence packet from w3m because w3m sends CSI?1000h every time. */ #if 0 stop_vt100_cmd(vt_parser, 0); #endif vt_parser->mouse_mode = mode; (*vt_parser->xterm_listener->set_mouse_report)(vt_parser->xterm_listener->self); #if 0 start_vt100_cmd(vt_parser, 0); #endif } } static void request_locator(vt_parser_t *vt_parser) { if (HAS_XTERM_LISTENER(vt_parser, request_locator)) { vt_mouse_report_mode_t orig; #if 0 stop_vt100_cmd(vt_parser, 0); #endif if (vt_parser->mouse_mode < LOCATOR_CHARCELL_REPORT) { orig = vt_parser->mouse_mode; vt_parser->mouse_mode = LOCATOR_CHARCELL_REPORT; } else { orig = 0; } vt_parser->locator_mode |= LOCATOR_REQUEST; (*vt_parser->xterm_listener->request_locator)(vt_parser->xterm_listener->self); vt_parser->locator_mode |= LOCATOR_REQUEST; if (orig) { orig = vt_parser->mouse_mode; } #if 0 start_vt100_cmd(vt_parser, 0); #endif } } static char *parse_title(vt_parser_t *vt_parser, char *src /* the caller should allocated */) { size_t len; ef_parser_t *parser; vt_char_encoding_t src_encoding; ef_char_t ch; u_int num_chars; vt_char_encoding_t dst_encoding; char *dst; if (src == NULL) { return NULL; } dst = NULL; len = strlen(src); if (vt_parser->set_title_using_hex) { if (!(len = bl_hex_decode(src, src, len))) { #ifdef DEBUG bl_debug_printf("Failed to decode %s as hex string.\n", src); #endif goto end; } src[len] = '\0'; } if (vt_parser->set_title_using_utf8 ? vt_parser->encoding == VT_UTF8 : 1) { parser = vt_parser->cc_parser; src_encoding = vt_parser->encoding; } else { if (!(parser = vt_char_encoding_parser_new(VT_UTF8))) { goto end; } src_encoding = VT_UTF8; } (*parser->init)(parser); (*parser->set_str)(parser, src, len); num_chars = 0; while ((*parser->next_char)(parser, &ch)) { if ((ef_bytes_to_int(ch.ch, ch.size) & ~0x80) < 0x20) { #ifdef DEBUG bl_debug_printf("%s which contains control characters is ignored for window title.\n", src); #endif goto end; } num_chars++; } /* locale encoding */ dst_encoding = vt_get_char_encoding("auto"); if (src_encoding == dst_encoding) { return src; } if ((dst = malloc(num_chars * UTF_MAX_SIZE + 1))) { (*parser->init)(parser); (*parser->set_str)(parser, src, len); len = vt_char_encoding_convert_with_parser(dst, num_chars * UTF_MAX_SIZE, dst_encoding, parser); dst[len] = '\0'; if (parser != vt_parser->cc_parser) { (*parser->destroy)(parser); } } end: free(src); return dst; } static void set_window_name(vt_parser_t *vt_parser, u_char *name /* should be malloc'ed or NULL. */ ) { free(vt_parser->win_name); vt_parser->win_name = name; if (HAS_XTERM_LISTENER(vt_parser, set_window_name)) { #if 0 stop_vt100_cmd(vt_parser, 0); #endif (*vt_parser->xterm_listener->set_window_name)(vt_parser->xterm_listener->self, name); #if 0 start_vt100_cmd(vt_parser, 0); #endif } } static void set_icon_name(vt_parser_t *vt_parser, u_char *name /* should be malloc'ed or NULL. */ ) { free(vt_parser->icon_name); vt_parser->icon_name = name; if (HAS_XTERM_LISTENER(vt_parser, set_icon_name)) { #if 0 stop_vt100_cmd(vt_parser, 0); #endif (*vt_parser->xterm_listener->set_icon_name)(vt_parser->xterm_listener->self, name); #if 0 start_vt100_cmd(vt_parser, 0); #endif } } static void switch_im_mode(vt_parser_t *vt_parser) { if (HAS_XTERM_LISTENER(vt_parser, switch_im_mode)) { #if 0 stop_vt100_cmd(vt_parser, 0); #endif (*vt_parser->xterm_listener->switch_im_mode)(vt_parser->xterm_listener->self); #if 0 start_vt100_cmd(vt_parser, 0); #endif } } static int im_is_active(vt_parser_t *vt_parser) { if (HAS_XTERM_LISTENER(vt_parser, im_is_active)) { return (*vt_parser->xterm_listener->im_is_active)(vt_parser->xterm_listener->self); } else { return 0; } } static void set_modkey_mode(vt_parser_t *vt_parser, int key, int mode) { if (key == 1) { if (-1 <= mode && mode <= 3) { vt_parser->modify_cursor_keys = mode; } } else if (key == 2) { if (-1 <= mode && mode <= 3) { vt_parser->modify_function_keys = mode; } } else if (key == 4) { if (0 <= mode && mode <= 2) { vt_parser->modify_other_keys = mode; } } } static void report_window_size(vt_parser_t *vt_parser, int by_char) { if (HAS_XTERM_LISTENER(vt_parser, get_window_size)) { int ps; u_int width; u_int height; char seq[5 + 1 /* ps */ + DIGIT_STR_LEN(u_int) * 2 + 1]; if (by_char) { width = vt_screen_get_logical_cols(vt_parser->screen); height = vt_screen_get_logical_rows(vt_parser->screen); ps = 8; } else { (*vt_parser->xterm_listener->get_window_size)(vt_parser->xterm_listener->self, &width, &height); ps = 4; } sprintf(seq, "\x1b[%d;%d;%dt", ps, height, width); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } } static void report_display_size(vt_parser_t *vt_parser, int by_char) { if (HAS_XTERM_LISTENER(vt_parser, get_display_size)) { int ps; u_int width; u_int height; char seq[5 + 1 /* ps */ + DIGIT_STR_LEN(u_int) * 2 + 1]; (*vt_parser->xterm_listener->get_display_size)(vt_parser->xterm_listener->self, &width, &height); if (by_char) { u_int col_width; u_int line_height; if (!get_cell_size(vt_parser, &col_width, &line_height) || (width /= col_width) == 0 || (height /= line_height) == 0) { return; } ps = 9; } else { ps = 5; } sprintf(seq, "\x1b[%d;%d;%dt", ps, height, width); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } } static void report_cell_size(vt_parser_t *vt_parser) { u_int col_width; u_int line_height; if (get_cell_size(vt_parser, &col_width, &line_height)) { char seq[6 + DIGIT_STR_LEN(u_int) * 2 + 1]; sprintf(seq, "\x1b[6;%d;%dt", line_height, col_width); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } } static void report_window_or_icon_name(vt_parser_t *vt_parser, int is_window) { char *seq; char *pre; char *title; size_t len; vt_char_encoding_t src_encoding; vt_char_encoding_t dst_encoding; if (is_window) { title = vt_parser->win_name; pre = "\x1b]l"; } else { title = vt_parser->icon_name; pre = "\x1b]L"; } if (!title) { title = ""; } /* see parse_title() */ src_encoding = vt_get_char_encoding("auto"); if (vt_parser->get_title_using_utf8) { dst_encoding = VT_UTF8; } else { dst_encoding = vt_parser->encoding; } len = strlen(title); if (src_encoding != dst_encoding) { char *p; if (!(p = alloca(len * UTF_MAX_SIZE + 1))) { goto error; } len = vt_char_encoding_convert(p, len * UTF_MAX_SIZE, dst_encoding, title, len, src_encoding); title = p; } if (!(seq = alloca(3 + len * (vt_parser->get_title_using_hex ? 2 : 1) + 3))) { goto error; } strcpy(seq, pre); if (vt_parser->get_title_using_hex) { len = bl_hex_encode(seq + 3, title, len); } else { memcpy(seq + 3, title, len); } strcpy(seq + 3 + len, "\x1b\\"); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); return; error: vt_write_to_pty(vt_parser->pty, pre, 3); vt_write_to_pty(vt_parser->pty, "\x1b\\", 2); return; } static void set_presentation_state(vt_parser_t *vt_parser, char *seq) { int row; int col; int page; char rend; char attr; char flag; if (sscanf(seq, "%d;%d;%d;%c;%c;%c;0;2;@;BB%%5%%5\x1b\\", &row, &col, &page, &rend, &attr, &flag) == 6) { vt_screen_goto(vt_parser->screen, col - 1, row - 1); if (rend & 0x20) { vt_parser->is_reversed = ((rend & 0x8) == 0x8); vt_parser->is_blinking = ((rend & 0x4) == 0x4); vt_parser->line_style &= ~LS_UNDERLINE; vt_parser->line_style |= ((rend & 0x2) ? LS_UNDERLINE_SINGLE : 0); vt_parser->is_bold = ((rend & 0x1) == 0x1); } if (attr & 0x20) { vt_parser->is_protected = ((attr & 0x1) == 0x1); } if (flag & 0x20) { vt_screen_set_auto_wrap(vt_parser->screen, ((flag & 0x8) == 0x8)); vt_screen_set_relative_origin(vt_parser->screen, ((flag & 0x1) == 0x1)); } } } static void report_presentation_state(vt_parser_t *vt_parser, int ps) { if (ps == 1) { /* DECCIR */ char seq[DIGIT_STR_LEN(u_int) * 3 + 31]; int rend = 0x40; int attr = 0x40; int flag = 0x40; if (vt_parser->is_reversed) { rend |= 0x8; } if (vt_parser->is_blinking) { rend |= 0x4; } if (vt_parser->line_style & LS_UNDERLINE) { rend |= 0x2; } if (vt_parser->is_bold) { rend |= 0x1; } if (vt_parser->is_protected) { attr |= 0x1; } if (vt_screen_is_auto_wrap(vt_parser->screen)) { flag |= 0x8; } if (vt_screen_is_relative_origin(vt_parser->screen)) { flag |= 0x1; } sprintf(seq, "\x1bP1$u%d;%d;%d;%c;%c;%c;0;2;@;BB%%5%%5\x1b\\", vt_screen_cursor_logical_row(vt_parser->screen) + 1, vt_screen_cursor_logical_col(vt_parser->screen) + 1, vt_screen_get_page_id(vt_parser->screen) + 1, rend, attr, flag); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } else if (ps == 2) { /* DECTABSR */ char *seq; u_int max_digit_len = 1; u_int cols = vt_screen_get_logical_cols(vt_parser->screen); u_int tmp = cols; while ((tmp /= 10) > 0) { max_digit_len++; } if ((seq = alloca(5 + (max_digit_len + 1) * cols + 3))) { u_int count; char *p; p = strcpy(seq, "\x1bP2$u") + 5; for (count = 0; count < cols; count++) { if (vt_screen_is_tab_stop(vt_parser->screen, count)) { sprintf(p, "%d/", count + 1); p += strlen(p); } } if (p != seq + 5) { p--; } strcpy(p, "\x1b\\"); vt_write_to_pty(vt_parser->pty, seq, p + 2 - seq); } } } static void report_color_table(vt_parser_t *vt_parser, int pu) { int color; u_int8_t r, g, b; char seq[5+(3*5+4)*256+255+3]; char *p; p = strcpy(seq, "\x1bP2$s") + 5; if (pu == 2) { /* RGB */ for (color = 0; color < 256; color++) { vt_get_color_rgba(color, &r, &g, &b, NULL); sprintf(p, "%d;2;%d;%d;%d/", color, r * 100 / 255, g * 100 / 255, b * 100 / 255); p += strlen(p); } } else if (pu == 1) { /* HLS */ int h, l, s; for (color = 0; color < 256; color++) { vt_get_color_rgba(color, &r, &g, &b, NULL); bl_rgb_to_hls(&h, &l, &s, r, g, b); sprintf(p, "%d;1;%d;%d;%d/", color, h, l, s); p += strlen(p); } } else { return; } strcpy(p - 1, "\x1b\\"); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } #ifndef NO_IMAGE static int cursor_char_is_picture_and_modified(vt_screen_t *screen) { vt_line_t *line; vt_char_t *ch; if ((line = vt_screen_get_cursor_line(screen)) && vt_line_is_modified(line) && (ch = vt_char_at(line, vt_screen_cursor_char_index(screen))) && vt_get_picture_char(ch)) { return 1; } else { return 0; } } /* Don't call this if vt_parser->sixel_scrolling is true. */ static int check_sixel_anim(vt_screen_t *screen, u_char *str, size_t left) { vt_line_t *line; vt_char_t *ch; if ((line = vt_screen_get_line(screen, 0)) && (ch = vt_char_at(line, 0)) && vt_get_picture_char(ch)) { while (--left > 0) { if (*(++str) == '\x1b') { if (--left == 0) { break; } if (*(++str) == 'P') { /* It seems animation sixel. */ return 1; } } } } return 0; } static void show_picture(vt_parser_t *vt_parser, char *file_path, int clip_beg_col, int clip_beg_row, int clip_cols, int clip_rows, int img_cols, int img_rows, int keep_aspect, int is_sixel /* 0: not sixel, 1: sixel, 2: sixel anim, 3: macro */ ) { #ifndef DONT_OPTIMIZE_DRAWING_PICTURE if (is_sixel == 2) { (*vt_parser->xterm_listener->show_tmp_picture)(vt_parser->xterm_listener->self, file_path); vt_parser->yield = 1; return; } #endif /* DONT_OPTIMIZE_DRAWING_PICTURE */ if (HAS_XTERM_LISTENER(vt_parser, get_picture_data)) { vt_char_t *data; #ifdef __DEBUG struct timeval tv1, tv2; gettimeofday(&tv1, NULL); #endif if ((data = (*vt_parser->xterm_listener->get_picture_data)( vt_parser->xterm_listener->self, file_path, &img_cols, &img_rows, NULL, NULL, is_sixel ? &vt_parser->sixel_palette : NULL, keep_aspect, 0)) && clip_beg_row < img_rows && clip_beg_col < img_cols) { vt_char_t *p; int row; int cursor_col; int orig_auto_wrap; #ifdef __DEBUG gettimeofday(&tv2, NULL); bl_debug_printf("Processing sixel time (msec) %lu - %lu = %lu\n", tv2.tv_sec * 1000 + tv2.tv_usec / 1000, tv1.tv_sec * 1000 + tv1.tv_usec / 1000, tv2.tv_sec * 1000 + tv2.tv_usec / 1000 - tv1.tv_sec * 1000 - tv1.tv_usec / 1000); #endif if (clip_cols == 0) { clip_cols = img_cols - clip_beg_col; } if (clip_rows == 0) { clip_rows = img_rows - clip_beg_row; } if (clip_beg_row + clip_rows > img_rows) { clip_rows = img_rows - clip_beg_row; } if (clip_beg_col + clip_cols > img_cols) { clip_cols = img_cols - clip_beg_col; } p = data + (img_cols * clip_beg_row); row = 0; if (is_sixel && !vt_parser->sixel_scrolling) { vt_screen_save_cursor(vt_parser->screen); /* XXX */ vt_parser->is_visible_cursor = 0; vt_screen_goto_home(vt_parser->screen); vt_screen_goto_beg_of_line(vt_parser->screen); } if (cursor_char_is_picture_and_modified(vt_parser->screen)) { /* Perhaps it is animation. */ interrupt_vt100_cmd(vt_parser); vt_parser->yield = 1; } orig_auto_wrap = vt_screen_is_auto_wrap(vt_parser->screen); vt_screen_set_auto_wrap(vt_parser->screen, 0); cursor_col = vt_screen_cursor_logical_col(vt_parser->screen); while (1) { vt_screen_overwrite_chars(vt_parser->screen, p + clip_beg_col, clip_cols); if (++row >= clip_rows) { break; } if (is_sixel && !vt_parser->sixel_scrolling) { if (!vt_screen_go_downward(vt_parser->screen, 1)) { break; } } else { vt_screen_line_feed(vt_parser->screen); } vt_screen_go_horizontally(vt_parser->screen, cursor_col); p += img_cols; } if (is_sixel) { if (vt_parser->sixel_scrolling) { if (!vt_parser->cursor_to_right_of_sixel && /* mlterm always enables DECSET 8452 in status line. */ !vt_status_line_is_focused(vt_parser->screen)) { vt_screen_line_feed(vt_parser->screen); vt_screen_go_horizontally(vt_parser->screen, cursor_col); } } else { vt_screen_restore_cursor(vt_parser->screen); /* XXX */ vt_parser->is_visible_cursor = 1; } } vt_str_destroy(data, img_cols * img_rows); vt_screen_set_auto_wrap(vt_parser->screen, orig_auto_wrap); if (strstr(file_path, "://")) { /* Showing remote image is very heavy. */ vt_parser->yield = 1; } } } } static void define_drcs_picture(vt_parser_t *vt_parser, char *path, ef_charset_t cs, int idx, u_int pix_width /* can be 0 */, u_int pix_height /* can be 0 */, u_int col_width, u_int line_height) { if (HAS_XTERM_LISTENER(vt_parser, get_picture_data)) { vt_char_t *data; int cols = 0; int rows = 0; int cols_small = 0; int rows_small = 0; if (pix_width > 0 && pix_height > 0) { if (old_drcs_sixel) { cols = pix_width / col_width; rows = pix_height / line_height; } else { cols = (pix_width + col_width - 1) / col_width; rows = (pix_height + line_height - 1) / line_height; } } if (idx <= 0x5f && (data = (*vt_parser->xterm_listener->get_picture_data)(vt_parser->xterm_listener->self, path, &cols, &rows, &cols_small, &rows_small, NULL, 0, 1))) { u_int pages; u_int offset = 0; vt_drcs_font_t *font; if (!vt_parser->drcs) { vt_parser->drcs = vt_drcs_new(); } if (!old_drcs_sixel) { cols_small = cols; rows_small = rows; } for (pages = (cols_small * rows_small + 95) / 96; pages > 0; pages--) { font = vt_drcs_get_font(vt_parser->drcs, cs, 1); vt_drcs_add_picture(font, vt_char_picture_id(vt_get_picture_char(data)), offset, idx, cols, rows, cols_small, rows_small); offset += (96 - idx); idx = 0; if (cs == CS94SB_ID(0x7e)) { cs = CS96SB_ID(0x30); } else if (cs == CS96SB_ID(0x7e)) { cs = CS94SB_ID(0x30); } else { cs++; } } vt_str_destroy(data, cols * rows); } } } static int increment_str(u_char **str, size_t *left); static int save_sixel_or_regis(vt_parser_t *vt_parser, char *path, u_char *dcs_beg, u_char **body /* q ... */ , size_t *body_len) { u_char *str_p = *body; size_t left = *body_len; int is_end; FILE *fp; if (left > 2 && *(str_p + 1) == '\0') { fp = fopen(path, "a"); is_end = *(str_p + 2); /* * dcs_beg will equal to str_p after str_p is * incremented by the following increment_str(). */ dcs_beg = (str_p += 2) + 1; left -= 2; } else { char *format; vt_color_t color; u_int8_t red; u_int8_t green; u_int8_t blue; fp = fopen(path, "w"); is_end = 0; if (strcmp(path + strlen(path) - 4, ".rgs") == 0) { /* Clear background by VT_BG_COLOR */ /* 13 + 3*3 + 1 = 23 */ format = "S(I(R%dG%dB%d))S(E)"; color = VT_BG_COLOR; } else if (strcmp(path + strlen(path) - 4, ".six") == 0) { /* * Set VT_FG_COLOR to the default value of the first entry of the sixel palette, * because some sixel graphics data has not palette definitions (#0;2;r;g;b). * '9' is a mark which means that this definition is added by mlterm itself. * (see c_sixel.c) */ /* 7 + 3*3 + 1 = 17 */ format = "#0;9;%d;%d;%d"; color = VT_FG_COLOR; } else { format = NULL; } if (format && HAS_XTERM_LISTENER(vt_parser, get_rgb) && (*vt_parser->xterm_listener->get_rgb)(vt_parser->xterm_listener->self, &red, &green, &blue, color)) { char color_seq[23]; if (color == VT_FG_COLOR) { /* sixel */ red = red * 100 / 255; green = green * 100 / 255; blue = blue * 100 / 255; } fwrite(dcs_beg, 1, str_p - dcs_beg + 1, fp); sprintf(color_seq, format, red, green, blue); fwrite(color_seq, 1, strlen(color_seq), fp); dcs_beg = str_p + 1; } /* * +1 in case str_p[left - vt_parser->r_buf.new_len] * points "\\" of "\x1b\\". */ if (left > vt_parser->r_buf.new_len + 1) { str_p += (left - vt_parser->r_buf.new_len - 1); left = vt_parser->r_buf.new_len + 1; } } while (1) { if (!increment_str(&str_p, &left)) { if (is_end == 2) { left++; break; } if (vt_parser->logging_vt_seq && use_ttyrec_format) { fclose(fp); free(path); *body = str_p; *body_len = left; return 0; } fwrite(dcs_beg, 1, str_p - dcs_beg + 1, fp); vt_parser->r_buf.left = 0; if (!receive_bytes(vt_parser)) { fclose(fp); memcpy(vt_parser->r_buf.chars, strcmp(path + strlen(path) - 4, ".six") == 0 ? "\x1bPq\0" : "\x1bPp\0", 4); free(path); vt_parser->r_buf.chars[4] = is_end; vt_parser->r_buf.filled_len = vt_parser->r_buf.left = 5; /* No more data in pty. */ vt_parser->yield = 1; *body = str_p; *body_len = left; return 0; } dcs_beg = str_p = CURRENT_STR_P(vt_parser); left = vt_parser->r_buf.left; } if (is_end == 2) { u_char *p; p = str_p; /* \x38 == '8' */ if (strncmp(p, "\x1d\x38k @\x1f", 6) == 0) { /* XXX Hack for biplane.six */ p += 6; } if (*p == 0x90 || /* XXX If left == 0 and next char is 'P'... */ (*p == CTL_ESC && left > p - str_p + 1 && *(p + 1) == 'P')) { /* continued ... */ is_end = 0; } else { str_p--; left++; break; } } /* * 0x9c is regarded as ST here, because sixel sequence * unuses it certainly. */ else if (*str_p == 0x9c) { is_end = 2; } else if (*str_p == CTL_ESC) { is_end = 1; } else if (is_end == 1) { if (*str_p == '\\') { is_end = 2; } else { is_end = 0; } } } fwrite(dcs_beg, 1, str_p - dcs_beg + 1, fp); fclose(fp); *body = str_p; *body_len = left; return 1; } static int check_cell_size(vt_parser_t *vt_parser, u_int col_width, u_int line_height) { u_int cw; u_int lh; /* * XXX * This works except vertical mode, but no problem because images are not * supported on vertical mode. */ if (get_cell_size(vt_parser, &cw, &lh) && cw == col_width && lh == line_height) { return 1; } else { return 0; } } #endif static void snapshot(vt_parser_t *vt_parser, vt_char_encoding_t encoding, char *file_name, vt_write_content_area_t area) { char buf[16]; char *path; int fd; ef_conv_t *conv; if (!(path = get_home_file_path(file_name, get_now_suffix(buf), "snp"))) { return; } fd = open(path, O_WRONLY | O_CREAT, 0600); free(path); if (fd == -1) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to open %s\n", file_name); #endif return; } if (encoding == VT_UNKNOWN_ENCODING || (conv = vt_char_encoding_conv_new(encoding)) == NULL) { conv = vt_parser->cc_conv; } vt_screen_write_content(vt_parser->screen, fd, conv, 0, area); if (conv != vt_parser->cc_conv) { (*conv->destroy)(conv); } close(fd); } static void set_col_size_of_width_a(vt_parser_t *vt_parser, u_int col_size_a) { if (col_size_a == 1 || col_size_a == 2) { #ifdef USE_LIBSSH2 /* Don't change it after vt_parser_set_pty() on mosh. See vt_parser_set_pty(). */ if (!vt_parser->pty || vt_pty_get_mode(vt_parser->pty) != PTY_MOSH) #endif { vt_parser->col_size_of_width_a = col_size_a; } } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " col size should be 1 or 2. default value 1 is used.\n"); #endif vt_parser->col_size_of_width_a = 1; } } /* * This function will destroy the content of pt. */ static void config_protocol_set(vt_parser_t *vt_parser, char *pt, int save) { int ret; char *dev; ret = vt_parse_proto_prefix(&dev, &pt, save); if (ret <= 0) { /* * ret == -1: do_challenge failed. * ret == 0: illegal format. * to_menu is necessarily 0 because it is pty that msg should be returned * to. */ vt_response_config(vt_parser->pty, ret < 0 ? "forbidden" : "error", NULL, 0); return; } if (dev && strlen(dev) <= 7 && strstr(dev, "font")) { char *key; char *val; if (vt_parse_proto(NULL, &key, &val, &pt, 0, 0) && val && HAS_CONFIG_LISTENER(vt_parser, set_font)) { /* * Screen is redrawn not in vt_parser->config_listener->set_font * but in stop_vt100_cmd, so it is not necessary to hold * vt_parser->config_listener->set_font between stop_vt100_cmd and * start_vt100_cmd. */ #if 0 stop_vt100_cmd(vt_parser, 0); #endif (*vt_parser->config_listener->set_font)(vt_parser->config_listener->self, dev, key, val, save); #if 0 start_vt100_cmd(vt_parser, 0); #endif } } else if (dev && strcmp(dev, "color") == 0) { char *key; char *val; if (vt_parse_proto(NULL, &key, &val, &pt, 0, 0) && val && HAS_CONFIG_LISTENER(vt_parser, set_color)) { /* * Screen is redrawn not in vt_parser->config_listener->set_color * but in stop_vt100_cmd, so it is not necessary to hold * vt_parser->config_listener->set_font between stop_vt100_cmd and * start_vt100_cmd. */ #if 0 stop_vt100_cmd(vt_parser, 0); #endif (*vt_parser->config_listener->set_color)(vt_parser->config_listener->self, dev, key, val, save); #if 0 start_vt100_cmd(vt_parser, 0); #endif } } else { stop_vt100_cmd(vt_parser, 0); if ((!HAS_CONFIG_LISTENER(vt_parser, exec) || !(*vt_parser->config_listener->exec)(vt_parser->config_listener->self, pt))) { bl_conf_write_t *conf; if (save) { char *path; /* XXX */ if ((path = bl_get_user_rc_path("mlterm/main")) == NULL) { return; } conf = bl_conf_write_open(path); free(path); } else { conf = NULL; } /* accept multiple key=value pairs. */ while (pt) { char *key; char *val; if (!vt_parse_proto(dev ? NULL : &dev, &key, &val, &pt, 0, 1)) { break; } if (conf) { /* XXX */ if (strcmp(key, "xim") != 0) { bl_conf_io_write(conf, key, val); } } if (val == NULL) { val = ""; } if (HAS_CONFIG_LISTENER(vt_parser, set) && (*vt_parser->config_listener->set)(vt_parser->config_listener->self, dev, key, val)) { if (!vt_parser->config_listener) { /* pty changed. */ break; } } dev = NULL; } if (conf) { bl_conf_write_close(conf); if (HAS_CONFIG_LISTENER(vt_parser, saved)) { (*vt_parser->config_listener->saved)(); } } } start_vt100_cmd(vt_parser, 0); } } static void config_protocol_set_simple(vt_parser_t *vt_parser, char *key, char *val, int visualize) { if (HAS_CONFIG_LISTENER(vt_parser, set)) { if (visualize) { stop_vt100_cmd(vt_parser, 0); } (*vt_parser->config_listener->set)(vt_parser->config_listener->self, NULL, key, val); if (visualize) { start_vt100_cmd(vt_parser, 0); } } } /* * This function will destroy the content of pt. */ static void config_protocol_get(vt_parser_t *vt_parser, char *pt, int to_menu, int *flag) { char *dev; char *key; int ret; if (to_menu == 0 && strchr(pt, ';') == NULL) { /* pt doesn't have challenge */ to_menu = -1; stop_vt100_cmd(vt_parser, 0); } #if 0 else { /* * It is assumed that screen is not redrawn not in * vt_parser->config_listener->get, so vt_parser->config_listener->get * is not held between stop_vt100_cmd and start_vt100_cmd. */ stop_vt100_cmd(vt_parser, 0); } #endif ret = vt_parse_proto(&dev, &key, NULL, &pt, to_menu == 0, 0); if (ret <= 0) { /* * ret == -1: do_challenge failed. * ret == 0: illegal format. * to_menu is necessarily 0 because it is pty that msg should be returned * to. */ vt_response_config(vt_parser->pty, ret < 0 ? "forbidden" : "error", NULL, 0); goto end; } if (dev && strlen(dev) <= 7 && strstr(dev, "font")) { char *cs; /* Compat with old format (3.6.3 or before): , */ cs = bl_str_sep(&key, ","); if (HAS_CONFIG_LISTENER(vt_parser, get_font)) { (*vt_parser->config_listener->get_font)(vt_parser->config_listener->self, dev, cs, to_menu); } } else if (dev && strcmp(dev, "color") == 0) { if (HAS_CONFIG_LISTENER(vt_parser, get_color)) { (*vt_parser->config_listener->get_color)(vt_parser->config_listener->self, key, to_menu); } } else if (HAS_CONFIG_LISTENER(vt_parser, get)) { (*vt_parser->config_listener->get)(vt_parser->config_listener->self, dev, key, to_menu); } end: if (to_menu == -1) { start_vt100_cmd(vt_parser, 0); } #if 0 else { start_vt100_cmd(vt_parser, 0); } #endif } #ifdef SUPPORT_ITERM2_OSC1337 #include /* bl_basename */ /* * This function will destroy the content of pt. */ static void iterm2_proprietary_set(vt_parser_t *vt_parser, char *pt) { if (strncmp(pt, "File=", 5) == 0) { /* See http://www.iterm2.com/images.html (2014/03/20) */ char *args; char *encoded; char *decoded; size_t e_len; u_int width; u_int height; char *path; int keep_aspect; args = pt + 5; width = height = 0; keep_aspect = 1; /* default value is 1. */ if ((encoded = strchr(args, ':'))) { char *beg; char *end; *(encoded++) = '\0'; if ((beg = strstr(args, "name=")) && ((end = strchr((beg += 5), ';')) || (end = beg + strlen(beg))) && (path = malloc(7 + (end - beg) + 1))) { char *file; char *new_path; size_t d_len; strcpy(path, "mlterm/"); d_len = bl_base64_decode(path + 7, beg, end - beg); path[7 + d_len] = '\0'; file = bl_basename(path); memmove(path + 7, file, strlen(file) + 1); new_path = bl_get_user_rc_path(path); free(path); path = new_path; } else { path = get_home_file_path("", vt_pty_get_slave_name(vt_parser->pty) + 5, "img"); } if ((beg = strstr(args, "width=")) && ((end = strchr((beg += 6), ';')) || (end = beg + strlen(beg)))) { *(end--) = '\0'; if ('0' <= *end && *end <= '9') { width = atoi(beg); } else if (*end == '%') { /* XXX vertical mode is not considered */ width = atoi(beg) * vt_screen_get_logical_cols(vt_parser->screen) / 100; } else { /* XXX Npx is not supported */ } *(end + 1) = ';'; /* For next strstr() */ } if ((beg = strstr(args, "height=")) && ((end = strchr((beg += 7), ';')) || (end = beg + strlen(beg)))) { *(end--) = '\0'; if ('0' <= *end && *end <= '9') { height = atoi(beg); } else if (*end == '%') { /* XXX vertical mode is not considered */ height = atoi(beg) * vt_screen_get_logical_rows(vt_parser->screen) / 100; } else { /* XXX Npx is not supported */ } /* *(end + 1) = ';'; */ } if ((beg = strstr(args, "preserveAspectRatio=")) && beg[20] == '0') { keep_aspect = 0; } } else { path = get_home_file_path("", vt_pty_get_slave_name(vt_parser->pty) + 5, "img"); } if (!path) { return; } #ifdef DEBUG else { bl_debug_printf(BL_DEBUG_TAG " OSC 1337 file is stored at %s.\n", path); } #endif if ((e_len = strlen(encoded)) > 0 && (decoded = malloc(e_len))) { size_t d_len; FILE *fp; if ((d_len = bl_base64_decode(decoded, encoded, e_len)) > 0 && (fp = fopen(path, "w"))) { fwrite(decoded, 1, d_len, fp); fclose(fp); show_picture(vt_parser, path, 0, 0, 0, 0, width, height, keep_aspect, 0); remove(path); } free(decoded); } free(path); } } #endif static int change_char_fine_color(vt_parser_t *vt_parser, int *ps, int num) { int proceed; vt_color_t color; if (ps[0] != 38 && ps[0] != 48) { return 0; } if (num >= 3 && ps[1] == 5) { proceed = 3; color = (ps[2] <= 0 ? 0 : ps[2]); } else if (num >= 5 && ps[1] == 2) { proceed = 5; color = vt_get_closest_color(ps[2] <= 0 ? 0 : ps[2], ps[3] <= 0 ? 0 : ps[3], ps[4] <= 0 ? 0 : ps[4]); } else { return 1; } if (vt_parser->use_ansi_colors) { if (ps[0] == 38) { vt_parser->fg_color = color; vt_screen_set_bce_fg_color(vt_parser->screen, color); } else /* if( ps[0] == 48) */ { vt_parser->bg_color = color; vt_screen_set_bce_bg_color(vt_parser->screen, color); } } return proceed; } static void change_char_attr(vt_parser_t *vt_parser, int flag) { vt_color_t fg_color; vt_color_t bg_color; fg_color = vt_parser->fg_color; bg_color = vt_parser->bg_color; if (flag == 0) { /* Normal */ fg_color = VT_FG_COLOR; bg_color = VT_BG_COLOR; vt_parser->is_bold = 0; vt_parser->is_italic = 0; vt_parser->line_style = 0; vt_parser->is_reversed = 0; vt_parser->is_blinking = 0; vt_parser->is_invisible = 0; } else if (flag == 1) { /* Bold */ vt_parser->is_bold = 1; } else if (flag == 2) { /* XXX Faint */ vt_parser->is_bold = 0; } else if (flag == 3) { /* Italic */ vt_parser->is_italic = 1; } else if (flag == 4) { /* Underscore */ vt_parser->line_style = (vt_parser->line_style & ~LS_UNDERLINE) | LS_UNDERLINE_SINGLE; } else if (flag == 5 || flag == 6) { /* Blink (6 is repidly blinking) */ vt_parser->is_blinking = 1; vt_screen_enable_blinking(vt_parser->screen); } else if (flag == 7) { /* Inverse */ vt_parser->is_reversed = 1; } else if (flag == 8) { vt_parser->is_invisible = 1; } else if (flag == 9) { vt_parser->line_style |= LS_CROSSED_OUT; } else if (flag == 21) { /* Double underscore */ vt_parser->line_style = (vt_parser->line_style & ~LS_UNDERLINE) | LS_UNDERLINE_DOUBLE; } else if (flag == 22) { /* Bold */ vt_parser->is_bold = 0; } else if (flag == 23) { /* Italic */ vt_parser->is_italic = 0; } else if (flag == 24) { /* Underline */ vt_parser->line_style &= ~LS_UNDERLINE; } else if (flag == 25) { /* blink */ vt_parser->is_blinking = 0; } else if (flag == 27) { vt_parser->is_reversed = 0; } else if (flag == 28) { vt_parser->is_invisible = 0; } else if (flag == 29) { vt_parser->line_style &= ~LS_CROSSED_OUT; } else if (flag == 39) { /* default fg */ fg_color = VT_FG_COLOR; } else if (flag == 49) { bg_color = VT_BG_COLOR; } else if (flag == 53) { vt_parser->line_style |= LS_OVERLINE; } else if (flag == 55) { vt_parser->line_style &= ~LS_OVERLINE; } else if (vt_parser->use_ansi_colors) { /* Color attributes */ if (30 <= flag && flag <= 37) { /* 30=VT_BLACK(0) ... 37=VT_WHITE(7) */ fg_color = flag - 30; } else if (40 <= flag && flag <= 47) { /* 40=VT_BLACK(0) ... 47=VT_WHITE(7) */ bg_color = flag - 40; } else if (90 <= flag && flag <= 97) { fg_color = (flag - 90) | VT_BOLD_COLOR_MASK; } else if (100 <= flag && flag <= 107) { bg_color = (flag - 100) | VT_BOLD_COLOR_MASK; } #ifdef DEBUG else { bl_warn_printf(BL_DEBUG_TAG " unknown char attr flag(%d).\n", flag); } #endif } if (fg_color != vt_parser->fg_color) { vt_parser->fg_color = fg_color; vt_screen_set_bce_fg_color(vt_parser->screen, fg_color); } if (bg_color != vt_parser->bg_color) { vt_parser->bg_color = bg_color; vt_screen_set_bce_bg_color(vt_parser->screen, bg_color); } } static void get_rgb(vt_parser_t *vt_parser, vt_color_t color) { u_int8_t red; u_int8_t green; u_int8_t blue; int ret; if (IS_ALT_COLOR(color)) { ret = (HAS_XTERM_LISTENER(vt_parser, get_rgb) && (*vt_parser->xterm_listener->get_rgb)(vt_parser->xterm_listener->self, &red, &green, &blue, color)); color = color + 0x100 - VT_BOLD_COLOR; } else { ret = vt_get_color_rgba(color, &red, &green, &blue, NULL); } if (ret) { char seq[4 + DIGIT_STR_LEN(int) + 1 + 18 + 2 + 1]; sprintf(seq, "\x1b]4;%d;rgb:%.2x%.2x/%.2x%.2x/%.2x%.2x\x1b\\", color, red, red, green, green, blue, blue); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } } static void get_fgbg_rgb(vt_parser_t *vt_parser, int ps /* 10, 11 */) { u_int8_t red; u_int8_t green; u_int8_t blue; if (HAS_XTERM_LISTENER(vt_parser, get_rgb) && (*vt_parser->xterm_listener->get_rgb)(vt_parser->xterm_listener->self, &red, &green, &blue, ps == 10 ? VT_FG_COLOR : VT_BG_COLOR)) { char seq[2 + DIGIT_STR_LEN(int) + 1 + 18 + 2 + 1]; sprintf(seq, "\x1b]%d;rgb:%.2x%.2x/%.2x%.2x/%.2x%.2x\x1b\\", ps, red, red, green, green, blue, blue); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } } /* * This function will destroy the content of pt. */ static void change_color_rgb(vt_parser_t *vt_parser, u_char *pt) { char *p; while ((p = strchr(pt, ';'))) { char *next; if ((next = strchr(p + 1, ';'))) { *(next++) = '\0'; } if (strcmp(p + 1, "?") == 0) { vt_color_t color; *p = '\0'; if ((color = vt_get_color(pt)) != VT_UNKNOWN_COLOR) { get_rgb(vt_parser, color); } } else { *p = '='; if ((p = alloca(6 + strlen(pt) + 1))) { sprintf(p, "color:%s", pt); config_protocol_set(vt_parser, p, 0); } } if (!next) { break; } pt = next; } } static char *get_special_color_name(const char c /* '0' - '4' */) { if (c == '0') { return "bd_color"; } else if (c == '1') { return "ul_color"; } else if (c == '2') { return "bl_color"; } else if (c == '3') { return "rv_color"; /* XXX Not supported for now */ } else /* if (c == '4') */ { return "it_color"; } } static void change_special_color(vt_parser_t *vt_parser, u_char *pt) { char *p; while ((p = strchr(pt, ';'))) { char *next; if ((next = strchr(p + 1, ';'))) { *(next++) = '\0'; } if ('0' <= *pt && *pt <= '4') { if (strcmp(p + 1, "?") == 0) { get_rgb(vt_parser, *pt - '0' + VT_BOLD_COLOR); } else { config_protocol_set_simple(vt_parser, get_special_color_name(*pt), p + 1, 0); } } if (!next) { break; } pt = next; } } static void change_fgbg_color(vt_parser_t *vt_parser, int ps /* 10, 11 */, u_char *pt) { while (1) { char *next; if ((next = strchr(pt, ';'))) { *(next++) = '\0'; } if (10 <= ps && ps <= 11) { if (strcmp(pt, "?") == 0) { get_fgbg_rgb(vt_parser, ps); } else { char *key; if (ps == 10) { key = "fg_color"; } else /* if (ps == 11) */ { key = "bg_color"; } config_protocol_set_simple(vt_parser, key, pt, 0); } } if (!next) { break; } pt = next; ps ++; } } static void reset_color_rgb(vt_parser_t *vt_parser, u_char *pt, int is_spcolor) { u_char *p; char seq[11]; int color; if (*pt == '\0') { if (is_spcolor) { for (color = '0'; color <= '4'; color++) { config_protocol_set_simple(vt_parser, get_special_color_name(color), "", 0); } } else { for (color = 0; color < 256; color++) { sprintf(seq, "color:%d=", color); config_protocol_set(vt_parser, seq, 0); } } } else { while ((p = bl_str_sep(&pt, ";"))) { if (is_spcolor) { if ('0' <= *p && *p <= '4') { config_protocol_set_simple(vt_parser, get_special_color_name(*p), "", 0); } } else { color = atoi(p); sprintf(seq, "color:%d=", color); config_protocol_set(vt_parser, seq, 0); } } } } static void set_selection(vt_parser_t *vt_parser, u_char *encoded) { if (HAS_XTERM_LISTENER(vt_parser, set_selection)) { u_char *p; u_char *targets; size_t e_len; size_t d_len; u_char *decoded; ef_char_t ch; vt_char_t *str; u_int str_len; if ((p = strchr(encoded, ';'))) { *p = '\0'; targets = encoded; encoded = p + 1; } else { targets = "s0"; } if ((e_len = strlen(encoded)) < 4 || !(decoded = alloca(e_len)) || (d_len = bl_base64_decode(decoded, encoded, e_len)) == 0 || !(str = vt_str_new(d_len))) { return; } str_len = 0; (*vt_parser->cc_parser->set_str)(vt_parser->cc_parser, decoded, d_len); while ((*vt_parser->cc_parser->next_char)(vt_parser->cc_parser, &ch)) { vt_char_set(&str[str_len++], ef_char_to_int(&ch), ch.cs, 0, 0, 0, 0, 0, 0, 0, 0, 0); } /* * It is assumed that screen is not redrawn not in * vt_parser->config_listener->get, so vt_parser->config_listener->get * is not held between stop_vt100_cmd and start_vt100_cmd. */ #if 0 stop_vt100_cmd(vt_parser, 0); #endif (*vt_parser->xterm_listener->set_selection)(vt_parser->xterm_listener->self, str, str_len, targets); #if 0 start_vt100_cmd(vt_parser, 0); #endif } } static void destroy_macro(vt_parser_t *vt_parser, int id /* should be less than vt_parser->num_macros */ ) { if (vt_parser->macros[id].is_sixel) { unlink(vt_parser->macros[id].str); vt_parser->macros[id].is_sixel = 0; vt_parser->macros[id].sixel_num++; } free(vt_parser->macros[id].str); vt_parser->macros[id].str = NULL; } static void destroy_all_macros(vt_parser_t *vt_parser) { u_int count; for (count = 0; count < vt_parser->num_macros; count++) { destroy_macro(vt_parser, count); } free(vt_parser->macros); vt_parser->macros = NULL; vt_parser->num_macros = 0; } static u_char *hex_to_text(u_char *hex) { u_char *text; u_char *p; size_t len; size_t count; int rep_count; u_char *rep_beg; int d[2]; int sub_count; len = strlen(hex) / 2 + 1; if (!(text = malloc(len))) { return NULL; } count = 0; rep_count = 1; rep_beg = NULL; sub_count = 0; /* Don't use sscanf() here because it works too slow. */ while (1) { if ('0' <= *hex && *hex <= '9') { d[sub_count++] = *hex - '0'; } else { u_char masked_hex; masked_hex = (*hex) & 0xcf; if ('A' <= masked_hex && masked_hex <= 'F') { d[sub_count++] = masked_hex - 'A' + 10; } else { sub_count = 0; if (*hex == '!') { rep_beg = NULL; if ((p = strchr(hex + 1, ';'))) { *p = '\0'; if ((rep_count = atoi(hex + 1)) > 1) { rep_beg = text + count; } hex = p; } } else if (*hex == ';' || *hex == '\0') { if (rep_beg) { size_t rep_len; if ((rep_len = text + count - rep_beg) > 0) { len += rep_len * (rep_count - 1); if (!(p = realloc(text, len))) { free(text); return NULL; } rep_beg += (p - text); text = p; while (--rep_count > 0) { strncpy(text + count, rep_beg, rep_len); count += rep_len; } } rep_beg = NULL; } if (*hex == '\0') { goto end; } } } } if (sub_count == 2) { text[count++] = (d[0] << 4) + d[1]; sub_count = 0; } hex++; } end: text[count] = '\0'; return text; } #define MAX_NUM_OF_MACRO 1024 #define MAX_DIGIT_OF_MACRO 4 static void define_macro(vt_parser_t *vt_parser, u_char *param, u_char *data) { u_char *p; int ps[3] = {0, 0, 0}; int num; p = param; num = 0; for (p = param; *p != 'z'; p++) { if ((*p == ';' || *p == '!') && num < 3) { *p = '\0'; ps[num++] = atoi(param); param = p + 1; } } if (ps[0] >= MAX_NUM_OF_MACRO) { return; } if (ps[1] == 1) { destroy_all_macros(vt_parser); } if (ps[0] >= vt_parser->num_macros) { void *p; if (*data == '\0' || !(p = realloc(vt_parser->macros, (ps[0] + 1) * sizeof(*vt_parser->macros)))) { return; } memset(p + vt_parser->num_macros * sizeof(*vt_parser->macros), 0, (ps[0] + 1 - vt_parser->num_macros) * sizeof(*vt_parser->macros)); vt_parser->macros = p; vt_parser->num_macros = ps[0] + 1; } else { destroy_macro(vt_parser, ps[0]); if (*data == '\0') { return; } } if (ps[2] == 1) { p = vt_parser->macros[ps[0]].str = hex_to_text(data); #ifndef NO_IMAGE if (p && (*p == 0x90 || (*(p++) == '\x1b' && *p == 'P'))) { for (p++; *p == ';' || ('0' <= *p && *p <= '9'); p++) ; if (*p == 'q' && (strrchr(p, 0x9c) || ((p = strrchr(p, '\\')) && *(p - 1) == '\x1b'))) { char prefix[5 + MAX_DIGIT_OF_MACRO + 1 + DIGIT_STR_LEN(vt_parser->macros[0].sixel_num) + 2]; char *path; sprintf(prefix, "macro%d_%d_", ps[0], vt_parser->macros[ps[0]].sixel_num); if ((path = get_home_file_path(prefix, vt_pty_get_slave_name(vt_parser->pty) + 5, "six"))) { FILE *fp; if ((fp = fopen(path, "w"))) { fwrite(vt_parser->macros[ps[0]].str, 1, strlen(vt_parser->macros[ps[0]].str), fp); fclose(fp); free(vt_parser->macros[ps[0]].str); vt_parser->macros[ps[0]].str = path; vt_parser->macros[ps[0]].is_sixel = 1; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Register %s to macro %d\n", path, ps[0]); #endif } } } } #endif } else { vt_parser->macros[ps[0]].str = strdup(data); } } static int write_loopback(vt_parser_t *vt_parser, const u_char *buf, size_t len, int enable_local_echo, int is_visual); static void invoke_macro(vt_parser_t *vt_parser, int id) { if (id < vt_parser->num_macros && vt_parser->macros[id].str) { #ifndef NO_IMAGE if (vt_parser->macros[id].is_sixel) { show_picture(vt_parser, vt_parser->macros[id].str, 0, 0, 0, 0, 0, 0, 0, 3); } else #endif { write_loopback(vt_parser, vt_parser->macros[id].str, strlen(vt_parser->macros[id].str), 0, 0); } } } static int response_termcap(vt_pty_t *pty, u_char *key, u_char *value) { u_char *response; if ((response = alloca(5 + strlen(key) + 1 + strlen(value) * 2 + 3))) { u_char *dst; sprintf(response, "\x1bP1+r%s=", key); for (dst = response + strlen(response); *value; value++, dst += 2) { dst[0] = (value[0] >> 4) & 0xf; dst[0] = (dst[0] > 9) ? (dst[0] + 'A' - 10) : (dst[0] + '0'); dst[1] = value[0] & 0xf; dst[1] = (dst[1] > 9) ? (dst[1] + 'A' - 10) : (dst[1] + '0'); } strcpy(dst, "\x1b\\"); vt_write_to_pty(pty, response, strlen(response)); return 1; } else { return 0; } } #define TO_INT(a) (((a) | 0x20) - ((a) <= '9' ? '0' : ('a' - 10))) static void report_termcap(vt_parser_t *vt_parser, u_char *key) { u_char *deckey; u_char *src; u_char *dst; if ((deckey = alloca(strlen(key) / 2 + 1))) { struct { u_char *tckey; u_char *tikey; int16_t spkey; /* vt_special_key_t */ int16_t modcode; } db[] = { {"%1", "khlp", SPKEY_F15, 0}, {"#1", "kHLP", SPKEY_F15, 2}, {"@0", "kfnd", SPKEY_FIND, 0}, {"*0", "kFND", SPKEY_FIND, 2}, {"*6", "kslt", SPKEY_SELECT, 0}, {"#6", "kSLT", SPKEY_SELECT, 2}, {"kh", "khome", SPKEY_HOME, 0}, {"#2", "kHOM", SPKEY_HOME, 2}, {"@7", "kend", SPKEY_END, 0}, {"*7", "kEND", SPKEY_END, 2}, {"kl", "kcub1", SPKEY_LEFT, 0}, {"kr", "kcuf1", SPKEY_RIGHT, 0}, {"ku", "kcuu1", SPKEY_UP, 0}, {"kd", "kcud1", SPKEY_DOWN, 0}, {"#4", "kLFT", SPKEY_LEFT, 2}, {"%i", "kRIT", SPKEY_RIGHT, 2}, {"kF", "kind", SPKEY_DOWN, 2}, {"kR", "kri", SPKEY_UP, 2}, {"k1", "kf1", SPKEY_F1, 0}, {"k2", "kf2", SPKEY_F2, 0}, {"k3", "kf3", SPKEY_F3, 0}, {"k4", "kf4", SPKEY_F4, 0}, {"k5", "kf5", SPKEY_F5, 0}, {"k6", "kf6", SPKEY_F6, 0}, {"k7", "kf7", SPKEY_F7, 0}, {"k8", "kf8", SPKEY_F8, 0}, {"k9", "kf9", SPKEY_F9, 0}, {"k;", "kf10", SPKEY_F10, 0}, {"F1", "kf11", SPKEY_F11, 0}, {"F2", "kf12", SPKEY_F12, 0}, {"F3", "kf13", SPKEY_F13, 0}, {"F4", "kf14", SPKEY_F14, 0}, {"F5", "kf15", SPKEY_F15, 0}, {"F6", "kf16", SPKEY_F16, 0}, {"F7", "kf17", SPKEY_F17, 0}, {"F8", "kf18", SPKEY_F18, 0}, {"F9", "kf19", SPKEY_F19, 0}, {"FA", "kf20", SPKEY_F20, 0}, {"FB", "kf21", SPKEY_F21, 0}, {"FC", "kf22", SPKEY_F22, 0}, {"FD", "kf23", SPKEY_F23, 0}, {"FE", "kf24", SPKEY_F24, 0}, {"FF", "kf25", SPKEY_F25, 0}, {"FG", "kf26", SPKEY_F26, 0}, {"FH", "kf27", SPKEY_F27, 0}, {"FI", "kf28", SPKEY_F28, 0}, {"FJ", "kf29", SPKEY_F29, 0}, {"FK", "kf30", SPKEY_F30, 0}, {"FL", "kf31", SPKEY_F31, 0}, {"FM", "kf32", SPKEY_F32, 0}, {"FN", "kf33", SPKEY_F33, 0}, {"FO", "kf34", SPKEY_F34, 0}, {"FP", "kf35", SPKEY_F35, 0}, {"FQ", "kf36", SPKEY_F36, 0}, {"FR", "kf37", SPKEY_F37, 0}, {"K1", "ka1", SPKEY_KP_HOME, 0}, {"K4", "kc1", SPKEY_KP_END, 0}, {"K3", "ka3", SPKEY_KP_PRIOR, 0}, {"K5", "kc3", SPKEY_KP_NEXT, 0}, {"kB", "kcbt", SPKEY_ISO_LEFT_TAB, 0}, /* { "kC" , "kclr" , SPKEY_CLEAR , 0 } , */ {"kD", "kdch1", SPKEY_DELETE, 0}, {"kI", "kich1", SPKEY_INSERT, 0}, {"kN", "knp", SPKEY_NEXT, 0}, {"kP", "kpp", SPKEY_PRIOR, 0}, {"%c", "kNXT", SPKEY_NEXT, 2}, {"%e", "kPRV", SPKEY_PRIOR, 2}, /* { "&8" , "kund" , SPKEY_UNDO , 0 } , */ {"kb", "kbs", SPKEY_BACKSPACE, 0}, {"Co", "colors", -1, 0}, {"TN", "name", -2, 0}, }; int idx; u_char *value; for (src = key, dst = deckey; src[0] && src[1]; src += 2) { *(dst++) = TO_INT(src[0]) * 16 + TO_INT(src[1]); } *dst = '\0'; value = NULL; for (idx = 0; idx < sizeof(db) / sizeof(db[0]); idx++) { if (strcmp(deckey, db[idx].tckey) == 0 || strcmp(deckey, db[idx].tikey) == 0) { if (db[idx].spkey == -1) { value = "256"; } else if (db[idx].spkey == -2) { value = "mlterm"; } else { value = vt_termcap_special_key_to_seq( vt_parser->termcap, db[idx].spkey, db[idx].modcode, /* vt_parser->is_app_keypad */ 0, vt_parser->is_app_cursor_keys, /* vt_parser->is_app_escape */ 0, vt_parser->modify_cursor_keys, vt_parser->modify_function_keys); } break; } } if (value && response_termcap(vt_parser->pty, key, value)) { return; } } vt_write_to_pty(vt_parser->pty, "\x1bP0+r\x1b\\", 7); } static void report_char_attr_status(vt_parser_t *vt_parser) { char color[10]; /* ";38;5;XXX" (256 color) */ vt_write_to_pty(vt_parser->pty, "\x1bP1$r0", 6); if (vt_parser->is_bold) { vt_write_to_pty(vt_parser->pty, ";1", 2); } if (vt_parser->is_italic) { vt_write_to_pty(vt_parser->pty, ";3", 2); } if (vt_parser->line_style & LS_UNDERLINE_SINGLE) { vt_write_to_pty(vt_parser->pty, ";4", 2); } if (vt_parser->is_blinking) { vt_write_to_pty(vt_parser->pty, ";5", 2); } if (vt_parser->is_reversed) { vt_write_to_pty(vt_parser->pty, ";7", 2); } if (vt_parser->is_invisible) { vt_write_to_pty(vt_parser->pty, ":8", 2); } if (vt_parser->line_style & LS_CROSSED_OUT) { vt_write_to_pty(vt_parser->pty, ";9", 2); } if (vt_parser->line_style & LS_UNDERLINE_DOUBLE) { vt_write_to_pty(vt_parser->pty, ";21", 3); } if (vt_parser->line_style & LS_OVERLINE) { vt_write_to_pty(vt_parser->pty, ":53", 3); } color[0] = ';'; if (IS_VTSYS_BASE_COLOR(vt_parser->fg_color)) { color[1] = '3'; color[2] = '0' + vt_parser->fg_color; } else if (IS_VTSYS_COLOR(vt_parser->fg_color)) { color[1] = '9'; color[2] = '0' + (vt_parser->fg_color - 8); } else if (IS_VTSYS256_COLOR(vt_parser->fg_color)) { sprintf(color + 1, "38;5;%d", vt_parser->fg_color); } else { goto bg_color; } vt_write_to_pty(vt_parser->pty, color, strlen(color)); bg_color: if (IS_VTSYS_BASE_COLOR(vt_parser->bg_color)) { color[1] = '4'; color[2] = '0' + vt_parser->bg_color; } else if (IS_VTSYS_COLOR(vt_parser->bg_color)) { color[1] = '1'; color[2] = '0'; color[3] = '0' + (vt_parser->bg_color - 8); } else if (IS_VTSYS256_COLOR(vt_parser->bg_color)) { sprintf(color, ";48;5;%d", vt_parser->bg_color); } else { goto end; } vt_write_to_pty(vt_parser->pty, color, strlen(color)); end: vt_write_to_pty(vt_parser->pty, "m\x1b\\", 3); } static void report_status(vt_parser_t *vt_parser, u_char *key) { u_char *val; u_char digits[DIGIT_STR_LEN(int)*3 + 3]; u_char *seq; if (strcmp(key, "\"q") == 0) { /* DECSCA */ val = vt_parser->is_protected ? "1" : "0"; /* Both 0 and 2 => is_protected = 0 */ } else if (strcmp(key, "\"p") == 0) { /* DECSCL */ val = "63;1"; } else if (strcmp(key, "r") == 0) { /* DECSTBM */ val = digits; sprintf(val, "%d;%d", vt_parser->screen->edit->vmargin_beg + 1, vt_parser->screen->edit->vmargin_end + 1); } else if (strcmp(key, "s") == 0) { /* DECSLRM */ val = digits; sprintf(val, "%d;%d", vt_parser->screen->edit->hmargin_beg + 1, vt_parser->screen->edit->hmargin_end + 1); } else if (strcmp(key, " q") == 0) { /* DECSCUR */ char vals[] = {'2', '4', '6', '\0', '1', '3', '5'}; digits[0] = vals[vt_parser->cursor_style]; digits[1] = '\0'; val = digits; } else if (strcmp(key, "$}") == 0) { /* DECSASD */ val = vt_status_line_is_focused(vt_parser->screen) ? "1" : "0"; } else if (strcmp(key, "$~") == 0) { /* DECSSDT */ val = vt_screen_has_status_line(vt_parser->screen) ? "2" : "0"; } else if (strcmp(key, "*x") == 0) { /* DECSACE */ val = vt_screen_is_using_rect_attr_select(vt_parser->screen) ? "2" : "1"; } else if (strcmp(key, "){") == 0) { /* DECSTGLT */ if (vt_parser->use_ansi_colors) { val = "0"; } else if (vt_parser->alt_colors.flags) { val = "1"; } else { val = "2"; } } else if (strcmp(key, "$|") == 0) { /* DECSCPP */ val = digits; sprintf(val, "%d", vt_screen_get_logical_cols(vt_parser->screen)); } else if (strcmp(key, "t") == 0 || strcmp(key, "*|") == 0) { /* DECSLPP/DECSNLS */ val = digits; sprintf(val, "%d", vt_screen_get_logical_rows(vt_parser->screen)); } else if (strcmp(key, "m") == 0) { /* SGR */ report_char_attr_status(vt_parser); return; } else { u_int ps = atoi(key); key += (strlen(key) - 2); if (strcmp(key, ",|") == 0) { /* DECAC */ u_int8_t red; u_int8_t green; u_int8_t blue; vt_color_t colors[] = { VT_FG_COLOR, VT_BG_COLOR } ; u_int count; if (ps == 2) { /* Window Frame */ goto error_validreq; } vt_color_force_linear_search(1); for (count = 0; count < sizeof(colors) / sizeof(colors[0]); count++) { if (!HAS_XTERM_LISTENER(vt_parser, get_rgb) || !(*vt_parser->xterm_listener->get_rgb)(vt_parser->xterm_listener->self, &red, &green, &blue, colors[count])) { goto error_validreq; } colors[count] = vt_get_closest_color(red, green, blue); } vt_color_force_linear_search(0); val = digits; sprintf(val, "1;%d;%d", colors[0], colors[1]); } else if (strcmp(key, ",}") == 0) { /* DECATC */ int idx; if (ps <= 15 && (vt_parser->alt_colors.flags & (1 << (idx = alt_color_idxs[ps])))) { val = digits; sprintf(val, "%d;%d;%d", ps, vt_parser->alt_colors.fg[idx], vt_parser->alt_colors.bg[idx]); } else { goto error_validreq; } } else { goto error_invalidreq; } } /* * XXX * xterm returns 1 for vaild request while 0 for invalid request. * VT520/525 manual says 0 for vaild request while 1 for invalid request, * but it's wrong. (http://twitter.com/ttdoda/status/911125737242992645) */ if ((seq = alloca(7 + strlen(val) + strlen(key) + 1))) { sprintf(seq, "\x1bP1$r%s%s\x1b\\", val, key); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } return; error_validreq: vt_write_to_pty(vt_parser->pty, "\x1bP1$r\x1b\\", 7); return; error_invalidreq: vt_write_to_pty(vt_parser->pty, "\x1bP0$r\x1b\\", 7); } static void clear_line_all(vt_parser_t *vt_parser) { vt_screen_clear_line_to_left(vt_parser->screen); vt_screen_clear_line_to_right(vt_parser->screen); } static void clear_display_all(vt_parser_t *vt_parser) { vt_screen_clear_below(vt_parser->screen); vt_screen_clear_above(vt_parser->screen); vt_screen_clear_size_attr(vt_parser->screen); } static int vtmode_num_to_idx(int mode) { int idx; for (idx = 0; idx < VTMODE_NUM; idx++) { if (vtmodes[idx] == mode) { return idx; } } return -1; } static int get_vtmode(vt_parser_t *vt_parser, int mode) { int idx; /* XXX These can be changed via OSC 5379 instead of DEC Private Mode Set. */ if (mode == 8428) { return (vt_parser->col_size_of_width_a == 1) ? 1 : 2; } else if (mode == 117) { return vt_screen_is_using_bce(vt_parser->screen) ? 1 : 2; } else if (mode == VTMODE(33)) { return (vt_parser->cursor_style & CS_BLINK) ? 2 : 1; } else /* XXX DECBKM affects *all* terms sharing vt_termcap, so vtmode_flags is not reliable. */ if (mode == 67) { return strcmp(vt_termcap_special_key_to_seq(vt_parser->termcap, SPKEY_BACKSPACE, 0, 0, 0, 0, 0, 0), "\x08") == 0 ? 1 : 2; } if ((idx = vtmode_num_to_idx(mode)) != -1) { if (vt_parser->vtmode_flags & (SHIFT_FLAG64(idx))) { return 1; /* set */ } else { return 2; /* reset */ } } if (mode == 8 /* DECARM (auto repeat) */ || mode == 64 /* DECPCCM (page cursor-coupling mode) */ || mode == 98 /* DECARSM (change lines per screen automatically by DECSLPP) */ || mode == 102 /* DECNULM (always dicard NUL character) */ || mode == 114 /* DECATCUM (alternate text color underline mode) */ || mode == 115 /* DECATCBM (alternate text color blink mode) */ || mode == 19 /* DECPEX (Ignore DECSTBM in MC and DECMC) */) { return 3; /* permanently set */ } else if (mode == 4 /* DECSCLM (smooth scroll) */ || mode == 9 /* X10 mouse report */ || mode == 38 /* Tek */ || mode == 45 /* reverse wraparound */ || mode == 1001 /* highlight mouse tracking */ || mode == 1011 /* scroll to bottom on key press */ || /* * GATM, SRTM, VEM, HEM, PUM, FEAM, FETM, MATM, TTM, SATM, TSM, EBM are * permanently reset on VT510. * (https://vt100.net/docs/vt510-rm/DECRQM.html) * * ERM => http://nanno.dip.jp/softlib/man/rlogin/ctrlcode.html#ERM */ mode == VTMODE(1) /* GATM */ || (VTMODE(5) <= mode && mode <= VTMODE(7)) /* SRTM, ERM, VEM */|| mode == VTMODE(10) /* HEM */ || mode == VTMODE(11) /* PUM */ || /* FEAM, FETM, MATM, TTM, SATM, TSM, EBM */ (VTMODE(13) <= mode && mode <= VTMODE(19)) || mode == VTMODE(18) /* ISM */) { return 4; /* permanently reset */ } return 0; /* not recognized */ } static void set_vtmode(vt_parser_t *vt_parser, int mode, int flag) { int idx; #ifdef DEBUG if (VTMODE_NUM != sizeof(vtmodes) / sizeof(vtmodes[0])) { bl_debug_printf(BL_DEBUG_TAG "vtmode table is broken.\n"); } #endif if ((idx = vtmode_num_to_idx(mode)) == -1) { #ifdef DEBUG debug_print_unknown("ESC [%s %d l\n", mode >= VTMODE(0) ? "" : " ?", mode >= VTMODE(0) ? mode - VTMODE(0) : mode); #endif return; } if (flag) { vt_parser->vtmode_flags |= (SHIFT_FLAG64(idx)); } else { vt_parser->vtmode_flags &= ~(SHIFT_FLAG64(idx)); } switch (idx) { case DECMODE_1: /* DECCKM */ vt_parser->is_app_cursor_keys = flag; break; case DECMODE_2: #ifdef USE_VT52 if (!(vt_parser->is_vt52_mode = (flag ? 0 : 1))) { /* * USASCII should be designated for G0-G3 here, but it is temporized by * using vt_init_encoding_parser() etc for now. */ vt_init_encoding_parser(vt_parser); } #endif break; case DECMODE_3: /* DECCOLM */ if (vt_parser->allow_deccolm) { /* XTERM compatibility [#1048321] */ if (!vt_parser->keep_screen_on_deccolm) { clear_display_all(vt_parser); vt_screen_goto(vt_parser->screen, 0, 0); } resize(vt_parser, flag ? 132 : 80, -1, 1); } break; #if 0 case DECMODE_4: /* DECSCLM smooth scrolling */ break; #endif case DECMODE_5: /* DECSCNM */ reverse_video(vt_parser, flag); break; case DECMODE_6: /* DECOM */ if (flag) { vt_screen_set_relative_origin(vt_parser->screen, 1); } else { vt_screen_set_relative_origin(vt_parser->screen, 0); } /* * cursor position is reset * (the same behavior of xterm 4.0.3, kterm 6.2.0 or so) */ vt_screen_goto(vt_parser->screen, 0, 0); break; case DECMODE_7: /* DECAWM */ vt_screen_set_auto_wrap(vt_parser->screen, flag); break; #if 0 case DECMODE_8: /* DECARM auto repeat */ break; case DECMODE_9: /* X10 mouse reporting */ break; case DECMODE_12: /* * XT_CBLINK * If cursor blinking is enabled, restart blinking. */ break; #endif case DECMODE_25: /* DECTCEM */ vt_parser->is_visible_cursor = flag; break; #if 0 case DECMODE_35: /* shift keys */ break; #endif case DECMODE_40: if ((vt_parser->allow_deccolm = flag)) { /* Compatible behavior with rlogin. (Not compatible with xterm) */ set_vtmode(vt_parser, 3, (vt_parser->vtmode_flags >> DECMODE_3) & 1); } break; case DECMODE_47: if (use_alt_buffer) { if (flag) { vt_screen_use_alternative_edit(vt_parser->screen); } else { vt_screen_use_normal_edit(vt_parser->screen); } } break; case DECMODE_66: /* DECNKM */ vt_parser->is_app_keypad = flag; break; case DECMODE_67: /* DECBKM have back space */ /* XXX Affects all terms sharing vt_termcap */ vt_termcap_set_key_seq(vt_parser->termcap, SPKEY_BACKSPACE, flag ? "\x08" : "\x7f"); break; case DECMODE_69: /* DECLRMM */ vt_screen_set_use_hmargin(vt_parser->screen, flag); break; case DECMODE_80: /* DECSDM */ vt_parser->sixel_scrolling = (flag ? 0 : 1); break; case DECMODE_95: /* DECNCSM */ vt_parser->keep_screen_on_deccolm = flag; break; case DECMODE_116: /* DECBBSM */ vt_parser->bold_affects_bg = flag; break; case DECMODE_117: /* DECECM */ vt_screen_set_use_bce(vt_parser->screen, (flag ? 0 : 1)); break; case DECMODE_1000: /* MOUSE_REPORT */ case DECMODE_1002: /* BUTTON_EVENT */ case DECMODE_1003: /* ANY_EVENT */ set_mouse_report(vt_parser, flag ? (MOUSE_REPORT + idx - DECMODE_1000) : 0); break; #if 0 case DECMODE_1001: /* X11 mouse highlighting */ break; #endif case DECMODE_1004: vt_parser->want_focus_event = flag; break; case DECMODE_1005: /* UTF8 */ case DECMODE_1006: /* SGR */ case DECMODE_1015: /* URXVT */ if (flag) { vt_parser->ext_mouse_mode = EXTENDED_MOUSE_REPORT_UTF8 + idx - DECMODE_1005; } else { vt_parser->ext_mouse_mode = 0; } break; case DECMODE_1010: /* scroll to bottom on tty output */ config_protocol_set_simple(vt_parser, "exit_backscroll_by_pty", flag ? "true" : "false", 0); break; #if 0 case DECMODE_1011: /* scroll to bottom on key press (always enabled) */ break; #endif case DECMODE_1034: if (get_vtmode(vt_parser, 1036) == 2 /* reset */) { config_protocol_set_simple(vt_parser, "mod_meta_mode", flag ? "8bit" : "none", 0); } break; case DECMODE_1036: config_protocol_set_simple(vt_parser, "mod_meta_mode", flag ? "esc" : (get_vtmode(vt_parser, 1034) == 1 ? "8bit" : "none"), 0); break; case DECMODE_1042: config_protocol_set_simple(vt_parser, "use_urgent_bell", flag ? "true" : "false", 0); break; case DECMODE_1047: if (use_alt_buffer) { if (flag) { vt_screen_use_alternative_edit(vt_parser->screen); } else { if (vt_screen_is_alternative_edit(vt_parser->screen)) { clear_display_all(vt_parser); vt_screen_use_normal_edit(vt_parser->screen); } } } break; case DECMODE_1048: if (use_alt_buffer) { if (flag) { save_cursor(vt_parser); } else { restore_cursor(vt_parser); } } break; case DECMODE_1049: if (use_alt_buffer) { if (flag) { if (!vt_screen_is_alternative_edit(vt_parser->screen)) { save_cursor(vt_parser); vt_screen_use_alternative_edit(vt_parser->screen); clear_display_all(vt_parser); } } else { if (vt_screen_is_alternative_edit(vt_parser->screen)) { vt_screen_use_normal_edit(vt_parser->screen); restore_cursor(vt_parser); } } } break; case DECMODE_2004: vt_parser->is_bracketed_paste_mode = flag; break; case DECMODE_7727: vt_parser->is_app_escape = flag; break; case DECMODE_8428: /* RLogin original */ vt_parser->col_size_of_width_a = (flag ? 1 : 2); break; case DECMODE_8452: /* RLogin original */ vt_parser->cursor_to_right_of_sixel = flag; break; case DECMODE_8800: if (flag) { vt_parser->unicode_policy |= USE_UNICODE_DRCS; } else { vt_parser->unicode_policy &= ~USE_UNICODE_DRCS; } break; case VTMODE_2: /* KAM */ if (!HAS_XTERM_LISTENER(vt_parser, lock_keyboard)) { if (flag) { vt_parser->vtmode_flags &= ~(SHIFT_FLAG64(idx)); /* unset flag */ } } else { (*vt_parser->xterm_listener->lock_keyboard)(vt_parser->xterm_listener->self, flag); } break; case VTMODE_4: /* IRM */ if (flag) { /* insert mode */ vt_parser->w_buf.output_func = vt_screen_insert_chars; } else { /* replace mode */ vt_parser->w_buf.output_func = vt_screen_overwrite_chars; } break; case VTMODE_12: /* SRM */ if (flag) { vt_pty_set_hook(vt_parser->pty, NULL); } else { vt_parser->pty_hook.pre_write = vt_parser_write_loopback; vt_pty_set_hook(vt_parser->pty, &vt_parser->pty_hook); } break; case VTMODE_20: /* LNM */ vt_parser->auto_cr = flag; break; case VTMODE_33: /* WYSTCURM */ if (flag) { vt_parser->cursor_style &= ~CS_BLINK; } else { vt_parser->cursor_style |= CS_BLINK; } break; case VTMODE_34: /* WYULCURM */ if (flag) { vt_parser->cursor_style |= CS_UNDERLINE; } else { vt_parser->cursor_style &= ~CS_UNDERLINE; } break; } } /* Options configurable by ~/.mlterm/main are not reset. */ static void soft_reset(vt_parser_t *vt_parser) { /* * XXX * Following options is not reset for now. * DECNRCM, DECAUPSS, DECKPM, DECRLM, DECPCTERM * (see http://vt100.net/docs/vt510-rm/DECSTR.html) */ /* "CSI m" (SGR) */ change_char_attr(vt_parser, 0); vt_init_encoding_parser(vt_parser); /* DECSC */ (vt_screen_is_alternative_edit(vt_parser->screen) ? &vt_parser->saved_alternate : &vt_parser->saved_normal)->is_saved = 0; /* DECSCA */ vt_parser->is_protected = 0; /* CSI < r, CSI < s, CSI < t (compatible with TeraTerm) */ vt_parser->im_is_active = 0; set_vtmode(vt_parser, 1, 0); /* DECCKM */ /* auto_wrap == 1 (compatible with xterm, not with VT220) */ set_vtmode(vt_parser, 7, 1); /* DECAWM */ set_vtmode(vt_parser, 25, 1); /* DECTCEM */ set_vtmode(vt_parser, 66, 0); /* DECNKM */ set_vtmode(vt_parser, 1000, 0); /* compatible with xterm */ set_vtmode(vt_parser, 1002, 0); /* compatible with xterm */ set_vtmode(vt_parser, 1003, 0); /* compatible with xterm */ set_vtmode(vt_parser, 1005, 0); /* compatible with xterm */ set_vtmode(vt_parser, 1006, 0); /* compatible with xterm */ set_vtmode(vt_parser, 1015, 0); /* compatible with xterm */ set_vtmode(vt_parser, 2004, 0); /* compatible with xterm */ set_vtmode(vt_parser, 7727, 0); /* compatible with xterm */ set_vtmode(vt_parser, VTMODE(2), 0); /* KAM */ set_vtmode(vt_parser, VTMODE(4), 0); /* IRM */ /* DECOM */ #if 0 set_vtmode(vt_parser, 6, 0); #else vt_screen_set_relative_origin(vt_parser->screen, 0); vt_parser->vtmode_flags &= ~(SHIFT_FLAG64(DECMODE_6)); #endif /* * DECSLRM is reset but DECLRMM is as it is. * (Compatible with xterm, not described in vt510 manual.) */ vt_screen_set_hmargin(vt_parser->screen, -1, -1); /* "CSI r" (DECSTBM) */ vt_screen_set_vmargin(vt_parser->screen, -1, -1); /* DECSC => Home position */ vt_screen_saved_cursor_to_home(vt_parser->screen); /* DECSASD */ vt_focus_main_screen(vt_parser->screen); } static void full_reset(vt_parser_t *vt_parser) { vt_screen_use_normal_edit(vt_parser->screen); vt_screen_goto_page(vt_parser->screen, 0); set_vtmode(vt_parser, 3, 0); /* DECCOLM */ soft_reset(vt_parser); /* XXX insufficient */ vt_screen_goto(vt_parser->screen, 0, 0); vt_screen_set_tab_size(vt_parser->screen, 8); clear_display_all(vt_parser); /* XXX off-screen pages are not cleared */ destroy_all_macros(vt_parser); destroy_drcs(vt_parser->drcs); /* Compatible with xterm (CSI > T / CSI > t) */ vt_parser->set_title_using_hex = vt_parser->get_title_using_hex = vt_parser->set_title_using_utf8 = vt_parser->get_title_using_utf8 = 0; } static void send_device_status(vt_parser_t *vt_parser, int num, int id) { char *seq; char amb[] = "\x1b[?884Xn"; if (num == 6) { /* XCPR */ if ((seq = alloca(6 + DIGIT_STR_LEN(int)+1))) { sprintf(seq, "\x1b[?%d;%d;%dR", vt_screen_cursor_logical_row(vt_parser->screen) + 1, vt_screen_cursor_logical_col(vt_parser->screen) + 1, vt_screen_get_page_id(vt_parser->screen) + 1); } else { return; } } else if (num == 15) { seq = "\x1b[?13n"; /* No printer */ } else if (num == 25) { seq = "\x1b[?21n"; /* UDKs are locked */ } else if (num == 26) { seq = "\x1b[?27;1;0;0n"; /* North American, Keyboard ready */ } else if (num == 53 || num == 55) { seq = "\x1b[?50n"; /* Locator ready */ } else if (num == 56) { seq = "\x1b[?57;1n"; /* Locator exists */ } else if (num == 62) { seq = "\x1b[0*{"; /* Macro Space (Pn = [num of bytes] / 16 (rounded down) */ } else if (num == 63) { /* checksum = 0 */ if ((seq = alloca(10+DIGIT_STR_LEN(int)+1))) { sprintf(seq, "\x1bP%d!~0000\x1b\\", id); } else { seq = "\x1bP0!~0000\x1b\\"; } } else if (num == 75) { seq = "\x1b[?70n"; /* Ready */ } else if (num == 85) { seq = "\x1b[?83n"; /* Not multiple-session */ } else if (num == 8840) { /* "CSI ? 8840 n" (TNREPTAMB) */ amb[6] = vt_parser->col_size_of_width_a + 0x30; seq = amb; } else { return; } vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } static void send_device_attributes(vt_pty_t *pty, int rank) { char *seq; if (rank == 1) { if (primary_da && (seq = alloca(4 + strlen(primary_da) + 1))) { sprintf(seq, "\x1b[?%sc", primary_da); } else { #ifndef NO_IMAGE seq = "\x1b[?63;1;2;3;4;7;29c"; #else seq = "\x1b[?63;1;2;7;29c"; #endif } } else if (rank == 2) { if (secondary_da && (seq = alloca(4 + strlen(secondary_da) + 1))) { sprintf(seq, "\x1b[>%sc", secondary_da); } else { /* * >=96: vim sets ttymouse=xterm2 * >=141: vim uses tcap-query. * >=277: vim uses sgr mouse tracking. * >=279: xterm supports DECSLRM/DECLRMM. */ seq = "\x1b[>24;279;0c"; } } else if (rank == 3) { seq = "\x1bP!|000000\x1b\\"; } else { return; } vt_write_to_pty(pty, seq, strlen(seq)); } static void send_display_extent(vt_pty_t *pty, u_int cols, u_int rows, int vmargin, int hmargin, int page) { char seq[DIGIT_STR_LEN(int) * 5 + 1]; sprintf(seq, "\x1b[%d;%d;%d;%d;%d\"w", rows, cols, hmargin, vmargin, page); vt_write_to_pty(pty, seq, strlen(seq)); } static void set_use_status_line(vt_parser_t *vt_parser, int ps) { u_int width; u_int height; if (ps <= 1) { vt_screen_set_use_status_line(vt_parser->screen, 0); } else if (ps == 2) { vt_screen_set_use_status_line(vt_parser->screen, 1); } else { return; } if (!HAS_XTERM_LISTENER(vt_parser, get_window_size)) { width = height = 0; } else { (*vt_parser->xterm_listener->get_window_size)(vt_parser->xterm_listener->self, &width, &height); } vt_set_pty_winsize(vt_parser->pty, vt_screen_get_logical_cols(vt_parser->screen), vt_screen_get_logical_rows(vt_parser->screen), width, height); } /* * For string outside escape sequences. */ static int increment_str(u_char **str, size_t *left) { if (--(*left) == 0) { return 0; } (*str)++; return 1; } /* * For string inside escape sequences. */ static int inc_str_in_esc_seq(vt_screen_t *screen, u_char **str_p, size_t *left, int want_ctrl) { while (1) { if (increment_str(str_p, left) == 0) { return 0; } if (**str_p < 0x20 || 0x7e < **str_p) { /* * cursor-control characters inside ESC sequences */ if (CTL_LF <= **str_p && **str_p <= CTL_FF) { vt_screen_line_feed(screen); /* XXX vt_parser->auto_cr is ignored for now. */ } else if (**str_p == CTL_CR) { vt_screen_goto_beg_of_line(screen); } else if (**str_p == CTL_BS) { vt_screen_go_back(screen, 1, 0); } else if (want_ctrl) { return 1; } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " Ignored 0x%x inside escape sequences.\n", **str_p); #endif } } else { return 1; } } } /* * Set use_c1=0 for 0x9c not to be regarded as ST if str can be encoded by utf8. * (UTF-8 uses 0x80-0x9f as printable characters.) */ static char *get_pt_in_esc_seq( u_char **str, size_t *left, int use_c1, /* OSC is terminated by not only ST(ESC \) but also 0x9c. */ int bel_terminate /* OSC is terminated by not only ST(ESC \) but also BEL. */ ) { u_char *pt; pt = *str; while (1) { if ((bel_terminate && **str == CTL_BEL) || (use_c1 && **str == 0x9c)) { **str = '\0'; break; } if (**str == CTL_ESC) { if (!increment_str(str, left)) { return NULL; } if (**str == '\\') { *((*str) - 1) = '\0'; break; } /* * Reset position ahead of unprintable character for compat with xterm. * e.g.) "\x1bP\x1b[A" is parsed as "\x1b[A" */ (*str) -= 2; (*left) += 2; return NULL; } if (!increment_str(str, left)) { return NULL; } } return pt; } #ifdef USE_VT52 inline static int parse_vt52_escape_sequence( vt_parser_t *vt_parser /* vt_parser->r_buf.left must be more than 0 */ ) { u_char *str_p; size_t left; str_p = CURRENT_STR_P(vt_parser); left = vt_parser->r_buf.left; if (!inc_str_in_esc_seq(vt_parser->screen, &str_p, &left, 0)) { return 0; } if (*str_p == 'A') { vt_screen_go_upward(vt_parser->screen, 1); } else if (*str_p == 'B') { vt_screen_go_downward(vt_parser->screen, 1); } else if (*str_p == 'C') { vt_screen_go_forward(vt_parser->screen, 1, 0); } else if (*str_p == 'D') { vt_screen_go_back(vt_parser->screen, 1, 0); } else if (*str_p == 'F') { /* Enter graphics mode */ } else if (*str_p == 'G') { /* Exit graphics mode */ } else if (*str_p == 'H') { vt_screen_goto(vt_parser->screen, 0, 0); } else if (*str_p == 'I') { if (vt_screen_cursor_logical_row(vt_parser->screen) == 0) { vt_screen_scroll_downward(vt_parser->screen, 1); } else { vt_screen_go_upward(vt_parser->screen, 1); } } else if (*str_p == 'J') { vt_screen_clear_below(vt_parser->screen); } else if (*str_p == 'K') { vt_screen_clear_line_to_right(vt_parser->screen); } else if (*str_p == 'Y') { int row; int col; if (!inc_str_in_esc_seq(vt_parser->screen, &str_p, &left, 0)) { return 0; } if (*str_p < ' ') { goto end; } row = *str_p - ' '; if (!inc_str_in_esc_seq(vt_parser->screen, &str_p, &left, 0)) { return 0; } if (*str_p < ' ') { goto end; } col = *str_p - ' '; vt_screen_goto(vt_parser->screen, col, row); } else if (*str_p == 'Z') { char msg[] = "\x1b/Z"; vt_write_to_pty(vt_parser->pty, msg, sizeof(msg) - 1); } else if (*str_p == '=') { /* Enter altenate keypad mode */ } else if (*str_p == '>') { /* Exit altenate keypad mode */ } else if (*str_p == '<') { vt_parser->is_vt52_mode = 0; } else { /* not VT52 control sequence */ return 1; } end: vt_parser->r_buf.left = left - 1; return 1; } #endif /* * Parse escape/control sequence. Note that *any* valid format sequence * is parsed even if mlterm doesn't support it. * * Return value: * 0 => vt_parser->r_buf.left == 0 * 1 => Finished parsing. (If current vt_parser->r_buf.chars is not escape *sequence, * return without doing anthing.) */ inline static int parse_vt100_escape_sequence( vt_parser_t *vt_parser /* vt_parser->r_buf.left must be more than 0 */ ) { u_char *str_p; size_t left; #if 0 if (vt_parser->r_buf.left == 0) { /* end of string */ return 1; } #endif str_p = CURRENT_STR_P(vt_parser); left = vt_parser->r_buf.left; if (*str_p == CTL_ESC) { #ifdef ESCSEQ_DEBUG bl_msg_printf("RECEIVED ESCAPE SEQUENCE(current left = %d: ESC", left); #endif #ifdef USE_VT52 if (vt_parser->is_vt52_mode) { return parse_vt52_escape_sequence(vt_parser); } #endif if (!inc_str_in_esc_seq(vt_parser->screen, &str_p, &left, 0)) { return 0; } if (*str_p == '2') { /* "ESC 2" DECCAHT */ vt_screen_clear_all_tab_stops(vt_parser->screen); } else if (*str_p == '6') { /* "ESC 6" DECBI */ vt_screen_go_back(vt_parser->screen, 1, 1); } else if (*str_p == '7') { /* "ESC 7" save cursor (DECSC) */ save_cursor(vt_parser); } else if (*str_p == '8') { /* "ESC 8" restore cursor (DECRC) */ restore_cursor(vt_parser); } else if (*str_p == '9') { /* "ESC 9" DECFI */ vt_screen_go_forward(vt_parser->screen, 1, 1); } else if (*str_p == '=') { /* "ESC =" application keypad (DECKPAM) */ vt_parser->is_app_keypad = 1; } else if (*str_p == '>') { /* "ESC >" normal keypad (DECKPNM) */ vt_parser->is_app_keypad = 0; } else if (*str_p == 'D') { /* "ESC D" index(scroll up) (IND) */ vt_screen_index(vt_parser->screen); } else if (*str_p == 'E') { /* "ESC E" next line (NEL) */ vt_screen_line_feed(vt_parser->screen); vt_screen_goto_beg_of_line(vt_parser->screen); } #if 0 else if (*str_p == 'F') { /* "ESC F" cursor to lower left corner of screen */ } #endif else if (*str_p == 'H' || *str_p == '1') { /* "ESC H" (HTS) / "ESC 1" (DECHTS) set tab */ vt_screen_set_tab_stop(vt_parser->screen); } else if (*str_p == 'I') { /* "ESC I" (HTJ) */ vt_screen_forward_tabs(vt_parser->screen, 1); } #if 0 else if (*str_p == 'K') { /* "ESC K" (PLD) Partial Line Down */ } else if (*str_p == 'L') { /* "ESC L" (PLU) Partial Line Up */ } #endif else if (*str_p == 'M') { /* "ESC M" reverse index(scroll down) */ vt_screen_reverse_index(vt_parser->screen); } else if (*str_p == 'Z') { /* "ESC Z" return terminal id (Obsolete form of CSI c) */ send_device_attributes(vt_parser->pty, 1); } else if (*str_p == 'c') { /* "ESC c" full reset (RIS) */ full_reset(vt_parser); } #if 0 else if (*str_p == 'l') { /* "ESC l" memory lock */ } #endif #if 0 else if (*str_p == 'm') { /* "ESC m" memory unlock */ } #endif else if (*str_p == '[') { /* * "ESC [" (CSI) * CSI P.....P I.....I F * 060-077 040-057 100-176 */ #define MAX_NUM_OF_PS 10 u_char para_ch = '\0'; u_char intmed_ch = '\0'; int ps[MAX_NUM_OF_PS]; int num; num = 0; while (1) { if (!inc_str_in_esc_seq(vt_parser->screen, &str_p, &left, 0)) { return 0; } if (*str_p == ';') { /* * "CSI ; n" is regarded as "CSI -1 ; n" */ if (num < MAX_NUM_OF_PS) { ps[num++] = -1; } } else if (0x3c <= *str_p && *str_p <= 0x3f) { /* parameter character except numeric, ':' and ';' (< = > ?). */ if (para_ch == '\0') { para_ch = *str_p; } } else { if ('0' <= *str_p && *str_p <= '9') { u_char digit[DIGIT_STR_LEN(int)+1]; int count; if (*str_p == '0') { /* 000000001 -> 01 */ while (left > 1 && *(str_p + 1) == '0') { str_p++; left--; } } digit[0] = *str_p; for (count = 1; count < DIGIT_STR_LEN(int); count++) { if (!inc_str_in_esc_seq(vt_parser->screen, &str_p, &left, 0)) { return 0; } if (*str_p < '0' || '9' < *str_p) { break; } digit[count] = *str_p; } digit[count] = '\0'; if (num < MAX_NUM_OF_PS) { ps[num++] = atoi(digit); #ifdef MAX_PS_DIGIT if (ps[num - 1] > MAX_PS_DIGIT) { ps[num - 1] = MAX_PS_DIGIT; } #endif } } if (*str_p < 0x30 || 0x3f < *str_p) { /* Is not a parameter character(0x30-0x3f). */ /* * "CSI 0 n" is *not* regarded as "CSI 0 ; -1 n" * "CSI n" is regarded as "CSI -1 n" * "CSI 0 ; n" is regarded as "CSI 0 ; -1 n" * "CSI ; n" which has been already regarded as * "CSI -1 ; n" is regarded as "CSI -1 ; -1 n" */ if (num == 0 || (*(str_p - 1) == ';' && num < MAX_NUM_OF_PS)) { ps[num++] = -1; } /* num is always greater than 0 */ break; } } } /* * Intermediate(0x20-0x2f) characters. * (Unexpected paremeter(0x30-0x3f) characters are also ignored.) */ while (0x20 <= *str_p && *str_p <= 0x3f) { if (*str_p <= 0x2f && intmed_ch == '\0') { intmed_ch = *str_p; } if (!inc_str_in_esc_seq(vt_parser->screen, &str_p, &left, 0)) { return 0; } } if (para_ch == '?') { if (intmed_ch == '$') { if (*str_p == 'p' && num > 0) { /* "CSI ? $ p" DECRQM */ char seq[3 + DIGIT_STR_LEN(u_int) + 5]; sprintf(seq, "\x1b[?%d;%d$y", ps[0], (ps[0] >= VTMODE(0)) ? 0 : get_vtmode(vt_parser, ps[0])); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } } else if (*str_p == 'h') { /* "CSI ? h" DEC Private Mode Set (DECSET) */ int count; for (count = 0; count < num; count++) { if (ps[count] < VTMODE(0)) { set_vtmode(vt_parser, ps[count], 1); } } } else if (*str_p == 'i') { /* "CSI ? i" (DECMC) */ if (ps[0] <= 0 || ps[0] == 10) { snapshot(vt_parser, VT_UTF8, vt_pty_get_slave_name(vt_parser->pty) + 5 /* skip /dev/ */, WCA_SCREEN); } else if (ps[0] == 1) { snapshot(vt_parser, VT_UTF8, vt_pty_get_slave_name(vt_parser->pty) + 5 /* skip /dev/ */, WCA_CURSOR_LINE); } else if (ps[0] == 11) { snapshot(vt_parser, VT_UTF8, vt_pty_get_slave_name(vt_parser->pty) + 5 /* skip /dev/ */, WCA_ALL); } } else if (*str_p == 'l') { /* "CSI ? l" DEC Private Mode Reset (DECRST) */ int count; for (count = 0; count < num; count++) { if (ps[count] < VTMODE(0)) { set_vtmode(vt_parser, ps[count], 0); } } } else if (*str_p == 'r') { /* "CSI ? r" Restore DEC Private Mode (xterm) */ int count; for (count = 0; count < num; count++) { if (ps[count] < VTMODE(0)) { int idx; if ((idx = vtmode_num_to_idx(ps[count])) != -1) { set_vtmode(vt_parser, ps[count], (vt_parser->saved_vtmode_flags & SHIFT_FLAG64(idx)) ? 1 : 0); } } } } else if (*str_p == 's') { /* "CSI ? s" Save DEC Private Mode (xterm) */ int count; for (count = 0; count < num; count++) { if (ps[count] < VTMODE(0)) { int idx; if ((idx = vtmode_num_to_idx(ps[count])) != -1) { if (vt_parser->vtmode_flags & SHIFT_FLAG64(idx)) { vt_parser->saved_vtmode_flags |= (SHIFT_FLAG64(idx)); } else { vt_parser->saved_vtmode_flags &= ~(SHIFT_FLAG64(idx)); } } } } } else if (*str_p == 'n') { /* "CSI ? n" Device Status Report (DSR) */ send_device_status(vt_parser, ps[0], num == 2 ? ps[1] : 0); } else if (*str_p == 'J') { /* "CSI ? J" DECSED (Selective Erase Display) */ vt_protect_store_t *save; if (ps[0] <= 0) { save = vt_screen_save_protected_chars(vt_parser->screen, -1 /* cursor row */, vt_screen_get_logical_rows(vt_parser->screen) - 1, 0); vt_screen_clear_below(vt_parser->screen); vt_screen_restore_protected_chars(vt_parser->screen, save); } else if (ps[0] == 1) { save = vt_screen_save_protected_chars(vt_parser->screen, 0, -1 /* cursor row */, 0); vt_screen_clear_above(vt_parser->screen); vt_screen_restore_protected_chars(vt_parser->screen, save); } else if (ps[0] == 2) { save = vt_screen_save_protected_chars(vt_parser->screen, 0, vt_screen_get_logical_rows(vt_parser->screen) - 1, 0); clear_display_all(vt_parser); vt_screen_restore_protected_chars(vt_parser->screen, save); } } else if (*str_p == 'K') { /* "CSI ? K" DECSEL (Selective Erase Line) */ vt_protect_store_t *save; save = vt_screen_save_protected_chars(vt_parser->screen, -1 /* cursor row */, -1 /* cursor row */, 0); if (ps[0] <= 0) { vt_screen_clear_line_to_right(vt_parser->screen); } else if (ps[0] == 1) { vt_screen_clear_line_to_left(vt_parser->screen); } else if (ps[0] == 2) { clear_line_all(vt_parser); } vt_screen_restore_protected_chars(vt_parser->screen, save); } else if (*str_p == 'S') { /* * "CSI ? Pi;Pa;Pv S" (Xterm original) * The number of palettes mlterm supports is 1024 alone. */ char *seq; if (num == 3 && ps[0] == 1 && (ps[1] == 1 /* read */ || ps[1] == 2 /* reset to default */ || ps[1] == 3 /* set (ps[2] is ignored) */ || ps[1] == 4 /* read the max allowd value */)) { seq = "\x1b[?1;0;1024S"; } else { seq = "\x1b[?1;3;0S"; } vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } else if (*str_p == 'W') { /* "CSI ? W" DECST8C */ vt_screen_set_tab_size(vt_parser->screen, 8); } #if 0 else if (*str_p == 'r') { /* "CSI ? r" Restore DEC Private Mode */ } #endif #if 0 else if (*str_p == 's') { /* "CSI ? s" Save DEC Private Mode */ } #endif /* Other final character */ else if (0x40 <= *str_p && *str_p <= 0x7e) { #ifdef DEBUG debug_print_unknown("ESC [ ? %c\n", *str_p); #endif } else { /* not VT100 control sequence. */ #ifdef ESCSEQ_DEBUG bl_msg_printf("=> not VT100 control sequence.\n"); #endif return 1; } } else if (para_ch == '<') { /* Teraterm compatible IME control sequence */ if (*str_p == 'r') { /* Restore IME state */ if (vt_parser->im_is_active != im_is_active(vt_parser)) { switch_im_mode(vt_parser); } } else if (*str_p == 's') { /* Save IME state */ vt_parser->im_is_active = im_is_active(vt_parser); } else if (*str_p == 't') { /* ps[0] = 0 (Close), ps[0] = 1 (Open) */ if (ps[0] != im_is_active(vt_parser)) { switch_im_mode(vt_parser); } } } else if (para_ch == '>') { if (*str_p == 'c') { /* "CSI > c" Secondary DA (DA2) */ send_device_attributes(vt_parser->pty, 2); } else if (*str_p == 'm') { /* "CSI > m" */ if (ps[0] == -1) { /* reset to initial value. */ set_modkey_mode(vt_parser, 1, 2); set_modkey_mode(vt_parser, 2, 2); set_modkey_mode(vt_parser, 4, 0); } else { if (num == 1 || ps[1] == -1) { if (ps[0] == 1 || /* modifyCursorKeys */ ps[0] == 2) /* modifyFunctionKeys */ { /* The default is 2. */ ps[1] = 2; } else /* if( ps[0] == 4) */ { /* * modifyOtherKeys * The default is 0. */ ps[1] = 0; } } set_modkey_mode(vt_parser, ps[0], ps[1]); } } else if (*str_p == 'n') { /* "CSI > n" */ if (num == 1) { if (ps[0] == -1) { ps[0] = 2; } /* -1: don't send modifier key code. */ set_modkey_mode(vt_parser, ps[0], -1); } } else if (*str_p == 'p') { /* "CSI > p" pointer mode */ vt_parser->hide_pointer_mode = ps[0]; } else if (*str_p == 't') { /* "CSI > t" */ int count; for (count = 0; count < num; count++) { if (ps[count] == 0) { vt_parser->set_title_using_hex = 1; } else if (ps[count] == 1) { vt_parser->get_title_using_hex = 1; } else if (ps[count] == 2) { vt_parser->set_title_using_utf8 = 1; } else if (ps[count] == 3) { vt_parser->get_title_using_utf8 = 1; } } } else if (*str_p == 'T') { /* "CSI > T" */ int count; for (count = 0; count < num; count++) { if (ps[count] == 0) { vt_parser->set_title_using_hex = 0; } else if (ps[count] == 1) { vt_parser->get_title_using_hex = 0; } else if (ps[count] == 2) { vt_parser->set_title_using_utf8 = 0; } else if (ps[count] == 3) { vt_parser->get_title_using_utf8 = 0; } } } else { /* * "CSI > c" */ } } else if (para_ch == '=') { if (*str_p == 'c') { /* "CSI = c" Tertiary DA (DA3) */ send_device_attributes(vt_parser->pty, 3); } } else if (intmed_ch == '!') { if (*str_p == 'p') { /* "CSI ! p" Soft Terminal Reset (DECSTR) */ soft_reset(vt_parser); } } else if (intmed_ch == '$') { if (*str_p == 'p') { /* "CSI $ p" DECRQM */ if (num > 0) { char seq[2 + DIGIT_STR_LEN(u_int) + 5]; sprintf(seq, "\x1b[%d;%d$y", ps[0], get_vtmode(vt_parser, VTMODE(ps[0]))); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } } else if (*str_p == '|') { /* "CSI $ |" DECSCPP */ /* * DECSCPP doesns't clear screen, reset scroll regions or moves the cursor * as does DECCOLM. */ if (ps[0] <= 0 || ps[0] == 80) { resize(vt_parser, 80, -1, 1); } else if (ps[0] == 132) { resize(vt_parser, 132, -1, 1); } } else if (*str_p == '}') { /* "CSI $ }" DECSASD */ if (ps[0] <= 0) { vt_focus_main_screen(vt_parser->screen); } else if (ps[0] == 1) { vt_focus_status_line(vt_parser->screen); } } else if (*str_p == '~') { /* "CSI $ ~" DECSSDT */ set_use_status_line(vt_parser, ps[0]); } else if (*str_p == 'u') { if (ps[0] == 1) { /* "CSI 1 $ u" DECRQTSR */ vt_write_to_pty(vt_parser->pty, "\x1bP0$s\x1b\\", 7); } else if (ps[0] == 2) { if (num == 2) { /* "CSI 2;Pu $ u" DECCTR */ report_color_table(vt_parser, ps[1]); } } } else if (*str_p == 'w') { /* "CSI $ w" DECRQPSR */ if (num == 1) { report_presentation_state(vt_parser, ps[0]); } } else { int count; if (*str_p == 'x') { /* DECFRA: Move Pc to the end */ int tmp; tmp = ps[0]; memmove(ps, ps + 1, sizeof(ps[0]) * 4); ps[4] = tmp; num--; } /* Set the default values to the 0-3 parameters. */ for (count = 0; count < 4; count++) { if (count >= num || ps[count] <= 0) { if (count == 2) { ps[count] = vt_screen_get_logical_rows(vt_parser->screen); } else if (count == 3) { ps[count] = vt_screen_get_logical_cols(vt_parser->screen); } else { ps[count] = 1; } } } if (ps[3] >= ps[1] && ps[2] >= ps[0]) { if (*str_p == 'z') { /* "CSI ... $ z" DECERA */ vt_screen_erase_area(vt_parser->screen, ps[1] - 1, ps[0] - 1, ps[3] - ps[1] + 1, ps[2] - ps[0] + 1); } else if (*str_p == '{') { /* "CSI ... $ {" DECSERA */ vt_protect_store_t *save; save = vt_screen_save_protected_chars(vt_parser->screen, ps[0] - 1, ps[2] - 1, 1); vt_screen_erase_area(vt_parser->screen, ps[1] - 1, ps[0] - 1, ps[3] - ps[1] + 1, ps[2] - ps[0] + 1); vt_screen_restore_protected_chars(vt_parser->screen, save); } else if (*str_p == 'v' && (num == 5 || num >= 8)) { /* "CSI ... $ v" DECCRA */ if (num == 5) { ps[5] = ps[6] = ps[7] = 1; /* default values of xterm */ } else { for (count = 4; count < 8; count++) { if (ps[count] <= 0) { ps[count] = 1; } } } vt_screen_copy_area(vt_parser->screen, ps[1] - 1, ps[0] - 1, ps[3] - ps[1] + 1, ps[2] - ps[0] + 1, ps[4] - 1, ps[6] - 1, ps[5] - 1, ps[7] - 1); } else if (*str_p == 'x') { /* "CSI ... $ x" DECFRA */ if (!iscntrl(ps[4])) { vt_screen_fill_area(vt_parser->screen, ps[4], vt_parser->is_protected, ps[1] - 1, ps[0] - 1, ps[3] - ps[1] + 1, ps[2] - ps[0] + 1); } } else if (*str_p == 'r') { /* "CSI Pt;Pl;Pb;Pr;...$r" DECCARA */ for (count = 4; count < num; count++) { vt_screen_change_attr_area(vt_parser->screen, ps[1] - 1, ps[0] - 1, ps[3] - ps[1] + 1, ps[2] - ps[0] + 1, ps[count]); } } else if (*str_p == 't') { /* "CSI Pt;Pl;Pb;Pr;...$t" DECRARA */ for (count = 4; count < num; count++) { vt_screen_reverse_attr_area(vt_parser->screen, ps[1] - 1, ps[0] - 1, ps[3] - ps[1] + 1, ps[2] - ps[0] + 1, ps[count]); } } } } } else if (intmed_ch == ' ') { if (*str_p == 'q') { /* "CSI SP q" DECSCUSR */ if (ps[0] < 2) { vt_parser->cursor_style = CS_BLOCK|CS_BLINK; } else if (ps[0] == 2) { vt_parser->cursor_style = CS_BLOCK; } else if (ps[0] == 3) { vt_parser->cursor_style = CS_UNDERLINE|CS_BLINK; } else if (ps[0] == 4) { vt_parser->cursor_style = CS_UNDERLINE; } else if (ps[0] == 5) { vt_parser->cursor_style = CS_BAR|CS_BLINK; } else if (ps[0] == 6) { vt_parser->cursor_style = CS_BAR; } } else { if (ps[0] <= 0) { ps[0] = 1; } if (*str_p == '@') { /* CSI SP @ (SL) */ vt_screen_scroll_leftward(vt_parser->screen, ps[0]); } else if (*str_p == 'A') { /* CSI SP A (SR) */ vt_screen_scroll_rightward(vt_parser->screen, ps[0]); } else if (*str_p == 'P') { /* CSI SP P (PPA) */ vt_screen_goto_page(vt_parser->screen, ps[0] - 1); } else if (*str_p == 'Q') { /* CSI SP Q (PPR) */ vt_screen_goto_next_page(vt_parser->screen, ps[0]); } else if (*str_p == 'R') { /* CSI SP R (PPB) */ vt_screen_goto_prev_page(vt_parser->screen, ps[0]); } else { /* * "CSI SP t"(DECSWBV), "CSI SP u"(DECSMBV) */ } } } else if (intmed_ch == '*') { if (ps[0] == -1) { ps[0] = 0; } if (*str_p == 'z') { /* "CSI Pn * z" DECINVM */ invoke_macro(vt_parser, ps[0]); } else if (*str_p == 'x') { /* "CSI Pn * x " DECSACE */ vt_screen_set_use_rect_attr_select(vt_parser->screen, ps[0] == 2); } else if (*str_p == '|') { /* "CSI Pn * |" DECSNLS */ resize(vt_parser, -1, ps[0], 1); } else if (*str_p == 'y') { /* "CSI Pn * y" DECRQCRA */ if (num >= 1) { u_int16_t checksum; char seq[6+DIGIT_STR_LEN(ps[0])+4+1]; if (ps[1] == 0) { #if 0 /* Ignore following parameters (https://vt100.net/docs/vt510-rm/DECRQCRA.html) */ num = 1; #else /* Compatible with xterm */ ps[1] = 1; #endif } switch(num) { case 1: case 2: ps[2] = 1; case 3: ps[3] = 1; case 4: ps[4] = vt_screen_get_rows(vt_parser->screen); case 5: ps[5] = vt_screen_get_cols(vt_parser->screen); } if (num == 1) { int page; checksum = 0; for (page = 0; page <= MAX_PAGE_ID; page++) { int i = vt_screen_get_checksum(vt_parser->screen, ps[3] - 1, ps[2] - 1, ps[5] - ps[3] + 1, ps[4] - ps[2] + 1, page); checksum += i; } } else { checksum = vt_screen_get_checksum(vt_parser->screen, ps[3] - 1, ps[2] - 1, ps[5] - ps[3] + 1, ps[4] - ps[2] + 1, ps[1] - 1); } sprintf(seq, "\x1bP%d!~%.4x\x1b\\", ps[0], checksum); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } } } else if (intmed_ch == '\'') { if (*str_p == '|') { /* "CSI ' |" DECRQLP */ request_locator(vt_parser); } else if (*str_p == '{') { /* "CSI Pn ' {" DECSLE */ int count; for (count = 0; count < num; count++) { if (ps[count] == 1) { vt_parser->locator_mode |= LOCATOR_BUTTON_DOWN; } else if (ps[count] == 2) { vt_parser->locator_mode &= ~LOCATOR_BUTTON_DOWN; } else if (ps[count] == 3) { vt_parser->locator_mode |= LOCATOR_BUTTON_UP; } else if (ps[count] == 4) { vt_parser->locator_mode &= ~LOCATOR_BUTTON_UP; } else { vt_parser->locator_mode &= ~(LOCATOR_BUTTON_UP | LOCATOR_BUTTON_DOWN); } } } else if (*str_p == '}') { /* "CSI ' }" DECIC */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_scroll_rightward_from_cursor(vt_parser->screen, ps[0]); } else if (*str_p == '~') { /* "CSI ' ~" DECDC */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_scroll_leftward_from_cursor(vt_parser->screen, ps[0]); } else if (*str_p == 'w') { /* "CSI ' w" DECEFR Filter Rectangle */ if (num == 4) { #if 0 if (top > ps[0] || left > ps[1] || bottom < ps[2] || right < ps[3]) { /* * XXX * An outside rectangle event should * be sent immediately. */ } #endif vt_parser->loc_filter.top = ps[0]; vt_parser->loc_filter.left = ps[1]; vt_parser->loc_filter.bottom = ps[2]; vt_parser->loc_filter.right = ps[3]; } vt_parser->locator_mode |= LOCATOR_FILTER_RECT; } else if (*str_p == 'z') { /* "CSI ' z" DECELR */ vt_parser->locator_mode &= ~LOCATOR_FILTER_RECT; memset(&vt_parser->loc_filter, 0, sizeof(vt_parser->loc_filter)); if (ps[0] <= 0) { if (vt_parser->mouse_mode >= LOCATOR_CHARCELL_REPORT) { set_mouse_report(vt_parser, 0); } } else { vt_parser->locator_mode |= ps[0] == 2 ? LOCATOR_ONESHOT : 0; set_mouse_report(vt_parser, (num == 1 || ps[1] <= 0 || ps[1] == 2) ? LOCATOR_CHARCELL_REPORT : LOCATOR_PIXEL_REPORT); } } } else if (intmed_ch == '\"') { if (*str_p == 'v') { /* "CSI " v" DECRQDE */ send_display_extent(vt_parser->pty, vt_screen_get_logical_cols(vt_parser->screen), vt_screen_get_logical_rows(vt_parser->screen), vt_parser->screen->edit->hmargin_beg + 1, vt_parser->screen->edit->vmargin_beg + 1, vt_screen_get_page_id(vt_parser->screen) + 1); } else if (*str_p == 'q') { /* "CSI " q" DECSCA */ if (ps[0] <= 0 || ps[0] == 2) { vt_parser->is_protected = 0; } else if (ps[0] == 1) { vt_parser->is_protected = 1; } } else { /* "CSI " p"(DECSCL) etc */ } } else if (intmed_ch == ',') { if (*str_p == '|') { /* "CSI Ps1;Ps2;Ps3,|" (DECAC) */ if (num == 3 && ps[0] == 1 && ((u_int)ps[1]) <= 255 && ((u_int)ps[2]) <= 255) { config_protocol_set_simple(vt_parser, "fg_color", vt_get_color_name(ps[1]), 0); config_protocol_set_simple(vt_parser, "bg_color", vt_get_color_name(ps[2]), 1); } } else if (*str_p == '}') { /* "CSI Ps1;Ps2;Ps3,}" (DECATC) */ if (num == 3 && ((u_int)ps[0]) <= 15 && ((u_int)ps[1]) <= 255 && ((u_int)ps[2] <= 255)) { int idx = alt_color_idxs[ps[0]]; vt_parser->alt_colors.flags |= (1 << idx); vt_parser->alt_colors.fg[idx] = ps[1]; vt_parser->alt_colors.bg[idx] = ps[2]; } } } else if (intmed_ch == ')') { if (*str_p == '{') { /* "CSI ) {" DECSTGLT */ if (ps[0] <= 0) { vt_parser->use_ansi_colors = 0; } else if (ps[0] <= 3) { /* * ps[0] == 1 or 2 enables "Alternate color", but mlterm always enables it * if DECATC specifies alternate colors. */ vt_parser->use_ansi_colors = 1; } } } else if (intmed_ch == '+') { if (*str_p == 'p') { /* "CSI + p" DECSR */ full_reset(vt_parser); if (ps[0] >= 0) { char seq[2+DIGIT_STR_LEN(ps[0])+3]; sprintf(seq, "\x1b[%d*q", ps[0]); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } } } /* Other para_ch(0x3a-0x3f) or intmed_ch(0x20-0x2f) */ else if (para_ch || intmed_ch) { #ifdef DEBUG debug_print_unknown("ESC [ %c %c\n", para_ch, intmed_ch, *str_p); #endif } else if (*str_p == '@') { /* "CSI @" insert blank chars (ICH) */ if (ps[0] <= 0) { ps[0] = 1; } /* inserting ps[0] blank characters. */ vt_screen_insert_blank_chars(vt_parser->screen, ps[0]); } else if (*str_p == 'A' || *str_p == 'k') { /* "CSI A" = CUU , "CSI k" = VPB */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_go_upward(vt_parser->screen, ps[0]); } else if (*str_p == 'B' || *str_p == 'e') { /* "CSI B" = CUD , "CSI e" = VPR */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_go_downward(vt_parser->screen, ps[0]); } else if (*str_p == 'C' || *str_p == 'a') { /* "CSI C" = CUF , "CSI a" = HPR */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_go_forward(vt_parser->screen, ps[0], 0); } else if (*str_p == 'D' || *str_p == 'j') { /* "CSI D" = CUB , "CSI j" = HPB */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_go_back(vt_parser->screen, ps[0], 0); } else if (*str_p == 'E') { /* "CSI E" down and goto first column (CNL) */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_go_downward(vt_parser->screen, ps[0]); vt_screen_goto_beg_of_line(vt_parser->screen); } else if (*str_p == 'F') { /* "CSI F" up and goto first column (CPL) */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_go_upward(vt_parser->screen, ps[0]); vt_screen_goto_beg_of_line(vt_parser->screen); } else if (*str_p == 'G' || *str_p == '`') { /* * "CSI G" (CHA), "CSI `" (HPA) * cursor position absolute. */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_go_horizontally(vt_parser->screen, ps[0] - 1); } else if (*str_p == 'H' || *str_p == 'f') { /* "CSI H" (CUP) "CSI f" (HVP) */ if (ps[0] <= 0) { ps[0] = 1; } if (num <= 1 || ps[1] <= 0) { ps[1] = 1; } vt_screen_goto(vt_parser->screen, ps[1] - 1, ps[0] - 1); } else if (*str_p == 'I') { /* "CSI I" cursor forward tabulation (CHT) */ if (ps[0] == -1) { /* * "CSI 0 I" => No tabulation. * "CSI I" => 1 taburation. */ ps[0] = 1; } vt_screen_forward_tabs(vt_parser->screen, ps[0]); } else if (*str_p == 'J') { /* "CSI J" Erase in Display (ED) */ if (ps[0] <= 0) { vt_screen_clear_below(vt_parser->screen); } else if (ps[0] == 1) { vt_screen_clear_above(vt_parser->screen); } else if (ps[0] == 2) { clear_display_all(vt_parser); } } else if (*str_p == 'K') { /* "CSI K" Erase in Line (EL) */ if (ps[0] <= 0) { vt_screen_clear_line_to_right(vt_parser->screen); } else if (ps[0] == 1) { vt_screen_clear_line_to_left(vt_parser->screen); } else if (ps[0] == 2) { clear_line_all(vt_parser); } } else if (*str_p == 'L') { /* "CSI L" IL */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_insert_new_lines(vt_parser->screen, ps[0]); } else if (*str_p == 'M') { /* "CSI M" DL */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_delete_lines(vt_parser->screen, ps[0]); } else if (*str_p == 'P') { /* "CSI P" delete chars (DCH) */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_delete_cols(vt_parser->screen, ps[0]); } else if (*str_p == 'S') { /* "CSI S" scroll up (SU) */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_scroll_upward(vt_parser->screen, ps[0]); } else if (*str_p == 'T') { /* "CSI T" scroll down (SD) */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_scroll_downward(vt_parser->screen, ps[0]); } else if (*str_p == 'U') { /* "CSI U" (NP) */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_goto_next_page(vt_parser->screen, ps[0]); vt_screen_goto_home(vt_parser->screen); } else if (*str_p == 'V') { /* "CSI V" (PP) */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_goto_prev_page(vt_parser->screen, ps[0]); vt_screen_goto_home(vt_parser->screen); } else if (*str_p == 'W') { /* "CSI W" Cursor Tabluation Control (CTC) */ if (ps[0] <= 0) { vt_screen_set_tab_stop(vt_parser->screen); } else if (ps[0] == 2) { vt_screen_clear_tab_stop(vt_parser->screen); } else if (ps[0] == 4 || ps[0] == 5) { vt_screen_clear_all_tab_stops(vt_parser->screen); } } else if (*str_p == 'X') { /* "CSI X" erase characters (ECH) */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_clear_cols(vt_parser->screen, ps[0]); } else if (*str_p == 'Z') { /* "CSI Z" cursor backward tabulation (CBT) */ if (ps[0] == -1) { /* * "CSI 0 Z" => No tabulation. * "CSI Z" => 1 taburation. */ ps[0] = 1; } vt_screen_backward_tabs(vt_parser->screen, ps[0]); } else if (*str_p == 'b') { /* "CSI b" repeat the preceding graphic character(REP) */ if (vt_parser->w_buf.last_ch) { int count; if (ps[0] <= 0) { ps[0] = 1; } for (count = 0; count < ps[0]; count++) { (*vt_parser->w_buf.output_func)(vt_parser->screen, vt_parser->w_buf.last_ch, 1); } vt_parser->w_buf.last_ch = NULL; } } else if (*str_p == 'c') { /* "CSI c" Primary DA (DA1) */ send_device_attributes(vt_parser->pty, 1); } else if (*str_p == 'd') { /* "CSI d" line position absolute(VPA) */ if (ps[0] <= 0) { ps[0] = 1; } vt_screen_go_vertically(vt_parser->screen, ps[0] - 1); } else if (*str_p == 'g') { /* "CSI g" tab clear (TBC) */ if (ps[0] <= 0) { vt_screen_clear_tab_stop(vt_parser->screen); } else if (ps[0] == 3) { vt_screen_clear_all_tab_stops(vt_parser->screen); } } else if (*str_p == 'h') { /* "CSI h" (SM) */ int count; for (count = 0; count < num; count++) { set_vtmode(vt_parser, VTMODE(ps[count]), 1); } } else if (*str_p == 'i') { /* "CSI i" (MC) */ if (ps[0] <= 0) { snapshot(vt_parser, VT_UTF8, vt_pty_get_slave_name(vt_parser->pty) + 5 /* skip /dev/ */, WCA_SCREEN); } else if (ps[0] == 1) { snapshot(vt_parser, VT_UTF8, vt_pty_get_slave_name(vt_parser->pty) + 5 /* skip /dev/ */, WCA_CURSOR_LINE); } } else if (*str_p == 'l') { /* "CSI l" (RM) */ int count; for (count = 0; count < num; count++) { set_vtmode(vt_parser, VTMODE(ps[count]), 0); } } else if (*str_p == 'm') { /* "CSI m" (SGR) */ int count; for (count = 0; count < num;) { int proceed; if ((proceed = change_char_fine_color(vt_parser, ps + count, num - count))) { count += proceed; } else { if (ps[count] < 0) { ps[count] = 0; } change_char_attr(vt_parser, ps[count++]); } } } else if (*str_p == 'n') { /* "CSI n" Device Status Report (DSR) */ if (ps[0] == 5) { /* Operating Status */ vt_write_to_pty(vt_parser->pty, "\x1b[0n", 4); } else if (ps[0] == 6) { /* CPR */ char seq[4 + DIGIT_STR_LEN(u_int) * 2 + 1]; sprintf(seq, "\x1b[%d;%dR", vt_screen_cursor_logical_row(vt_parser->screen) + 1, vt_screen_cursor_logical_col(vt_parser->screen) + 1); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); } } else if (*str_p == 'r') { /* "CSI r" set scroll region (DECSTBM) */ if (ps[0] < 0) { ps[0] = 0; } if (num <= 1 || ps[1] < 0) { ps[1] = 0; } vt_screen_set_vmargin(vt_parser->screen, ps[0] - 1, ps[1] - 1); vt_screen_goto(vt_parser->screen, 0, 0); } else if (*str_p == 's') { /* "CSI s" SCOSC or DECSLRM */ if (num <= 1 || ps[1] <= 0) { ps[1] = vt_screen_get_logical_cols(vt_parser->screen); } if (vt_screen_set_hmargin(vt_parser->screen, ps[0] <= 0 ? 0 : ps[0] - 1, ps[1] - 1)) { vt_screen_goto(vt_parser->screen, 0, 0); } else if (num == 1 && ps[0] == -1) { save_cursor(vt_parser); } } else if (*str_p == 't') { /* "CSI t" */ if (ps[0] == 4 || ps[0] == 8) { if (num == 2) { ps[2] = -1; num = 3; } if (num == 3) { resize(vt_parser, ps[2], ps[1], ps[0] == 8); } } else if (ps[0] == 9) { if (num == 2 && 0 <= ps[1] && ps[1] <= 3) { int flag; if (ps[1] >= 2) { flag = ps[1]; /* MAXIMIZE VERTICALLY or HORIZONTALLY */ } else { flag = (ps[1] == 0 ? 1 /* UNMAXIMIZE */ : 4 /* MAXIMIZE FULL */); } set_maximize(vt_parser, flag); } } else if (ps[0] == 10) { /* XXX full screen is not supported for now. */ } else if (ps[0] == 7) { char cmd[] = "update_all"; config_protocol_set(vt_parser, cmd, 0); } else if (ps[0] == 11) { vt_write_to_pty(vt_parser->pty, "\x1b[1t", 4); /* XXX always non-iconified */ } else if (ps[0] == 13) { vt_write_to_pty(vt_parser->pty, "\x1b[3;0;0t", 8); } else if (ps[0] == 14) { report_window_size(vt_parser, 0); } else if (ps[0] == 15) { report_display_size(vt_parser, 0); } else if (ps[0] == 16) { report_cell_size(vt_parser); } else if (ps[0] == 18) { report_window_size(vt_parser, 1); } else if (ps[0] == 19) { report_display_size(vt_parser, 1); } else if (ps[0] == 20) { report_window_or_icon_name(vt_parser, 0); } else if (ps[0] == 21) { report_window_or_icon_name(vt_parser, 1); } else if (ps[0] >= 24) { /* * "CSI Pn t" DECSLPP * This changes not only the number of lines but also * the number of pages, but mlterm doesn't change the latter. */ resize(vt_parser, -1, ps[0], 1); } else if (num == 2) { if (ps[0] == 22) { /* * XXX * If Icon and window title are pushed by ps[1] = 0 and either of them is poped, * the other should be poped. * But it is not supported for now. * esctest: XtermWinopsTests.test_XtermWinops_PushIconAndWindow_PopIcon and * XtermWinopsTests.test_XtermWinops_PushIconAndWindow_PopWindow fails by this. */ if (ps[1] == 0 || ps[1] == 1) { push_to_saved_names(&vt_parser->saved_icon_names, vt_parser->icon_name); } if (ps[1] == 0 || ps[1] == 2) { push_to_saved_names(&vt_parser->saved_win_names, vt_parser->win_name); } } else if (ps[0] == 23) { if ((ps[1] == 0 || ps[1] == 1) && vt_parser->saved_icon_names.num > 0) { set_icon_name(vt_parser, pop_from_saved_names(&vt_parser->saved_icon_names)); } if ((ps[1] == 0 || ps[1] == 2) && vt_parser->saved_win_names.num > 0) { set_window_name(vt_parser, pop_from_saved_names(&vt_parser->saved_win_names)); } } } } else if (*str_p == 'u') { /* "CSI u" (SCORC) */ restore_cursor(vt_parser); } else if (*str_p == 'x') { /* "CSI x" request terminal parameters (DECREQTPARM) */ /* XXX the same as rxvt */ if (ps[0] < 0) { ps[0] = 0; } if (ps[0] == 0 || ps[0] == 1) { char seq[] = "\x1b[X;1;1;112;112;1;0x"; /* '+ 0x30' lets int to char */ seq[2] = ps[0] + 2 + 0x30; vt_write_to_pty(vt_parser->pty, seq, sizeof(seq) - 1); } } #if 0 else if (*str_p == '^') { /* "CSI ^" initiate hilite mouse tracking. */ } #endif /* Other final character */ else if (0x40 <= *str_p && *str_p <= 0x7e) { #ifdef DEBUG debug_print_unknown("ESC [ %c\n", *str_p); #endif } else { /* not VT100 control sequence. */ #ifdef ESCSEQ_DEBUG bl_msg_printf("=> not VT100 control sequence.\n"); #endif return 1; } } else if (*str_p == ']') { /* "ESC ]" (OSC) */ char digit[DIGIT_STR_LEN(int)+1]; int count; int ps; u_char *pt; if (!inc_str_in_esc_seq(vt_parser->screen, &str_p, &left, 0)) { return 0; } for (count = 0; count < DIGIT_STR_LEN(int); count++) { if ('0' <= *str_p && *str_p <= '9') { digit[count] = *str_p; if (!inc_str_in_esc_seq(vt_parser->screen, &str_p, &left, 0)) { return 0; } } else { break; } } if (count > 0 && *str_p == ';') { digit[count] = '\0'; /* if digit is illegal , ps is set 0. */ ps = atoi(digit); #ifdef MAX_PS_DIGIT if (ps > MAX_PS_DIGIT) { ps = MAX_PS_DIGIT; } #endif if (!inc_str_in_esc_seq(vt_parser->screen, &str_p, &left, 1)) { return 0; } } else { /* Illegal OSC format */ ps = -1; } pt = str_p; /* * Skip string which was already parsed. * +1 in case str_p[left - vt_parser->r_buf.new_len] points * "\\" of "\x1b\\". */ if (left > vt_parser->r_buf.new_len + 1) { str_p += (left - vt_parser->r_buf.new_len - 1); left = vt_parser->r_buf.new_len + 1; } if (!get_pt_in_esc_seq(&str_p, &left, 0, 1)) { if (left == 0) { return 0; } #ifdef DEBUG else { debug_print_unknown("ESC ] %d ; ???\n", ps); } #endif } else if (ps == 0) { /* "OSC 0" change icon name and window title */ if (*pt != '\0') { if ((pt = parse_title(vt_parser, strdup(pt)))) { set_window_name(vt_parser, pt); set_icon_name(vt_parser, strdup(pt)); } } } else if (ps == 1) { /* "OSC 1" change icon name */ if (*pt != '\0') { if ((pt = parse_title(vt_parser, strdup(pt)))) { set_icon_name(vt_parser, pt); } } } else if (ps == 2) { /* "OSC 2" change window title */ if (*pt != '\0') { if ((pt = parse_title(vt_parser, strdup(pt)))) { set_window_name(vt_parser, pt); } } } else if (ps == 4) { /* "OSC 4" change 256 color */ change_color_rgb(vt_parser, pt); } else if (ps == 5) { /* "OSC 5" change colorBD/colorUL */ change_special_color(vt_parser, pt); } else if (ps == 10) { /* "OSC 10" fg color */ change_fgbg_color(vt_parser, 10, pt); } else if (ps == 11) { /* "OSC 11" bg color */ change_fgbg_color(vt_parser, 11, pt); } else if (ps == 12) { /* "OSC 12" cursor bg color */ if (strcmp(pt, "?") != 0) /* ?:query rgb */ { /* XXX do nothing for now .*/ } else { config_protocol_set_simple(vt_parser, "cursor_bg_color", pt, 1); } } else if (ps == 20) { /* "OSC 20" (Eterm compatible) */ /* edit commands */ char *p; /* XXX discard all adjust./op. settings.*/ /* XXX may break multi-byte char string. */ if ((p = strchr(pt, ';'))) { *p = '\0'; } if ((p = strchr(pt, ':'))) { *p = '\0'; } if (*pt == '\0') { /* * Do not change current edit but * alter diaplay setting. * XXX nothing can be done for now. */ return 0; } config_protocol_set_simple(vt_parser, "wall_picture", pt, 1); } #if 0 else if (ps == 46) { /* "OSC 46" change log file */ } else if (ps == 50) { /* "OSC 50" set font */ } #endif else if (ps == 52) { set_selection(vt_parser, pt); } else if (ps == 104) { reset_color_rgb(vt_parser, pt, 0); } else if (ps == 105) { reset_color_rgb(vt_parser, pt, 1); } #if 0 else if (ps == 110) { config_protocol_set_simple(vt_parser, "fg_color", "black", 1); } else if (ps == 111) { config_protocol_set_simple(vt_parser, "bg_color", "white", 1); } else if (ps == 112) { config_protocol_set_simple(vt_parser, "cursor_bg_color", "black", 1); } #endif #ifdef SUPPORT_ITERM2_OSC1337 else if (ps == 1337) { iterm2_proprietary_set(vt_parser, pt); } #endif else if (ps == 5379) { /* "OSC 5379" set */ config_protocol_set(vt_parser, pt, 0); } else if (ps == 5380) { /* "OSC 5380" get */ config_protocol_get(vt_parser, pt, 0, NULL); } else if (ps == 5381) { /* "OSC 5381" get(menu) */ config_protocol_get(vt_parser, pt, 1, NULL); } else if (ps == 5383) { /* "OSC 5383" set&save */ config_protocol_set(vt_parser, pt, 1); } #ifdef DEBUG else if (ps == -1) { debug_print_unknown("ESC ] %s\n", pt); } else { debug_print_unknown("ESC ] %d ; %s\n", ps, pt); } #endif } else if (*str_p == 'P') { /* "ESC P" DCS */ u_char *dcs_beg; #ifndef NO_IMAGE char *path; #endif while (1) { /* ESC P ... */ dcs_beg = str_p - 1; break; parse_dcs: /* 0x90 ... */ dcs_beg = str_p; break; } do { if (!increment_str(&str_p, &left)) { return 0; } } while (*str_p == ';' || ('0' <= *str_p && *str_p <= '9')); #ifndef NO_IMAGE if (/* sixel */ (*str_p == 'q' && (path = get_home_file_path("", vt_pty_get_slave_name(vt_parser->pty) + 5, "six"))) || /* ReGIS */ (*str_p == 'p' && (path = get_home_file_path("", vt_pty_get_slave_name(vt_parser->pty) + 5, "rgs")))) { if (!save_sixel_or_regis(vt_parser, path, dcs_beg, &str_p, &left)) { return 0; } if (strcmp(path + strlen(path) - 4, ".six") == 0) { show_picture(vt_parser, path, 0, 0, 0, 0, 0, 0, 0, (!vt_parser->sixel_scrolling && check_sixel_anim(vt_parser->screen, str_p, left)) ? 2 : 1); } else { /* ReGIS */ int orig_flag; orig_flag = vt_parser->sixel_scrolling; vt_parser->sixel_scrolling = 0; show_picture(vt_parser, path, 0, 0, 0, 0, 0, 0, 0, 1 /* is_sixel (vt_parser->sixel_scrolling is applied) */); vt_parser->sixel_scrolling = orig_flag; } free(path); } else #endif /* NO_IMAGE */ if (*str_p == '{') { /* DECDLD */ u_char *param; ef_charset_t cs; int num; u_char *p; int ps[9]; int idx; int is_end; u_int col_width; u_int line_height; if (*dcs_beg == '\x1b') { param = dcs_beg + 2; } else /* if( *dcs_beg == '\x90') */ { param = dcs_beg + 1; } for (num = 0; num < 9; num++) { u_char c; p = param; while ('0' <= *param && *param <= '9') { param++; } c = *param; if (c != ';' && c != '{') { break; } *param = '\0'; ps[num] = *p ? atoi(p) : 0; *(param++) = c; /* restore in case of restarting to parse from the begining. */ } if (num != 8) { if (!get_pt_in_esc_seq(&str_p, &left, 1, 0)) { return 0; } } else { char *path; if (!increment_str(&str_p, &left)) { return 0; } if (*str_p == ' ') { /* ESC ( SP Ft */ if (!increment_str(&str_p, &left)) { return 0; } } idx = ps[1]; if (0x30 <= *str_p && *str_p <= 0x7e) { /* Ft */ if (ps[7] == 0) { cs = CS94SB_ID(*str_p); } else { cs = CS96SB_ID(*str_p); } if (ps[3] <= 4 || ps[3] >= 255) { col_width = 15; } else { col_width = ps[3]; } if (ps[6] == 0 || ps[6] >= 255) { line_height = 12; } else { line_height = ps[6]; } } else { cs = UNKNOWN_CS; col_width = line_height = 0; } #ifndef NO_IMAGE if (ps[5] == 3 && cs != UNKNOWN_CS && (path = get_home_file_path("", vt_pty_get_slave_name(vt_parser->pty) + 5, "six"))) { /* DRCS Sixel */ u_char *orig_drcs_header; size_t drcs_header_len = str_p - dcs_beg + 1; u_char *orig_sixel_size = NULL; size_t sixel_size_len = 0; int tmp; int pix_width = 0; int pix_height = 0; orig_drcs_header = alloca(drcs_header_len); memcpy(orig_drcs_header, dcs_beg, drcs_header_len); dcs_beg = str_p - 1; /* skip sixel header parameters */ do { if (!increment_str(&str_p, &left)) { free(path); return 0; } } while (*str_p == ';' || ('0' <= *str_p && *str_p <= '9')); if (*str_p != 'q') { dcs_beg--; dcs_beg[0] = '\x1b'; dcs_beg[1] = 'P'; dcs_beg[2] = 'q'; str_p--; /* str_p points 'q' */ left++; } else { dcs_beg[0] = '\x1b'; dcs_beg[1] = 'P'; if (left == 0) { return 0; } } /* * Read width and height of sixel graphics from "Pan;Pad;Ph;Pv. * If failed, it is impossible to scale image pieces according to Pcmw and Pcmh. */ if (str_p[1] == '"' && !check_cell_size(vt_parser, col_width, line_height)) { if (left < 2) { /* XXX */ return 0; } if (sscanf(str_p + 2, "%d;%d;%d;%d", &tmp, &tmp, &pix_width, &pix_height) == 4 && pix_width > 0 && pix_height > 0) { sixel_size_len = 1; /* q */ while (left > ++sixel_size_len && '0' <= str_p[sixel_size_len] && str_p[sixel_size_len] <= ';'); orig_sixel_size = alloca(sixel_size_len); memcpy(orig_sixel_size, str_p, sixel_size_len); if (str_p[sixel_size_len] == 'q') { /* * Starting DRCS Sixel: q"Pan;Pad;Ph;Pv#... * Continuing DRCS Sixel: q"Pan;Pad;Ph;Pv\0q... */ str_p += sixel_size_len; left -= sixel_size_len; } } } if (!save_sixel_or_regis(vt_parser, path, dcs_beg, &str_p, &left)) { /* * q"Pan;Pad;Ph;Pvq\0... * ^^^^^^ */ memmove(vt_parser->r_buf.chars + drcs_header_len + sixel_size_len, vt_parser->r_buf.chars + 2 /* ESC P */, vt_parser->r_buf.filled_len - 2); /* * q"Pan;Pad;Ph;Pvq\0... * ^^^^^^^^^^^^^^^ */ memcpy(vt_parser->r_buf.chars + drcs_header_len, orig_sixel_size, sixel_size_len); memcpy(vt_parser->r_buf.chars, orig_drcs_header, drcs_header_len); vt_parser->r_buf.filled_len += (drcs_header_len - 2 + sixel_size_len); vt_parser->r_buf.left += (drcs_header_len - 2 + sixel_size_len); return 0; } define_drcs_picture(vt_parser, path, cs, idx, pix_width, pix_height, col_width, line_height); free(path); } else #endif { u_char *pt = str_p; vt_drcs_font_t *font; if (!get_pt_in_esc_seq(&str_p, &left, 1, 0)) { return 0; } if (cs == UNKNOWN_CS) { if (ps[2] == 2) { destroy_drcs(vt_parser->drcs); } } else { if (ps[2] == 0) { vt_drcs_final(vt_parser->drcs, cs); } else if (ps[2] == 2) { vt_drcs_final_full(vt_parser->drcs); } if (!vt_parser->drcs) { vt_parser->drcs = vt_drcs_new(); } font = vt_drcs_get_font(vt_parser->drcs, cs, 1); while (1) { p = ++pt; while (*pt == '/' || ('?' <= *pt && *pt <= '~')) { pt++; } if (*pt) { *pt = '\0'; is_end = 0; } else { is_end = 1; } if (*p) { if (strlen(p) == (col_width + 1) * ((line_height + 5) / 6) - 1) { vt_drcs_add_glyph(font, idx, p, col_width, line_height); } #ifdef DEBUG else { bl_debug_printf(BL_DEBUG_TAG "DRCS illegal size %s\n", p); } #endif idx++; } if (is_end) { break; } } } } } } else { u_char *macro; u_char *tckey; u_char *status; u_char *present; macro = tckey = status = present = NULL; if ((*str_p == '!' && *(str_p + 1) == 'z') || ((*str_p == '+' || *str_p == '$') && *(str_p + 1) == 'q') || (*str_p == '$' && *(str_p + 1) == 't')) { if (left <= 2) { left = 0; return 0; } str_p += 2; left -= 2; if (*(str_p - 1) == 'z' /* && *(str_p - 2) == '!' */) { /* DECDMAC */ macro = str_p; } else if (*(str_p - 1) == 'q') { if (*(str_p - 2) == '$') { /* DECRQSS */ status = str_p; } else { /* Termcap query */ tckey = str_p; } } else /* if (*(str_p - 1) == t && *(str_p - 2) == '$') */ { /* DECRSPS */ present = str_p; } } else { if (!increment_str(&str_p, &left)) { return 0; } } /* * +1 in case str_p[left - vt_parser->r_buf.new_len] points * "\\" of "\x1b\\". */ if (left > vt_parser->r_buf.new_len + 1) { str_p += (left - vt_parser->r_buf.new_len - 1); left = vt_parser->r_buf.new_len + 1; } if (get_pt_in_esc_seq(&str_p, &left, 1, 0)) { if (macro) { define_macro(vt_parser, dcs_beg + (*dcs_beg == '\x1b' ? 2 : 1), macro); } else if (status) { report_status(vt_parser, status); } else if (tckey) { report_termcap(vt_parser, tckey); } else if (present) { set_presentation_state(vt_parser, present); } } else if (left == 0) { return 0; } } } else if (*str_p == 'X' || *str_p == '^' || *str_p == '_') { /* * "ESC X" SOS * "ESC ^" PM * "ESC _" APC */ if (!inc_str_in_esc_seq(vt_parser->screen, &str_p, &left, 0)) { return 0; } /* +1 in case str_p[left - new_len] points "\\" of "\x1b\\". */ if (left > vt_parser->r_buf.new_len + 1) { str_p += (left - vt_parser->r_buf.new_len - 1); left = vt_parser->r_buf.new_len + 1; } if (!get_pt_in_esc_seq(&str_p, &left, 1, 0) && left == 0) { return 0; } } /* Other final character */ else if (0x30 <= *str_p && *str_p <= 0x7e) { #ifdef DEBUG debug_print_unknown("ESC %c\n", *str_p); #endif } /* intermediate character */ else if (0x20 <= *str_p && *str_p <= 0x2f) { /* * ESC I.....I F * 033 040-057 060-176 */ u_int ic_num; ic_num = 0; /* In case more than one intermediate(0x20-0x2f) chars. */ do { ic_num++; if (!inc_str_in_esc_seq(vt_parser->screen, &str_p, &left, 0)) { return 0; } } while (0x20 <= *str_p && *str_p <= 0x2f); if (ic_num == 1 || ic_num == 2) { if (ic_num == 1 && *(str_p - 1) == '#') { if ('3' <= *str_p && *str_p <= '6') { vt_line_t *line; line = vt_screen_get_cursor_line(vt_parser->screen); if (*str_p == '3') { /* * "ESC # 3" DEC double-height line, * top half (DECDHL) */ vt_line_set_size_attr(line, DOUBLE_HEIGHT_TOP); } else if (*str_p == '4') { /* * "ESC # 4" DEC double-height line, * bottom half (DECDHL) */ vt_line_set_size_attr(line, DOUBLE_HEIGHT_BOTTOM); } else if (*str_p == '5') { /* * "ESC # 5" DEC single-with line (DECSWL) */ vt_line_set_size_attr(line, 0); } else /* if( *str_p == '6') */ { /* * "ESC # 6" DEC double-with line (DECDWL) */ vt_line_set_size_attr(line, DOUBLE_WIDTH); } } else if (*str_p == '8') { /* "ESC # 8" DEC screen alignment test (DECALN) */ vt_screen_set_vmargin(vt_parser->screen, -1, -1); vt_screen_set_use_hmargin(vt_parser->screen, 0); vt_screen_goto(vt_parser->screen, 0, 0); vt_screen_fill_area(vt_parser->screen, 'E', vt_parser->is_protected, 0, 0, vt_screen_get_logical_cols(vt_parser->screen), vt_screen_get_logical_rows(vt_parser->screen)); } } else if (*(str_p - ic_num) == '(' || *(str_p - ic_num) == '$') { /* * "ESC ("(Registered CS), * "ESC ( SP"(DRCS) or "ESC $" * See vt_convert_to_internal_ch() about CS94MB_ID. */ if (IS_ENCODING_BASED_ON_ISO2022(vt_parser->encoding)) { /* ESC ( will be processed in mef. */ return 1; } vt_parser->g0 = (*(str_p - ic_num) == '$') ? CS94MB_ID(*str_p) : CS94SB_ID(*str_p); if (!vt_parser->is_so) { vt_parser->gl = vt_parser->g0; } } else if (*(str_p - ic_num) == ')') { /* "ESC )"(Registered CS) or "ESC ( SP"(DRCS) */ if (IS_ENCODING_BASED_ON_ISO2022(vt_parser->encoding)) { /* ESC ) will be processed in mef. */ return 1; } vt_parser->g1 = (*(str_p - ic_num) == '$') ? CS94MB_ID(*str_p) : CS94SB_ID(*str_p); if (vt_parser->is_so) { vt_parser->gl = vt_parser->g1; } } else if (*(str_p - ic_num) == '-') { /* "ESC -"(Registered CS) or "ESC - SP"(DRCS) */ if (IS_ENCODING_BASED_ON_ISO2022(vt_parser->encoding)) { /* ESC ) will be processed in mef. */ return 1; } vt_parser->g1 = CS96SB_ID(*str_p); if (vt_parser->is_so) { vt_parser->gl = vt_parser->g1; } } else { /* * "ESC SP F", "ESC SP G", "ESC SP L", "ESC SP M", * "ESC SP N" etc ... */ } } } else { /* not VT100 control sequence. */ #ifdef ESCSEQ_DEBUG bl_msg_printf("=> not VT100 control sequence.\n"); #endif return 1; } #ifdef ESCSEQ_DEBUG bl_msg_printf("\n"); #endif } else if (*str_p == CTL_SI) { if (IS_ENCODING_BASED_ON_ISO2022(vt_parser->encoding)) { /* SI will be processed in mef. */ return 1; } #ifdef ESCSEQ_DEBUG bl_debug_printf(BL_DEBUG_TAG " receiving SI\n"); #endif vt_parser->gl = vt_parser->g0; vt_parser->is_so = 0; } else if (*str_p == CTL_SO) { if (IS_ENCODING_BASED_ON_ISO2022(vt_parser->encoding)) { /* SO will be processed in mef. */ return 1; } #ifdef ESCSEQ_DEBUG bl_debug_printf(BL_DEBUG_TAG " receiving SO\n"); #endif vt_parser->gl = vt_parser->g1; vt_parser->is_so = 1; } else if (CTL_LF <= *str_p && *str_p <= CTL_FF) { #ifdef ESCSEQ_DEBUG bl_debug_printf(BL_DEBUG_TAG " receiving LF\n"); #endif vt_screen_line_feed(vt_parser->screen); if (vt_parser->auto_cr) { vt_screen_goto_beg_of_line(vt_parser->screen); } } else if (*str_p == CTL_CR) { #ifdef ESCSEQ_DEBUG bl_debug_printf(BL_DEBUG_TAG " receiving CR\n"); #endif vt_screen_goto_beg_of_line(vt_parser->screen); } else if (*str_p == CTL_TAB) { #ifdef ESCSEQ_DEBUG bl_debug_printf(BL_DEBUG_TAG " receiving TAB\n"); #endif vt_screen_forward_tabs(vt_parser->screen, 1); } else if (*str_p == CTL_BS) { #ifdef ESCSEQ_DEBUG bl_debug_printf(BL_DEBUG_TAG " receiving BS\n"); #endif vt_screen_go_back(vt_parser->screen, 1, 0); } else if (*str_p == CTL_BEL) { #ifdef ESCSEQ_DEBUG bl_debug_printf(BL_DEBUG_TAG " receiving BEL\n"); #endif if (HAS_XTERM_LISTENER(vt_parser, bel)) { stop_vt100_cmd(vt_parser, 0); (*vt_parser->xterm_listener->bel)(vt_parser->xterm_listener->self); /* * XXX * start_vt100_cmd( ... , *1*) erases cursor which * xterm_listener::bell drew if bell mode is visual. */ start_vt100_cmd(vt_parser, 1); } } else if (*str_p == 0x90) { goto parse_dcs; } else if (*str_p == 0x18) { if (vt_parser->r_buf.left < 3) { return 0; } if (memcmp(str_p + 1, "B01", 3) == 0) { vt_parser->is_zmodem_ready = 1; /* rz */ } #if 0 else if (memcmp(str_p + 1, "B00", 3) == 0) { vt_parser->is_zmodem_ready = 2; /* sz */ } #endif } else { /* not VT100 control sequence */ return 1; } #ifdef EDIT_DEBUG vt_edit_dump(vt_parser->screen->edit); #endif vt_parser->r_buf.left = left - 1; return 1; } static int parse_vt100_sequence(vt_parser_t *vt_parser) { ef_char_t ch; size_t prev_left; while (1) { prev_left = vt_parser->r_buf.left; /* * parsing character encoding. */ (*vt_parser->cc_parser->set_str)(vt_parser->cc_parser, CURRENT_STR_P(vt_parser), vt_parser->r_buf.left); while ((*vt_parser->cc_parser->next_char)(vt_parser->cc_parser, &ch)) { int ret; ef_charset_t orig_cs; orig_cs = ch.cs; ret = vt_convert_to_internal_ch(vt_parser, &ch); if (ret == 1) { if (vt_parser->gl != US_ASCII && orig_cs == US_ASCII) { orig_cs = vt_parser->gl; } if (vt_parser->cs != orig_cs) { vt_parser->cs = orig_cs; } #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_IND) if (IS_ISCII(ch.cs) && ch.size == 2) { ch.size = 1; put_char(vt_parser, ef_char_to_int(&ch), ch.cs, ch.property); ch.ch[0] = ch.ch[1]; /* nukta is always combined. */ ch.property |= EF_COMBINING; } #endif put_char(vt_parser, ef_char_to_int(&ch), ch.cs, ch.property); vt_parser->r_buf.left = vt_parser->cc_parser->left; } else if (ret == -1) { /* * This is a control sequence (C0 or C1), so * reparsing this char in vt100_escape_sequence() ... */ vt_parser->cc_parser->left++; vt_parser->cc_parser->is_eos = 0; break; } } vt_parser->r_buf.left = vt_parser->cc_parser->left; flush_buffer(vt_parser); if (vt_parser->cc_parser->is_eos) { /* expect more input */ break; } /* * parsing other vt100 sequences. * (vt_parser->w_buf is always flushed here.) */ if (!parse_vt100_escape_sequence(vt_parser)) { /* expect more input */ break; } #ifdef EDIT_ROUGH_DEBUG vt_edit_dump(vt_parser->screen->edit); #endif if (vt_parser->r_buf.left == prev_left) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " unrecognized sequence[%.2x] is received , ignored...\n", *CURRENT_STR_P(vt_parser)); #endif vt_parser->r_buf.left--; } if (vt_parser->r_buf.left == 0) { break; } } /* * If only one window is shown on screen, it is not necessary to process * pending events for other windows. * But multiple windows can be shown even on framebuffer now, so it is * commented out. */ #if 0 if (vt_parser->yield) { vt_parser->yield = 0; return 0; } #endif return 1; } static int write_loopback(vt_parser_t *vt_parser, const u_char *buf, size_t len, int enable_local_echo, int is_visual /* 1: stop_vt100_cmd(1), -1: stop_vt100_cmd(0) */ ) { char *orig_buf; size_t orig_left; if (!vt_parser->pty || /* vt_term_write_loopback() in open_pty_intern() in ui_screen_manager.c can * be called when vt_parser->pty is NULL */ vt_pty_get_master_fd(vt_parser->pty) != -1) { if (vt_parser->r_buf.len < len && !change_read_buffer_size(&vt_parser->r_buf, len)) { return 0; } if ((orig_left = vt_parser->r_buf.left) > 0) { if (!(orig_buf = alloca(orig_left))) { return 0; } memcpy(orig_buf, CURRENT_STR_P(vt_parser), orig_left); } memcpy(vt_parser->r_buf.chars, buf, len); vt_parser->r_buf.filled_len = vt_parser->r_buf.left = vt_parser->r_buf.new_len = len; } else { /* for vterm compatible library */ if (vt_parser->r_buf.len < len + vt_parser->r_buf.left && !change_read_buffer_size(&vt_parser->r_buf, len + vt_parser->r_buf.left)) { return 0; } memmove(vt_parser->r_buf.chars, vt_parser->r_buf.chars + vt_parser->r_buf.filled_len - vt_parser->r_buf.left, vt_parser->r_buf.left); memcpy(vt_parser->r_buf.chars + vt_parser->r_buf.left, buf, len); vt_parser->r_buf.filled_len = (vt_parser->r_buf.left += len); vt_parser->r_buf.new_len = len; orig_left = 0; } if (is_visual) { start_vt100_cmd(vt_parser, 1); } if (enable_local_echo) { vt_screen_enable_local_echo(vt_parser->screen); } /* * bidi and visual-indian is always stopped from here. * If you want to call {start|stop}_vt100_cmd (where vt_xterm_event_listener * is called), * the second argument of it shoule be 0. */ parse_vt100_sequence(vt_parser); if (is_visual) { stop_vt100_cmd(vt_parser, is_visual > 0); } if (orig_left > 0) { memcpy(vt_parser->r_buf.chars, orig_buf, orig_left); vt_parser->r_buf.filled_len = vt_parser->r_buf.left = orig_left; } return 1; } static int is_transferring_data(vt_parser_t *vt_parser) { int progress_cur; int progress_len; int state; vt_char_t *bar; if ((state = vt_transfer_get_state(&progress_cur, &progress_len)) >= 0 && (bar = alloca(sizeof(vt_char_t) * (progress_len + 2)))) { int count; start_vt100_cmd(vt_parser, 1); if (progress_cur == 0) { char *msg; char *p1; char *p2; size_t len; size_t pre_len; if (vt_parser->is_transferring_data == 0x1) { pre_len = 5; p1 = "Send "; p2 = send_file ? send_file : ""; } else { pre_len = 8; p1 = "Save in "; p2 = recv_dir ? recv_dir : "~/.mlterm/recv"; } len = 10 + pre_len + strlen(p2); if ((msg = alloca(len + 1))) { memcpy(msg, "\r\nZMODEM: ", 10); memcpy(msg + 10, p1, pre_len); strcpy(msg + 10 + pre_len, p2); } write_loopback(vt_parser, msg, len, 0, 0); vt_screen_line_feed(vt_parser->screen); } vt_screen_goto_beg_of_line(vt_parser->screen); vt_screen_clear_line_to_right(vt_parser->screen); vt_str_init(bar, progress_len + 2); vt_char_set(bar, '|', US_ASCII, 0, 0, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0); for (count = 0; count < progress_cur; count++) { vt_char_set(bar + 1 + count, '*', US_ASCII, 0, 0, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0); } for (; count < progress_len; count++) { vt_char_set(bar + 1 + count, ' ', US_ASCII, 0, 0, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0); } vt_char_set(bar + 1 + progress_len, '|', US_ASCII, 0, 0, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0); vt_screen_overwrite_chars(vt_parser->screen, bar, progress_len + 2); if (state == 0) { vt_screen_line_feed(vt_parser->screen); vt_screen_goto_beg_of_line(vt_parser->screen); stop_vt100_cmd(vt_parser, 1); vt_parser->is_transferring_data = 0; return 0; } stop_vt100_cmd(vt_parser, 1); } return 1; } /* sending or receiving data via zmodem */ static void transfer_data(vt_parser_t *vt_parser) { receive_bytes(vt_parser); do { u_char input[4096]; u_char output[(2 * (1024 + 4 + 1)) + 1]; u_int len = 0; size_t copy_len; if ((copy_len = vt_parser->r_buf.left) > sizeof(input) - 1) { copy_len = sizeof(input) - 1; } memcpy(input, CURRENT_STR_P(vt_parser), copy_len); input[copy_len] = '\0'; if ((vt_parser->r_buf.left -= copy_len) > 0) { memmove(vt_parser->r_buf.chars, CURRENT_STR_P(vt_parser), vt_parser->r_buf.left); vt_parser->r_buf.filled_len = vt_parser->r_buf.left; } vt_transfer_data(input, copy_len, output, &len, sizeof(output)); if (len > 0) { vt_write_to_pty(vt_parser->pty, output, len); } } while (is_transferring_data(vt_parser) && receive_bytes(vt_parser) > 0); } /* This function assumes vt_pty_is_loopback(vt_parser->pty) is false if do_zcan is true. */ static void transfer_cancel(vt_parser_t *vt_parser, int do_zcan) { if (vt_parser->is_transferring_data) { vt_parser->is_transferring_data = 0; vt_parser->r_buf.left = 0; vt_transfer_cancel(); } #if 0 else if (vt_parser->is_zmodem_ready == 0) { return; } #endif vt_parser->is_zmodem_ready = 0; if (do_zcan) { vt_write_to_pty(vt_parser->pty, "**\x18\x18\x18\x18\x18\x18\x18\x18" "\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08", 20); } } static char *convert_to_locale_encoding(char *str, ef_parser_t *parser, vt_char_encoding_t encoding) { vt_char_encoding_t locale_encoding; char *new_str; size_t len = strlen(str); if ((locale_encoding = vt_get_char_encoding(bl_get_codeset())) == VT_UNKNOWN_ENCODING) { locale_encoding = encoding; } if (locale_encoding == encoding || (new_str = alloca(len * 2 + 1)) == NULL) { new_str = str; } else { if (parser) { (*parser->init)(parser); (*parser->set_str)(parser, str, len); new_str[vt_char_encoding_convert_with_parser(new_str, len * 2, locale_encoding, parser)] = '\0'; } else { new_str[vt_char_encoding_convert(new_str, len * 2, locale_encoding, str, len - 5, encoding)] = '\0'; } } return strdup(new_str); } /* --- global functions --- */ void vt_set_use_alt_buffer(int use) { use_alt_buffer = use; } void vt_set_unicode_noconv_areas(char *areas) { unicode_noconv_areas = set_area_to_table(unicode_noconv_areas, &num_unicode_noconv_areas, areas); } void vt_set_full_width_areas(char *areas) { full_width_areas = set_area_to_table(full_width_areas, &num_full_width_areas, areas); } void vt_set_half_width_areas(char *areas) { half_width_areas = set_area_to_table(half_width_areas, &num_half_width_areas, areas); } void vt_set_use_ttyrec_format(int use) { use_ttyrec_format = use; } #ifdef USE_LIBSSH2 void vt_set_use_scp_full(int use) { use_scp_full = use; } #endif void vt_set_recv_dir(const char *dir) { if (strstr(dir, "..")) { /* insecure dir name */ bl_msg_printf("%s is insecure dir name.\n", dir); } else { free(recv_dir); recv_dir = strdup(dir); } } void vt_set_timeout_read_pty(u_long timeout) { timeout_read_pty = timeout; } void vt_set_primary_da(char *da) { free(primary_da); primary_da = strdup(da); } void vt_set_secondary_da(char *da) { free(secondary_da); secondary_da = strdup(da); } void vt_set_local_echo_wait(u_int msec) { local_echo_wait_msec = msec; } void vt_parser_final(void) { vt_config_proto_final(); free(unicode_noconv_areas); num_unicode_noconv_areas = 0; free(full_width_areas); num_full_width_areas = 0; free(half_width_areas); num_half_width_areas = 0; vt_set_auto_detect_encodings(""); } vt_parser_t *vt_parser_new(vt_screen_t *screen, vt_termcap_ptr_t termcap, vt_char_encoding_t encoding, int is_auto_encoding, int use_auto_detect, int logging_vt_seq, vt_unicode_policy_t policy, u_int col_size_a, int use_char_combining, int use_multi_col_char, const char *win_name, const char *icon_name, int use_ansi_colors, vt_alt_color_mode_t alt_color_mode, vt_cursor_style_t cursor_style, int ignore_broadcasted_chars) { vt_parser_t *vt_parser; if ((vt_parser = calloc(1, sizeof(vt_parser_t))) == NULL) { return NULL; } vt_str_init(vt_parser->w_buf.chars, PTY_WR_BUFFER_SIZE); vt_parser->w_buf.output_func = vt_screen_overwrite_chars; vt_parser->pty_hook.self = vt_parser; vt_parser->screen = screen; vt_parser->termcap = termcap; vt_parser->log_file = -1; vt_parser->cs = UNKNOWN_CS; vt_parser->fg_color = VT_FG_COLOR; vt_parser->bg_color = VT_BG_COLOR; vt_parser->use_char_combining = use_char_combining; vt_parser->use_multi_col_char = use_multi_col_char; vt_parser->is_auto_encoding = is_auto_encoding; vt_parser->use_auto_detect = use_auto_detect; vt_parser->logging_vt_seq = logging_vt_seq; vt_parser->unicode_policy = policy; vt_parser->cursor_style = cursor_style; vt_parser->is_visible_cursor = 1; vt_parser->hide_pointer_mode = 2; /* Compatible with xterm 344 */ if ((vt_parser->cc_conv = vt_char_encoding_conv_new(encoding)) == NULL) { goto error; } if ((vt_parser->cc_parser = vt_char_encoding_parser_new(encoding)) == NULL) { goto error; } vt_parser->encoding = encoding; if (win_name) { vt_parser->win_name = strdup(win_name); } if (icon_name) { vt_parser->icon_name = strdup(icon_name); } vt_parser->gl = US_ASCII; vt_parser->g0 = US_ASCII; vt_parser->g1 = US_ASCII; set_col_size_of_width_a(vt_parser, col_size_a); /* Default value of modify_*_keys except modify_other_keys is 2. */ vt_parser->modify_cursor_keys = 2; vt_parser->modify_function_keys = 2; vt_parser->sixel_scrolling = 1; vt_parser->use_ansi_colors = use_ansi_colors; vt_parser->alt_color_mode = alt_color_mode; vt_parser->saved_vtmode_flags = vt_parser->vtmode_flags = INITIAL_VTMODE_FLAGS; vt_parser->ignore_broadcasted_chars = ignore_broadcasted_chars; return vt_parser; error: if (vt_parser->cc_conv) { (*vt_parser->cc_conv->destroy)(vt_parser->cc_conv); } if (vt_parser->cc_parser) { (*vt_parser->cc_parser->destroy)(vt_parser->cc_parser); } free(vt_parser); return NULL; } int vt_parser_destroy(vt_parser_t *vt_parser) { vt_str_final(vt_parser->w_buf.chars, PTY_WR_BUFFER_SIZE); (*vt_parser->cc_parser->destroy)(vt_parser->cc_parser); (*vt_parser->cc_conv->destroy)(vt_parser->cc_conv); destroy_drcs(vt_parser->drcs); destroy_all_macros(vt_parser); free(vt_parser->sixel_palette); if (vt_parser->log_file != -1) { close(vt_parser->log_file); } free(vt_parser->r_buf.chars); free(vt_parser->win_name); free(vt_parser->icon_name); free(vt_parser->saved_win_names.names); free(vt_parser->saved_icon_names.names); free(vt_parser); return 1; } void vt_parser_set_pty(vt_parser_t *vt_parser, vt_pty_t *pty) { #ifdef USE_LIBSSH2 /* See set_col_size_of_width_a() */ if (!vt_parser->pty && vt_pty_get_mode(pty) == PTY_MOSH) { #ifdef USE_WIN32API char *env = getenv("MOSH_AWIDTH"); if (!env) { putenv(vt_parser->col_size_of_width_a == 2 ? "MOSH_AWIDTH=2" : "MOSH_AWIDTH=1"); } else { vt_parser->col_size_of_width_a = (*env == '2' ? 2 : 1); } #else vt_parser->col_size_of_width_a = (wcwidth(0x25a0) == 2) ? 2 : 1; #endif } #endif vt_parser->pty = pty; } void vt_parser_set_xterm_listener(vt_parser_t *vt_parser, vt_xterm_event_listener_t *xterm_listener) { vt_parser->xterm_listener = xterm_listener; } void vt_parser_set_config_listener(vt_parser_t *vt_parser, vt_config_event_listener_t *config_listener) { vt_parser->config_listener = config_listener; } int vt_parse_vt100_sequence(vt_parser_t *vt_parser) { clock_t beg; if (vt_parser->is_transferring_data) { /* vt_parser->pty is always non-NULL value. */ transfer_data(vt_parser); return 1; } if (vt_screen_local_echo_wait(vt_parser->screen, local_echo_wait_msec)) { return 1; } if (!vt_parser->pty || receive_bytes(vt_parser) == 0) { return 0; } beg = clock(); start_vt100_cmd(vt_parser, 1); vt_screen_disable_local_echo(vt_parser->screen); /* * bidi and visual-indian is always stopped from here. * If you want to call {start|stop}_vt100_cmd (where vt_xterm_event_listener * is called), * the second argument of it shoule be 0. */ while (parse_vt100_sequence(vt_parser) && !vt_parser->is_transferring_data && /* (PTY_RD_BUFFER_SIZE / 2) is baseless. */ vt_parser->r_buf.filled_len >= (PTY_RD_BUFFER_SIZE / 2) && clock() - beg < timeout_read_pty && receive_bytes(vt_parser)) ; stop_vt100_cmd(vt_parser, 1); return 1; } int vt_parser_write_modified_key(vt_parser_t *vt_parser, int key, /* should be less than 0x80 */ int modcode) { if (vt_parser->modify_other_keys == 2) { char *buf; if (!((modcode - 1) == 1 /* is shift */ && (('!' <= key && key < 'A') || ('Z' < key && key < 'a') || ('z' < key && key <= '~'))) && (buf = alloca(10))) { sprintf(buf, "\x1b[%d;%du", key, modcode); vt_write_to_pty(vt_parser->pty, buf, strlen(buf)); return 1; } } return 0; } int vt_parser_write_special_key(vt_parser_t *vt_parser, vt_special_key_t key, int modcode, int is_numlock) { char *buf; if ((buf = vt_termcap_special_key_to_seq( vt_parser->termcap, key, modcode, (vt_parser->is_app_keypad && !is_numlock), vt_parser->is_app_cursor_keys, vt_parser->is_app_escape, vt_parser->modify_cursor_keys, vt_parser->modify_function_keys))) { vt_write_to_pty(vt_parser->pty, buf, strlen(buf)); return 1; } else { return 0; } } int vt_parser_write_loopback(vt_parser_t *vt_parser, const u_char *buf, size_t len) { return write_loopback(vt_parser, buf, len, 0, 1); } int vt_parser_show_message(vt_parser_t *vt_parser, char *msg) { char *buf; size_t len; if (!(buf = alloca((len = 3 + strlen(msg) + 4)))) { return 0; } if (vt_screen_is_local_echo_mode(vt_parser->screen)) { sprintf(buf, "\r\n%s\x1b[K", msg); return write_loopback(vt_parser, buf, len - 2, 0, -1); } else { sprintf(buf, "\x1b[H%s\x1b[K", msg); return write_loopback(vt_parser, buf, len - 1, 1, -1); } } #if 1 /* defined(__ANDROID__) || defined(__APPLE__) || defined(USE_SDL2) */ int vt_parser_preedit(vt_parser_t *vt_parser, const u_char *buf, size_t len) { if (!(vt_parser->line_style & LS_UNDERLINE)) { char *new_buf; size_t new_len; if ((new_buf = alloca((new_len = 4 + len + 5)))) { memcpy(new_buf, "\x1b[4m", 4); memcpy(new_buf + 4, buf, len); memcpy(new_buf + 4 + len, "\x1b[24m", 5); buf = new_buf; len = new_len; } } return write_loopback(vt_parser, buf, len, 1, 1); } #endif int vt_parser_local_echo(vt_parser_t *vt_parser, const u_char *buf, size_t len) { size_t count; if (len == 1) { if (vt_parser->prev_local_echo_char == buf[0]) { vt_screen_local_echo_wait(vt_parser->screen, 0); vt_parse_vt100_sequence(vt_parser); return 1; } else { vt_parser->prev_local_echo_char = buf[0]; } } else { vt_parser->prev_local_echo_char = 0; } for (count = 0; count < len; count++) { if (buf[count] < 0x20) { vt_screen_local_echo_wait(vt_parser->screen, 0); vt_parse_vt100_sequence(vt_parser); return 1; } } vt_parse_vt100_sequence(vt_parser); if (!(vt_parser->line_style & LS_UNDERLINE)) { char *new_buf; size_t new_len; if ((new_buf = alloca((new_len = 4 + len + 5)))) { memcpy(new_buf, "\x1b[4m", 4); memcpy(new_buf + 4, buf, len); memcpy(new_buf + 4 + len, "\x1b[24m", 5); buf = new_buf; len = new_len; } } return write_loopback(vt_parser, buf, len, 1, 1); } int vt_parser_change_encoding(vt_parser_t *vt_parser, vt_char_encoding_t encoding) { ef_parser_t *cc_parser; ef_conv_t *cc_conv; cc_conv = vt_char_encoding_conv_new(encoding); cc_parser = vt_char_encoding_parser_new(encoding); if (cc_parser == NULL || cc_conv == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " encoding not changed.\n"); #endif if (cc_parser) { (*cc_parser->destroy)(cc_parser); } if (cc_conv) { (*cc_conv->destroy)(cc_conv); } return 0; } #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " encoding changed.\n"); #endif (*vt_parser->cc_parser->destroy)(vt_parser->cc_parser); (*vt_parser->cc_conv->destroy)(vt_parser->cc_conv); vt_parser->encoding = encoding; vt_parser->cc_parser = cc_parser; vt_parser->cc_conv = cc_conv; /* reset */ vt_parser->gl = US_ASCII; vt_parser->g0 = US_ASCII; vt_parser->g1 = US_ASCII; vt_parser->is_so = 0; vt_parser->is_auto_encoding = 0; return 1; } size_t vt_parser_convert_to(vt_parser_t *vt_parser, u_char *dst, size_t len, ef_parser_t *parser) { return (*vt_parser->cc_conv->convert)(vt_parser->cc_conv, dst, len, parser); } void vt_init_encoding_parser(vt_parser_t *vt_parser) { (*vt_parser->cc_parser->init)(vt_parser->cc_parser); vt_parser->gl = US_ASCII; vt_parser->g0 = US_ASCII; vt_parser->g1 = US_ASCII; vt_parser->is_so = 0; } void vt_init_encoding_conv(vt_parser_t *vt_parser) { (*vt_parser->cc_conv->init)(vt_parser->cc_conv); /* * XXX * this causes unexpected behaviors in some applications(e.g. biew) , * but this is necessary , since 0x00 - 0x7f is not necessarily US-ASCII * in these encodings but key input or selection paste assumes that * 0x00 - 0x7f should be US-ASCII at the initial state. */ if (IS_STATEFUL_ENCODING(vt_parser->encoding)) { vt_init_encoding_parser(vt_parser); } } int vt_set_auto_detect_encodings(char *encodings) { char *p; u_int count; if (num_auto_detect_encodings > 0) { for (count = 0; count < num_auto_detect_encodings; count++) { (*auto_detect[count].parser->destroy)(auto_detect[count].parser); } free(auto_detect); num_auto_detect_encodings = 0; } free(auto_detect_encodings); if (*encodings == '\0') { auto_detect_encodings = NULL; return 1; } else { auto_detect_encodings = strdup(encodings); } if (!(auto_detect = malloc(sizeof(*auto_detect) * (bl_count_char_in_str(encodings, ',') + 1)))) { return 0; } while ((p = bl_str_sep(&encodings, ","))) { if ((auto_detect[num_auto_detect_encodings].encoding = vt_get_char_encoding(p)) != VT_UNKNOWN_ENCODING) { num_auto_detect_encodings++; } } if (num_auto_detect_encodings == 0) { free(auto_detect); return 0; } for (count = 0; count < num_auto_detect_encodings; count++) { auto_detect[count].parser = vt_char_encoding_parser_new(auto_detect[count].encoding); } return 1; } /* * XXX * ef_map_ucs4_to_iscii() in ef_ucs4_iscii.h is used directly in * vt_convert_to_internal_ch(), though it should be used internally in mef * library */ int ef_map_ucs4_to_iscii(ef_char_t *non_ucs, u_int32_t ucs4_code); /* * Return value * 1: Succeed * 0: Error * -1: Control sequence */ int vt_convert_to_internal_ch(vt_parser_t *vt_parser, ef_char_t *orig_ch) { ef_char_t ch; ch = *orig_ch; /* * UCS <-> OTHER CS */ if (ch.cs == ISO10646_UCS4_1) { u_char decsp; if ((vt_parser->unicode_policy & NOT_USE_UNICODE_BOXDRAW_FONT) && (decsp = vt_convert_ucs_to_decsp(ef_char_to_int(&ch)))) { ch.ch[0] = decsp; ch.size = 1; ch.cs = DEC_SPECIAL; ch.property = 0; } #if 1 /* See http://github.com/saitoha/drcsterm/ */ else if ((vt_parser->unicode_policy & USE_UNICODE_DRCS) && vt_convert_unicode_pua_to_drcs(&ch)) { if (ch.cs == US_ASCII) { vt_drcs_font_t *font; if ((font = vt_drcs_get_font(vt_parser->drcs, US_ASCII, 0)) && vt_drcs_is_picture(font, ch.ch[0])) { ch.cs = CS_REVISION_1(US_ASCII); } } /* * Go to end to skip 'if (ch.ch[0] == 0x7f) { return 0; }' in next block. * Otherwise, 0x10XX7f doesn't work. */ goto end_func; } #endif else { ef_char_t non_ucs; u_int32_t code = ef_char_to_int(&ch); ch.property = modify_ucs_property(code, vt_parser->col_size_of_width_a, ch.property); if (vt_parser->unicode_policy & NOT_USE_UNICODE_FONT) { /* convert ucs4 to appropriate charset */ if (!is_noconv_unicode(ch.ch) && ef_map_locale_ucs4_to(&non_ucs, &ch) && non_ucs.cs != ISO8859_6_R && /* ARABIC */ non_ucs.cs != ISO8859_8_R) /* HEBREW */ { /* Use width property of unicode (the original charset). */ non_ucs.property = ch.property; ch = non_ucs; goto end_block; } } #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_IND) if ((vt_parser->unicode_policy & CONVERT_UNICODE_TO_ISCII) && 0x900 <= code && code <= 0xd7f) { int ret = ef_map_ucs4_to_iscii(&non_ucs, code); if (!HAS_XTERM_LISTENER(vt_parser,check_iscii_font) || /* non_ucs.cs is set if ef_map_ucs4_to_iscii() fails. */ !(*vt_parser->xterm_listener->check_iscii_font)(vt_parser->xterm_listener->self, non_ucs.cs)) { goto end_block; } if (ret) { ch.ch[0] = non_ucs.ch[0]; ch.cs = non_ucs.cs; ch.size = 1; /* ch.property is not changed. */ } else { switch (code & 0x07f) { case 0x0c: ch.ch[0] = '\xa6'; break; case 0x3d: ch.ch[0] = '\xea'; break; case 0x44: ch.ch[0] = '\xdf'; break; case 0x50: ch.ch[0] = '\xa1'; break; case 0x58: ch.ch[0] = '\xb3'; break; case 0x59: ch.ch[0] = '\xb4'; break; case 0x5a: ch.ch[0] = '\xb5'; break; case 0x5b: ch.ch[0] = '\xba'; break; case 0x5c: ch.ch[0] = '\xbf'; break; case 0x5d: ch.ch[0] = '\xc0'; break; case 0x5e: ch.ch[0] = '\xc9'; break; case 0x60: ch.ch[0] = '\xaa'; break; case 0x61: ch.ch[0] = '\xa7'; break; case 0x62: ch.ch[0] = '\xdb'; break; case 0x63: ch.ch[0] = '\xdc'; break; default: goto end_block; } ch.ch[1] = '\xe9'; /* non_ucs.cs is set if ef_map_ucs4_to_iscii() fails. */ ch.cs = non_ucs.cs; ch.size = 2; /* ch.property is not changed. */ } } #endif end_block: ; } } else if (ch.cs != US_ASCII) { if ((vt_parser->unicode_policy & ONLY_USE_UNICODE_FONT) || /* XXX converting japanese gaiji to ucs. */ ch.cs == JISC6226_1978_NEC_EXT || ch.cs == JISC6226_1978_NECIBM_EXT || ch.cs == JISX0208_1983_MAC_EXT || ch.cs == SJIS_IBM_EXT || /* XXX converting RTL characters to ucs. */ ch.cs == ISO8859_6_R || /* Arabic */ ch.cs == ISO8859_8_R /* Hebrew */ #if 0 /* GB18030_2000 2-byte chars(==GBK) are converted to UCS */ || (encoding == VT_GB18030 && ch.cs == GBK) #endif ) { ef_char_t ucs; if (ef_map_to_ucs4(&ucs, &ch)) { u_int32_t code = ef_char_to_int(&ucs); ef_charset_t orig_cs = ch.cs; ch = ucs; /* Use width property of the original charset. */ ch.property = modify_ucs_property(code, vt_parser->col_size_of_width_a, ef_get_ucs_property(code)) & ~(EF_FULLWIDTH|EF_AWIDTH); if (IS_FULLWIDTH_CS(orig_cs)) { ch.property |= EF_FULLWIDTH; } } } else if (IS_FULLWIDTH_CS(ch.cs)) { ch.property |= EF_FULLWIDTH; } } if (ch.size == 1) { /* single byte cs */ vt_drcs_font_t *font; if ((ch.ch[0] == 0x0 || ch.ch[0] == 0x7f) && (!(font = vt_drcs_get_font(vt_parser->drcs, US_ASCII, 0)) || !(vt_drcs_is_picture(font, ch.ch[0])))) { /* DECNULM is always set => discarding 0x0 */ #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " 0x0/0x7f sequence is received , ignored...\n"); #endif return 0; } else if ((ch.ch[0] & 0x7f) <= 0x1f && ch.cs == US_ASCII) { /* Control sequence (C0 or C1) */ return -1; } if (vt_is_msb_set(ch.cs)) { SET_MSB(ch.ch[0]); } else { if (ch.cs == US_ASCII && vt_parser->gl != US_ASCII) { /* XXX prev_ch should not be static. */ static u_char prev_ch; static ef_charset_t prev_gl = US_ASCII; if (IS_CS94MB(vt_parser->gl)) { if (vt_parser->gl == prev_gl && prev_ch) { ch.ch[1] = ch.ch[0]; ch.ch[0] = prev_ch; ch.size = 2; ch.property = EF_FULLWIDTH; prev_ch = 0; prev_gl = US_ASCII; } else { prev_ch = ch.ch[0]; prev_gl = vt_parser->gl; return 0; } } ch.cs = vt_parser->gl; } if (ch.cs == DEC_SPECIAL) { u_int16_t ucs; if ((vt_parser->unicode_policy & ONLY_USE_UNICODE_BOXDRAW_FONT) && (ucs = vt_convert_decsp_to_ucs(ch.ch[0]))) { ef_int_to_bytes(ch.ch, 4, ucs); ch.size = 4; ch.cs = ISO10646_UCS4_1; ch.property = modify_ucs_property(ucs, vt_parser->col_size_of_width_a, ef_get_ucs_property(ucs)); } } } } else { /* * NON UCS <-> NON UCS */ /* multi byte cs */ /* * XXX hack * how to deal with johab 10-4-4(8-4-4) font ? * is there any uhc font ? */ if (ch.cs == JOHAB) { ef_char_t uhc; if (ef_map_johab_to_uhc(&uhc, &ch) == 0) { return 0; } ch = uhc; } /* * XXX * switching option whether this conversion is done should * be introduced. */ if (ch.cs == UHC) { ef_char_t ksc; if (ef_map_uhc_to_ksc5601_1987(&ksc, &ch) == 0) { return 0; } ch = ksc; } } end_func: *orig_ch = ch; return 1; } void vt_parser_set_alt_color_mode(vt_parser_t *vt_parser, vt_alt_color_mode_t mode) { vt_parser->alt_color_mode = mode; } void vt_set_broadcasting(int flag) { is_broadcasting = flag; } int vt_parser_is_broadcasting(vt_parser_t *vt_parser) { return (is_broadcasting && !vt_parser->ignore_broadcasted_chars); } int true_or_false(const char *str) { if (strcmp(str, "true") == 0) { return 1; } else if (strcmp(str, "false") == 0) { return 0; } else { return -1; } } int vt_parser_get_config( vt_parser_t *vt_parser, vt_pty_t *output, /* if vt_parser->pty == output, NULL is set */ char *key, int to_menu, int *flag) { char *value; char digit[DIGIT_STR_LEN(u_int) + 1]; char cwd[PATH_MAX]; if (strcmp(key, "encoding") == 0) { value = vt_get_char_encoding_name(vt_parser->encoding); } else if (strcmp(key, "is_auto_encoding") == 0) { if (vt_parser->is_auto_encoding) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "word_separators") == 0) { value = vt_get_word_separators(); } else if (strcmp(key, "regard_uri_as_word") == 0) { if (vt_get_regard_uri_as_word()) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "use_alt_buffer") == 0) { if (use_alt_buffer) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "vt_color_mode") == 0) { value = vt_get_color_mode(); } else if (strcmp(key, "use_ansi_colors") == 0) { if (vt_parser->use_ansi_colors) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "tabsize") == 0) { sprintf(digit, "%d", vt_screen_get_tab_size(vt_parser->screen)); value = digit; } else if (strcmp(key, "logsize") == 0) { if (vt_screen_log_size_is_unlimited(vt_parser->screen)) { value = "unlimited"; } else { sprintf(digit, "%d", vt_screen_get_log_size(vt_parser->screen)); value = digit; } } else if (strcmp(key, "static_backscroll_mode") == 0) { if (vt_get_backscroll_mode(vt_parser->screen) == BSM_STATIC) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "use_combining") == 0) { if (vt_parser->use_char_combining) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "col_size_of_width_a") == 0) { if (vt_parser->col_size_of_width_a == 2) { value = "2"; } else { value = "1"; } } else if (strcmp(key, "locale") == 0) { value = bl_get_locale(); } else if (strcmp(key, "pwd") == 0) { value = getcwd(cwd, sizeof(cwd)); } else if (strcmp(key, "logging_vt_seq") == 0) { if (vt_parser->logging_vt_seq) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "vt_seq_format") == 0) { if (use_ttyrec_format) { value = "ttyrec"; } else { value = "raw"; } } else if (strcmp(key, "rows") == 0) { sprintf(digit, "%d", vt_screen_get_logical_rows(vt_parser->screen)); value = digit; } else if (strcmp(key, "cols") == 0) { sprintf(digit, "%d", vt_screen_get_logical_cols(vt_parser->screen)); value = digit; } else if (strcmp(key, "not_use_unicode_font") == 0) { if (vt_parser->unicode_policy & NOT_USE_UNICODE_FONT) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "only_use_unicode_font") == 0) { if (vt_parser->unicode_policy & ONLY_USE_UNICODE_FONT) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "box_drawing_font") == 0) { if (vt_parser->unicode_policy & NOT_USE_UNICODE_BOXDRAW_FONT) { value = "decsp"; } else if (vt_parser->unicode_policy & ONLY_USE_UNICODE_BOXDRAW_FONT) { value = "unicode"; } else { value = "noconv"; } } else if (strcmp(key, "auto_detect_encodings") == 0) { if ((value = auto_detect_encodings) == NULL) { value = ""; } } else if (strcmp(key, "use_auto_detect") == 0) { if (vt_parser->use_auto_detect) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "allow_scp") == 0) { #ifdef USE_LIBSSH2 if (use_scp_full) { value = "true"; } else #endif { value = "false"; } } else if (strcmp(key, "unicode_noconv_areas") == 0) { response_area_table(vt_parser->pty, key, unicode_noconv_areas, num_unicode_noconv_areas, to_menu); return 1; } else if (strcmp(key, "unicode_full_width_areas") == 0) { response_area_table(vt_parser->pty, key, full_width_areas, num_full_width_areas, to_menu); return 1; } else if (strcmp(key, "unicode_half_width_areas") == 0) { response_area_table(vt_parser->pty, key, half_width_areas, num_half_width_areas, to_menu); return 1; } else if (strcmp(key, "blink_cursor") == 0) { if (vt_parser->cursor_style & CS_BLINK) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "ignore_broadcasted_chars") == 0) { if (vt_parser->ignore_broadcasted_chars) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "broadcast") == 0) { if (is_broadcasting) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "use_multi_column_char") == 0) { if (vt_parser->use_multi_col_char) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "old_drcs_sixel") == 0) { if (old_drcs_sixel) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "send_file") == 0) { if (send_file) { value = send_file; } else { value = ""; } } else if (strcmp(key, "receive_directory") == 0) { if (recv_dir) { value = recv_dir; } else { value = ""; } } else if (strcmp(key, "local_echo_wait") == 0) { sprintf(digit, "%d", local_echo_wait_msec); value = digit; } else if (strcmp(key, "challenge") == 0) { value = vt_get_proto_challenge(); if (to_menu < 0) { to_menu = 0; } } else { /* Continue to process it in x_screen.c */ return 0; } if (!output) { output = vt_parser->pty; } /* value is never set NULL above. */ #if 0 if (!value) { vt_response_config(output, "error", NULL, to_menu); } #endif if (flag) { *flag = value ? true_or_false(value) : -1; } else { vt_response_config(output, key, value, to_menu); } return 1; } /* Called in visual context */ int vt_parser_set_config(vt_parser_t *vt_parser, char *key, char *value) { if (strcmp(key, "encoding") == 0) { if (strcmp(value, "auto") == 0) { vt_parser->is_auto_encoding = strcasecmp(value, "auto") == 0 ? 1 : 0; } return 0; /* Continue to process it in x_screen.c */ } else if (strcmp(key, "logging_msg") == 0) { if (true_or_false(value) > 0) { bl_set_msg_log_file_name("mlterm/msg.log"); } else { bl_set_msg_log_file_name(NULL); } } else if (strcmp(key, "word_separators") == 0) { vt_set_word_separators(value); } else if (strcmp(key, "regard_uri_as_word") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { vt_set_regard_uri_as_word(flag); } } else if (strcmp(key, "vt_color_mode") == 0) { vt_set_color_mode(value); } else if (strcmp(key, "use_alt_buffer") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { use_alt_buffer = flag; } } else if (strcmp(key, "use_ansi_colors") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { vt_parser->use_ansi_colors = flag; } } else if (strcmp(key, "unicode_noconv_areas") == 0) { vt_set_unicode_noconv_areas(value); } else if (strcmp(key, "unicode_full_width_areas") == 0) { vt_set_full_width_areas(value); } else if (strcmp(key, "unicode_half_width_areas") == 0) { vt_set_half_width_areas(value); } else if (strcmp(key, "tabsize") == 0) { u_int tab_size; if (bl_str_to_uint(&tab_size, value)) { vt_screen_set_tab_size(vt_parser->screen, tab_size); } } else if (strcmp(key, "static_backscroll_mode") == 0) { vt_bs_mode_t mode; if (strcmp(value, "true") == 0) { mode = BSM_STATIC; } else if (strcmp(value, "false") == 0) { mode = BSM_DEFAULT; } else { return 1; } vt_set_backscroll_mode(vt_parser->screen, mode); } else if (strcmp(key, "use_combining") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { vt_parser->use_char_combining = flag; } } else if (strcmp(key, "col_size_of_width_a") == 0) { u_int size; if (strcmp(value, "switch") == 0) { size = vt_parser->col_size_of_width_a == 1 ? 2 : 1; } else if (!bl_str_to_uint(&size, value)) { goto end; } set_col_size_of_width_a(vt_parser, size); end: ; } else if (strcmp(key, "locale") == 0) { bl_locale_init(value); } else if (strcmp(key, "logging_vt_seq") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { vt_parser->logging_vt_seq = flag; } } else if (strcmp(key, "vt_seq_format") == 0) { use_ttyrec_format = (strcmp(value, "ttyrec") == 0); } else if (strcmp(key, "geometry") == 0) { u_int cols; u_int rows; if (sscanf(value, "%ux%u", &cols, &rows) == 2) { resize(vt_parser, cols, rows, 1); } } else if (strcmp(key, "box_drawing_font") == 0) { if (strcmp(value, "unicode") == 0) { vt_parser->unicode_policy &= ~NOT_USE_UNICODE_BOXDRAW_FONT; vt_parser->unicode_policy |= ONLY_USE_UNICODE_BOXDRAW_FONT; } else if (strcmp(value, "decsp") == 0) { vt_parser->unicode_policy &= ~ONLY_USE_UNICODE_BOXDRAW_FONT; vt_parser->unicode_policy |= NOT_USE_UNICODE_BOXDRAW_FONT; } else { vt_parser->unicode_policy &= (~NOT_USE_UNICODE_BOXDRAW_FONT & ~ONLY_USE_UNICODE_BOXDRAW_FONT); } } else if (strcmp(key, "auto_detect_encodings") == 0) { vt_set_auto_detect_encodings(value); } else if (strcmp(key, "use_auto_detect") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { vt_parser->use_auto_detect = flag; } } else if (strcmp(key, "blink_cursor") == 0) { if (strcmp(value, "true") == 0) { vt_parser->cursor_style |= CS_BLINK; } else { vt_parser->cursor_style &= ~CS_BLINK; } } else if (strcmp(key, "ignore_broadcasted_chars") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { vt_parser->ignore_broadcasted_chars = flag; } } else if (strcmp(key, "broadcast") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { is_broadcasting = flag; } } else if (strcmp(key, "use_multi_column_char") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { vt_parser->use_multi_col_char = flag; } } else if (strcmp(key, "old_drcs_sixel") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { old_drcs_sixel = flag; } } else if (strcmp(key, "local_echo_wait") == 0) { u_int msec; if (bl_str_to_uint(&msec, value)) { local_echo_wait_msec = msec; } } else if (strncmp(key, "send_file", 9) == 0) { if (strstr(value, "..")) { /* insecure file name */ bl_msg_printf("%s is insecure file name.\n", value); } else { if (key[9] == '\0') { free(send_file); send_file = convert_to_locale_encoding(value, vt_parser->cc_parser, vt_parser->encoding); } else if (strcmp(key + 9, "_utf8") == 0) { /* Hack for set_xdnd_config() in ui_screen.c */ free(send_file); send_file = convert_to_locale_encoding(value, NULL, VT_UTF8); } } } else { /* Continue to process it in x_screen.c */ return 0; } return 1; } /* Called in visual context */ int vt_parser_exec_cmd(vt_parser_t *vt_parser, char *cmd) { if (strcmp(cmd, "gen_proto_challenge") == 0) { vt_gen_proto_challenge(); } else if (strcmp(cmd, "full_reset") == 0) { vt_parser_reset(vt_parser, 0); } else if (strncmp(cmd, "snapshot", 8) == 0) { char **argv; int argc; if ((argv = bl_argv_alloca(cmd)) && bl_arg_str_to_array(argv, &argc, cmd)) { vt_char_encoding_t encoding; char *file; if (argc >= 3) { encoding = vt_get_char_encoding(argv[2]); } else { encoding = VT_UNKNOWN_ENCODING; } if (argc >= 2) { file = argv[1]; } else { /* skip /dev/ */ file = vt_pty_get_slave_name(vt_parser->pty) + 5; } if (strstr(file, "..")) { /* insecure file name */ bl_msg_printf("%s is insecure file name.\n", file); } else { snapshot(vt_parser, encoding, file, WCA_ALL); } } } else if (strcmp(cmd, "zmodem_start") == 0) { int count = 0; while (1) { if (!vt_pty_is_loopback(vt_parser->pty)) { if ((send_file || recv_dir || (recv_dir = bl_get_user_rc_path("mlterm/recv"))) && vt_transfer_start(send_file, recv_dir, 0, vt_screen_get_cols(vt_parser->screen) / 2 + 1)) { vt_parser->is_zmodem_ready = 0; vt_parser->is_transferring_data = (send_file ? 0x1 : 0x2); vt_parser->r_buf.left = 0; transfer_data(vt_parser); } else { transfer_cancel(vt_parser, 1); /* send_file is freed in vt_transfer_start() */ } send_file = NULL; break; } if (++count == 10) { bl_msg_printf("Retry zmodem_start.\n"); break; } bl_usleep(100000); } } #if !defined(NO_IMAGE) && defined(ENABLE_OSC5379PICTURE) else if (strncmp(cmd, "show_picture ", 13) == 0 || strncmp(cmd, "add_frame ", 10) == 0) { int clip_beg_col = 0; int clip_beg_row = 0; int clip_cols = 0; int clip_rows = 0; int img_cols = 0; int img_rows = 0; char **argv; int argc; if (!(argv = bl_argv_alloca(cmd)) || !bl_arg_str_to_array(argv, &argc, cmd) || argc == 1) { return 1; } if (argc >= 3) { int has_img_size; if (strchr(argv[argc - 1], '+')) { sscanf(argv[argc - 1], "%dx%d+%d+%d", &clip_cols, &clip_rows, &clip_beg_col, &clip_beg_row); has_img_size = (argc >= 4); } else { has_img_size = 1; } if (has_img_size) { sscanf(argv[2], "%dx%d", &img_cols, &img_rows); } } if (*argv[0] == 's') { show_picture(vt_parser, argv[1], clip_beg_col, clip_beg_row, clip_cols, clip_rows, img_cols, img_rows, 0); } else if (HAS_XTERM_LISTENER(vt_parser, add_frame_to_animation)) { (*vt_parser->xterm_listener->add_frame_to_animation)(vt_parser->xterm_listener->self, argv[1], &img_cols, &img_rows); } } #endif #ifdef USE_LIBSSH2 else if (strncmp(cmd, "scp ", 4) == 0) { char **argv; int argc; if ((argv = bl_argv_alloca(cmd)) && bl_arg_str_to_array(argv, &argc, cmd) && (argc == 3 || argc == 4)) { vt_char_encoding_t encoding; if (!argv[3] || (encoding = vt_get_char_encoding(argv[3])) == VT_UNKNOWN_ENCODING) { encoding = vt_parser->encoding; } vt_pty_ssh_scp(vt_parser->pty, vt_parser->encoding, encoding, argv[2], argv[1], use_scp_full, recv_dir, vt_screen_get_cols(vt_parser->screen) / 2 + 1); } } #endif else { return 0; } return 1; } /* * level=1: Unuse loopback, Output ZCAN. */ void vt_parser_reset(vt_parser_t *vt_parser, int level) { #ifdef USE_LIBSSH2 if (level >= 1) { if (vt_pty_is_loopback(vt_parser->pty)) { if (vt_pty_get_mode(vt_parser->pty) == PTY_MOSH) { vt_pty_mosh_set_use_loopback(vt_parser->pty, 0); } else { vt_pty_ssh_set_use_loopback(vt_parser->pty, 0); } } } #endif soft_reset(vt_parser); vt_parser->r_buf.left = 0; /* Reset DCS or OSC etc sequence */ vt_parser->sixel_scrolling = 1; transfer_cancel(vt_parser, level >= 1); } #define MOUSE_POS_LIMIT (0xff - 0x20) #define EXT_MOUSE_POS_LIMIT (0x7ff - 0x20) void vt_parser_report_mouse_tracking(vt_parser_t *vt_parser, int col, int row, int button, int is_released, /* is_released is 0 if PointerMotion */ int key_state, int button_state) { if (vt_parser->mouse_mode >= LOCATOR_CHARCELL_REPORT) { char seq[10 + DIGIT_STR_LEN(int)*4 + 1]; int ev; int is_outside_filter_rect; is_outside_filter_rect = 0; if (vt_parser->loc_filter.top > row || vt_parser->loc_filter.left > col || vt_parser->loc_filter.bottom < row || vt_parser->loc_filter.right < col) { vt_parser->loc_filter.top = vt_parser->loc_filter.bottom = row; vt_parser->loc_filter.left = vt_parser->loc_filter.right = col; if (vt_parser->locator_mode & LOCATOR_FILTER_RECT) { vt_parser->locator_mode &= ~LOCATOR_FILTER_RECT; is_outside_filter_rect = 1; } } if (button == 0) { if (is_outside_filter_rect) { ev = 10; } else if (vt_parser->locator_mode & LOCATOR_REQUEST) { ev = 1; } else { return; } } else { if ((is_released && !(vt_parser->locator_mode & LOCATOR_BUTTON_UP)) || (!is_released && !(vt_parser->locator_mode & LOCATOR_BUTTON_DOWN))) { return; } if (button == 1) { ev = is_released ? 3 : 2; } else if (button == 2) { ev = is_released ? 5 : 4; } else if (button == 3) { ev = is_released ? 7 : 6; } else { ev = 1; } } sprintf(seq, "\x1b[%d;%d;%d;%d;%d&w", ev, button_state, row, col, vt_screen_get_page_id(vt_parser->screen) + 1); vt_write_to_pty(vt_parser->pty, seq, strlen(seq)); if (vt_parser->locator_mode & LOCATOR_ONESHOT) { set_mouse_report(vt_parser, 0); vt_parser->locator_mode = 0; } } else { /* * Max length is SGR style => ESC [ < %d ; %d(col) ; %d(row) ; %c('M' or * 'm') NULL * 1 1 1 3 1 3 1 3 1 1 1 */ u_char seq[17]; size_t seq_len; if (is_released && vt_parser->ext_mouse_mode != EXTENDED_MOUSE_REPORT_SGR) { key_state = 0; button = 3; } else if (button == 0) { /* PointerMotion */ button = 3 + 32; } else { if (is_released) { /* for EXTENDED_MOUSE_REPORT_SGR */ key_state += 0x80; } button--; /* button1 == 0, button2 == 1, button3 == 2 */ while (button >= 3) { /* Wheel mouse */ key_state += 64; button -= 3; } } if (vt_parser->ext_mouse_mode == EXTENDED_MOUSE_REPORT_SGR) { sprintf(seq, "\x1b[<%d;%d;%d%c", (button + key_state) & 0x7f, col, row, ((button + key_state) & 0x80) ? 'm' : 'M'); seq_len = strlen(seq); } else if (vt_parser->ext_mouse_mode == EXTENDED_MOUSE_REPORT_URXVT) { sprintf(seq, "\x1b[%d;%d;%dM", 0x20 + button + key_state, col, row); seq_len = strlen(seq); } else { memcpy(seq, "\x1b[M", 3); seq[3] = 0x20 + button + key_state; if (vt_parser->ext_mouse_mode == EXTENDED_MOUSE_REPORT_UTF8) { int ch; u_char *p; p = seq + 4; if (col > EXT_MOUSE_POS_LIMIT) { col = EXT_MOUSE_POS_LIMIT; } if ((ch = 0x20 + col) >= 0x80) { *(p++) = ((ch >> 6) & 0x1f) | 0xc0; *(p++) = (ch & 0x3f) | 0x80; } else { *(p++) = ch; } if (row > EXT_MOUSE_POS_LIMIT) { row = EXT_MOUSE_POS_LIMIT; } if ((ch = 0x20 + row) >= 0x80) { *(p++) = ((ch >> 6) & 0x1f) | 0xc0; *p = (ch & 0x3f) | 0x80; } else { *p = ch; } seq_len = p - seq + 1; } else { seq[4] = 0x20 + (col < MOUSE_POS_LIMIT ? col : MOUSE_POS_LIMIT); seq[5] = 0x20 + (row < MOUSE_POS_LIMIT ? row : MOUSE_POS_LIMIT); seq_len = 6; } } vt_write_to_pty(vt_parser->pty, seq, seq_len); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " [reported cursor pos] %d %d\n", col, row); #endif } } mlterm-3.8.9/vtemu/vt_parser.h010064400017600000144000000340001356600660700150550ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_VT100_PARSER_H__ #define __VT_VT100_PARSER_H__ #include /* u_xxx */ #include #include #include "vt_pty.h" #include "vt_screen.h" #include "vt_char_encoding.h" #include "vt_drcs.h" #include "vt_termcap.h" #include "vt_config_proto.h" #define PTY_WR_BUFFER_SIZE 100 #if 0 #define ENABLE_OSC5379PICTURE #endif /* * Possible patterns are: * NOT_USE_UNICODE_FONT(0x1) * USE_UNICODE_PROPERTY(0x2) * NOT_USE_UNICODE_FONT|USE_UNICODE_PROPERTY(0x3) * ONLY_USE_UNICODE_FONT(0x4) */ typedef enum vt_unicode_policy { NO_UNICODE_POLICY = 0x0, NOT_USE_UNICODE_FONT = 0x1, ONLY_USE_UNICODE_FONT = 0x2, NOT_USE_UNICODE_BOXDRAW_FONT = 0x4, ONLY_USE_UNICODE_BOXDRAW_FONT = 0x8, USE_UNICODE_DRCS = 0x10, CONVERT_UNICODE_TO_ISCII = 0x20, UNICODE_POLICY_MAX } vt_unicode_policy_t; typedef enum vt_mouse_report_mode { NO_MOUSE_REPORT = 0, MOUSE_REPORT = 0x1, BUTTON_EVENT_MOUSE_REPORT = 0x2, ANY_EVENT_MOUSE_REPORT = 0x3, LOCATOR_CHARCELL_REPORT = 0x4, LOCATOR_PIXEL_REPORT = 0x5, } vt_mouse_report_mode_t; typedef enum vt_extended_mouse_report_mode { NO_EXTENDED_MOUSE_REPORT = 0, EXTENDED_MOUSE_REPORT_UTF8 = 0x1, EXTENDED_MOUSE_REPORT_SGR = 0x2, EXTENDED_MOUSE_REPORT_URXVT = 0x3, } vt_extended_mouse_report_mode_t; typedef enum vt_locator_report_mode { LOCATOR_BUTTON_DOWN = 0x1, LOCATOR_BUTTON_UP = 0x2, LOCATOR_ONESHOT = 0x4, LOCATOR_REQUEST = 0x8, LOCATOR_FILTER_RECT = 0x10, } vt_locator_report_mode_t; typedef enum vt_alt_color_mode { ALT_COLOR_BOLD = 0x1, ALT_COLOR_UNDERLINE = 0x2, ALT_COLOR_BLINKING = 0x4, ALT_COLOR_REVERSE = 0x8, ALT_COLOR_ITALIC = 0x10, ALT_COLOR_CROSSED_OUT = 0x20, } vt_alt_color_mode_t; typedef enum vt_cursor_style { CS_BLOCK = 0x0, CS_UNDERLINE = 0x1, CS_BAR = 0x2, CS_BLINK = 0x4, CS_BOX = 0x8, } vt_cursor_style_t; typedef struct vt_write_buffer { vt_char_t chars[PTY_WR_BUFFER_SIZE]; u_int filled_len; /* for "CSI b"(REP) sequence */ vt_char_t *last_ch; int (*output_func)(vt_screen_t *, vt_char_t *chars, u_int); } vt_write_buffer_t; typedef struct vt_read_buffer { u_char *chars; size_t len; size_t filled_len; size_t left; /* not parsed bytes */ size_t new_len; } vt_read_buffer_t; typedef struct vt_xterm_event_listener { void *self; void (*start)(void *); /* called in *visual* context. (Note that not logical) */ void (*stop)(void *); /* called in visual context. */ void (*interrupt)(void *); /* called in visual context. */ void (*resize)(void *, u_int, u_int, int); /* called in visual context. */ void (*reverse_video)(void *, int); /* called in visual context. */ void (*set_mouse_report)(void *); /* called in visual context. */ void (*request_locator)(void *); /* called in visual context. */ void (*set_window_name)(void *, u_char *); /* called in logical context. */ void (*set_icon_name)(void *, u_char *); /* called in logical context. */ void (*bel)(void *); /* called in visual context. */ int (*im_is_active)(void *); /* called in logical context. */ void (*switch_im_mode)(void *); /* called in logical context. */ void (*set_selection)(void *, vt_char_t *, u_int, u_char *); /* called in logical context. */ void (*get_display_size)(void *, u_int *, u_int *); /* called in logical context. */ void (*get_window_size)(void *, u_int *, u_int *); /* called in logical context. */ int (*get_rgb)(void *, u_int8_t *, u_int8_t *, u_int8_t *, vt_color_t); /* called in logical context. */ vt_char_t *(*get_picture_data)(void *, char *, int *, int *, int *, int *, u_int32_t **, int, int); /* called in logical context. */ int (*get_emoji_data)(void *, vt_char_t *, vt_char_t *); /* called in logical context. */ void (*show_tmp_picture)(void *, char *); /* called in logical context. */ #ifdef ENABLE_OSC5379PICTURE void (*add_frame_to_animation)(void *, char *, int *, int *);/* called in logical context. */ #endif int (*check_iscii_font)(void *, ef_charset_t); /* called in logical context. */ void (*lock_keyboard)(void *, int); /* called in logical context. */ } vt_xterm_event_listener_t; /* * !! Notice !! * Validation of Keys and vals is not checked before these event called by * vt_parser. */ typedef struct vt_config_event_listener { void *self; /* Assume that exec, set and get affect each window. */ int (*exec)(void *, char *); int (*set)(void *, char *, char *, char *); void (*get)(void *, char *, char *, int); /* Assume that saved, set_font and set_color affect all window. */ void (*saved)(void); /* Event that mlterm/main file was changed. */ void (*set_font)(void *, char *, char *, char *, int); void (*get_font)(void *, char *, char *, int); void (*set_color)(void *, char *, char *, char *, int); void (*get_color)(void *, char *, int); } vt_config_event_listener_t; typedef struct vt_parser *vt_parser_ptr_t; typedef struct vt_storable_states { int is_saved : 1; int is_bold : 1; int is_italic : 1; int is_reversed : 1; int is_blinking : 1; int is_invisible : 1; int is_protected : 1; int is_relative_origin : 1; int last_column_flag : 1; /* vt_line_style_t */ int line_style : 7; /* vt_color_t */ u_int16_t fg_color; /* vt_color_t */ u_int16_t bg_color; ef_charset_t cs; } vt_storable_states_t; typedef struct vt_saved_names { char **names; u_int num; } vt_saved_names_t; typedef struct vt_macro { u_char *str; int8_t is_sixel; u_int8_t sixel_num; } vt_macro_t; typedef struct vt_parser { vt_read_buffer_t r_buf; vt_write_buffer_t w_buf; vt_pty_t *pty; vt_pty_hook_t pty_hook; vt_screen_t *screen; vt_termcap_ptr_t termcap; ef_parser_t *cc_parser; /* char code parser */ ef_conv_t *cc_conv; /* char code converter */ /* vt_char_encoding_t */ u_int16_t encoding; /* ef_charset_t */ u_int16_t cs; /* vt_color_t */ u_int16_t fg_color; /* vt_color_t */ u_int16_t bg_color; vt_xterm_event_listener_t *xterm_listener; vt_config_event_listener_t *config_listener; int log_file; char *win_name; char *icon_name; struct { u_int16_t top; u_int16_t left; u_int16_t bottom; u_int16_t right; } loc_filter; struct { u_int16_t flags; u_int8_t fg[16]; u_int8_t bg[16]; } alt_colors; /* for save/restore cursor */ vt_storable_states_t saved_normal; vt_storable_states_t saved_alternate; vt_saved_names_t saved_win_names; vt_saved_names_t saved_icon_names; vt_drcs_t *drcs; vt_macro_t *macros; u_int num_macros; u_int32_t *sixel_palette; u_int64_t vtmode_flags; u_int64_t saved_vtmode_flags; /* vt_unicode_policy_t */ int8_t unicode_policy; /* vt_mouse_report_mode_t */ int8_t mouse_mode; /* vt_extended_mouse_report_mode_t */ int8_t ext_mouse_mode; /* vt_locator_report_mode_t */ int8_t locator_mode; /* vt_alt_color_mode_t */ int8_t alt_color_mode; u_int8_t col_size_of_width_a; /* 1 or 2 */ /* vt_cursor_style_t */ int8_t cursor_style; /* vt_line_style_t */ int8_t line_style; int8_t modify_cursor_keys; int8_t modify_function_keys; int8_t modify_other_keys; u_char prev_local_echo_char; u_int8_t hide_pointer_mode; /* Used for non iso2022 encoding */ /* ef_charset_t */ u_int16_t gl; /* ef_charset_t */ u_int16_t g0; /* ef_charset_t */ u_int16_t g1; /* XXX Use (vt_parser->xxxxx ? 1 : 0) in copying these flags to int, otherwise int is -1. */ int is_so : 1; int is_bold : 1; int is_italic : 1; int is_reversed : 1; int is_blinking : 1; int is_invisible : 1; int use_char_combining : 1; int use_multi_col_char : 1; int logging_vt_seq : 1; int is_app_keypad : 1; int is_app_cursor_keys : 1; int is_app_escape : 1; int is_bracketed_paste_mode : 1; int allow_deccolm : 1; int keep_screen_on_deccolm : 1; int want_focus_event : 1; int im_is_active : 1; int sixel_scrolling : 1; int cursor_to_right_of_sixel : 1; int yield : 1; int is_auto_encoding : 1; int use_auto_detect : 1; int is_visible_cursor : 1; int is_protected : 1; int ignore_broadcasted_chars : 1; int set_title_using_hex : 1; int get_title_using_hex : 1; int set_title_using_utf8 : 1; int get_title_using_utf8 : 1; int auto_cr : 1; int bold_affects_bg : 1; int use_ansi_colors : 1; int is_transferring_data : 2; /* 0x1=send 0x2=recv */ int is_zmodem_ready : 1; #ifdef USE_VT52 int is_vt52_mode : 1; #endif } vt_parser_t; void vt_set_use_alt_buffer(int use); void vt_set_unicode_noconv_areas(char *areas); void vt_set_full_width_areas(char *areas); void vt_set_half_width_areas(char *areas); void vt_set_use_ttyrec_format(int use); #ifdef USE_LIBSSH2 void vt_set_use_scp_full(int use); #else #define vt_set_use_scp_full(use) (0) #endif void vt_set_recv_dir(const char *dir); void vt_set_timeout_read_pty(u_long timeout); void vt_set_primary_da(char *da); void vt_set_secondary_da(char *da); void vt_set_local_echo_wait(u_int msec); #define vt_parser_init vt_config_proto_init void vt_parser_final(void); vt_parser_t *vt_parser_new(vt_screen_t *screen, vt_termcap_ptr_t termcap, vt_char_encoding_t encoding, int is_auto_encoding, int use_auto_detect, int logging_vt_seq, vt_unicode_policy_t policy, u_int col_size_a, int use_char_combining, int use_multi_col_char, const char *win_name, const char *icon_name, int use_ansi_colors, vt_alt_color_mode_t alt_color_mode, vt_cursor_style_t cursor_style, int ignore_broadcasted_chars); int vt_parser_destroy(vt_parser_t *vt_parser); void vt_parser_set_pty(vt_parser_t *vt_parser, vt_pty_t *pty); void vt_parser_set_xterm_listener(vt_parser_t *vt_parser, vt_xterm_event_listener_t *xterm_listener); void vt_parser_set_config_listener(vt_parser_t *vt_parser, vt_config_event_listener_t *config_listener); #define vt_parser_is_sending_data(parser) ((parser)->is_transferring_data & 0x1) #define vt_parser_is_transferring_data(parser) ((parser)->is_transferring_data) #define vt_parser_is_zmodem_ready(parser) ((parser)->is_zmodem_ready) int vt_parse_vt100_sequence(vt_parser_t *vt_parser); #define vt_parser_has_pending_sequence(vt_parser) \ ((vt_parser)->r_buf.left > 0 || (vt_parser)->is_transferring_data) int vt_parser_write_modified_key(vt_parser_t *vt_parser, int key, int modcode); int vt_parser_write_special_key(vt_parser_t *vt_parser, vt_special_key_t key, int modcode, int is_numlock); /* Must be called in visual context. */ int vt_parser_write_loopback(vt_parser_t *vt_parser, const u_char *buf, size_t len); /* Must be called in visual context. */ int vt_parser_show_message(vt_parser_t *vt_parser, char *msg); #if 1 /* defined(__ANDROID__) || defined(__APPLE__) || defined(USE_SDL2) */ /* Must be called in visual context. */ int vt_parser_preedit(vt_parser_t *vt_parser, const u_char *buf, size_t len); #endif /* Must be called in visual context. */ int vt_parser_local_echo(vt_parser_t *vt_parser, const u_char *buf, size_t len); int vt_parser_change_encoding(vt_parser_t *vt_parser, vt_char_encoding_t encoding); #define vt_parser_get_encoding(vt_parser) ((vt_parser)->encoding) size_t vt_parser_convert_to(vt_parser_t *vt_parser, u_char *dst, size_t len, ef_parser_t *parser); void vt_init_encoding_parser(vt_parser_t *vt_parser); void vt_init_encoding_conv(vt_parser_t *vt_parser); #define vt_get_window_name(vt_parser) ((vt_parser)->win_name) #define vt_get_icon_name(vt_parser) ((vt_parser)->icon_name) #define vt_parser_set_use_char_combining(vt_parser, use) \ ((vt_parser)->use_char_combining = (use)) #define vt_parser_is_using_char_combining(vt_parser) ((vt_parser)->use_char_combining) #define vt_parser_is_using_multi_col_char(vt_parser) ((vt_parser)->use_multi_col_char) #define vt_parser_get_mouse_report_mode(vt_parser) ((vt_parser)->mouse_mode) #define vt_parser_is_bracketed_paste_mode(vt_parser) \ ((vt_parser)->is_bracketed_paste_mode) #define vt_parser_want_focus_event(vt_parser) ((vt_parser)->want_focus_event) #define vt_parser_set_unicode_policy(vt_parser, policy) \ ((vt_parser)->unicode_policy = (policy)) #define vt_parser_get_unicode_policy(vt_parser) ((vt_parser)->unicode_policy) int vt_set_auto_detect_encodings(char *encodings); int vt_convert_to_internal_ch(vt_parser_t *vt_parser, ef_char_t *ch); #define vt_parser_select_drcs(vt_parser) vt_drcs_select((vt_parser)->drcs) void vt_parser_set_alt_color_mode(vt_parser_t *vt_parser, vt_alt_color_mode_t mode); #define vt_parser_get_alt_color_mode(vt_parser) ((vt_parser)->alt_color_mode) void vt_set_broadcasting(int flag); int vt_parser_is_broadcasting(vt_parser_t *vt_parser); int true_or_false(const char *str); int vt_parser_get_config(vt_parser_t *vt_parser, vt_pty_t *output, char *key, int to_menu, int *flag); int vt_parser_set_config(vt_parser_t *vt_parser, char *key, char *val); int vt_parser_exec_cmd(vt_parser_t *vt_parser, char *cmd); void vt_parser_reset(vt_parser_t *vt_parser, int level); void vt_parser_report_mouse_tracking(vt_parser_t *vt_parser, int col, int row, int button, int is_released, int key_state, int button_state); #define vt_parser_is_visible_cursor(vt_parser) ((vt_parser)->is_visible_cursor) #define vt_parser_get_cursor_style(vt_parser) ((vt_parser)->cursor_style) #define vt_parser_get_hide_pointer_mode(vt_parser) ((vt_parser)->hide_pointer_mode) #endif mlterm-3.8.9/vtemu/vt_pty.c010064400017600000144000000172221356600660700143770ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include "vt_pty_intern.h" #include #include /* realloc/alloca */ #include #include #include /* DIGIT_STR_LEN */ #include #include /* ttyname/pipe */ #include /* sscanf */ #include /* fcntl/O_BINARY */ #ifdef USE_WIN32API #include #else #include #endif #if 0 #define __DEBUG #endif /* --- global functions --- */ vt_pty_t *vt_pty_new(const char *cmd_path, /* can be NULL */ char **cmd_argv, /* can be NULL(only if cmd_path is NULL) */ char **env, /* can be NULL */ const char *host, /* DISPLAY env or remote host */ const char *work_dir, /* can be NULL */ const char *pass, /* can be NULL */ const char *pubkey, /* can be NULL */ const char *privkey, /* can be NULL */ u_int cols, u_int rows, u_int width_pix, u_int height_pix) { vt_pty_t *pty; #ifndef USE_WIN32API if (!pass) { pty = vt_pty_unix_new(cmd_path, cmd_argv, env, host, work_dir, cols, rows, width_pix, height_pix); } else #endif { #if defined(USE_LIBSSH2) if (strncmp(host, "mosh://", 7) == 0) { pty = vt_pty_mosh_new(cmd_path, cmd_argv, env, host + 7, pass, pubkey, privkey, cols, rows, width_pix, height_pix); } else { pty = vt_pty_ssh_new(cmd_path, cmd_argv, env, host, pass, pubkey, privkey, cols, rows, width_pix, height_pix); } #elif defined(USE_WIN32API) pty = vt_pty_pipe_new(cmd_path, cmd_argv, env, host, pass, cols, rows); #else pty = NULL; #endif } if (pty) { vt_config_menu_init(&pty->config_menu); } return pty; } vt_pty_t *vt_pty_new_with(int master, int slave, pid_t child_pid, u_int cols, u_int rows, u_int width_pix, u_int height_pix) { vt_pty_t *pty; #ifndef USE_WIN32API #if 1 struct stat st; if (fstat(master, &st) == 0 && (st.st_mode & S_IFCHR)) #else if (ptsname(master)) #endif { pty = vt_pty_unix_new_with(master, slave, child_pid, ":0.0", cols, rows, width_pix, height_pix); } else #endif { /* XXX vt_pty_ssh_new_with() and vt_pty_pipe_new_with() haven't been implemented yet. */ pty = NULL; } if (pty) { vt_config_menu_init(&pty->config_menu); } return pty; } int vt_pty_destroy(vt_pty_t *pty) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " vt_pty_destroy is called for %p.\n", pty); #endif if (pty->pty_listener && pty->pty_listener->closed) { (*pty->pty_listener->closed)(pty->pty_listener->self); } #ifdef DEBUG else { bl_debug_printf(BL_DEBUG_TAG " %s is not set.\n", pty->pty_listener ? "pty_listener->closed" : "pty listener"); } #endif free(pty->buf); free(pty->cmd_line); vt_config_menu_final(&pty->config_menu); (*pty->final)(pty); free(pty); return 1; } int vt_set_pty_winsize(vt_pty_t *pty, u_int cols, u_int rows, u_int width_pix, u_int height_pix) { return (*pty->set_winsize)(pty, cols, rows, width_pix, height_pix); } /* * Return size of lost bytes. */ size_t vt_write_to_pty(vt_pty_t *pty, u_char *buf, size_t len /* if 0, flushing buffer. */ ) { u_char *w_buf; size_t w_buf_size; ssize_t written_size; void *p; w_buf_size = pty->left + len; if (w_buf_size == 0) { return 0; } #if 0 /* * Little influence without this buffering. */ else if (len > 0 && w_buf_size < 16) { /* * Buffering until 16 bytes. */ if (pty->size < 16) { if ((p = realloc(pty->buf, 16)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed. %d characters not written.\n", len); #endif return len; } pty->size = 16; pty->buf = p; } memcpy(&pty->buf[pty->left], buf, len); pty->left = w_buf_size; #if 0 bl_debug_printf("buffered(not written) %d characters.\n", pty->left); #endif return 0; } #endif if (/* pty->buf && */ len == 0) { w_buf = pty->buf; } else if (/* pty->buf == NULL && */ pty->left == 0) { w_buf = buf; } else if ((w_buf = alloca(w_buf_size))) { memcpy(w_buf, pty->buf, pty->left); memcpy(&w_buf[pty->left], buf, len); } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " alloca() failed. %d characters not written.\n", len); #endif return len; } #ifdef __DEBUG { int i; for (i = 0; i < w_buf_size; i++) { bl_msg_printf("%.2x", w_buf[i]); } bl_msg_printf("\n"); } #endif if (pty->hook) { written_size = (*pty->hook->pre_write)(pty->hook->self, w_buf, w_buf_size); } written_size = (*pty->write)(pty, w_buf, w_buf_size); if (written_size < 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " write() failed.\n"); #endif written_size = 0; } if (written_size == w_buf_size) { pty->left = 0; return 0; } /* w_buf_size - written_size == not_written_size */ if (w_buf_size - written_size > pty->size) { if ((p = realloc(pty->buf, w_buf_size - written_size)) == NULL) { size_t lost; if (pty->size == 0) { lost = w_buf_size - written_size; pty->left = 0; } else { lost = w_buf_size - written_size - pty->size; memcpy(pty->buf, &w_buf[written_size], pty->size); pty->left = pty->size; } #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed. %d characters are not written.\n", lost); #endif return lost; } else { pty->size = pty->left = w_buf_size - written_size; pty->buf = p; } } else { pty->left = w_buf_size - written_size; } memcpy(pty->buf, &w_buf[written_size], pty->left); #if 0 bl_debug_printf("%d is not written.\n", pty->left); #endif return 0; } size_t vt_read_pty(vt_pty_t *pty, u_char *buf, size_t left) { size_t read_size; read_size = 0; while (1) { ssize_t ret; ret = (*pty->read)(pty, &buf[read_size], left); if (ret <= 0) { return read_size; } else { read_size += ret; left -= ret; } } } void vt_response_config(vt_pty_t *pty, char *key, char *value, int to_menu) { char *res; char *fmt; size_t res_len; res_len = 1 + strlen(key) + 1; if (value) { res_len += (1 + strlen(value)); fmt = "#%s=%s\n"; } else { fmt = "#%s\n"; } if (!(res = alloca(res_len + 1))) { res = "#error\n"; } sprintf(res, fmt, key, value); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s\n", res); #endif if (to_menu < 0) { if (pty->pty_listener && pty->pty_listener->show_config) { /* '\n' -> '\0' */ res[strlen(res) - 1] = '\0'; (*pty->pty_listener->show_config)(pty->pty_listener->self, res + 1); } } else if (to_menu > 0) { vt_config_menu_write(&pty->config_menu, res, res_len); } else { vt_write_to_pty(pty, res, res_len); } } /* * Always return non-NULL value. * XXX Static data can be returned. (Not reentrant) */ char *vt_pty_get_slave_name(vt_pty_t *pty) { static char virt_name[9 + DIGIT_STR_LEN(int)+1]; #ifndef USE_WIN32API char *name; if (pty->slave >= 0 && (name = ttyname(pty->slave))) { return name; } #endif /* Virtual pty name */ #ifdef USE_LIBSSH2 sprintf(virt_name, "/dev/vpty%d", ((pty->child_pid >> 1) & 0xfff)); /* child_pid == channel */ #else sprintf(virt_name, "/dev/vpty%d", pty->master); #endif return virt_name; } int vt_start_config_menu(vt_pty_t *pty, char *cmd_path, int x, int y, char *display) { return vt_config_menu_start(&pty->config_menu, cmd_path, x, y, display, pty); } mlterm-3.8.9/vtemu/vt_pty.h010064400017600000144000000105011356600660700143750ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_PTY_H__ #define __VT_PTY_H__ #include /* USE_WIN32API */ #include /* u_int/u_char */ #include "vt_config_menu.h" /* USE_MOSH is defined in vt_pty_mosh.cpp */ #if defined(USE_LIBSSH2) && !defined(USE_MOSH) #include "vt_char_encoding.h" /* * defined(__CYGWIN__) is not to link libpthread to mlterm for now. * * OPEN_PTY_SYNC is defined in java/Makefile.in * * Note that bl_dialog() in open_pty() in vt_term.c might cause segfault if * OPEN_PTY_ASYNC is defined on platforms other than WIN32GUI, */ #if (defined(USE_WIN32API) && !defined(OPEN_PTY_SYNC)) || \ (defined(HAVE_PTHREAD) && (defined(__CYGWIN__) || defined(__MSYS__))) #endif #endif /* USE_LIBSSH2 */ #ifdef __HAIKU__ #define OPEN_PTY_ASYNC #endif typedef enum { PTY_NONE, PTY_LOCAL, PTY_SSH, PTY_MOSH, PTY_PIPE, } vt_pty_mode_t; typedef struct vt_pty_event_listener { void *self; /* Called when vt_pty_destroy. */ void (*closed)(void *); void (*show_config)(void *, char *); } vt_pty_event_listener_t; typedef struct vt_pty_hook { void *self; size_t (*pre_write)(void *, u_char *, size_t); } vt_pty_hook_t; typedef struct vt_pty { int master; /* master pty fd */ int slave; /* slave pty fd */ pid_t child_pid; /* Used in vt_write_to_pty */ u_char *buf; size_t left; size_t size; int (*final)(struct vt_pty *); int (*set_winsize)(struct vt_pty *, u_int, u_int, u_int, u_int); ssize_t (*write)(struct vt_pty *, u_char*, size_t); ssize_t (*read)(struct vt_pty *, u_char*, size_t); vt_pty_event_listener_t *pty_listener; vt_pty_hook_t *hook; vt_config_menu_t config_menu; struct _stored { int master; int slave; ssize_t (*write)(struct vt_pty *, u_char*, size_t); ssize_t (*read)(struct vt_pty *, u_char*, size_t); u_int ref_count; } *stored; char *cmd_line; vt_pty_mode_t mode; } vt_pty_t; vt_pty_t *vt_pty_new(const char *cmd_path, char **cmd_argv, char **env, const char *host, const char *work_dir, const char *pass, const char *pubkey, const char *privkey, u_int cols, u_int rows, u_int width_pix, u_int height_pix); vt_pty_t *vt_pty_new_with(int master, int slave, pid_t child_pid, u_int cols, u_int rows, u_int width_pix, u_int height_pix); int vt_pty_destroy(vt_pty_t *pty); #define vt_pty_set_listener(pty, listener) ((pty)->pty_listener = listener) int vt_set_pty_winsize(vt_pty_t *pty, u_int cols, u_int rows, u_int width_pix, u_int height_pix); size_t vt_write_to_pty(vt_pty_t *pty, u_char *buf, size_t len); size_t vt_read_pty(vt_pty_t *pty, u_char *buf, size_t left); void vt_response_config(vt_pty_t *pty, char *key, char *value, int to_menu); #define vt_pty_get_pid(pty) ((pty)->child_pid) #define vt_pty_get_master_fd(pty) ((pty)->master) #define vt_pty_get_slave_fd(pty) ((pty)->slave) char *vt_pty_get_slave_name(vt_pty_t *pty); int vt_start_config_menu(vt_pty_t *pty, char *cmd_path, int x, int y, char *display); #define vt_pty_get_cmd_line(pty) ((pty)->cmd_line) #define vt_pty_set_hook(pty, hk) ((pty)->hook = hk) #define vt_pty_get_mode(pty) ((pty)->mode) #define vt_pty_is_loopback(pty) ((pty)->stored != NULL) #ifdef USE_LIBSSH2 #ifndef USE_MOSH void *vt_search_ssh_session(const char *host, const char *port, const char *user); int vt_pty_ssh_set_use_loopback(vt_pty_t *pty, int use); int vt_pty_ssh_scp(vt_pty_t *pty, vt_char_encoding_t pty_encoding, vt_char_encoding_t path_encoding, char *dst_path, char *src_path, int use_scp_full, const char *recv_dir, u_int progress_len); void vt_pty_ssh_set_cipher_list(const char *list); void vt_pty_ssh_set_keepalive_interval(u_int interval_sec); u_int vt_pty_ssh_keepalive(u_int spent_msec); void vt_pty_ssh_set_use_x11_forwarding(void *session, int use_x11_forwarding); int vt_pty_ssh_poll(void *fds); u_int vt_pty_ssh_get_x11_fds(int **fds); int vt_pty_ssh_send_recv_x11(int idx, int bidirection); void vt_pty_ssh_set_use_auto_reconnect(int flag); #ifdef USE_WIN32API void vt_pty_ssh_set_pty_read_trigger(void (*func)(void)); #endif #endif int vt_pty_mosh_set_use_loopback(vt_pty_t *pty, int use); #ifdef USE_WIN32API void vt_pty_mosh_set_pty_read_trigger(void (*func)(void)); #endif #endif #endif mlterm-3.8.9/vtemu/vt_pty_intern.h010064400017600000144000000027561356600660700157710ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_PTY_INTERN_H__ #define __VT_PTY_INTERN_H__ #include "vt_pty.h" /* See android/jni/ui_event_source.c */ #ifdef __ANDROID__ #undef vt_config_menu_write extern char *android_config_response; #define vt_config_menu_write(config_menu, buf, len) \ (android_config_response = strncpy(calloc(len + 1, 1), buf, len)) #endif vt_pty_t *vt_pty_unix_new(const char *cmd_path, char **cmd_argv, char **env, const char *host, const char *work_dir, u_int cols, u_int rows, u_int width_pix, u_int height_pix); vt_pty_t *vt_pty_unix_new_with(int master, int slave, pid_t child_pid, const char *host, u_int cols, u_int rows, u_int width_pix, u_int height_pix); vt_pty_t *vt_pty_ssh_new(const char *cmd_path, char **cmd_argv, char **env, const char *host, const char *pass, const char *pubkey, const char *privkey, u_int cols, u_int rows, u_int width_pix, u_int height_pix); vt_pty_t *vt_pty_pipe_new(const char *cmd_path, char **cmd_argv, char **env, const char *host, const char *pass, u_int cols, u_int rows); vt_pty_t *vt_pty_mosh_new(const char *cmd_path, char **cmd_argv, char **env, const char *host, const char *pass, const char *pubkey, const char *privkey, u_int cols, u_int rows, u_int width_pix, u_int height_pix); #endif mlterm-3.8.9/vtemu/vt_pty_mosh.c010064400017600000144000000047001356600660700154220ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_pty_intern.h" #ifndef NO_DYNAMIC_LOAD_SSH #include /* NULL */ #include #include #ifndef LIBDIR #define MOSHLIB_DIR "/usr/local/lib/mlterm/" #else #define MOSHLIB_DIR LIBDIR "/mlterm/" #endif #if 0 #define __DEBUG #endif /* --- static variables --- */ static vt_pty_t *(*mosh_new)(const char *, char **, char **, const char *, const char *, const char *, const char *, u_int, u_int, u_int, u_int); static int (*mosh_set_use_loopback)(vt_pty_t *, int); static int (*mosh_set_pty_read_trigger)(void (*func)(void)); static int is_tried; static bl_dl_handle_t handle; #ifdef USE_WIN32API static void (*trigger_pty_read)(void); #endif /* --- static functions --- */ static void load_library(void) { is_tried = 1; if (!(handle = bl_dl_open(MOSHLIB_DIR, "ptymosh")) && !(handle = bl_dl_open("", "ptymosh"))) { bl_error_printf("MOSH: Could not load.\n"); return; } bl_dl_close_at_exit(handle); mosh_new = bl_dl_func_symbol(handle, "vt_pty_mosh_new"); mosh_set_use_loopback = bl_dl_func_symbol(handle, "vt_pty_mosh_set_use_loopback"); #ifdef USE_WIN32API mosh_set_pty_read_trigger = bl_dl_func_symbol(handle, "vt_pty_mosh_set_pty_read_trigger"); if (trigger_pty_read) { vt_pty_mosh_set_pty_read_trigger(trigger_pty_read); } #endif } #endif /* --- global functions --- */ vt_pty_t *vt_pty_mosh_new(const char *cmd_path, char **cmd_argv, char **env, const char *uri, const char *pass, const char *pubkey, const char *privkey, u_int cols, u_int rows, u_int width_pix, u_int height_pix) { #ifndef NO_DYNAMIC_LOAD_SSH if (!is_tried) { load_library(); } if (mosh_new) { return (*mosh_new)(cmd_path, cmd_argv, env, uri, pass, pubkey, privkey, cols, rows, width_pix, height_pix); } #endif return NULL; } int vt_pty_mosh_set_use_loopback(vt_pty_t *pty, int use) { #ifndef NO_DYNAMIC_LOAD_SSH if (mosh_set_use_loopback) { return (*mosh_set_use_loopback)(pty, use); } #endif return 0; } #ifdef USE_WIN32API void vt_pty_mosh_set_pty_read_trigger(void (*func)(void)) { #ifndef NO_DYNAMIC_LOAD_SSH /* This function can be called before vt_pty_mosh_new() */ if (!is_tried) { trigger_pty_read = func; } else if (mosh_set_pty_read_trigger) { (*mosh_set_pty_read_trigger)(func); } #endif } #endif mlterm-3.8.9/vtemu/vt_pty_pipewin32.c010064400017600000144000000363121356600660700163000ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_pty_intern.h" #include #include #include /* close */ #include /* strchr/memcpy */ #include /* putenv/alloca */ #include #include /* realloc/alloca */ #include #include #include #if 0 #define __DEBUG #endif typedef struct vt_pty_pipe { vt_pty_t pty; HANDLE master_input; /* master read(stdout,stderr) */ HANDLE master_output; /* master write */ HANDLE slave_stdout; /* slave write */ HANDLE child_proc; int8_t is_plink; u_char rd_ch; int8_t rd_ready; HANDLE rd_ev; } vt_pty_pipe_t; static HANDLE* child_procs; /* Notice: The first element is "ADDED_CHILD" event */ static DWORD num_child_procs; static void (*trigger_pty_read)(void); /* --- static functions --- */ static DWORD WINAPI wait_child_exited(LPVOID thr_param) { DWORD ev; #ifdef __DEBUG bl_debug_printf("Starting wait_child_exited thread.\n"); #endif while (1) { ev = WaitForMultipleObjects(num_child_procs, child_procs, FALSE, INFINITE); if (ev > WAIT_OBJECT_0 && ev < WAIT_OBJECT_0 + num_child_procs) { #ifdef __DEBUG bl_debug_printf("%dth child exited.\n", ev); #endif /* XXX regarding pid_t as HANDLE */ bl_trigger_sig_child(child_procs[ev - WAIT_OBJECT_0]); CloseHandle(child_procs[ev - WAIT_OBJECT_0]); child_procs[ev - WAIT_OBJECT_0] = child_procs[--num_child_procs]; } if (num_child_procs == 1) { break; } } free(child_procs); num_child_procs = 0; child_procs = NULL; #ifdef __DEBUG bl_debug_printf("Exiting wait_child_exited thread.\n"); #endif ExitThread(0); return 0; } /* * Monitors handle for input. Exits when child exits or pipe is broken. */ static DWORD WINAPI wait_pty_read(LPVOID thr_param) { vt_pty_pipe_t *pty = (vt_pty_pipe_t*)thr_param; DWORD n_rd; #ifdef __DEBUG bl_debug_printf("Starting wait_pty_read thread.\n"); #endif while (1) { if (!ReadFile(pty->master_input, &pty->rd_ch, 1, &n_rd, NULL) || n_rd == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ReadFile() failed."); #endif if (GetLastError() == ERROR_BROKEN_PIPE) { /* * If slave_stdout member is not necessary, wait_child_exited * is called here and wait_child_exited thread becomes * unnecessary. (But master_input is never broken until * slave_stdout is closed even if child process exited, so * wait_child_exited thread is necessary.) */ #ifdef DEBUG bl_msg_printf(" ==> ERROR_BROKEN_PIPE."); #endif } #ifdef DEBUG bl_msg_printf("\n"); #endif break; } /* Exit GetMessage() in x_display_receive_next_event(). */ (*trigger_pty_read)(); WaitForSingleObject(pty->rd_ev, INFINITE); if (!pty->child_proc) { break; } #ifdef __DEBUG bl_debug_printf("Exit WaitForSingleObject\n"); #endif } #ifdef __DEBUG bl_debug_printf("Exiting wait_pty_read thread.\n"); #endif ExitThread(0); return 0; } static int pty_open(vt_pty_pipe_t *pty, const char *cmd_path, char *const cmd_argv[]) { HANDLE output_read_tmp, output_write; HANDLE input_write_tmp, input_read; HANDLE error_write; SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; STARTUPINFO si; char *cmd_line; output_read_tmp = input_write_tmp = output_write = input_read = error_write = 0; /* Set up the security attributes struct. */ sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* Create the child output pipe. */ if (!CreatePipe(&output_read_tmp, &output_write, &sa, 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreatePipe() failed.\n"); #endif return 0; } /* * Create a duplicate of the output write handle for the std error * write handle. This is necessary in case the child application * closes one of its std output handles. */ if (!DuplicateHandle(GetCurrentProcess(), output_write, GetCurrentProcess(), &error_write, 0, TRUE, DUPLICATE_SAME_ACCESS)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " DuplicateHandle() failed.\n"); #endif goto error1; } /* Create the child input pipe. */ if (!CreatePipe(&input_read, &input_write_tmp, &sa, 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreatePipe() failed.\n"); #endif goto error1; } /* * Create new output read handle and the input write handles. Set * the Properties to FALSE. Otherwise, the child inherits the * properties and, as a result, non-closeable handles to the pipes * are created. */ if (!DuplicateHandle(GetCurrentProcess(), output_read_tmp, GetCurrentProcess(), &pty->master_input, /* Address of new handle. */ 0, FALSE, /* Make it uninheritable. */ DUPLICATE_SAME_ACCESS)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " DuplicateHandle() failed.\n"); #endif goto error1; } else if (!DuplicateHandle(GetCurrentProcess(), input_write_tmp, GetCurrentProcess(), &pty->master_output, /* Address of new handle. */ 0, FALSE, /* Make it uninheritable. */ DUPLICATE_SAME_ACCESS)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " DuplicateHandle() failed.\n"); #endif CloseHandle(pty->master_input); goto error1; } /* * Close inheritable copies of the handles you do not want to be * inherited. * * !! Notice !! * After here, goto error2 if error happens. */ CloseHandle(output_read_tmp); CloseHandle(input_write_tmp); /* Set up the start up info struct. */ ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES | STARTF_FORCEOFFFEEDBACK; si.hStdOutput = output_write; si.hStdInput = input_read; si.hStdError = error_write; /* * Use this if you want to hide the child: * si.wShowWindow = SW_HIDE; * Note that dwFlags must include STARTF_USESHOWWINDOW if you want to * use the wShowWindow flags. */ if (cmd_argv) { int count; size_t cmd_line_len; /* Because cmd_path == cmd_argv[0], cmd_argv[0] is ignored. */ cmd_line_len = strlen(cmd_path) + 1; for (count = 1; cmd_argv[count] != NULL; count++) { cmd_line_len += (strlen(cmd_argv[count]) + 1); } if ((cmd_line = alloca(sizeof(char) * cmd_line_len)) == NULL) { CloseHandle(pty->master_input); CloseHandle(pty->master_output); goto error2; } strcpy(cmd_line, cmd_path); for (count = 1; cmd_argv[count] != NULL; count++) { strcat(cmd_line, " "); strcat(cmd_line, cmd_argv[count]); } } else { cmd_line = cmd_path; } if (!CreateProcess(cmd_path, cmd_line, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreateProcess() failed.\n"); #endif CloseHandle(pty->master_input); CloseHandle(pty->master_output); goto error2; } pty->slave_stdout = output_write; /* Set global child process handle to cause threads to exit. */ pty->child_proc = pi.hProcess; if (strstr(cmd_path, "plink")) { pty->is_plink = 1; } else { pty->is_plink = 0; } /* close unnecessary handles. */ CloseHandle(pi.hThread); CloseHandle(input_read); CloseHandle(error_write); return 1; error1: if (output_read_tmp) { CloseHandle(output_read_tmp); } if (input_write_tmp) { CloseHandle(input_write_tmp); } error2: if (output_write) { CloseHandle(output_write); } if (error_write) { CloseHandle(error_write); } if (input_read) { CloseHandle(input_read); } return 0; } static int final(vt_pty_t *p) { vt_pty_pipe_t *pty; int count; DWORD size; pty = (vt_pty_pipe_t*)p; /* * TerminateProcess must be called before CloseHandle. * If pty->child_proc is not in child_procs, pty->child_proc is already * closed in wait_child_exited, so TerminateProcess is not called. */ for (count = 0; count < num_child_procs; count++) { if (pty->child_proc == child_procs[count]) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Terminate process %d\n", pty->child_proc); #endif TerminateProcess(pty->child_proc, 0); break; } } /* Used to check if child process is dead or not in wait_pty_read. */ pty->child_proc = 0; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Trying to terminate wait_pty_read thread."); #endif /* * If wait_pty_read waits in ReadFile( pty->master_input), * CloseHandle( pty->master_input) causes process to be blocked. * (Even if child process exits, ReadFile in wait_pty_read doesn't * exit by ERROR_BROKEN_PIPE, because pty->slave_stdout remains * opened in parent process.) * Write a dummy data to child process, and wait_pty_read waits * in WaitForSingleObject(pty->rd_ev). * Then close pty->slave_stdout and set pty->rd_ev. * As a result, wait_pty_read thread exits. */ WriteFile(pty->slave_stdout, "", 1, &size, NULL); CloseHandle(pty->slave_stdout); SetEvent(pty->rd_ev); #ifdef __DEBUG bl_msg_printf(" => Finished.\n"); #endif CloseHandle(pty->master_input); CloseHandle(pty->master_output); CloseHandle(pty->rd_ev); return 1; } static int set_winsize(vt_pty_t *pty, u_int cols, u_int rows, u_int width_pix, u_int height_pix) { if (((vt_pty_pipe_t*)pty)->is_plink) { /* * XXX Hack */ u_char opt[5]; opt[0] = 0xff; opt[1] = (cols >> 8) & 0xff; opt[2] = cols & 0xff; opt[3] = (rows >> 8) & 0xff; opt[4] = rows & 0xff; vt_write_to_pty(pty, opt, 5); return 1; } return 0; } /* * Return size of lost bytes. */ static ssize_t write_to_pty(vt_pty_t *pty, u_char *buf, size_t len) { DWORD written_size; if (!WriteFile(((vt_pty_pipe_t*)pty)->master_output, buf, len, &written_size, NULL)) { if (GetLastError() == ERROR_BROKEN_PIPE) { return -1; } } FlushFileBuffers(((vt_pty_pipe_t*)pty)->master_output); return written_size; } static ssize_t read_pty(vt_pty_t *p, u_char *buf, size_t len) { vt_pty_pipe_t *pty; ssize_t n_rd; pty = (vt_pty_pipe_t*)p; if (pty->rd_ch == '\0' && !pty->rd_ready) { return 0; } if (pty->rd_ch != '\0') { buf[0] = pty->rd_ch; n_rd = 1; len--; pty->rd_ch = '\0'; pty->rd_ready = 1; } else { n_rd = 0; } while (len > 0) { DWORD ret; if (!PeekNamedPipe(pty->master_input, NULL, 0, NULL, &ret, NULL) || ret == 0 || !ReadFile(pty->master_input, &buf[n_rd], len, &ret, NULL) || ret == 0) { break; } n_rd += ret; len -= ret; } if (n_rd == 0) { SetEvent(pty->rd_ev); pty->rd_ready = 0; } #if 0 else { int i; for (i = 0; i < n_rd; i++) { if (buf[i] == 0xff) { bl_msg_printf("Server Option => "); bl_msg_printf("%d ", buf[i++]); if (i < n_rd) printf("%d ", buf[i++]); if (i < n_rd) printf("%d ", buf[i++]); if (i < n_rd) printf("%d ", buf[i++]); if (i < n_rd) printf("%d ", buf[i++]); } } } #endif return n_rd; } /* --- global functions --- */ vt_pty_t *vt_pty_pipe_new(const char *cmd_path, /* can be NULL */ char **cmd_argv, /* can be NULL(only if cmd_path is NULL) */ char **env, /* can be NULL */ const char *uri, const char *pass, u_int cols, u_int rows) { vt_pty_pipe_t *pty; HANDLE thrd; DWORD tid; char ev_name[25]; char *user; char *proto; char *host; char *port; int idx; if (num_child_procs == 0) { /* * Initialize child_procs array. */ if ((child_procs = malloc(sizeof(HANDLE))) == NULL) { return NULL; } child_procs[0] = CreateEvent(NULL, FALSE, FALSE, "ADDED_CHILD"); num_child_procs = 1; /* Launch the thread that wait for child exited. */ if (!(thrd = CreateThread(NULL, 0, wait_child_exited, NULL, 0, &tid))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreateThread() failed.\n"); #endif return NULL; } CloseHandle(thrd); } if ((pty = calloc(1, sizeof(vt_pty_pipe_t))) == NULL) { return NULL; } if (env) { while (*env) { char *p; char *key; char *val; if ((key = alloca(strlen(*env) + 1)) && (p = strchr(strcpy(key, *env), '='))) { *p = '\0'; val = ++p; SetEnvironmentVariable(key, val); #ifdef __DEBUG bl_debug_printf("Env: %s=%s\n", key, val); #endif } env++; } } if (!cmd_path || /* ! cmd_argv || */ (strstr(cmd_path, "plink") && cmd_argv[0] && !cmd_argv[1])) { char *p; if (!(cmd_argv = alloca(sizeof(char*) * 8)) || !(p = alloca(strlen(uri) + 1)) || !bl_parse_uri(&proto, &user, &host, &port, NULL, NULL, strcpy(p, uri))) { free(pty); return NULL; } if (!cmd_path) { cmd_path = "plink.exe"; } idx = 0; cmd_argv[idx++] = cmd_path; if (proto) { if ((p = alloca(strlen(proto) + 2))) { sprintf(p, "-%s", proto); cmd_argv[idx++] = p; /* -pw option can only be used with SSH. */ if (strcmp(proto, "ssh") == 0) { cmd_argv[idx++] = "-pw"; cmd_argv[idx++] = pass; } } } if (user || (user = getenv("USERNAME"))) { cmd_argv[idx++] = "-l"; cmd_argv[idx++] = user; } cmd_argv[idx++] = host; cmd_argv[idx++] = NULL; } if (!(pty_open(pty, cmd_path, cmd_argv))) { free(pty); return NULL; } snprintf(ev_name, sizeof(ev_name), "PTY_READ_READY%x", (int)pty->child_proc); pty->rd_ev = CreateEvent(NULL, FALSE, FALSE, ev_name); #ifdef __DEBUG bl_debug_printf("Created pty read event: %s\n", ev_name); #endif pty->pty.master = (int)pty->master_output; /* XXX Cast HANDLE => int */ pty->pty.slave = (int)pty->slave_stdout; /* XXX Cast HANDLE => int */ pty->pty.child_pid = (pid_t)pty->child_proc; /* Cast HANDLE => pid_t */ pty->pty.final = final; pty->pty.set_winsize = set_winsize; pty->pty.write = write_to_pty; pty->pty.read = read_pty; pty->pty.mode = PTY_PIPE; if (set_winsize(&pty->pty, cols, rows, 0, 0) == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_set_pty_winsize() failed.\n"); #endif } /* Launch the thread that read the child's output. */ if (!(thrd = CreateThread(NULL, 0, wait_pty_read, (LPVOID)pty, 0, &tid))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreateThread() failed.\n"); #endif vt_pty_destroy(&pty->pty); return NULL; } else { void *p; CloseHandle(thrd); /* Add to child_procs */ if (!(p = realloc(child_procs, sizeof(HANDLE) * (num_child_procs + 1)))) { vt_pty_destroy(&pty->pty); return NULL; } child_procs = p; child_procs[num_child_procs++] = pty->child_proc; /* * Exit WaitForMultipleObjects in wait_child_proc and do * WaitForMultipleObjects * again with new child_procs. */ SetEvent(child_procs[0]); #ifdef __DEBUG bl_warn_printf(BL_DEBUG_TAG " Added child procs NUM %d ADDED-HANDLE %d:%d.\n", num_child_procs, child_procs[num_child_procs - 1], pty->child_proc); #endif return &pty->pty; } } void vt_pty_set_pty_read_trigger(void (*func)(void)) { trigger_pty_read = func; } mlterm-3.8.9/vtemu/vt_pty_ssh.c010064400017600000144000000250041356600660700152510ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include /* bl_get_codeset() */ #ifdef NO_DYNAMIC_LOAD_SSH #include "libptyssh/vt_pty_ssh.c" #else /* NO_DYNAMIC_LOAD_SSH */ #include "vt_pty_intern.h" #include /* snprintf */ #include /* strcmp */ #include #include #include #include /* bl_basename */ #include /* alloca */ #include #ifndef LIBDIR #define SSHLIB_DIR "/usr/local/lib/mlterm/" #else #define SSHLIB_DIR LIBDIR "/mlterm/" #endif #if 0 #define __DEBUG #endif /* --- static variables --- */ static vt_pty_t *(*ssh_new)(const char *, char **, char **, const char *, const char *, const char *, const char *, u_int, u_int, u_int, u_int); static void *(*search_ssh_session)(const char *, const char *, const char *); static int (*ssh_set_use_loopback)(vt_pty_t *, int); static int (*ssh_scp)(vt_pty_t *, int, char *, char *, u_int); static void (*ssh_set_cipher_list)(const char *); static void (*ssh_set_keepalive_interval)(u_int); static u_int (*ssh_keepalive)(u_int); static void (*ssh_set_use_x11_forwarding)(void *, int); static int (*ssh_poll)(void *); static u_int (*ssh_get_x11_fds)(int **); static int (*ssh_send_recv_x11)(int, int); static void (*ssh_set_use_auto_reconnect)(int); #ifdef USE_WIN32API static int (*ssh_set_pty_read_trigger)(void (*func)(void)); #endif static int is_tried; static bl_dl_handle_t handle; /* * Not to load libptyssh.so until mlterm actually connects to a ssh server. * "mlterm 4460 child_info_fork::abort: address space needed by 'cygcrypto-1.0.0.dll' * (0x1660000) is already occupied" error may happen on startup without this. */ static u_int keepalive_interval_sec; static int auto_reconnect; #ifdef USE_WIN32API static void (*trigger_pty_read)(void); #endif /* --- static functions --- */ static void load_library(void) { is_tried = 1; if (!(handle = bl_dl_open(SSHLIB_DIR, "ptyssh")) && !(handle = bl_dl_open("", "ptyssh"))) { bl_error_printf("SSH: Could not load.\n"); return; } bl_dl_close_at_exit(handle); ssh_new = bl_dl_func_symbol(handle, "vt_pty_ssh_new"); search_ssh_session = bl_dl_func_symbol(handle, "vt_search_ssh_session"); ssh_set_use_loopback = bl_dl_func_symbol(handle, "vt_pty_ssh_set_use_loopback"); ssh_scp = bl_dl_func_symbol(handle, "vt_pty_ssh_scp_intern"); ssh_set_cipher_list = bl_dl_func_symbol(handle, "vt_pty_ssh_set_cipher_list"); ssh_set_keepalive_interval = bl_dl_func_symbol(handle, "vt_pty_ssh_set_keepalive_interval"); ssh_keepalive = bl_dl_func_symbol(handle, "vt_pty_ssh_keepalive"); ssh_set_use_x11_forwarding = bl_dl_func_symbol(handle, "vt_pty_ssh_set_use_x11_forwarding"); ssh_poll = bl_dl_func_symbol(handle, "vt_pty_ssh_poll"); ssh_get_x11_fds = bl_dl_func_symbol(handle, "vt_pty_ssh_get_x11_fds"); ssh_send_recv_x11 = bl_dl_func_symbol(handle, "vt_pty_ssh_send_recv_x11"); ssh_set_use_auto_reconnect = bl_dl_func_symbol(handle, "vt_pty_ssh_set_use_auto_reconnect"); if (keepalive_interval_sec > 0) { vt_pty_ssh_set_keepalive_interval(keepalive_interval_sec); keepalive_interval_sec = 0; } if (auto_reconnect) { vt_pty_ssh_set_use_auto_reconnect(1); auto_reconnect = 0; } #ifdef USE_WIN32API ssh_set_pty_read_trigger = bl_dl_func_symbol(handle, "vt_pty_ssh_set_pty_read_trigger"); if (trigger_pty_read) { vt_pty_ssh_set_pty_read_trigger(trigger_pty_read); } #endif } /* --- global functions --- */ vt_pty_t *vt_pty_ssh_new(const char *cmd_path, char **cmd_argv, char **env, const char *uri, const char *pass, const char *pubkey, const char *privkey, u_int cols, u_int rows, u_int width_pix, u_int height_pix) { if (!is_tried) { load_library(); } if (ssh_new) { return (*ssh_new)(cmd_path, cmd_argv, env, uri, pass, pubkey, privkey, cols, rows, width_pix, height_pix); } else { return NULL; } } void *vt_search_ssh_session(const char *host, const char *port, /* can be NULL */ const char *user /* can be NULL */ ) { if (search_ssh_session) { return (*search_ssh_session)(host, port, user); } else { return NULL; } } int vt_pty_ssh_set_use_loopback(vt_pty_t *pty, int use) { if (ssh_set_use_loopback) { return (*ssh_set_use_loopback)(pty, use); } else { return 0; } } void vt_pty_ssh_set_cipher_list(const char *list) { /* This function can be called before vt_pty_ssh_new() */ if (!is_tried) { load_library(); } if (ssh_set_cipher_list) { (*ssh_set_cipher_list)(list); } } void vt_pty_ssh_set_keepalive_interval(u_int interval_sec) { /* This function can be called before vt_pty_ssh_new() */ if (!is_tried) { keepalive_interval_sec = interval_sec; } else if (ssh_set_keepalive_interval) { (*ssh_set_keepalive_interval)(interval_sec); } } u_int vt_pty_ssh_keepalive(u_int spent_msec) { if (ssh_keepalive) { return (*ssh_keepalive)(spent_msec); } else { return keepalive_interval_sec * 1000; } } void vt_pty_ssh_set_use_x11_forwarding(void *session, int use) { /* This function can be called before vt_pty_ssh_new() */ if (!is_tried) { load_library(); } if (ssh_set_use_x11_forwarding) { (*ssh_set_use_x11_forwarding)(session, use); } } int vt_pty_ssh_poll(void *fds) { if (ssh_poll) { return (*ssh_poll)(fds); } else { return 0; } } u_int vt_pty_ssh_get_x11_fds(int **fds) { if (ssh_get_x11_fds) { return (*ssh_get_x11_fds)(fds); } else { return 0; } } int vt_pty_ssh_send_recv_x11(int idx, int bidirection) { if (ssh_send_recv_x11) { return (*ssh_send_recv_x11)(idx, bidirection); } else { return 0; } } void vt_pty_ssh_set_use_auto_reconnect(int use) { /* This function can be called before vt_pty_ssh_new() */ if (!is_tried) { auto_reconnect = use; } else if (ssh_set_use_auto_reconnect) { (*ssh_set_use_auto_reconnect)(use); } } #ifdef USE_WIN32API void vt_pty_ssh_set_pty_read_trigger(void (*func)(void)) { /* This function can be called before vt_pty_ssh_new() */ if (!is_tried) { trigger_pty_read = func; } else if (ssh_set_pty_read_trigger) { (*ssh_set_pty_read_trigger)(func); } } #endif #endif /* NO_DYNAMIC_LOAD_SSH */ int vt_pty_ssh_scp(vt_pty_t *pty, vt_char_encoding_t pty_encoding, /* Not VT_UNKNOWN_ENCODING */ vt_char_encoding_t path_encoding, /* Not VT_UNKNOWN_ENCODING */ char *dst_path, char *src_path, int use_scp_full, const char *recv_dir, u_int progress_len) { int dst_is_remote; int src_is_remote; char *file; char *_dst_path; char *_src_path; size_t len; char *p; vt_char_encoding_t locale_encoding; if (strncmp(dst_path, "remote:", 7) == 0) { dst_path += 7; dst_is_remote = 1; } else if (strncmp(dst_path, "local:", 6) == 0) { dst_path += 6; dst_is_remote = 0; } else { dst_is_remote = -1; } if (strncmp(src_path, "local:", 6) == 0) { src_path += 6; src_is_remote = 0; } else if (strncmp(src_path, "remote:", 7) == 0) { src_path += 7; src_is_remote = 1; } else { if (dst_is_remote == -1) { src_is_remote = 0; dst_is_remote = 1; } else { src_is_remote = (!dst_is_remote); } } if (dst_is_remote == -1) { dst_is_remote = (!src_is_remote); } else if (dst_is_remote == src_is_remote) { bl_msg_printf("SCP: Destination host(%s) and source host(%s) is the same.\n", dst_path, src_path); return 0; } if (vt_pty_is_loopback(pty) /* using loopback (mlconfig etc) */ || use_scp_full) { /* do nothing */ } else { if (!dst_is_remote) { if (recv_dir) { dst_path = recv_dir; } else { char *prefix = bl_get_home_dir(); if (!(p = alloca(strlen(prefix) + 13 + 1))) { return 0; } #ifdef USE_WIN32API sprintf(p, "%s\\mlterm\\recv", prefix); #else sprintf(p, "%s/.mlterm/recv", prefix); #endif dst_path = p; } bl_mkdir_for_file(dst_path, 0700); } else { /* mkdir ~/.mlterm/scp in advance on the remote host. */ dst_path = ".mlterm/recv"; } } /* scp /tmp/TEST /home/user => scp /tmp/TEST /home/user/TEST */ file = bl_basename(src_path); if ((p = alloca(strlen(dst_path) + strlen(file) + 2))) { #ifdef USE_WIN32API if (!dst_is_remote) { sprintf(p, "%s\\%s", dst_path, file); } else #endif { sprintf(p, "%s/%s", dst_path, file); } dst_path = p; } #if 0 bl_debug_printf("SCP: %s%s -> %s%s\n", src_is_remote ? "remote:" : "local:", src_path, dst_is_remote ? "remote:" : "local:", dst_path); #endif if (path_encoding != pty_encoding) { /* convert to terminal encoding */ len = strlen(dst_path); if ((_dst_path = alloca(len * 2 + 1))) { _dst_path[vt_char_encoding_convert(_dst_path, len * 2, pty_encoding, dst_path, len, path_encoding)] = '\0'; } len = strlen(src_path); if ((_src_path = alloca(len * 2 + 1))) { _src_path[vt_char_encoding_convert(_src_path, len * 2, pty_encoding, src_path, len, path_encoding)] = '\0'; } } else { _dst_path = dst_path; _src_path = src_path; } if ((locale_encoding = vt_get_char_encoding(bl_get_codeset())) == VT_UNKNOWN_ENCODING) { locale_encoding = path_encoding; } if (src_is_remote) { /* Remote: convert to terminal encoding */ if (_src_path) { src_path = _src_path; } /* Local: convert to locale encoding */ len = strlen(dst_path); if (locale_encoding != path_encoding && (p = alloca(len * 2 + 1))) { p[vt_char_encoding_convert(p, len * 2, locale_encoding, dst_path, len, path_encoding)] = '\0'; dst_path = p; } } else /* if( dst_is_remote) */ { /* Remote: convert to terminal encoding */ if (_dst_path) { dst_path = _dst_path; } /* Local: convert to locale encoding */ len = strlen(src_path); if (locale_encoding != path_encoding && (p = alloca(len * 2 + 1))) { p[vt_char_encoding_convert(p, len * 2, locale_encoding, src_path, len, path_encoding)] = '\0'; src_path = p; } } #ifdef NO_DYNAMIC_LOAD_SSH if (vt_pty_ssh_scp_intern(pty, src_is_remote, dst_path, src_path, progress_len)) #else if (ssh_scp && (*ssh_scp)(pty, src_is_remote, dst_path, src_path, progress_len)) #endif { return 1; } else { return 0; } } mlterm-3.8.9/vtemu/vt_pty_unix.c010064400017600000144000000122401356600660700154350ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_pty_intern.h" #include /* sprintf */ #include /* close */ #include #include #include /* signal/SIGWINCH */ #include /* strchr/memcpy */ #include /* putenv */ #include #include /* realloc/alloca */ #include /* strdup */ #include #include /* bl_basename */ #include /* bl_killpg */ #ifdef USE_UTMP #include #endif #ifdef __APPLE__ #include #include #endif #if 0 #define __DEBUG #endif typedef struct vt_pty_unix { vt_pty_t pty; #ifdef USE_UTMP bl_utmp_t utmp; #endif } vt_pty_unix_t; /* --- static functions --- */ static int final(vt_pty_t *pty) { #ifdef USE_UTMP if (((vt_pty_unix_t*)pty)->utmp) { bl_utmp_destroy(((vt_pty_unix_t*)pty)->utmp); } #endif #ifdef __DEBUG bl_debug_printf("PTY fd %d is closed\n", pty->master); #endif bl_pty_close(pty->master); close(pty->slave); return 1; } static int set_winsize(vt_pty_t *pty, u_int cols, u_int rows, u_int width_pix, u_int height_pix) { struct winsize ws; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " win size cols %d rows %d width %d height %d.\n", cols, rows, width_pix, height_pix); #endif ws.ws_col = cols; ws.ws_row = rows; ws.ws_xpixel = width_pix; ws.ws_ypixel = height_pix; if (ioctl(pty->master, TIOCSWINSZ, &ws) < 0) { #ifdef DBEUG bl_warn_printf(BL_DEBUG_TAG " ioctl(TIOCSWINSZ) failed.\n"); #endif return 0; } if (pty->child_pid > 1) { int pgrp; #ifdef TIOCGPGRP if (ioctl(pty->master, TIOCGPGRP, &pgrp) != -1) { if (pgrp > 0) { bl_killpg(pgrp, SIGWINCH); } } else #endif { bl_killpg(pty->child_pid, SIGWINCH); } } return 1; } static ssize_t write_to_pty(vt_pty_t *pty, u_char *buf, size_t len) { #ifdef __APPLE__ ssize_t ret; /* * XXX * If a child shell exits by 'exit' command, mlterm doesn't receive SIG_CHLD on * iOS 4.3 with japanese software keyboard. */ if ((ret = write(pty->master, buf, len)) < 0 && errno == EIO) { bl_trigger_sig_child(pty->child_pid); } return ret; #else return write(pty->master, buf, len); #endif } static ssize_t read_pty(vt_pty_t *pty, u_char *buf, size_t len) { return read(pty->master, buf, len); } /* --- global functions --- */ vt_pty_t *vt_pty_unix_new(const char *cmd_path, /* If NULL, child prcess is not exec'ed. */ char **cmd_argv, /* can be NULL(only if cmd_path is NULL) */ char **env, /* can be NULL */ const char *host, const char *work_dir, u_int cols, u_int rows, u_int width_pix, u_int height_pix) { vt_pty_t *pty; int master; int slave; pid_t pid; pid = bl_pty_fork(&master, &slave); if (pid == -1) { return NULL; } if (pid == 0) { /* child process */ if (work_dir) { chdir(work_dir); } /* reset signals and spin off the command interpreter */ signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGCHLD, SIG_DFL); signal(SIGPIPE, SIG_DFL); /* * setting environmental variables. */ if (env) { while (*env) { /* * an argument string of putenv() must be allocated memory. * (see SUSV2) */ putenv(strdup(*env)); env++; } } #if 0 /* * XXX is this necessary ? * * mimick login's behavior by disabling the job control signals. * a shell that wants them can turn them back on */ signal(SIGTSTP, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN); #endif if (!cmd_path) { goto return_pty; } if (strchr(cmd_path, '/') == NULL) { execvp(cmd_path, cmd_argv); } else { execv(cmd_path, cmd_argv); } #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " exec(%s) failed.\n", cmd_path); #endif exit(1); } /* parent process */ return_pty: if (!(pty = vt_pty_unix_new_with(master, slave, pid, host, cols, rows, width_pix, height_pix))) { close(master); close(slave); } return pty; } vt_pty_t *vt_pty_unix_new_with(int master, int slave, pid_t child_pid, const char *host, u_int cols, u_int rows, u_int width_pix, u_int height_pix) { vt_pty_t *pty; if ((pty = calloc(1, sizeof(vt_pty_unix_t))) == NULL) { return NULL; } pty->final = final; pty->set_winsize = set_winsize; pty->write = write_to_pty; pty->read = read_pty; pty->master = master; pty->slave = slave; pty->mode = PTY_LOCAL; if ((pty->child_pid = child_pid) > 0) { /* Parent process */ #ifdef USE_UTMP if ((((vt_pty_unix_t*)pty)->utmp = bl_utmp_new(vt_pty_get_slave_name(pty), host, pty->master)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG "utmp failed.\n"); #endif } #endif if (set_winsize(pty, cols, rows, width_pix, height_pix) == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_set_pty_winsize() failed.\n"); #endif } } return pty; } mlterm-3.8.9/vtemu/vt_screen.c010064400017600000144000001555751356600660700150600ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_screen.h" #include /* abs */ #include /* write */ #include #include #include /* malloc/free */ #include /* strdup */ #include /* BL_MIN */ #include "vt_char_encoding.h" #include "vt_str_parser.h" #define ROW_IN_LOGS(screen, row) (vt_get_num_logged_lines(&(screen)->logs) + row) #if 1 #define EXIT_BS_AT_BOTTOM #endif /* --- static variables --- */ static char *word_separators = " .,:;/|@()[]{}"; static int regard_uri_as_word = 0; /* --- static functions --- */ static int get_n_prev_char_pos(vt_screen_t *screen, int *char_index, int *row, int n) { int count; *char_index = vt_cursor_char_index(screen->edit); *row = vt_cursor_row(screen->edit); for (count = 0; count < n; count++) { if (*char_index == 0) { return 0; } (*char_index)--; } return 1; } static int is_word_separator(vt_char_t *ch) { char *p; char c; if (vt_char_cs(ch) != US_ASCII) { return 0; } p = word_separators; c = vt_char_code(ch); while (*p) { if (c == *p) { return 1; } p++; } return 0; } /* * callbacks of vt_edit_scroll_event_listener_t. */ /* * Don't operate vt_model_t in this function because vt_model_t is not scrolled * yet. * Operate vt_model_t in scrolled_out_lines_finished(). */ static void receive_scrolled_out_line(void *p, vt_line_t *line) { vt_screen_t *screen; screen = p; if (vt_status_line_is_focused(screen)) { return; } if (screen->screen_listener && screen->screen_listener->line_scrolled_out) { (*screen->screen_listener->line_scrolled_out)(screen->screen_listener->self); } if (screen->logvis) { (*screen->logvis->visual_line)(screen->logvis, line); } else { line->num_filled_chars = vt_line_get_num_filled_chars_except_sp_with_func(line, vt_char_equal); } vt_log_add(&screen->logs, line); /* XXX see vt_line_iscii_visual() */ #if 1 if (line->num_chars > vt_screen_get_logical_cols(screen)) { /* * line->num_filled_chars can be more than line->num_chars * without vt_line_reset() here because line is visualized. */ vt_line_reset(line); vt_line_set_updated(line); vt_str_final(line->chars + vt_screen_get_logical_cols(screen), line->num_chars - vt_screen_get_logical_cols(screen)); line->num_chars = vt_screen_get_logical_cols(screen); } else #endif { vt_line_set_size_attr(line, 0); } if (vt_screen_is_backscrolling(screen) == BSM_STATIC) { screen->backscroll_rows++; } if (screen->search) { screen->search->row--; } } static void scrolled_out_lines_finished(void *p) { vt_screen_t *screen; screen = p; if (vt_screen_is_backscrolling(screen) == BSM_DEFAULT) { vt_screen_set_modified_all(screen); } } static int window_scroll_upward_region(void *p, int beg_row, int end_row, u_int size) { vt_screen_t *screen; screen = p; if (screen->is_backscrolling) { /* * Not necessary to scrolling window. If backscroll_mode is BSM_DEFAULT, * vt_screen_set_modified_all() in scrolled_out_lines_finished() later. */ return 1; } if (!screen->screen_listener || !screen->screen_listener->window_scroll_upward_region) { return 0; } return (*screen->screen_listener->window_scroll_upward_region)(screen->screen_listener->self, beg_row, end_row, size); } static int window_scroll_downward_region(void *p, int beg_row, int end_row, u_int size) { vt_screen_t *screen; screen = p; if (screen->is_backscrolling) { /* * Not necessary to scrolling window. If backscroll_mode is BSM_DEFAULT, * vt_screen_set_modified_all() in scrolled_out_lines_finished() later. */ return 1; } if (!screen->screen_listener || !screen->screen_listener->window_scroll_downward_region) { return 0; } return (*screen->screen_listener->window_scroll_downward_region)(screen->screen_listener->self, beg_row, end_row, size); } static int modify_region(vt_screen_t *screen, /* visual */ int *end_char_index, int *end_row) { int row; vt_line_t *line; /* Removing empty lines of the end. */ row = *end_row; while ((line = vt_screen_get_line(screen, row)) == NULL || vt_line_is_empty(line)) { if (--row < 0 && abs(row) > vt_get_num_logged_lines(&screen->logs)) { return 0; } } if (row < *end_row) { if (vt_line_is_rtl(line)) { *end_char_index = vt_line_beg_char_index_regarding_rtl(line); } else { if ((*end_char_index = vt_line_get_num_filled_chars_except_sp(line)) > 0) { (*end_char_index)--; } } *end_row = row; } return 1; } static void convert_col_to_char_index(vt_screen_t *screen, /* visual */ vt_line_t *line, int *beg_char_index, int *end_char_index, /* end + 1 */ int beg_col, int end_col) { int padding; int beg; int end; u_int rest; if (vt_line_is_rtl(line) && (padding = vt_screen_get_cols(screen) - vt_line_get_num_filled_cols(line)) > 0) { beg_col -= padding; end_col -= padding; } *beg_char_index = vt_convert_col_to_char_index(line, &rest, beg_col, 0); if ((end = vt_line_get_num_filled_chars_except_sp(line)) <= *beg_char_index || (end == *beg_char_index + 1 && rest > 0)) { *beg_char_index = end; } else if ((beg = vt_line_beg_char_index_regarding_rtl(line)) > *beg_char_index) { *beg_char_index = beg; } *end_char_index = vt_convert_col_to_char_index(line, NULL, end_col, 0) + 1; if (end < *end_char_index) { *end_char_index = end; } } static int reverse_or_restore_color_rect(vt_screen_t *screen, /* visual */ int beg_col, int beg_row, int end_col, int end_row, int (*func)(vt_line_t *, int)) { int row; int beg_char_index; int end_char_index; vt_line_t *line; if (beg_col > end_col) { int col; col = beg_col; beg_col = end_col; end_col = col; } for (row = beg_row; row <= end_row; row++) { if ((line = vt_screen_get_line(screen, row))) { int char_index; convert_col_to_char_index(screen, line, &beg_char_index, &end_char_index, beg_col, end_col); for (char_index = beg_char_index; char_index < end_char_index; char_index++) { (*func)(line, char_index); } } } return 1; } static int reverse_or_restore_color(vt_screen_t *screen, /* visual */ int beg_char_index, int beg_row, int end_char_index, int end_row, int (*func)(vt_line_t *, int)) { /* * LTR line: a * ^beg ^end * RTL line: c * ^end ^beg * ^beg_regarding_rtl * <>: selected region */ int char_index; int row; vt_line_t *line; u_int size_except_sp; int beg_regarding_rtl; if (!modify_region(screen, &end_char_index, &end_row)) { return 0; } /* Removing empty lines of the beginning. */ row = beg_row; while (1) { if (!(line = vt_screen_get_line(screen, row)) || vt_line_is_empty(line)) { goto next_line; } size_except_sp = vt_line_get_num_filled_chars_except_sp(line); beg_regarding_rtl = vt_line_beg_char_index_regarding_rtl(line); if (vt_line_is_rtl(line)) { if (row > beg_row || beg_char_index >= size_except_sp) { beg_char_index = BL_MAX(size_except_sp, 1) - 1; } else if (beg_char_index < beg_regarding_rtl) { goto next_line; } } else { if (row > beg_row || beg_char_index < beg_regarding_rtl) { beg_char_index = beg_regarding_rtl; } else if (beg_char_index >= size_except_sp) { goto next_line; } } break; next_line: if (++row > end_row) { return 0; } } if (row < end_row) { if (vt_line_is_rtl(line)) { for (char_index = beg_regarding_rtl; char_index <= beg_char_index; char_index++) { (*func)(line, char_index); } } else { for (char_index = beg_char_index; char_index < size_except_sp; char_index++) { (*func)(line, char_index); } } for (row++; row < end_row; row++) { if (vt_line_is_empty((line = vt_screen_get_line(screen, row)))) { continue; } size_except_sp = vt_line_get_num_filled_chars_except_sp(line); for (char_index = vt_line_beg_char_index_regarding_rtl(line); char_index < size_except_sp; char_index++) { (*func)(line, char_index); } } if (vt_line_is_empty((line = vt_screen_get_line(screen, row)))) { return 1; } size_except_sp = vt_line_get_num_filled_chars_except_sp(line); beg_regarding_rtl = vt_line_beg_char_index_regarding_rtl(line); if (vt_line_is_rtl(line)) { beg_char_index = BL_MAX(size_except_sp, 1) - 1; } else { beg_char_index = beg_regarding_rtl; } } /* row == end_row */ if (vt_line_is_rtl(line)) { if (end_char_index < size_except_sp) { for (char_index = BL_MAX(end_char_index, beg_regarding_rtl); char_index <= beg_char_index; char_index++) { (*func)(line, char_index); } } } else { if (end_char_index >= beg_regarding_rtl) { for (char_index = beg_char_index; char_index < BL_MIN(end_char_index + 1, size_except_sp); char_index++) { (*func)(line, char_index); } } } return 1; } static u_int check_or_copy_region_rect( vt_screen_t *screen, /* visual */ vt_char_t *chars, /* Behavior is undefined if chars is insufficient. */ u_int num_chars, int beg_col, int beg_row, int end_col, int end_row) { int row; vt_line_t *line; u_int region_size; int beg_char_index; int end_char_index; if (beg_col > end_col) { int col; col = beg_col; beg_col = end_col; end_col = col; } region_size = 0; for (row = beg_row; row <= end_row; row++) { if ((line = vt_screen_get_line(screen, row))) { u_int size; convert_col_to_char_index(screen, line, &beg_char_index, &end_char_index, beg_col, end_col); size = end_char_index - beg_char_index; if (chars && num_chars >= region_size + size) { vt_line_copy_logical_str(line, chars + region_size, beg_char_index, size); } region_size += size; if (row < end_row) { if (chars && num_chars >= region_size + 1) { vt_char_copy(chars + region_size, vt_nl_ch()); } region_size++; } } } return region_size; } static u_int check_or_copy_region( vt_screen_t *screen, /* visual */ vt_char_t *chars, /* Behavior is undefined if chars is insufficient. */ u_int num_chars, int beg_char_index, /* can be over size_except_sp */ int beg_row, int end_char_index, /* can be over size_except_sp */ int end_row) { /* * LTR line: a * ^beg ^end * RTL line: c * ^end ^beg * ^beg_regarding_rtl * <>: selected region */ vt_line_t *line; u_int size; u_int region_size; u_int size_except_sp; int beg_regarding_rtl; int row; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "region: %d %d %d %d\n", beg_char_index, beg_row, end_char_index, end_row); #endif if (!modify_region(screen, &end_char_index, &end_row)) { return 0; } row = beg_row; /* Removing empty lines of the beginning. */ while (1) { if (!(line = vt_screen_get_line(screen, row)) || vt_line_is_empty(line)) { goto next_line; } size_except_sp = vt_line_get_num_filled_chars_except_sp(line); beg_regarding_rtl = vt_line_beg_char_index_regarding_rtl(line); if (vt_line_is_rtl(line)) { if (row > beg_row || beg_char_index >= size_except_sp) { beg_char_index = BL_MAX(size_except_sp, 1) - 1; } else if (beg_char_index < beg_regarding_rtl) { goto next_line; } } else { if (row > beg_row || beg_char_index < beg_regarding_rtl) { beg_char_index = beg_regarding_rtl; } else if (beg_char_index >= size_except_sp) { goto next_line; } } break; next_line: if (++row > end_row) { return 0; } } region_size = 0; if (row < end_row) { if (vt_line_is_rtl(line)) { size = beg_char_index - beg_regarding_rtl + 1; if (chars && num_chars >= region_size + size) { vt_line_copy_logical_str(line, chars + region_size, beg_regarding_rtl, size); } } else { size = size_except_sp - beg_char_index; if (chars && num_chars >= region_size + size) { vt_line_copy_logical_str(line, chars + region_size, beg_char_index, size); } } region_size += size; if (!vt_line_is_continued_to_next(line)) { if (chars && num_chars > region_size) { vt_char_copy(chars + region_size, vt_nl_ch()); } region_size++; } for (row++; row < end_row; row++) { line = vt_screen_get_line(screen, row); beg_regarding_rtl = vt_line_beg_char_index_regarding_rtl(line); size = vt_line_get_num_filled_chars_except_sp(line) - beg_regarding_rtl; if (chars && num_chars >= region_size + size) { vt_line_copy_logical_str(line, chars + region_size, beg_regarding_rtl, size); } region_size += size; if (!vt_line_is_continued_to_next(line)) { if (chars && num_chars > region_size) { vt_char_copy(chars + region_size, vt_nl_ch()); } region_size++; } } if (vt_line_is_empty((line = vt_screen_get_line(screen, row)))) { return region_size; } size_except_sp = vt_line_get_num_filled_chars_except_sp(line); beg_regarding_rtl = vt_line_beg_char_index_regarding_rtl(line); if (vt_line_is_rtl(line)) { beg_char_index = BL_MAX(size_except_sp, 1) - 1; } else { beg_char_index = beg_regarding_rtl; } } /* row == end_row */ if (size_except_sp == 0) { /* do nothing */ } else if (vt_line_is_rtl(line)) { if (end_char_index < size_except_sp) { if (end_char_index < beg_regarding_rtl) { end_char_index = beg_regarding_rtl; } size = beg_char_index - end_char_index + 1; if (chars && num_chars >= region_size + size) { vt_line_copy_logical_str(line, chars + region_size, end_char_index, size); } region_size += size; } } else { if (end_char_index >= beg_regarding_rtl) { if (end_char_index >= size_except_sp) { end_char_index = size_except_sp - 1; } size = end_char_index - beg_char_index + 1; if (chars && num_chars >= region_size + size) { vt_line_copy_logical_str(line, chars + region_size, beg_char_index, size); } region_size += size; } } return region_size; } static u_int32_t get_msec_time(void) { #ifdef HAVE_GETTIMEOFDAY struct timeval tv; gettimeofday(&tv, NULL); /* XXX '/ 1000' => '>> 10' and '* 1000' => '<< 10' */ return (tv.tv_sec << 10) + (tv.tv_usec >> 10); #else return time(NULL) << 10; #endif } static void change_edit(vt_screen_t *screen, vt_edit_t *edit) { vt_screen_disable_local_echo(screen); if (edit != screen->status_edit) { if (screen->logvis) { (*screen->logvis->init)(screen->logvis, &edit->model, &edit->cursor); } if (screen->main_edit) { screen->main_edit = edit; } if (screen->edit != screen->status_edit) { vt_edit_set_modified_all(edit); } } else { screen->main_edit = screen->edit; } edit->bce_ch = screen->edit->bce_ch; screen->edit = edit; } static vt_edit_t *get_edit(vt_screen_t *screen, u_int page_id) { if (page_id == 0) { if (vt_screen_is_alternative_edit(screen)) { return &screen->alt_edit; } else { return &screen->normal_edit; } } else if (page_id <= MAX_PAGE_ID) { if (screen->page_edits == NULL) { int count; if (!(screen->page_edits = malloc(sizeof(vt_edit_t) * MAX_PAGE_ID))) { return NULL; } for (count = 0; count < MAX_PAGE_ID; count++) { vt_edit_init(screen->page_edits + count, &screen->edit_scroll_listener, vt_edit_get_cols(&screen->normal_edit), vt_edit_get_rows(&screen->normal_edit), vt_edit_get_tab_size(&screen->normal_edit), 1, screen->normal_edit.use_bce); } } return screen->page_edits + (page_id - 1); } return NULL; } static vt_edit_t *status_edit_new(vt_edit_t *main_edit) { vt_edit_t *status_edit; if ((status_edit = malloc(sizeof(vt_edit_t)))) { vt_edit_init(status_edit, main_edit->scroll_listener, vt_edit_get_cols(main_edit), 1, vt_edit_get_tab_size(main_edit), 1, main_edit->use_bce); } return status_edit; } /* --- global functions --- */ void vt_set_word_separators(const char *seps) { static char *default_word_separators; if (default_word_separators) { if (word_separators != default_word_separators) { free(word_separators); } if (seps == NULL || *seps == '\0') { /* Fall back to default. */ word_separators = default_word_separators; return; } } else if (seps == NULL || *seps == '\0') { /* Not changed */ return; } else { /* Store the default value. */ default_word_separators = word_separators; } word_separators = bl_str_unescape(seps); } char *vt_get_word_separators(void) { return word_separators; } void vt_set_regard_uri_as_word(int flag) { regard_uri_as_word = flag; } int vt_get_regard_uri_as_word(void) { return regard_uri_as_word; } vt_screen_t *vt_screen_new(u_int cols, u_int rows, u_int tab_size, u_int num_log_lines, int use_bce, vt_bs_mode_t bs_mode) { vt_screen_t *screen; if ((screen = calloc(1, sizeof(vt_screen_t))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc failed.\n"); #endif return NULL; } screen->edit_scroll_listener.self = screen; screen->edit_scroll_listener.receive_scrolled_out_line = receive_scrolled_out_line; screen->edit_scroll_listener.scrolled_out_lines_finished = scrolled_out_lines_finished; screen->edit_scroll_listener.window_scroll_upward_region = window_scroll_upward_region; screen->edit_scroll_listener.window_scroll_downward_region = window_scroll_downward_region; if (!vt_edit_init(&screen->normal_edit, &screen->edit_scroll_listener, cols, rows, tab_size, 1, use_bce)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_edit_init(normal_edit) failed.\n"); #endif goto error1; } if (!vt_edit_init(&screen->alt_edit, &screen->edit_scroll_listener, cols, rows, tab_size, 0, use_bce)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_edit_init(alt_edit) failed.\n"); #endif goto error2; } screen->edit = &screen->normal_edit; if (!vt_log_init(&screen->logs, num_log_lines)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_log_init failed.\n"); #endif goto error3; } screen->backscroll_mode = bs_mode; return screen; error3: vt_edit_final(&screen->normal_edit); error2: vt_edit_final(&screen->alt_edit); error1: free(screen); return NULL; } int vt_screen_destroy(vt_screen_t *screen) { /* * this should be done before vt_edit_final() since termscr->logvis refers * to vt_edit_t and may have some data structure for it. */ if (screen->logvis) { (*screen->logvis->logical)(screen->logvis); (*screen->logvis->destroy)(screen->logvis); } vt_edit_final(&screen->normal_edit); vt_edit_final(&screen->alt_edit); if (screen->page_edits) { int count; for (count = 0; count < MAX_PAGE_ID; count++) { vt_edit_final(screen->page_edits + count); } free(screen->page_edits); } if (screen->status_edit) { vt_edit_final(screen->status_edit); free(screen->status_edit); } vt_log_final(&screen->logs); vt_screen_search_final(screen); free(screen); return 1; } void vt_screen_set_listener(vt_screen_t *screen, vt_screen_event_listener_t *screen_listener) { screen->screen_listener = screen_listener; } /* This considers status line ('rows' contains status line) */ int vt_screen_resize(vt_screen_t *screen, u_int cols, u_int rows, int pack) { u_int old_rows = vt_edit_get_rows(&screen->normal_edit); if (screen->status_edit) { vt_edit_resize(screen->status_edit, cols, 1); if (vt_screen_has_status_line(screen) && rows >= 2) { rows--; } } vt_edit_resize(&screen->normal_edit, cols, rows); vt_edit_resize(&screen->alt_edit, cols, rows); if (screen->stored_edit) { vt_edit_resize(&screen->stored_edit->edit, cols, rows); } if (screen->page_edits) { int count; for (count = 0; count < MAX_PAGE_ID; count++) { vt_edit_resize(screen->page_edits + count, cols, rows); } } if (pack && rows > old_rows) { u_int n_scroll = vt_get_num_logged_lines(&screen->logs); if (n_scroll > 0) { u_int count; if (n_scroll > rows - old_rows) { n_scroll = rows - old_rows; } vt_edit_scroll_downward(&screen->normal_edit, n_scroll); for (count = 0; count < n_scroll; count++) { vt_line_t *src = vt_log_get(&screen->logs, vt_get_num_logged_lines(&screen->logs) - n_scroll + count); vt_line_t *dst = vt_edit_get_line(&screen->normal_edit, count); /* vt_screen_resize() is always called in logical context. */ vt_line_ctl_logical(src); vt_line_copy(dst, src); vt_line_set_modified_all(dst); vt_edit_go_downward(&screen->normal_edit, 0); } vt_log_rollback_index(&screen->logs, n_scroll); return 2; } } return 1; } /* This considers status line */ int vt_screen_cursor_row(vt_screen_t *screen) { int row = vt_cursor_row(screen->edit); if (vt_status_line_is_focused(screen)) { row += vt_edit_get_rows(screen->main_edit); } return row; } /* This considers status line */ int vt_screen_cursor_row_in_screen(vt_screen_t *screen) { int row = vt_screen_cursor_row(screen); if (screen->backscroll_rows > 0) { if ((row += screen->backscroll_rows) >= vt_screen_get_rows(screen)) { return -1; } } return row; } u_int vt_screen_get_logical_cols(vt_screen_t *screen) { if (screen->logvis && screen->logvis->is_visual) { return (*screen->logvis->logical_cols)(screen->logvis); } else { return vt_edit_get_cols(screen->edit); } } /* This considers status line */ u_int vt_screen_get_rows(vt_screen_t *screen) { u_int rows; rows = vt_edit_get_rows(screen->edit); if (vt_screen_has_status_line(screen)) { if (vt_status_line_is_focused(screen)) { rows += vt_edit_get_rows(screen->main_edit); } else { rows ++; } } return rows; } /* This ignores status line */ u_int vt_screen_get_logical_rows(vt_screen_t *screen) { if (screen->logvis && screen->logvis->is_visual) { return (*screen->logvis->logical_rows)(screen->logvis); } else { return vt_edit_get_rows(screen->edit); } } int vt_screen_convert_scr_row_to_abs(vt_screen_t *screen, int row) { return row - screen->backscroll_rows; } /* This considers status line */ vt_line_t *vt_screen_get_line(vt_screen_t *screen, int row) { if (row < 0) { return vt_log_get(&screen->logs, ROW_IN_LOGS(screen, row)); } else if (vt_screen_has_status_line(screen)) { if (row == vt_edit_get_rows(screen->main_edit)) { return vt_edit_get_line(screen->status_edit, 0); } else { return vt_edit_get_line(screen->main_edit, row); } } else { return vt_edit_get_line(screen->edit, row); } } /* This considers status line */ vt_line_t *vt_screen_get_line_in_screen(vt_screen_t *screen, int row) { if (screen->is_backscrolling && screen->backscroll_rows > 0) { row -= screen->backscroll_rows; if (row < 0) { return vt_log_get(&screen->logs, ROW_IN_LOGS(screen, row)); } } if (vt_screen_has_status_line(screen)) { if (row == vt_edit_get_rows(screen->main_edit)) { return vt_edit_get_line(screen->status_edit, 0); } else { return vt_edit_get_line(screen->main_edit, row); } } else { return vt_edit_get_line(screen->edit, row); } } void vt_screen_set_modified_all(vt_screen_t *screen) { int row; vt_line_t *line; u_int num_rows = vt_screen_get_rows(screen); for (row = 0; row < num_rows; row++) { if ((line = vt_screen_get_line_in_screen(screen, row))) { vt_line_set_modified_all(line); } } } int vt_screen_add_logical_visual(vt_screen_t *screen, vt_logical_visual_t *logvis) { (*logvis->init)(logvis, &screen->edit->model, &screen->edit->cursor); if (screen->logvis) { if (screen->container_logvis == NULL && (screen->container_logvis = vt_logvis_container_new()) == NULL) { return 0; } vt_logvis_container_add(screen->container_logvis, screen->logvis); vt_logvis_container_add(screen->container_logvis, logvis); screen->logvis = screen->container_logvis; } else { screen->logvis = logvis; } return 1; } int vt_screen_destroy_logical_visual(vt_screen_t *screen) { if (screen->logvis) { (*screen->logvis->logical)(screen->logvis); (*screen->logvis->destroy)(screen->logvis); screen->logvis = NULL; screen->container_logvis = NULL; return 1; } else { return 0; } } int vt_screen_render(vt_screen_t *screen) { if (screen->logvis) { return (*screen->logvis->render)(screen->logvis); } else { return 0; } } int vt_screen_visual(vt_screen_t *screen) { if (screen->logvis) { return (*screen->logvis->visual)(screen->logvis); } else { return 1; } } int vt_screen_logical(vt_screen_t *screen) { if (screen->logvis) { return (*screen->logvis->logical)(screen->logvis); } else { return 1; } } vt_bs_mode_t vt_screen_is_backscrolling(vt_screen_t *screen) { if (screen->is_backscrolling == BSM_STATIC) { if (screen->backscroll_rows < vt_get_log_size(&screen->logs)) { return BSM_STATIC; } else { return BSM_DEFAULT; } } else { return screen->is_backscrolling; } } void vt_set_backscroll_mode(vt_screen_t *screen, vt_bs_mode_t mode) { screen->backscroll_mode = mode; if (screen->is_backscrolling) { screen->is_backscrolling = mode; } } void vt_enter_backscroll_mode(vt_screen_t *screen) { screen->is_backscrolling = screen->backscroll_mode; } void vt_exit_backscroll_mode(vt_screen_t *screen) { screen->is_backscrolling = 0; screen->backscroll_rows = 0; vt_screen_set_modified_all(screen); } int vt_screen_backscroll_to(vt_screen_t *screen, int row) { if (!screen->is_backscrolling) { return 0; } if (row > 0) { screen->backscroll_rows = 0; } else { screen->backscroll_rows = abs(row); } vt_screen_set_modified_all(screen); #ifdef EXIT_BS_AT_BOTTOM if (screen->backscroll_rows == 0) { vt_exit_backscroll_mode(screen); } #endif return 1; } int vt_screen_backscroll_upward(vt_screen_t *screen, u_int size) { vt_line_t *line; u_int count; u_int num_rows; if (!screen->is_backscrolling) { return 0; } if (screen->backscroll_rows < size) { size = screen->backscroll_rows; } if (size == 0) { return 0; } screen->backscroll_rows -= size; num_rows = vt_screen_get_rows(screen); if (!screen->screen_listener || !screen->screen_listener->window_scroll_upward_region || !(*screen->screen_listener->window_scroll_upward_region)( screen->screen_listener->self, 0, num_rows - 1, size)) { for (count = 0; count < num_rows - size; count++) { if ((line = vt_screen_get_line_in_screen(screen, count)) == NULL) { break; } vt_line_set_modified_all(line); } } for (count = num_rows - size; count < num_rows; count++) { if ((line = vt_screen_get_line_in_screen(screen, count)) == NULL) { break; } vt_line_set_modified_all(line); } #ifdef EXIT_BS_AT_BOTTOM if (screen->backscroll_rows == 0) { vt_exit_backscroll_mode(screen); } #endif return 1; } int vt_screen_backscroll_downward(vt_screen_t *screen, u_int size) { vt_line_t *line; u_int count; int num_rows; if (!screen->is_backscrolling) { return 0; } if (vt_get_num_logged_lines(&screen->logs) < screen->backscroll_rows + size) { size = vt_get_num_logged_lines(&screen->logs) - screen->backscroll_rows; } if (size == 0) { return 0; } screen->backscroll_rows += size; num_rows = vt_screen_get_rows(screen); if (!screen->screen_listener || !screen->screen_listener->window_scroll_downward_region || !(*screen->screen_listener->window_scroll_downward_region)( screen->screen_listener->self, 0, num_rows - 1, size)) { for (count = size; count < num_rows; count++) { if ((line = vt_screen_get_line_in_screen(screen, count)) == NULL) { break; } vt_line_set_modified_all(line); } } for (count = 0; count < size; count++) { if ((line = vt_screen_get_line_in_screen(screen, count)) == NULL) { break; } vt_line_set_modified_all(line); } return 1; } int vt_screen_reverse_color(vt_screen_t *screen, int beg_char_index, int beg_row, int end_char_index, int end_row, int is_rect) { if (is_rect) { return reverse_or_restore_color_rect(screen, beg_char_index, beg_row, end_char_index, end_row, vt_line_reverse_color); } else { return reverse_or_restore_color(screen, beg_char_index, beg_row, end_char_index, end_row, vt_line_reverse_color); } } int vt_screen_restore_color(vt_screen_t *screen, int beg_char_index, int beg_row, int end_char_index, int end_row, int is_rect) { if (is_rect) { return reverse_or_restore_color_rect(screen, beg_char_index, beg_row, end_char_index, end_row, vt_line_restore_color); } else { return reverse_or_restore_color(screen, beg_char_index, beg_row, end_char_index, end_row, vt_line_restore_color); } } u_int vt_screen_copy_region(vt_screen_t *screen, vt_char_t *chars, u_int num_chars, int beg_char_index, int beg_row, int end_char_index, int end_row, int is_rect) { if (is_rect) { return check_or_copy_region_rect(screen, chars, num_chars, beg_char_index, beg_row, end_char_index, end_row); } else { return check_or_copy_region(screen, chars, num_chars, beg_char_index, beg_row, end_char_index, end_row); } } u_int vt_screen_get_region_size(vt_screen_t *screen, int beg_char_index, int beg_row, int end_char_index, int end_row, int is_rect) { if (is_rect) { return check_or_copy_region_rect(screen, NULL, 0, beg_char_index, beg_row, end_char_index, end_row); } else { return check_or_copy_region(screen, NULL, 0, beg_char_index, beg_row, end_char_index, end_row); } } int vt_screen_get_line_region(vt_screen_t *screen, int *beg_row, int *end_char_index, int *end_row, int base_row) { int row; vt_line_t *line; vt_line_t *next_line; /* * finding the end of line. */ row = base_row; if ((line = vt_screen_get_line(screen, row)) == NULL || vt_line_is_empty(line)) { return 0; } while (1) { if (!vt_line_is_continued_to_next(line)) { break; } if ((next_line = vt_screen_get_line(screen, row + 1)) == NULL || vt_line_is_empty(next_line)) { break; } line = next_line; row++; } *end_char_index = line->num_filled_chars - 1; *end_row = row; /* * finding the beginning of line. */ row = base_row; while (1) { if ((line = vt_screen_get_line(screen, row - 1)) == NULL || vt_line_is_empty(line) || !vt_line_is_continued_to_next(line)) { break; } row--; } *beg_row = row; return 1; } int vt_screen_get_word_region(vt_screen_t *screen, int *beg_char_index, int *beg_row, int *end_char_index, int *end_row, int base_char_index, int base_row) { int row; int char_index; vt_line_t *line; vt_line_t *base_line; vt_char_t *ch; int flag; if ((base_line = vt_screen_get_line(screen, base_row)) == NULL || vt_line_is_empty(base_line)) { return 0; } if (regard_uri_as_word) { char *orig; u_int len; vt_char_t *str; orig = word_separators; word_separators = "\" '`<>|"; regard_uri_as_word = 0; /* Not return 0 */ vt_screen_get_word_region(screen, beg_char_index, beg_row, end_char_index, end_row, base_char_index, base_row); word_separators = orig; regard_uri_as_word = 1; if ((len = check_or_copy_region(screen, NULL, 0, *beg_char_index, *beg_row, *end_char_index, *end_row)) > 0 && (str = vt_str_alloca(len))) { u_int count; int slash_num; vt_str_init(str, len); check_or_copy_region(screen, str, len, *beg_char_index, *beg_row, *end_char_index, *end_row); for (slash_num = 0, count = 0; count < len; count++) { if (vt_char_cs(str + count) == US_ASCII) { switch (vt_char_code(str + count)) { case '/': if (++slash_num == 1) { continue; } /* Fall through */ case '@': vt_str_final(str, len); return 1; } } } vt_str_final(str, len); } } if (is_word_separator(vt_char_at(base_line, base_char_index))) { *beg_char_index = base_char_index; *end_char_index = base_char_index; *beg_row = base_row; *end_row = base_row; return 1; } flag = vt_char_is_fullwidth(vt_char_at(base_line, base_char_index)); /* * search the beg of word */ row = base_row; char_index = base_char_index; line = base_line; while (1) { if (char_index == 0) { if ((line = vt_screen_get_line(screen, row - 1)) == NULL || vt_line_is_empty(line) || !vt_line_is_continued_to_next(line)) { *beg_char_index = char_index; break; } row--; char_index = line->num_filled_chars - 1; } else { char_index--; } ch = vt_char_at(line, char_index); if (is_word_separator(ch) || flag != vt_char_is_fullwidth(ch)) { *beg_char_index = char_index + 1; break; } } *beg_row = row; /* * search the end of word. */ row = base_row; char_index = base_char_index; line = base_line; while (1) { if (char_index == line->num_filled_chars - 1) { if (!vt_line_is_continued_to_next(line) || (line = vt_screen_get_line(screen, row + 1)) == NULL || vt_line_is_empty(line)) { *end_char_index = char_index; break; } row++; char_index = 0; } else { char_index++; } ch = vt_char_at(line, char_index); if (is_word_separator(ch) || flag != vt_char_is_fullwidth(ch)) { *end_char_index = char_index - 1; break; } } *end_row = row; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " selected word region: %d %d => %d %d %d %d\n", base_char_index, base_row, *beg_char_index, *beg_row, *end_char_index, *end_row); #endif return 1; } int vt_screen_search_init(vt_screen_t *screen, int (*match)(size_t *, size_t *, void *, u_char *, int)) { if (screen->search) { return 0; } if (!(screen->search = malloc(sizeof(*screen->search)))) { return 0; } screen->search->match = match; vt_screen_search_reset_position(screen); return 1; } void vt_screen_search_final(vt_screen_t *screen) { free(screen->search); screen->search = NULL; } int vt_screen_search_reset_position(vt_screen_t *screen) { if (!screen->search) { return 0; } /* char_index == -1 has special meaning. */ screen->search->char_index = -1; screen->search->row = -1; return 1; } /* * It is assumed that this function is called in *visual* context. * * XXX * It is not supported to match text in multiple lines. */ int vt_screen_search_find(vt_screen_t *screen, int *beg_char_index, /* visual position is returned */ int *beg_row, /* visual position is returned */ int *end_char_index, /* visual position is returned */ int *end_row, /* visual position is returned */ void *regex, int backward) { vt_char_t *line_str; u_int cols; ef_parser_t *parser; ef_conv_t *conv; u_char *buf; size_t buf_len; vt_line_t *line; int step; int res; if (!screen->search) { return 0; } cols = vt_screen_get_logical_cols(screen); if (!(line_str = vt_str_alloca(cols))) { return 0; } vt_str_init(line_str, cols); buf_len = vt_screen_get_logical_cols(screen) * VTCHAR_UTF_MAX_SIZE + 1; if (!(buf = alloca(buf_len))) { return 0; } if (!(parser = vt_str_parser_new())) { return 0; } if (!(conv = vt_char_encoding_conv_new(VT_UTF8))) { (*parser->destroy)(parser); return 0; } /* char_index == -1 has special meaning. */ if (screen->search->char_index == -1) { screen->search->char_index = vt_screen_cursor_char_index(screen); screen->search->row = vt_screen_cursor_row(screen); } *beg_char_index = screen->search->char_index; *beg_row = screen->search->row; step = (backward ? -1 : 1); #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Search start from %d %d\n", *beg_char_index, *beg_row); #endif res = 0; for (; (line = vt_screen_get_line(screen, *beg_row)); (*beg_row) += step) { size_t line_len; size_t match_beg; size_t match_len; if ((line_len = vt_line_get_num_filled_chars_except_sp(line)) == 0) { continue; } /* * Visual => Logical */ vt_line_copy_logical_str(line, line_str, 0, line_len); (*parser->init)(parser); if (backward) { vt_str_parser_set_str(parser, line_str, (*beg_row != screen->search->row) ? line_len : BL_MIN(*beg_char_index + 1, line_len)); *beg_char_index = 0; } else { if (*beg_row != screen->search->row) { *beg_char_index = 0; } else if (line_len <= *beg_char_index) { continue; } vt_str_parser_set_str(parser, line_str + (*beg_char_index), line_len - *beg_char_index); } (*conv->init)(conv); *(buf + (*conv->convert)(conv, buf, buf_len - 1, parser)) = '\0'; if ((*screen->search->match)(&match_beg, &match_len, regex, buf, backward)) { size_t count; u_int comb_size; int beg; int end; vt_get_combining_chars(line_str + (*beg_char_index), &comb_size); for (count = 0; count < match_beg; count++) { /* Ignore 2nd and following bytes. */ if ((buf[count] & 0xc0) != 0x80) { if (comb_size > 0) { comb_size--; } else if ((++(*beg_char_index)) >= line_len - 1) { break; } else { vt_get_combining_chars(line_str + (*beg_char_index), &comb_size); } } } *end_char_index = (*beg_char_index) - 1; for (; count < match_beg + match_len; count++) { /* Ignore 2nd and following bytes. */ if ((buf[count] & 0xc0) != 0x80) { if (comb_size > 0) { comb_size--; } else if ((++(*end_char_index)) >= line_len - 1) { break; } else { vt_get_combining_chars(line_str + (*end_char_index), &comb_size); } } } if (*end_char_index < *beg_char_index) { continue; } *end_row = *beg_row; if (backward) { if (*beg_char_index > 0) { screen->search->char_index = *beg_char_index - 1; screen->search->row = *beg_row; } else { screen->search->char_index = vt_screen_get_logical_cols(screen) - 1; screen->search->row = *beg_row - 1; } } else { screen->search->char_index = *beg_char_index + 1; screen->search->row = *beg_row; } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Search position x %d y %d\n", screen->search->char_index, screen->search->row); #endif /* * Logical => Visual * * XXX Incomplete * Current implementation have problems like this. * (logical)RRRLLLNNN => (visual)NNNLLLRRR * Searching LLLNNN => ^^^^^^ hits but only NNNL is reversed. */ beg = vt_line_convert_logical_char_index_to_visual(line, *beg_char_index, NULL); end = vt_line_convert_logical_char_index_to_visual(line, *end_char_index, NULL); if (beg > end) { *beg_char_index = end; *end_char_index = beg; } else { *beg_char_index = beg; *end_char_index = end; } if (vt_line_is_rtl(line)) { int char_index; /* XXX for x_selection */ char_index = -(*beg_char_index); *beg_char_index = -(*end_char_index); *end_char_index = char_index; } res = 1; break; } } (*parser->destroy)(parser); (*conv->destroy)(conv); vt_str_final(line_str, vt_screen_get_logical_cols(screen)); return res; } int vt_screen_blink(vt_screen_t *screen) { int has_blinking_char; has_blinking_char = 0; if (screen->has_blinking_char) { int char_index; int row; vt_line_t *line; u_int num_rows = vt_screen_get_rows(screen); for (row = 0; row + screen->backscroll_rows < num_rows; row++) { if ((line = vt_screen_get_line(screen, row)) == NULL) { continue; } for (char_index = 0; char_index < line->num_filled_chars; char_index++) { if (vt_char_is_blinking(line->chars + char_index)) { vt_line_set_modified(line, char_index, char_index); has_blinking_char = 1; } } } if (screen->backscroll_rows == 0) { screen->has_blinking_char = has_blinking_char; } } return has_blinking_char; } /* * VT100 commands * * !! Notice !! * These functions are called under logical order mode. */ vt_char_t *vt_screen_get_n_prev_char(vt_screen_t *screen, int n) { int char_index; int row; vt_line_t *line; if (!get_n_prev_char_pos(screen, &char_index, &row, 1)) { return NULL; } if ((line = vt_edit_get_line(screen->edit, row)) == NULL) { return NULL; } return vt_char_at(line, char_index); } int vt_screen_combine_with_prev_char(vt_screen_t *screen, u_int32_t code, ef_charset_t cs, int is_fullwidth, int is_comb, vt_color_t fg_color, vt_color_t bg_color, int is_bold, int is_italic, int line_style, int is_blinking, int is_protected) { int char_index; int row; vt_char_t *ch; vt_line_t *line; if (!get_n_prev_char_pos(screen, &char_index, &row, 1)) { return 0; } if ((line = vt_edit_get_line(screen->edit, row)) == NULL) { return 0; } if ((ch = vt_char_at(line, char_index)) == NULL) { return 0; } if (!vt_char_combine(ch, code, cs, is_fullwidth, is_comb, fg_color, bg_color, is_bold, is_italic, line_style, is_blinking, is_protected)) { return 0; } vt_line_set_modified(line, char_index, char_index); return 1; } int vt_screen_insert_chars(vt_screen_t *screen, vt_char_t *chars, u_int len) { return vt_edit_insert_chars(screen->edit, chars, len); } int vt_screen_insert_new_lines(vt_screen_t *screen, u_int size) { u_int count; if (size > vt_edit_get_rows(screen->edit)) { size = vt_edit_get_rows(screen->edit); } for (count = 0; count < size; count++) { vt_edit_insert_new_line(screen->edit); } return 1; } int vt_screen_overwrite_chars(vt_screen_t *screen, vt_char_t *chars, u_int len) { return vt_edit_overwrite_chars(screen->edit, chars, len); } int vt_screen_delete_lines(vt_screen_t *screen, u_int size) { u_int count; if (size > vt_edit_get_rows(screen->edit)) { size = vt_edit_get_rows(screen->edit); } for (count = 0; count < size; count++) { if (!vt_edit_delete_line(screen->edit)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " deleting nonexisting lines.\n"); #endif return 0; } } return 1; } int vt_screen_go_forward(vt_screen_t *screen, u_int size, int scroll) { u_int count; for (count = 0; count < size; count++) { if (!vt_edit_go_forward(screen->edit, 0)) { if (scroll) { if (size > vt_edit_get_cols(screen->edit)) { size = vt_edit_get_cols(screen->edit); if (size <= count) { break; } } vt_edit_scroll_leftward(screen->edit, size - count); break; } #ifdef DEBUG else { bl_warn_printf(BL_DEBUG_TAG " cursor cannot go forward any more.\n"); } #endif return 0; } } return 1; } int vt_screen_go_back(vt_screen_t *screen, u_int size, int scroll) { u_int count; for (count = 0; count < size; count++) { if (!vt_edit_go_back(screen->edit, 0)) { if (scroll) { if (size > vt_edit_get_cols(screen->edit)) { size = vt_edit_get_cols(screen->edit); if (size <= count) { break; } } vt_edit_scroll_rightward(screen->edit, size - count); break; } #ifdef DEBUG else { bl_warn_printf(BL_DEBUG_TAG " cursor cannot go back any more.\n"); } #endif return 0; } } return 1; } int vt_screen_go_upward(vt_screen_t *screen, u_int size) { u_int count; for (count = 0; count < size; count++) { if (!vt_edit_go_upward(screen->edit, 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " cursor cannot go upward any more.\n"); #endif return 0; } } return 1; } int vt_screen_go_downward(vt_screen_t *screen, u_int size) { u_int count; for (count = 0; count < size; count++) { if (!vt_edit_go_downward(screen->edit, 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " cursor cannot go downward any more.\n"); #endif return 0; } } return 1; } int vt_screen_use_normal_edit(vt_screen_t *screen) { if (screen->edit != &screen->normal_edit) { int col = screen->edit->cursor.col; int row = screen->edit->cursor.row; change_edit(screen, &screen->normal_edit); vt_edit_goto(screen->edit, col, row); return 1; } else { return 0; } } int vt_screen_use_alternative_edit(vt_screen_t *screen) { if (screen->edit != &screen->alt_edit) { int col = screen->edit->cursor.col; int row = screen->edit->cursor.row; change_edit(screen, &screen->alt_edit); vt_edit_goto(screen->edit, col, row); return 1; } else { return 0; } } /* * This function must be called in logical context in order to swap * stored_edit->edit and screen->edit in the same conditions. */ int vt_screen_enable_local_echo(vt_screen_t *screen) { if (!screen->stored_edit) { if (!(screen->stored_edit = malloc(sizeof(vt_stored_edit_t)))) { return 0; } screen->stored_edit->edit = *screen->edit; /* * New data is allocated in screen->edit, not in stored_edit->edit * because screen->edit allocated here will be deleted and * stored_edit->edit will be revived in vt_screen_disable_local_echo(). */ if (!vt_edit_clone(screen->edit, &screen->stored_edit->edit)) { free(screen->stored_edit); screen->stored_edit = NULL; return 0; } screen->edit->is_logging = 0; } screen->stored_edit->time = get_msec_time(); return 1; } int vt_screen_local_echo_wait(vt_screen_t *screen, int msec /* 0: stored_edit->time = 0 (>= get_msec_time() is always false.) */ ) { if (screen->stored_edit) { if (msec == 0) { screen->stored_edit->time = 0; } else if (screen->stored_edit->time + msec >= get_msec_time()) { return 1; } } return 0; } /* * This function must be called in logical context in order to swap * stored_edit->edit and screen->edit in the same conditions. */ int vt_screen_disable_local_echo(vt_screen_t *screen) { u_int row; u_int num_rows; vt_line_t *old_line; vt_line_t *new_line; if (!screen->stored_edit) { return 0; } num_rows = vt_edit_get_rows(screen->edit); /* * Set modified flag to the difference between the current edit and the stored * one * to restore the screen before starting local echo. */ for (row = 0; row < num_rows; row++) { if ((new_line = vt_edit_get_line(&screen->stored_edit->edit, row)) && (old_line = vt_edit_get_line(screen->edit, row)) && (vt_line_is_modified(old_line) || old_line->num_filled_chars != new_line->num_filled_chars #if 1 || !vt_str_bytes_equal(old_line->chars, new_line->chars, new_line->num_filled_chars) #endif )) { vt_line_set_modified_all(new_line); } } vt_edit_final(screen->edit); *screen->edit = screen->stored_edit->edit; free(screen->stored_edit); screen->stored_edit = NULL; return 1; } void vt_screen_copy_area(vt_screen_t *screen, int src_col, int src_row, u_int num_copy_cols, u_int num_copy_rows, u_int src_page, int dst_col, int dst_row, u_int dst_page) { vt_edit_t *src_edit; vt_edit_t *dst_edit; if (src_page > MAX_PAGE_ID) { src_page = MAX_PAGE_ID; } if (dst_page > MAX_PAGE_ID) { dst_page = MAX_PAGE_ID; } if ((src_edit = get_edit(screen, src_page)) && (dst_edit = get_edit(screen, dst_page))) { vt_edit_copy_area(src_edit, src_col, src_row, num_copy_cols, num_copy_rows, dst_edit, dst_col, dst_row); } } u_int16_t vt_screen_get_checksum(vt_screen_t *screen, int col, int row, u_int num_cols, u_int num_rows, int page) { vt_edit_t *edit; if (page > MAX_PAGE_ID) { page = MAX_PAGE_ID; } if ((edit = get_edit(screen, page))) { return vt_edit_get_checksum(edit, col, row, num_cols, num_rows); } return 0; } void vt_screen_enable_blinking(vt_screen_t *screen) { screen->has_blinking_char = 1; } int vt_screen_write_content(vt_screen_t *screen, int fd, ef_conv_t *conv, int clear_at_end, vt_write_content_area_t area) { int beg; int end; vt_char_t *buf; u_int num; u_char conv_buf[512]; ef_parser_t *vt_str_parser; #if 1 /* for sig_error in vt_term_manager.c */ vt_screen_logical(screen); #endif if (area == WCA_CURSOR_LINE) { beg = vt_screen_cursor_row(screen); end = beg + 1; } else { end = vt_screen_get_rows(screen); if (area == WCA_ALL) { beg = -vt_screen_get_num_logged_lines(screen); } else /* if (area == WCA_SCREEN) */ { beg = 0; } } /* WCA_CURSOR_LINE may cause num == 0. */ if ((num = vt_screen_get_region_size(screen, 0, beg, 0, end, 0)) == 0) { return 0; } if ((buf = vt_str_alloca(num)) == NULL) { return 0; } vt_str_init(buf, num); vt_screen_copy_region(screen, buf, num, 0, beg, 0, end, 0); if (!(vt_str_parser = vt_str_parser_new())) { return 0; } (*vt_str_parser->init)(vt_str_parser); vt_str_parser_set_str(vt_str_parser, buf, num); (*conv->init)(conv); while (!vt_str_parser->is_eos && (num = (*conv->convert)(conv, conv_buf, sizeof(conv_buf), vt_str_parser)) > 0) { write(fd, conv_buf, num); } if (clear_at_end) { write(fd, "\n\x1b[1000S\x1b[H", 11); } (*vt_str_parser->destroy)(vt_str_parser); return 1; } int vt_screen_get_page_id(vt_screen_t *screen) { if (screen->edit == &screen->normal_edit || screen->edit == &screen->alt_edit /* alt edit is regarded as 0 */) { return 0; } else if (screen->page_edits) { return screen->edit - screen->page_edits + 1; } return -1; } int vt_screen_goto_page(vt_screen_t *screen, u_int page_id) { vt_edit_t *edit; if (page_id > MAX_PAGE_ID) { page_id = MAX_PAGE_ID; } if ((edit = get_edit(screen, page_id))) { vt_edit_goto(edit, screen->edit->cursor.col, screen->edit->cursor.row); if (vt_edit_get_tab_size(edit) != vt_edit_get_tab_size(screen->edit)) { vt_edit_set_tab_size(edit, vt_edit_get_tab_size(screen->edit)); } edit->vmargin_beg = screen->edit->vmargin_beg; edit->vmargin_end = screen->edit->vmargin_end; edit->hmargin_beg = screen->edit->hmargin_beg; edit->hmargin_end = screen->edit->hmargin_end; edit->use_margin = screen->edit->use_margin; edit->is_logging = screen->edit->is_logging; edit->is_relative_origin = screen->edit->is_relative_origin; edit->is_auto_wrap = screen->edit->is_auto_wrap; edit->use_bce = screen->edit->use_bce; edit->use_rect_attr_select = screen->edit->use_rect_attr_select; change_edit(screen, edit); return 1; } return 0; } int vt_screen_goto_next_page(vt_screen_t *screen, u_int offset) { int page_id = vt_screen_get_page_id(screen); if (page_id != -1) { return vt_screen_goto_page(screen, page_id + offset); } return 0; } int vt_screen_goto_prev_page(vt_screen_t *screen, u_int offset) { int page_id = vt_screen_get_page_id(screen); if (page_id != -1) { if (page_id < offset) { page_id = offset; } return vt_screen_goto_page(screen, page_id - offset); } return 0; } void vt_screen_set_use_status_line(vt_screen_t *screen, int use) { if (use) { if (!vt_screen_has_status_line(screen)) { if ((!screen->status_edit && !(screen->status_edit = status_edit_new(screen->edit))) || /* XXX status line is *not* supported on vertical mode */ (screen->logvis && !screen->logvis->is_reversible)) { return; } screen->main_edit = screen->edit; screen->has_status_line = 1; vt_edit_set_modified_all(screen->status_edit); /* * XXX * I don't know whether the cursor goes to home position or not, * but vttest 11.2.6.2.1 seems to assume it. * (https://vt100.net/docs/vt510-rm/DECSSDT.html doesn't describe it.) */ #if 1 vt_edit_goto(screen->status_edit, 0, 0); #endif vt_screen_resize(screen, vt_edit_get_cols(screen->main_edit), vt_edit_get_rows(screen->main_edit), 0); } } else { if (vt_screen_has_status_line(screen)) { screen->has_status_line = 0; vt_screen_resize(screen, vt_edit_get_cols(screen->main_edit), vt_edit_get_rows(screen->main_edit) + 1, 0); screen->main_edit = NULL; } } } void vt_focus_status_line(vt_screen_t *screen) { if (!screen->status_edit && !(screen->status_edit = status_edit_new(screen->edit))) { return; } if (!vt_status_line_is_focused(screen)) { change_edit(screen, screen->status_edit); } } void vt_focus_main_screen(vt_screen_t *screen) { if (screen->main_edit && vt_status_line_is_focused(screen)) { change_edit(screen, screen->main_edit); } } mlterm-3.8.9/vtemu/vt_screen.h010064400017600000144000000356161356600660700150560ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_SCREEN_H__ #define __VT_SCREEN_H__ #include #include /* int8_t */ #include #include "vt_edit.h" #include "vt_logs.h" #include "vt_logical_visual.h" #define MAX_PAGE_ID 8 typedef struct vt_screen_event_listener { void *self; int (*screen_is_static)(void *); void (*line_scrolled_out)(void *); int (*window_scroll_upward_region)(void *, int, int, u_int); int (*window_scroll_downward_region)(void *, int, int, u_int); } vt_screen_event_listener_t; typedef enum vt_bs_mode { BSM_NONE = 0x0, BSM_DEFAULT, BSM_STATIC, BSM_MAX } vt_bs_mode_t; typedef enum vt_write_content_area { WCA_ALL, WCA_CURSOR_LINE, WCA_SCREEN, } vt_write_content_area_t; typedef struct vt_stored_edit { vt_edit_t edit; u_int32_t time; } vt_stored_edit_t; typedef struct vt_screen { /* public(readonly) */ vt_edit_t *edit; /* * private */ vt_edit_t normal_edit; vt_edit_t alt_edit; vt_edit_t *page_edits; /* stores 8 pages */ vt_stored_edit_t *stored_edit; /* Store logical edits. */ vt_edit_t *main_edit; vt_edit_t *status_edit; vt_edit_scroll_event_listener_t edit_scroll_listener; vt_logs_t logs; vt_logical_visual_t *logvis; vt_logical_visual_t *container_logvis; vt_screen_event_listener_t *screen_listener; struct { int (*match)(size_t *, size_t *, void *, u_char *, int); /* Logical order */ int char_index; int row; } * search; u_int backscroll_rows; /* vt_bs_mode_t */ int8_t backscroll_mode; int8_t is_backscrolling; int8_t has_blinking_char; int8_t has_status_line; } vt_screen_t; void vt_set_word_separators(const char *seps); char *vt_get_word_separators(void); void vt_set_regard_uri_as_word(int flag); int vt_get_regard_uri_as_word(void); #define vt_free_word_separators() vt_set_word_separators(NULL) vt_screen_t *vt_screen_new(u_int cols, u_int rows, u_int tab_size, u_int num_log_lines, int use_bce, vt_bs_mode_t bs_mode); int vt_screen_destroy(vt_screen_t *screen); void vt_screen_set_listener(vt_screen_t *screen, vt_screen_event_listener_t *screen_listener); /* This considers status line */ int vt_screen_resize(vt_screen_t *screen, u_int cols, u_int rows, int pack); #define vt_screen_set_use_bce(screen, use) \ vt_edit_set_use_bce(&(screen)->alt_edit, vt_edit_set_use_bce(&(screen)->normal_edit, use)) #define vt_screen_is_using_bce(screen) vt_edit_is_using_bce((screen)->edit) #define vt_screen_set_bce_fg_color(screen, fg_color) \ vt_edit_set_bce_fg_color((screen)->edit, fg_color) #define vt_screen_set_bce_bg_color(screen, bg_color) \ vt_edit_set_bce_bg_color((screen)->edit, bg_color) #define vt_screen_cursor_char_index(screen) vt_cursor_char_index((screen)->edit) #define vt_screen_cursor_col(screen) vt_cursor_col((screen)->edit) /* XXX Don't call this in visual context for now. */ #define vt_screen_cursor_logical_col(screen) vt_edit_cursor_logical_col((screen)->edit) /* This considers status line */ int vt_screen_cursor_row(vt_screen_t *screen); /* This considers status line */ int vt_screen_cursor_row_in_screen(vt_screen_t *screen); /* XXX Don't call this in visual context for now. */ #define vt_screen_cursor_logical_row(screen) vt_edit_cursor_logical_row((screen)->edit) #define vt_screen_get_cols(screen) vt_edit_get_cols((screen)->edit) /* This considers status line */ u_int vt_screen_get_rows(vt_screen_t *screen); u_int vt_screen_get_logical_cols(vt_screen_t *screen); u_int vt_screen_get_logical_rows(vt_screen_t *screen); #define vt_screen_get_log_size(screen) vt_get_log_size(&(screen)->logs) #define vt_screen_change_log_size(screen, log_size) vt_change_log_size(&(screen)->logs, log_size) #define vt_screen_unlimit_log_size(screen) vt_unlimit_log_size(&(screen)->logs) #define vt_screen_log_size_is_unlimited(screen) vt_log_size_is_unlimited(&(screen)->logs) #define vt_screen_get_num_logged_lines(screen) vt_get_num_logged_lines(&(screen)->logs) int vt_screen_convert_scr_row_to_abs(vt_screen_t *screen, int row); /* This considers status line */ vt_line_t *vt_screen_get_line(vt_screen_t *screen, int row); /* This considers status line */ vt_line_t *vt_screen_get_line_in_screen(vt_screen_t *screen, int row); #define vt_screen_get_cursor_line(screen) \ vt_edit_get_line((screen)->edit, vt_cursor_row((screen)->edit)) void vt_screen_set_modified_all(vt_screen_t *screen); int vt_screen_add_logical_visual(vt_screen_t *screen, vt_logical_visual_t *logvis); int vt_screen_destroy_logical_visual(vt_screen_t *screen); int vt_screen_render(vt_screen_t *screen); int vt_screen_visual(vt_screen_t *screen); int vt_screen_logical(vt_screen_t *screen); #define vt_screen_logical_visual_is_reversible(screen) \ (!(screen)->logvis || (screen)->logvis->is_reversible) vt_bs_mode_t vt_screen_is_backscrolling(vt_screen_t *screen); void vt_set_backscroll_mode(vt_screen_t *screen, vt_bs_mode_t mode); #define vt_get_backscroll_mode(screen) ((screen)->backscroll_mode) void vt_enter_backscroll_mode(vt_screen_t *screen); void vt_exit_backscroll_mode(vt_screen_t *screen); int vt_screen_backscroll_to(vt_screen_t *screen, int row); int vt_screen_backscroll_upward(vt_screen_t *screen, u_int size); int vt_screen_backscroll_downward(vt_screen_t *screen, u_int size); #define vt_screen_get_tab_size(screen) vt_edit_get_tab_size((screen)->edit) #define vt_screen_set_tab_size(screen, tab_size) vt_edit_set_tab_size((screen)->edit, tab_size) #define vt_screen_is_tab_stop(screen, col) vt_edit_is_tab_stop((screen)->edit, col) int vt_screen_restore_color(vt_screen_t *screen, int beg_char_index, int beg_row, int end_char_index, int end_row, int is_rect); int vt_screen_reverse_color(vt_screen_t *screen, int beg_char_index, int beg_row, int end_char_index, int end_row, int is_rect); u_int vt_screen_copy_region(vt_screen_t *screen, vt_char_t *chars, u_int num_chars, int beg_char_index, int beg_row, int end_char_index, int end_row, int is_rect); u_int vt_screen_get_region_size(vt_screen_t *screen, int beg_char_index, int beg_row, int end_char_index, int end_row, int is_rect); int vt_screen_get_line_region(vt_screen_t *screen, int *beg_row, int *end_char_index, int *end_row, int base_row); int vt_screen_get_word_region(vt_screen_t *screen, int *beg_char_index, int *beg_row, int *end_char_index, int *end_row, int base_char_index, int base_row); int vt_screen_search_init(vt_screen_t *screen, int (*match)(size_t *, size_t *, void *, u_char *, int)); void vt_screen_search_final(vt_screen_t *screen); int vt_screen_search_reset_position(vt_screen_t *screen); int vt_screen_search_find(vt_screen_t *screen, int *beg_char_index, int *beg_row, int *end_char_index, int *end_row, void *regex, int backward); int vt_screen_blink(vt_screen_t *screen); /* * VT100 commands (called in logical context) */ vt_char_t *vt_screen_get_n_prev_char(vt_screen_t *screen, int n); int vt_screen_combine_with_prev_char(vt_screen_t *screen, u_int32_t code, ef_charset_t cs, int is_fullwidth, int is_comb, vt_color_t fg_color, vt_color_t bg_color, int is_bold, int is_italic, int line_style, int is_blinking, int is_protected); int vt_screen_insert_chars(vt_screen_t *screen, vt_char_t *chars, u_int len); #define vt_screen_insert_blank_chars(screen, len) vt_edit_insert_blank_chars((screen)->edit, len) #define vt_screen_forward_tabs(screen, num) vt_edit_forward_tabs((screen)->edit, num) #define vt_screen_backward_tabs(screen, num) vt_edit_backward_tabs((screen)->edit, num) #define vt_screen_set_tab_stop(screen) vt_edit_set_tab_stop((screen)->edit) #define vt_screen_clear_tab_stop(screen) vt_edit_clear_tab_stop((screen)->edit) #define vt_screen_clear_all_tab_stops(screen) vt_edit_clear_all_tab_stops((screen)->edit) int vt_screen_insert_new_lines(vt_screen_t *screen, u_int size); #define vt_screen_line_feed(screen) vt_edit_go_downward((screen)->edit, SCROLL) int vt_screen_overwrite_chars(vt_screen_t *screen, vt_char_t *chars, u_int len); #define vt_screen_delete_cols(screen, len) vt_edit_delete_cols((screen)->edit, len) int vt_screen_delete_lines(vt_screen_t *screen, u_int size); #define vt_screen_clear_cols(screen, cols) vt_edit_clear_cols((screen)->edit, cols) #define vt_screen_clear_line_to_right(screen) vt_edit_clear_line_to_right((screen)->edit) #define vt_screen_clear_line_to_left(screen) vt_edit_clear_line_to_left((screen)->edit) #define vt_screen_clear_below(screen) vt_edit_clear_below((screen)->edit) #define vt_screen_clear_above(screen) vt_edit_clear_above((screen)->edit) #define vt_screen_save_protected_chars(screen, beg_row, end_row, relative) \ vt_edit_save_protected_chars((screen)->edit, beg_row, end_row, relative) #define vt_screen_restore_protected_chars(screen, save) \ vt_edit_restore_protected_chars((screen)->edit, save) #define vt_screen_set_vmargin(screen, beg, end) vt_edit_set_vmargin((screen)->edit, beg, end) #define vt_screen_set_use_hmargin(screen, use) vt_edit_set_use_hmargin((screen)->edit, use) #define vt_screen_set_hmargin(screen, beg, end) vt_edit_set_hmargin((screen)->edit, beg, end) #define vt_screen_index(screen) vt_edit_go_downward((screen)->edit, SCROLL) #define vt_screen_reverse_index(screen) vt_edit_go_upward((screen)->edit, SCROLL) #define vt_screen_scroll_upward(screen, size) vt_edit_scroll_upward((screen)->edit, size) #define vt_screen_scroll_downward(screen, size) vt_edit_scroll_downward((screen)->edit, size) #define vt_screen_scroll_leftward(screen, size) vt_edit_scroll_leftward((screen)->edit, size) #define vt_screen_scroll_rightward(screen, size) vt_edit_scroll_rightward((screen)->edit, size) #define vt_screen_scroll_leftward_from_cursor(screen, size) \ vt_edit_scroll_leftward_from_cursor((screen)->edit, size) #define vt_screen_scroll_rightward_from_cursor(screen, size) \ vt_edit_scroll_rightward_from_cursor((screen)->edit, size) int vt_screen_go_forward(vt_screen_t *screen, u_int size, int scroll); int vt_screen_go_back(vt_screen_t *screen, u_int size, int scroll); int vt_screen_go_upward(vt_screen_t *screen, u_int size); int vt_screen_go_downward(vt_screen_t *screen, u_int size); #define vt_screen_goto_beg_of_line(screen) vt_edit_goto_beg_of_line((screen)->edit) #define vt_screen_go_horizontally(screen, col) \ vt_edit_goto((screen)->edit, col, vt_edit_cursor_logical_row((screen)->edit)) #define vt_screen_go_vertically(screen, row) \ vt_edit_goto((screen)->edit, vt_edit_cursor_logical_col((screen)->edit), row) #define vt_screen_goto_home(screen) vt_edit_goto_home((screen)->edit) #define vt_screen_goto(screen, col, row) vt_edit_goto((screen)->edit, col, row) #define vt_screen_set_relative_origin(screen, flag) \ vt_edit_set_relative_origin((screen)->edit, flag) #define vt_screen_is_relative_origin(screen) vt_edit_is_relative_origin((screen)->edit) #define vt_screen_set_auto_wrap(screen, flag) vt_edit_set_auto_wrap((screen)->edit, flag) #define vt_screen_is_auto_wrap(screen) vt_edit_is_auto_wrap((screen)->edit) #define vt_screen_set_last_column_flag(screen, flag) \ vt_edit_set_last_column_flag((screen)->edit, flag) #define vt_screen_get_last_column_flag(screen) vt_edit_get_last_column_flag((screen)->edit) #define vt_screen_get_bce_ch(screen) vt_edit_get_bce_ch((screen)->edit) #define vt_screen_save_cursor(screen) vt_edit_save_cursor((screen)->edit) #define vt_screen_saved_cursor_to_home(screen) vt_edit_saved_cursor_to_home((screen)->edit) #define vt_screen_restore_cursor(screen) vt_edit_restore_cursor((screen)->edit) int vt_screen_cursor_visible(vt_screen_t *screen); int vt_screen_cursor_invisible(vt_screen_t *screen); #define vt_screen_is_cursor_visible(screen) ((screen)->is_cursor_visible) /* * XXX * Note that alt_edit/normal_edit are directly switched by ui_picture.c without * using following 3 functions. */ #define vt_screen_is_alternative_edit(screen) ((screen)->edit == &(screen)->alt_edit) int vt_screen_use_normal_edit(vt_screen_t *screen); int vt_screen_use_alternative_edit(vt_screen_t *screen); #define vt_screen_is_local_echo_mode(screen) ((screen)->stored_edit) int vt_screen_enable_local_echo(vt_screen_t *screen); int vt_screen_local_echo_wait(vt_screen_t *screen, int msec); int vt_screen_disable_local_echo(vt_screen_t *screen); #define vt_screen_fill_area(screen, code, is_protected, col, beg, num_cols, num_rows) \ vt_edit_fill_area((screen)->edit, code, is_protected, col, beg, num_cols, num_rows) void vt_screen_copy_area(vt_screen_t *screen, int src_col, int src_row, u_int num_copy_cols, u_int num_copy_rows, u_int src_page, int dst_col, int dst_row, u_int dst_page); #define vt_screen_erase_area(screen, col, row, num_cols, num_rows) \ vt_edit_erase_area((screen)->edit, col, row, num_cols, num_rows) #define vt_screen_change_attr_area(screen, col, row, num_cols, num_rows, attr) \ vt_edit_change_attr_area((screen)->edit, col, row, num_cols, num_rows, \ vt_char_change_attr, attr) #define vt_screen_reverse_attr_area(screen, col, row, num_cols, num_rows, attr) \ vt_edit_change_attr_area((screen)->edit, col, row, num_cols, num_rows, \ vt_char_reverse_attr, attr) u_int16_t vt_screen_get_checksum(vt_screen_t *screen, int col, int row, u_int num_cols, u_int num_rows, int page); #define vt_screen_set_use_rect_attr_select(screen, use) \ vt_edit_set_use_rect_attr_select((screen)->edit, use) #define vt_screen_is_using_rect_attr_select(screen) \ vt_edit_is_using_rect_attr_select((screen)->edit) #define vt_screen_clear_size_attr(screen) vt_edit_clear_size_attr((screen)->edit) void vt_screen_enable_blinking(vt_screen_t *screen); int vt_screen_write_content(vt_screen_t *screen, int fd, ef_conv_t *conv, int clear_at_end, vt_write_content_area_t area); int vt_screen_get_page_id(vt_screen_t *screen); int vt_screen_goto_page(vt_screen_t *screen, u_int page_id); int vt_screen_goto_next_page(vt_screen_t *screen, u_int offset); int vt_screen_goto_prev_page(vt_screen_t *prev, u_int offset); #define vt_screen_cursor_is_rtl(screen) \ ((screen)->logvis ? vt_logical_visual_cursor_is_rtl((screen)->logvis) : 0) /* This considers status line */ #define vt_screen_has_status_line(screen) ((screen)->has_status_line) /* This considers status line */ void vt_screen_set_use_status_line(vt_screen_t *screen, int use); /* This considers status line */ #define vt_status_line_is_focused(screen) ((screen)->edit == (screen)->status_edit) /* This considers status line */ void vt_focus_status_line(vt_screen_t *screen); /* This considers status line */ void vt_focus_main_screen(vt_screen_t *screen); #endif mlterm-3.8.9/vtemu/vt_shape.c010064400017600000144000000157101356600660700146630ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_shape.h" #include /* alloca */ #include "vt_ctl_loader.h" #include "vt_ot_layout.h" /* --- static functions --- */ static int combine_replacing_code(vt_char_t *dst, vt_char_t *src, u_int new_code, int8_t offset, u_int8_t width, int was_vcol) { u_int code; dst = vt_char_combine_simple(dst, src); code = vt_char_code(src); if (IS_VAR_WIDTH_CHAR(code) || (code == 0 && was_vcol)) { vt_char_set_cs(dst, ISO10646_UCS4_1_V); vt_char_set_position(dst, offset, width); was_vcol = 1; } else { vt_char_set_cs(dst, ISO10646_UCS4_1); was_vcol = 0; } vt_char_set_code(dst, new_code); return was_vcol; } static int replace_code(vt_char_t *ch, u_int new_code, int was_vcol) { u_int code; code = vt_char_code(ch); if (IS_VAR_WIDTH_CHAR(code) || (code == 0 && was_vcol)) { vt_char_set_cs(ch, ISO10646_UCS4_1_V); was_vcol = 1; } else { vt_char_set_cs(ch, ISO10646_UCS4_1); was_vcol = 0; } vt_char_set_code(ch, new_code); return was_vcol; } /* --- global functions --- */ #ifndef NO_DYNAMIC_LOAD_CTL #ifdef __APPLE__ u_int vt_shape_arabic(vt_char_t *, u_int, vt_char_t *, u_int) __attribute__((weak)); u_int16_t vt_is_arabic_combining(vt_char_t *, vt_char_t *, vt_char_t *) __attribute__((weak)); u_int vt_shape_iscii(vt_char_t *, u_int, vt_char_t *, u_int) __attribute__((weak)); #endif u_int vt_shape_arabic(vt_char_t *dst, u_int dst_len, vt_char_t *src, u_int src_len) { u_int (*func)(vt_char_t *dst, u_int dst_len, vt_char_t *src, u_int src_len); if (!(func = vt_load_ctl_bidi_func(VT_SHAPE_ARABIC))) { return 0; } return (*func)(dst, dst_len, src, src_len); } u_int16_t vt_is_arabic_combining(vt_char_t *prev2, /* can be NULL */ vt_char_t *prev, /* must be ISO10646_UCS4_1 character */ vt_char_t *ch /* must be ISO10646_UCS4_1 character */ ) { u_int16_t (*func)(vt_char_t *, vt_char_t *, vt_char_t *); if (!(func = vt_load_ctl_bidi_func(VT_IS_ARABIC_COMBINING))) { return 0; } return (*func)(prev2, prev, ch); } u_int vt_shape_iscii(vt_char_t *dst, u_int dst_len, vt_char_t *src, u_int src_len) { u_int (*func)(vt_char_t *dst, u_int dst_len, vt_char_t *src, u_int src_len); if (!(func = vt_load_ctl_iscii_func(VT_SHAPE_ISCII))) { return 0; } return (*func)(dst, dst_len, src, src_len); } #endif #ifdef USE_OT_LAYOUT u_int vt_shape_ot_layout(vt_char_t *dst, u_int dst_len, vt_char_t *src, u_int src_len, ctl_info_t ctl_info) { int src_pos; u_int dst_filled; u_int32_t *ucs_buf; u_int ucs_filled; u_int32_t *shaped_buf; u_int shaped_filled; int8_t *offsets; u_int8_t *widths; vt_char_t *ch; vt_char_t *dst_shaped; u_int count; vt_font_t prev_font; vt_font_t cur_font; void *xfont; vt_char_t *comb; u_int comb_size; int src_pos_mark; int was_vcol; #define DST_LEN (dst_len * (MAX_COMB_SIZE + 1)) if ((ucs_buf = alloca(src_len * (MAX_COMB_SIZE + 1) * sizeof(*ucs_buf))) == NULL || (shaped_buf = alloca(DST_LEN * sizeof(*shaped_buf))) == NULL || (offsets = alloca(DST_LEN * sizeof(*offsets))) == NULL || (widths = alloca(DST_LEN * sizeof(*widths))) == NULL) { return 0; } dst_filled = 0; ucs_filled = 0; dst_shaped = NULL; prev_font = UNKNOWN_CS; xfont = NULL; for (src_pos = 0; src_pos < src_len; src_pos++) { ch = &src[src_pos]; cur_font = vt_char_font(ch); comb = vt_get_combining_chars(ch, &comb_size); if (FONT_CS(cur_font) == US_ASCII && (!comb || vt_char_cs(comb) != PICTURE_CHARSET)) { cur_font &= ~US_ASCII; cur_font |= ISO10646_UCS4_1; } if (prev_font != cur_font) { if (ucs_filled) { shaped_filled = vt_ot_layout_shape(xfont, shaped_buf, DST_LEN, offsets, widths, NULL, ucs_buf, ucs_filled); /* * If EOL char is a ot_layout byte which presents two ot_layouts * and its second ot_layout is out of screen, 'shaped_filled' is * greater than 'dst + dst_len - dst_shaped'. */ if (shaped_filled > dst + dst_len - dst_shaped) { shaped_filled = dst + dst_len - dst_shaped; } #ifdef __DEBUG { int i; for (i = 0; i < ucs_filled; i++) { bl_msg_printf("%.2x ", ucs_buf[i]); } bl_msg_printf("=>\n"); for (i = 0; i < shaped_filled; i++) { bl_msg_printf("%.2x ", shaped_buf[i]); } bl_msg_printf("\n"); } #endif was_vcol = 0; for (count = 0; count < shaped_filled; count++, dst_shaped++, src_pos_mark++) { if (offsets[count] || widths[count]) { was_vcol = combine_replacing_code(--dst_shaped, vt_get_base_char(&src[--src_pos_mark]), shaped_buf[count], offsets[count], widths[count], was_vcol); } else { was_vcol = replace_code(dst_shaped, shaped_buf[count], was_vcol); } } dst_filled = dst_shaped - dst; ucs_filled = 0; dst_shaped = NULL; } if (FONT_CS(cur_font) == ISO10646_UCS4_1) { xfont = vt_ot_layout_get_font(ctl_info.ot_layout->term, cur_font); } else { xfont = NULL; } } prev_font = cur_font; if (xfont) { if (dst_shaped == NULL) { dst_shaped = &dst[dst_filled]; src_pos_mark = src_pos; } if (!vt_char_is_null(ch)) { ucs_buf[ucs_filled++] = vt_char_code(ch); for (; comb_size > 0; comb_size--) { ucs_buf[ucs_filled++] = vt_char_code(comb++); } } vt_char_copy(&dst[dst_filled++], vt_get_base_char(ch)); if (dst_filled >= dst_len) { break; } } else { vt_char_copy(&dst[dst_filled++], ch); if (dst_filled >= dst_len) { return dst_filled; } } } if (ucs_filled) { shaped_filled = vt_ot_layout_shape(xfont, shaped_buf, DST_LEN, offsets, widths, NULL, ucs_buf, ucs_filled); /* * If EOL char is a ot_layout byte which presents two ot_layouts and its * second * ot_layout is out of screen, 'shaped_filled' is greater then * 'dst + dst_len - dst_shaped'. */ if (shaped_filled > dst + dst_len - dst_shaped) { shaped_filled = dst + dst_len - dst_shaped; } was_vcol = 0; for (count = 0; count < shaped_filled; count++, dst_shaped++, src_pos_mark++) { if (offsets[count] || widths[count]) { was_vcol = combine_replacing_code(--dst_shaped, vt_get_base_char(&src[--src_pos_mark]), shaped_buf[count], offsets[count], widths[count], was_vcol); } else { was_vcol = replace_code(dst_shaped, shaped_buf[count], was_vcol); } } dst_filled = dst_shaped - dst; } return dst_filled; } #endif mlterm-3.8.9/vtemu/vt_shape.h010064400017600000144000000020271356600660700146650ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_SHAPING_H__ #define __VT_SHAPING_H__ #include /* u_int */ #include "vt_char.h" #include "vt_iscii.h" #include "vt_line.h" /* ctl_info_t */ #define IS_ARABIC_CHAR(ucode) (((ucode)&0xffffff00) == 0x600) #define IS_VAR_WIDTH_CHAR(ucode) (0x900 <= (ucode) && (ucode) <= 0xd7f) #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_FRIBIDI) u_int vt_shape_arabic(vt_char_t *dst, u_int dst_len, vt_char_t *src, u_int src_len); u_int16_t vt_is_arabic_combining(vt_char_t *prev2, vt_char_t *prev, vt_char_t *ch); #else #define vt_shape_arabic (NULL) #define vt_is_arabic_combining(a, b, c) (0) #endif #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_IND) u_int vt_shape_iscii(vt_char_t *dst, u_int dst_len, vt_char_t *src, u_int src_len); #else #define vt_shape_iscii (NULL) #endif u_int vt_shape_ot_layout(vt_char_t *dst, u_int dst_len, vt_char_t *src, u_int src_len, ctl_info_t ctl_info); #endif /* __VT_SHAPING_H__ */ mlterm-3.8.9/vtemu/vt_str.c010064400017600000144000000042601356600660700143710ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include "vt_str.h" #include #include /* malloc */ /* --- global functions --- */ /* * string functions */ void vt_str_init(vt_char_t *str, u_int size) { u_int count; for (count = 0; count < size; count++) { vt_char_init(str++); } } vt_char_t *vt_str_new(u_int size) { vt_char_t *str; if ((str = malloc(sizeof(vt_char_t) * size)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc() failed.\n"); #endif return NULL; } vt_str_init(str, size); return str; } void vt_str_final(vt_char_t *str, u_int size) { u_int count; for (count = 0; count < size; count++) { vt_char_final(&str[count]); } } void vt_str_destroy(vt_char_t *str, u_int size) { vt_str_final(str, size); free(str); } /* * dst and src may overlap. */ int vt_str_copy(vt_char_t *dst, vt_char_t *src, u_int size) { u_int count; if (size == 0 || dst == src) { return 0; } if (dst < src) { for (count = 0; count < size; count++) { vt_char_copy(dst++, src++); } } else if (dst > src) { dst += size; src += size; for (count = 0; count < size; count++) { vt_char_copy(--dst, --src); } } return 1; } u_int vt_str_cols(vt_char_t *chars, u_int len) { int count; u_int cols; cols = 0; for (count = 0; count < len; count++) { cols += vt_char_cols(&chars[count]); } return cols; } /* * XXX * Returns inaccurate result in dealing with combined characters. * Even if they have the same bytes, false is returned since * vt_char_t:multi_ch-s never point the same address.) */ int vt_str_equal(vt_char_t *str1, vt_char_t *str2, u_int len) { return memcmp(str1, str2, sizeof(vt_char_t) * len) == 0; } int vt_str_bytes_equal(vt_char_t *str1, vt_char_t *str2, u_int len) { int count; for (count = 0; count < len; count++) { if (!vt_char_code_equal(str1++, str2++)) { return 0; } } return 1; } #ifdef DEBUG void vt_str_dump(vt_char_t *chars, u_int len) { int count; for (count = 0; count < len; count++) { vt_char_dump(&chars[count]); } bl_msg_printf("\n"); } #endif mlterm-3.8.9/vtemu/vt_str.h010064400017600000144000000013601356600660700143740ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_STR_H__ #define __VT_STR_H__ #include /* alloca */ #include "vt_char.h" void vt_str_init(vt_char_t *str, u_int size); #define vt_str_alloca(size) ((vt_char_t*)alloca(sizeof(vt_char_t) * (size))) vt_char_t *vt_str_new(u_int size); void vt_str_final(vt_char_t *str, u_int size); void vt_str_destroy(vt_char_t *str, u_int size); int vt_str_copy(vt_char_t *dst, vt_char_t *src, u_int size); u_int vt_str_cols(vt_char_t *chars, u_int len); int vt_str_equal(vt_char_t *str1, vt_char_t *str2, u_int len); int vt_str_bytes_equal(vt_char_t *str1, vt_char_t *str2, u_int len); #ifdef DEBUG void vt_str_dump(vt_char_t *chars, u_int len); #endif #endif mlterm-3.8.9/vtemu/vt_str_parser.c010064400017600000144000000074751356600660700157600ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_str_parser.h" #include /* memcpy */ #include #include #include "vt_char_encoding.h" /* vt_is_msb_set */ #include "vt_drcs.h" typedef struct vt_str_parser { ef_parser_t parser; /* * !! Notice !! * ef_parser_reset() and ef_parser_mark() don't recognize these members. */ vt_char_t *str; u_int left; u_int comb_left; } vt_str_parser_t; /* --- static functions --- */ static int next_char(ef_parser_t *parser, ef_char_t *ch) { vt_str_parser_t *vt_str_parser; vt_char_t *vt_ch; u_int comb_size; vt_str_parser = (vt_str_parser_t*)parser; /* hack for ef_parser_reset */ vt_str_parser->str -= (parser->left - vt_str_parser->left); vt_str_parser->left = parser->left; while (1) { if (vt_str_parser->parser.is_eos) { goto err; } ef_parser_mark(parser); /* * skipping NULL */ if (!vt_char_is_null(vt_str_parser->str)) { break; } vt_str_parser->left--; vt_str_parser->str++; if (vt_str_parser->left == 0) { vt_str_parser->parser.is_eos = 1; } } vt_ch = vt_str_parser->str; if (vt_str_parser->comb_left > 0) { vt_char_t *combs; if ((combs = vt_get_combining_chars(vt_ch, &comb_size)) == NULL || comb_size < vt_str_parser->comb_left) { /* strange ! */ vt_str_parser->comb_left = 0; goto err; } vt_ch = &combs[comb_size - vt_str_parser->comb_left]; if (--vt_str_parser->comb_left == 0) { vt_str_parser->left--; vt_str_parser->str++; } } else { if (vt_get_combining_chars(vt_ch, &comb_size)) { vt_str_parser->comb_left = comb_size; } else { vt_str_parser->left--; vt_str_parser->str++; } } ch->cs = vt_char_cs(vt_ch); ch->size = CS_SIZE(ch->cs); ef_int_to_bytes(ch->ch, ch->size, vt_char_code(vt_ch)); /* * Android doesn't support PUA as follows. (tested on Android 4.0) * * e.g.) UTF8:0x4f88819a (U+10805a) * W/dalvikvm( 4527): JNI WARNING: input is not valid Modified UTF-8: illegal *start byte 0xf4 * I/dalvikvm( 4527): at dalvik.system.NativeStart.run(Native Method) * E/dalvikvm( 4527): VM aborting */ #ifndef __ANDROID__ if (!vt_convert_drcs_to_unicode_pua(ch)) #endif { /* XXX */ ch->property = 0; if (vt_is_msb_set(ch->cs)) { UNSET_MSB(ch->ch[0]); } } if (vt_str_parser->left == 0) { vt_str_parser->parser.is_eos = 1; } /* hack for ef_parser_reset */ parser->left = vt_str_parser->left; if (vt_char_is_null(vt_ch)) { return next_char(parser, ch); } return 1; err: /* hack for ef_parser_reset */ parser->left = vt_str_parser->left; return 0; } static void init(ef_parser_t *ef_parser) { vt_str_parser_t *vt_str_parser; vt_str_parser = (vt_str_parser_t*)ef_parser; ef_parser_init(ef_parser); vt_str_parser->str = NULL; vt_str_parser->left = 0; vt_str_parser->comb_left = 0; } static void set_str(ef_parser_t *ef_parser, u_char *str, size_t size) { /* do nothing */ } static void destroy(ef_parser_t *s) { free(s); } /* --- global functions --- */ ef_parser_t *vt_str_parser_new(void) { vt_str_parser_t *vt_str_parser; if ((vt_str_parser = malloc(sizeof(vt_str_parser_t))) == NULL) { return NULL; } init((ef_parser_t*)vt_str_parser); vt_str_parser->parser.init = init; vt_str_parser->parser.set_str = set_str; vt_str_parser->parser.destroy = destroy; vt_str_parser->parser.next_char = next_char; return (ef_parser_t*)vt_str_parser; } void vt_str_parser_set_str(ef_parser_t *ef_parser, vt_char_t *str, u_int size) { vt_str_parser_t *vt_str_parser; vt_str_parser = (vt_str_parser_t*)ef_parser; vt_str_parser->parser.is_eos = 0; vt_str_parser->parser.left = size; vt_str_parser->str = str; vt_str_parser->left = size; } mlterm-3.8.9/vtemu/vt_str_parser.h010064400017600000144000000005101356600660700157440ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_STR_PARSER_H__ #define __VT_STR_PARSER_H__ #include #include #include "vt_char.h" ef_parser_t *vt_str_parser_new(void); void vt_str_parser_set_str(ef_parser_t *ef_parser, vt_char_t *str, u_int size); #endif mlterm-3.8.9/vtemu/vt_term.c010064400017600000144000000567631356600660700145470ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_term.h" #include /* malloc/free */ #include #include /* strdup */ #include #include /* bl_parse_uri */ #include #include "vt_pty.h" #include "vt_parser.h" #include "vt_screen.h" #ifdef OPEN_PTY_ASYNC #ifdef USE_WIN32API #include #include /* _beginthreadex */ #else #include #endif typedef struct { vt_term_t *term; char *cmd_path; char **argv; char **env; char *host; char *work_dir; char *pass; char *pubkey; char *privkey; u_int width_pix; u_int height_pix; } pty_args_t; #endif /* --- global variables --- */ #ifndef NO_IMAGE /* XXX */ void (*vt_term_pty_closed_event)(vt_term_t *); #endif #if defined(__ANDROID__) && defined(USE_LIBSSH2) /* XXX */ int start_with_local_pty = 0; #endif /* --- static functions --- */ #ifdef OPEN_PTY_ASYNC static void pty_args_destroy(pty_args_t *args) { int count; free(args->cmd_path); free(args->host); free(args->work_dir); free(args->pass); free(args->pubkey); free(args->privkey); if (args->argv) { for (count = 0; args->argv[count]; count++) { free(args->argv[count]); } free(args->argv); } if (args->env) { for (count = 0; args->env[count]; count++) { free(args->env[count]); } free(args->env); } free(args); } static pty_args_t *pty_args_new(vt_term_t *term, const char *cmd_path, char **argv, char **env, const char *host, const char *work_dir, const char *pass, const char *pubkey, const char *privkey, u_int width_pix, u_int height_pix) { pty_args_t *args; u_int num; u_int count; if (!(args = calloc(1, sizeof(pty_args_t)))) { return NULL; } args->term = term; if (cmd_path) { args->cmd_path = strdup(cmd_path); } if (host) { args->host = strdup(host); } if (work_dir) { args->work_dir = strdup(work_dir); } if (pass) { args->pass = strdup(pass); } if (pubkey) { args->pubkey = strdup(pubkey); } if (privkey) { args->privkey = strdup(privkey); } args->width_pix = width_pix; args->height_pix = height_pix; if (argv) { for (num = 0; argv[num]; num++) ; if ((args->argv = malloc(sizeof(char *) * (num + 1)))) { for (count = 0; count < num; count++) { args->argv[count] = strdup(argv[count]); } args->argv[count] = NULL; } } else { args->argv = NULL; } if (env) { for (num = 0; env[num]; num++) ; if ((args->env = malloc(sizeof(char *) * (num + 1)))) { for (count = 0; count < num; count++) { args->env[count] = strdup(env[count]); } args->env[count] = NULL; } } else { args->env = NULL; } return args; } #ifdef USE_WIN32API static u_int __stdcall #else static void * #endif open_pty(void *p) { pty_args_t *args; vt_pty_t *pty; #ifdef USE_WIN32API static HANDLE mutex; if (!mutex) { mutex = CreateMutex(NULL, FALSE, NULL); } WaitForSingleObject(mutex, INFINITE); #else static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_detach(pthread_self()); pthread_mutex_lock(&mutex); #endif args = p; pty = vt_pty_new(args->cmd_path, args->argv, args->env, args->host, args->work_dir, args->pass, args->pubkey, args->privkey, vt_screen_get_logical_cols(args->term->screen), vt_screen_get_logical_rows(args->term->screen), args->width_pix, args->height_pix); if (pty) { if (args->pass) { args->term->uri = strdup(args->host); } vt_term_plug_pty(args->term, pty); } else { bl_dialog(BL_DIALOG_ALERT, "Failed to open pty"); args->term->return_special_pid = 1; bl_trigger_sig_child(-10); args->term->return_special_pid = 0; } pty_args_destroy(args); #ifdef USE_WIN32API ReleaseMutex(mutex); #else pthread_mutex_unlock(&mutex); #endif return 0; } #endif /* Must be called in visual context. */ static void set_use_local_echo(vt_term_t *term, int flag) { if (term->use_local_echo != flag && !(term->use_local_echo = flag)) { vt_screen_logical(term->screen); vt_screen_disable_local_echo(term->screen); vt_screen_visual(term->screen); } } /* --- global functions --- */ void vt_term_final(void) { vt_parser_final(); vt_termcap_final(); } vt_term_t *vt_term_new(const char *term_type, u_int cols, u_int rows, u_int tab_size, u_int log_size, vt_char_encoding_t encoding, int is_auto_encoding, int use_auto_detect, int logging_vt_seq, vt_unicode_policy_t policy, u_int col_size_a, int use_char_combining, int use_multi_col_char, int use_ctl, vt_bidi_mode_t bidi_mode, const char *bidi_separators, int use_dynamic_comb, vt_bs_mode_t bs_mode, vt_vertical_mode_t vertical_mode, int use_local_echo, const char *win_name, const char *icon_name, int use_ansi_colors, vt_alt_color_mode_t alt_color_mode, int use_ot_layout, vt_cursor_style_t cursor_style, int ignore_broadcasted_chars) { vt_termcap_ptr_t termcap; vt_term_t *term; if (!(termcap = vt_termcap_get(term_type))) { return NULL; } if ((term = calloc(1, sizeof(vt_term_t))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc failed.\n"); #endif return NULL; } if (!(term->screen = vt_screen_new(cols, rows, tab_size, log_size, vt_termcap_bce_is_enabled(termcap), bs_mode))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_screen_new failed.\n"); #endif goto error; } term->use_ot_layout = use_ot_layout; #ifndef NOT_CONVERT_TO_ISCII #ifdef USE_HARFBUZZ if (!term->use_ot_layout) #endif { policy |= CONVERT_UNICODE_TO_ISCII; } #endif if (!(term->parser = vt_parser_new(term->screen, termcap, encoding, is_auto_encoding, use_auto_detect, logging_vt_seq, policy, col_size_a, use_char_combining, use_multi_col_char, win_name, icon_name, use_ansi_colors, alt_color_mode, cursor_style, ignore_broadcasted_chars))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_parser_new failed.\n"); #endif goto error; } if (bidi_separators) { term->bidi_separators = bl_str_unescape(bidi_separators); } term->vertical_mode = vertical_mode; term->bidi_mode = bidi_mode; term->use_ctl = use_ctl; term->use_dynamic_comb = use_dynamic_comb; term->use_local_echo = use_local_echo; return term; error: if (term->screen) { vt_screen_destroy(term->screen); } if (term->parser) { vt_parser_destroy(term->parser); } free(term); return NULL; } void vt_term_destroy(vt_term_t *term) { #ifndef NO_IMAGE if (vt_term_pty_closed_event) { (*vt_term_pty_closed_event)(term); } #endif free(term->user_data); if (term->pty) { vt_pty_destroy(term->pty); } else if (term->pty_listener) { (*term->pty_listener->closed)(term->pty_listener->self); } free(term->uri); free(term->icon_path); free(term->bidi_separators); vt_screen_destroy(term->screen); vt_parser_destroy(term->parser); free(term); } void vt_term_zombie(vt_term_t *term) { if (term->pty) { vt_pty_t *pty; pty = term->pty; /* Should be NULL because vt_pty_destroy calls term->pty_listener->closed. */ term->pty = NULL; vt_pty_destroy(pty); } #ifdef DEBUG else { bl_debug_printf(BL_DEBUG_TAG " term is already zombie.\n"); } #endif } /* The caller should swap width_pix and height_pix in vertical mode. */ int vt_term_open_pty(vt_term_t *term, const char *cmd_path, char **argv, char **env, const char *host, const char *work_dir, const char *pass, const char *pubkey, const char *privkey, u_int width_pix, u_int height_pix) { if (!term->pty) { #ifdef OPEN_PTY_ASYNC char *host_dup; char *user; char *server; char *port; if (pass && (host_dup = alloca(strlen(host) + 1)) && bl_parse_uri(NULL, &user, &server, &port, NULL, NULL, strcpy(host_dup, host)) #ifdef USE_LIBSSH2 && !vt_search_ssh_session(server, port, user) #endif ) { pty_args_t *args; if (!(args = pty_args_new(term, cmd_path, argv, env, host, work_dir, pass, pubkey, privkey, width_pix, height_pix))) { return 0; } #ifdef USE_WIN32API { HANDLE thrd; u_int tid; if ((thrd = _beginthreadex(NULL, 0, open_pty, args, 0, &tid))) { CloseHandle(thrd); return 1; } return 0; } #else { pthread_t thrd; if (pthread_create(&thrd, NULL, open_pty, args) == 0) { return 1; } else { return 0; } } #endif } else #endif /* OPEN_PTY_ASYNC */ { vt_pty_t *pty; if (!(pty = vt_pty_new(cmd_path, argv, env, host, work_dir, pass, pubkey, privkey, vt_screen_get_logical_cols(term->screen), vt_screen_get_logical_rows(term->screen), width_pix, height_pix))) { bl_dialog(BL_DIALOG_ALERT, "Failed to open pty"); return 0; } if (pass) { term->uri = strdup(host); } vt_term_plug_pty(term, pty); } } return 1; } int vt_term_plug_pty(vt_term_t *term, vt_pty_t *pty /* Not NULL */) { if (!term->pty) { if (term->pty_listener) { vt_pty_set_listener(pty, term->pty_listener); term->pty_listener = NULL; } vt_parser_set_pty(term->parser, pty); term->pty = pty; } return 1; } int vt_term_attach(vt_term_t *term, vt_xterm_event_listener_t *xterm_listener, vt_config_event_listener_t *config_listener, vt_screen_event_listener_t *screen_listener, vt_pty_event_listener_t *pty_listener) { if (term->is_attached) { /* already attached */ return 0; } vt_parser_set_xterm_listener(term->parser, xterm_listener); vt_parser_set_config_listener(term->parser, config_listener); vt_screen_set_listener(term->screen, screen_listener); if (term->pty) { vt_pty_set_listener(term->pty, pty_listener); } else { term->pty_listener = pty_listener; } term->is_attached = 1; return 1; } int vt_term_detach(vt_term_t *term) { if (!term->is_attached) { /* already detached. */ return 0; } vt_parser_set_xterm_listener(term->parser, NULL); vt_parser_set_config_listener(term->parser, NULL); vt_screen_set_listener(term->screen, NULL); if (term->pty) { vt_pty_set_listener(term->pty, NULL); } else { term->pty_listener = NULL; } term->is_attached = 0; return 1; } void vt_term_set_use_ot_layout(vt_term_t *term, int flag) { #if defined(USE_HARFBUZZ) && !defined(NOT_CONVERT_TO_ISCII) vt_unicode_policy_t policy; policy = vt_parser_get_unicode_policy(term->parser); if (flag) { policy &= ~CONVERT_UNICODE_TO_ISCII; } else { policy |= CONVERT_UNICODE_TO_ISCII; } vt_parser_set_unicode_policy(term->parser, policy); #endif term->use_ot_layout = flag; } int vt_term_get_master_fd(vt_term_t *term) { if (term->pty == NULL) { return -1; } return vt_pty_get_master_fd(term->pty); } int vt_term_get_slave_fd(vt_term_t *term) { if (term->pty == NULL) { return -1; } return vt_pty_get_slave_fd(term->pty); } /* * Always return non-NULL value. * XXX Static data can be returned. (Not reentrant) */ char *vt_term_get_slave_name(vt_term_t *term) { if (term->pty == NULL) { return "/dev/zombie"; } return vt_pty_get_slave_name(term->pty); } pid_t vt_term_get_child_pid(vt_term_t *term) { if (term->pty == NULL) { #ifdef OPEN_PTY_ASYNC return term->return_special_pid ? -10 : -1; #else return -1; #endif } return vt_pty_get_pid(term->pty); } pid_t vt_term_get_pty_mode(vt_term_t *term) { if (term->pty == NULL) { return PTY_NONE; } return vt_pty_get_mode(term->pty); } size_t vt_term_write(vt_term_t *term, u_char *buf, size_t len) { if (term->pty == NULL || vt_parser_is_transferring_data(term->parser)) { return 0; } if (term->use_local_echo) { vt_parser_local_echo(term->parser, buf, len); } return vt_write_to_pty(term->pty, buf, len); } /* The caller should swap width_pix and height_pix in vertical mode. */ int vt_term_resize(vt_term_t *term, u_int cols, u_int rows, u_int width_pix, u_int height_pix) { int ret; vt_screen_logical(term->screen); ret = vt_screen_resize(term->screen, cols, rows, 1); vt_screen_render(term->screen); vt_screen_visual(term->screen); if (term->pty) { /* Don't use cols and rows because status line might change rows in vt_screen_resize(). */ vt_set_pty_winsize(term->pty, vt_screen_get_logical_cols(term->screen), vt_screen_get_logical_rows(term->screen), width_pix, height_pix); } return ret; } int vt_term_unhighlight_cursor(vt_term_t *term, int revert_visual) { vt_line_t *line; int ret; #ifdef DEBUG if (term->screen->logvis && !term->screen->logvis->is_visual) { bl_debug_printf(BL_DEBUG_TAG " vt_term_unhighlight_cursor() should be called in visual context but" " is called in logical context.\n"); } #endif vt_screen_logical(term->screen); if ((line = vt_screen_get_cursor_line(term->screen)) == NULL || vt_line_is_empty(line)) { ret = 0; } else { vt_line_set_modified(line, vt_screen_cursor_char_index(term->screen), vt_screen_cursor_char_index(term->screen)); ret = 1; } if (revert_visual) { /* vt_screen_render(term->screen); */ vt_screen_visual(term->screen); } return ret; } /* * Not implemented yet. */ #if 0 void vt_term_set_modified_region(vt_term_t *term, int beg_char_index, int beg_row, u_int nchars, u_int nrows) { return; } #endif /* * Not used. */ #if 0 void vt_term_set_modified_region_in_screen(vt_term_t *term, int beg_char_index, int beg_row, u_int nchars, u_int nrows) { int row; vt_line_t *line; int revert_to_visual; /* * This function is usually called in visual context, and sometimes * called in logical context. (see flush_scroll_cache() in x_screen.c) */ if (!vt_screen_logical_visual_is_reversible(term->screen) && vt_screen_logical(term->screen)) { revert_to_visual = 1; } else { revert_to_visual = 0; } for (row = beg_row; row < beg_row + nrows; row++) { if ((line = vt_screen_get_line_in_screen(term->screen, row))) { vt_line_set_modified(line, beg_char_index, beg_char_index + nchars - 1); } } if (revert_to_visual) { /* vt_screen_render(term->screen); */ vt_screen_visual(term->screen); } } #endif void vt_term_set_modified_lines(vt_term_t *term, int beg, int end) { int row; vt_line_t *line; int revert_to_visual; /* * This function is usually called in visual context, and sometimes * called in logical context. (see flush_scroll_cache() in x_screen.c) */ if (!vt_screen_logical_visual_is_reversible(term->screen) && vt_screen_logical(term->screen)) { revert_to_visual = 1; } else { revert_to_visual = 0; } for (row = beg; row <= end; row++) { if ((line = vt_screen_get_line(term->screen, row))) { vt_line_set_modified_all(line); } } if (revert_to_visual) { /* vt_screen_render(term->screen); */ vt_screen_visual(term->screen); } } void vt_term_set_modified_lines_in_screen(vt_term_t *term, int beg, int end) { int row; vt_line_t *line; int revert_to_visual; /* * This function is usually called in visual context, and sometimes * called in logical context. (see flush_scroll_cache() in x_screen.c) */ if (!vt_screen_logical_visual_is_reversible(term->screen) && vt_screen_logical(term->screen)) { revert_to_visual = 1; } else { revert_to_visual = 0; } for (row = beg; row <= end; row++) { if ((line = vt_screen_get_line_in_screen(term->screen, row))) { vt_line_set_modified_all(line); } } if (revert_to_visual) { /* vt_screen_render(term->screen); */ vt_screen_visual(term->screen); } } void vt_term_set_modified_all_lines_in_screen(vt_term_t *term) { int revert_to_visual; /* * This function is usually called in visual context, and sometimes * called in logical context. (see flush_scroll_cache() in x_screen.c) */ if (!vt_screen_logical_visual_is_reversible(term->screen) && vt_screen_logical(term->screen)) { revert_to_visual = 1; } else { revert_to_visual = 0; } vt_screen_set_modified_all(term->screen); if (revert_to_visual) { /* vt_screen_render(term->screen); */ vt_screen_visual(term->screen); } } void vt_term_updated_all(vt_term_t *term) { int row; vt_line_t *line; #ifdef DEBUG if (term->screen->logvis && !term->screen->logvis->is_visual) { bl_debug_printf(BL_DEBUG_TAG " vt_term_updated_all() should be called in visual context but" " is called in logical context.\n"); } #endif if (!vt_screen_logical_visual_is_reversible(term->screen)) { vt_screen_logical(term->screen); } for (row = 0; row < vt_edit_get_rows(term->screen->edit); row++) { if ((line = vt_screen_get_line_in_screen(term->screen, row))) { vt_line_set_updated(line); } } if (!vt_screen_logical_visual_is_reversible(term->screen)) { /* vt_screen_render(term->screen); */ vt_screen_visual(term->screen); } } /* * Return value: * 1 => Updated * 0 => Not updated(== not necessary to redraw) */ int vt_term_update_special_visual(vt_term_t *term) { vt_logical_visual_t *logvis; int had_logvis = 0; int has_logvis = 0; had_logvis = vt_screen_destroy_logical_visual(term->screen); if (term->use_dynamic_comb) { if ((logvis = vt_logvis_comb_new())) { if (vt_screen_add_logical_visual(term->screen, logvis)) { has_logvis = 1; if (vt_parser_is_using_char_combining(term->parser)) { bl_msg_printf( "Set use_combining=false forcibly " "to enable use_dynamic_comb.\n"); vt_parser_set_use_char_combining(term->parser, 0); } } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_screen_add_logical_visual failed.\n"); #endif (*logvis->destroy)(logvis); } } #ifdef DEBUG else { bl_warn_printf(BL_DEBUG_TAG " vt_logvis_comb_new() failed.\n"); } #endif } /* Vertical mode, BiDi and ISCII can't coexist. */ /* Similar if-else conditions exist in update_special_visual in x_screen.c. */ if (term->vertical_mode) { if ((logvis = vt_logvis_vert_new(term->vertical_mode))) { if (vt_screen_add_logical_visual(term->screen, logvis)) { has_logvis = 1; } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_screen_add_logical_visual failed.\n"); #endif (*logvis->destroy)(logvis); } } #ifdef DEBUG else { bl_warn_printf(BL_DEBUG_TAG " vt_logvis_vert_new() failed.\n"); } #endif } else if (term->use_ctl && (vt_term_get_encoding(term) == VT_UTF8 || IS_ISCII_ENCODING(vt_term_get_encoding(term)))) { if ((logvis = vt_logvis_ctl_new(term->bidi_mode, term->bidi_separators, term->use_ot_layout ? term : NULL))) { if (vt_screen_add_logical_visual(term->screen, logvis)) { has_logvis = 1; } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_screen_add_logical_visual failed.\n"); #endif (*logvis->destroy)(logvis); } } #ifdef DEBUG else { bl_warn_printf(BL_DEBUG_TAG " vt_logvis_ctl_new() failed.\n"); } #endif } if (had_logvis || has_logvis) { vt_screen_render(term->screen); vt_screen_visual(term->screen); return 1; } else { return 0; } } void vt_term_enter_backscroll_mode(vt_term_t *term) { /* XXX */ if (term->vertical_mode) { bl_msg_printf("Not supported backscrolling in vertical mode.\n"); return; } return vt_enter_backscroll_mode(term->screen); } void vt_term_set_icon_path(vt_term_t *term, const char *path) { free(term->icon_path); if (path && *path) { term->icon_path = strdup(path); } else { term->icon_path = NULL; } } void vt_term_set_bidi_separators(vt_term_t *term, const char *bidi_separators) { free(term->bidi_separators); if (bidi_separators && *bidi_separators) { term->bidi_separators = bl_str_unescape(bidi_separators); } else { term->bidi_separators = NULL; } } int vt_term_get_config(vt_term_t *term, vt_term_t *output, /* if term == output, NULL is set */ char *key, int to_menu, int *flag) { char *value; if (vt_parser_get_config(term->parser, output ? output->pty : NULL, key, to_menu, flag)) { return 1; } if (strcmp(key, "vertical_mode") == 0) { value = vt_get_vertical_mode_name(term->vertical_mode); } else if (strcmp(key, "use_dynamic_comb") == 0) { if (term->use_dynamic_comb) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "use_ctl") == 0) { if (term->use_ctl) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "bidi_mode") == 0) { value = vt_get_bidi_mode_name(term->bidi_mode); } else if (strcmp(key, "bidi_separators") == 0) { if ((value = term->bidi_separators) == NULL) { value = ""; } } #ifdef USE_OT_LAYOUT else if (strcmp(key, "use_ot_layout") == 0) { if (term->use_ot_layout) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "ot_features") == 0) { value = vt_get_ot_layout_attr(OT_FEATURES); } else if (strcmp(key, "ot_script") == 0) { value = vt_get_ot_layout_attr(OT_SCRIPT); } #endif else if (strcmp(key, "pty_name") == 0) { if (output) { if ((value = vt_get_window_name(term->parser)) == NULL) { value = ""; } } else { value = vt_term_get_slave_name(term); } } else if (strcmp(key, "icon_path") == 0) { if ((value = term->icon_path) == NULL) { value = ""; } } else if (strcmp(key, "use_local_echo") == 0) { if (term->use_local_echo) { value = "true"; } else { value = "false"; } #if defined(__ANDROID__) && defined(USE_LIBSSH2) } else if (strcmp(key, "start_with_local_pty") == 0) { value = start_with_local_pty ? "true" : "false"; #endif } else { /* Continue to process it in x_screen.c */ return 0; } if (!output) { output = term; } /* value is never set NULL above. */ #if 0 if (!value) { vt_response_config(output->pty, "error", NULL, to_menu); } #endif if (flag) { *flag = value ? true_or_false(value) : -1; } else { vt_response_config(output->pty, key, value, to_menu); } return 1; } /* Called in visual context */ int vt_term_set_config(vt_term_t *term, char *key, char *value) { if (vt_parser_set_config(term->parser, key, value)) { /* do nothing */ } else if (strcmp(key, "use_local_echo") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { set_use_local_echo(term, flag); } } #ifdef USE_OT_LAYOUT else if (strcmp(key, "ot_script") == 0) { vt_set_ot_layout_attr(value, OT_SCRIPT); } else if (strcmp(key, "ot_features") == 0) { vt_set_ot_layout_attr(value, OT_FEATURES); } #endif else { /* Continue to process it in x_screen.c */ return 0; } return 1; } mlterm-3.8.9/vtemu/vt_term.h010064400017600000144000000324201356600660700145340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ /* * !! Notice !! * Don't provide any methods modifying vt_model_t and vt_logs_t states * unless these are logicalized in advance. */ #ifndef __VT_TERM_H__ #define __VT_TERM_H__ #include /* USE_WIN32API */ #include "vt_pty.h" #include "vt_parser.h" #include "vt_screen.h" typedef struct vt_term { /* * private */ vt_pty_t *pty; vt_pty_event_listener_t *pty_listener; /* pool until pty opened. */ vt_parser_t *parser; vt_screen_t *screen; /* * private */ char *icon_path; char *uri; char *bidi_separators; /* vt_bidi_mode_t */ int8_t bidi_mode; /* vt_vertical_mode_t */ int8_t vertical_mode; int8_t use_ctl; int8_t use_dynamic_comb; int8_t use_ot_layout; int8_t use_local_echo; int8_t is_attached; #ifdef OPEN_PTY_ASYNC int8_t return_special_pid; #endif void *user_data; } vt_term_t; /* XXX */ extern void (*vt_term_pty_closed_event)(vt_term_t *); #if defined(__ANDROID__) && defined(USE_LIBSSH2) /* XXX */ extern int start_with_local_pty; #endif #define vt_term_init vt_parser_init void vt_term_final(void); vt_term_t *vt_term_new(const char *term_type, u_int cols, u_int rows, u_int tab_size, u_int log_size, vt_char_encoding_t encoding, int is_auto_encoding, int use_auto_detect, int logging_vt_seq, vt_unicode_policy_t policy, u_int col_size_a, int use_char_combining, int use_multi_col_char, int use_ctl, vt_bidi_mode_t bidi_mode, const char *bidi_separators, int use_dynamic_comb, vt_bs_mode_t bs_mode, vt_vertical_mode_t vertical_mode, int use_local_echo, const char *win_name, const char *icon_name, int use_ansi_colors, vt_alt_color_mode_t alt_color_mode, int use_ot_layout, vt_cursor_style_t cursor_style, int ignore_broadcasted_chars); void vt_term_destroy(vt_term_t *term); void vt_term_zombie(vt_term_t *term); int vt_term_open_pty(vt_term_t *term, const char *cmd_path, char **argv, char **env, const char *host, const char *work_dir, const char *pass, const char *pubkey, const char *privkey, u_int width_pix, u_int height_pix); int vt_term_plug_pty(vt_term_t *term, vt_pty_t *pty); #define vt_term_pty_is_opened(term) ((term)->pty != NULL) int vt_term_attach(vt_term_t *term, vt_xterm_event_listener_t *xterm_listener, vt_config_event_listener_t *config_listener, vt_screen_event_listener_t *screen_listener, vt_pty_event_listener_t *pty_listner); int vt_term_detach(vt_term_t *term); #define vt_term_is_attached(term) ((term)->is_attached) #define vt_term_is_sending_data(term) vt_parser_is_sending_data((term)->parser) #define vt_term_is_zmodem_ready(term) vt_parser_is_zmodem_ready((term)->parser) #define vt_term_parse_vt100_sequence(term) vt_parse_vt100_sequence((term)->parser) #define vt_term_reset_pending_vt100_sequence(term) vt_reset_pending_vt100_sequence((term)->parser) #define vt_term_response_config(term, key, value, to_menu) \ vt_response_config((term)->pty, key, value, to_menu) #define vt_term_change_encoding(term, encoding) \ vt_parser_change_encoding((term)->parser, encoding) #define vt_term_get_encoding(term) vt_parser_get_encoding((term)->parser) #define vt_term_set_use_ctl(term, flag) ((term)->use_ctl = (flag)) #define vt_term_is_using_ctl(term) ((term)->use_ctl) #define vt_term_set_bidi_mode(term, mode) ((term)->bidi_mode = (mode)) #define vt_term_get_bidi_mode(term) ((term)->bidi_mode) void vt_term_set_use_ot_layout(vt_term_t *term, int flag); #define vt_term_is_using_ot_layout(term) ((term)->use_ot_layout) #define vt_term_set_vertical_mode(term, mode) ((term)->vertical_mode = (mode)) #define vt_term_get_vertical_mode(term) ((term)->vertical_mode) #define vt_term_set_use_dynamic_comb(term, use) ((term)->use_dynamic_comb = (use)) #define vt_term_is_using_dynamic_comb(term) ((term)->use_dynamic_comb) #define vt_term_convert_to(term, dst, len, _parser) \ vt_parser_convert_to((term)->parser, dst, len, _parser) #define vt_term_init_encoding_parser(term) vt_init_encoding_parser((term)->parser) #define vt_term_init_encoding_conv(term) vt_init_encoding_conv((term)->parser) int vt_term_get_master_fd(vt_term_t *term); int vt_term_get_slave_fd(vt_term_t *term); char *vt_term_get_slave_name(vt_term_t *term); pid_t vt_term_get_child_pid(vt_term_t *term); pid_t vt_term_get_pty_mode(vt_term_t *term); size_t vt_term_write(vt_term_t *term, u_char *buf, size_t len); #define vt_term_write_modified_key(term, key, modcode) \ ((term)->pty ? vt_parser_write_modified_key((term)->parser, key, modcode) : 0) #define vt_term_write_special_key(term, key, modcode, is_numlock) \ ((term)->pty ? vt_parser_write_special_key((term)->parser, key, modcode, is_numlock) : 0) /* Must be called in visual context. */ #define vt_term_write_loopback(term, buf, len) \ vt_parser_write_loopback((term)->parser, buf, len) /* Must be called in visual context. */ #define vt_term_show_message(term, msg) vt_parser_show_message((term)->parser, msg) #if 1 /* defined(__ANDROID__) || defined(__APPLE__) || defined(USE_SDL2) */ /* Must be called in visual context. */ #define vt_term_preedit(term, buf, len) vt_parser_preedit((term)->parser, buf, len) #endif int vt_term_resize(vt_term_t *term, u_int cols, u_int rows, u_int width_pix, u_int height_pix); #define vt_term_cursor_col(term) vt_screen_cursor_col((term)->screen) #define vt_term_cursor_char_index(term) vt_screen_cursor_char_index((term)->screen) #define vt_term_cursor_row(term) vt_screen_cursor_row((term)->screen) #define vt_term_cursor_row_in_screen(term) vt_screen_cursor_row_in_screen((term)->screen) int vt_term_unhighlight_cursor(vt_term_t *term, int revert_visual); #define vt_term_get_cols(term) vt_screen_get_cols((term)->screen) #define vt_term_get_rows(term) vt_screen_get_rows((term)->screen) #define vt_term_get_logical_cols(term) vt_screen_get_logical_cols((term)->screen) #define vt_term_get_logical_rows(term) vt_screen_get_logical_rows((term)->screen) #define vt_term_get_log_size(term) vt_screen_get_log_size((term)->screen) #define vt_term_change_log_size(term, log_size) vt_screen_change_log_size((term)->screen, log_size) #define vt_term_unlimit_log_size(term) vt_screen_unlimit_log_size((term)->screen) #define vt_term_log_size_is_unlimited(term) vt_screen_log_size_is_unlimited((term)->screen) #define vt_term_get_num_logged_lines(term) vt_screen_get_num_logged_lines((term)->screen) #define vt_term_convert_scr_row_to_abs(term, row) \ vt_screen_convert_scr_row_to_abs((term)->screen, row) #define vt_term_get_line(term, row) vt_screen_get_line(term->screen, row) #define vt_term_get_line_in_screen(term, row) vt_screen_get_line_in_screen((term)->screen, row) #define vt_term_get_cursor_line(term) vt_screen_get_cursor_line((term)->screen) #if 0 void vt_term_set_modified_region(vt_term_t *term, int beg_char_index, int beg_row, u_int nchars, u_int nrows); void vt_term_set_modified_region_in_screen(vt_term_t *term, int beg_char_index, int beg_row, u_int nchars, u_int nrows); #endif void vt_term_set_modified_lines(vt_term_t *term, int beg, int end); void vt_term_set_modified_lines_in_screen(vt_term_t *term, int beg, int end); void vt_term_set_modified_all_lines_in_screen(vt_term_t *term); void vt_term_updated_all(vt_term_t *term); int vt_term_update_special_visual(vt_term_t *term); #define vt_term_logical_visual_is_reversible(term) \ vt_screen_logical_visual_is_reversible((term)->screen) #define vt_term_is_backscrolling(term) vt_screen_is_backscrolling((term)->screen) void vt_term_enter_backscroll_mode(vt_term_t *term); #define vt_term_exit_backscroll_mode(term) vt_exit_backscroll_mode((term)->screen) #define vt_term_backscroll_to(term, row) vt_screen_backscroll_to((term)->screen, row) #define vt_term_backscroll_upward(term, size) vt_screen_backscroll_upward((term)->screen, size) #define vt_term_backscroll_downward(term, size) vt_screen_backscroll_downward((term)->screen, size) #define vt_term_reverse_color(term, beg_char_index, beg_row, end_char_index, end_row, is_rect) \ vt_screen_reverse_color((term)->screen, beg_char_index, beg_row, end_char_index, end_row, is_rect) #define vt_term_restore_color(term, beg_char_index, beg_row, end_char_index, end_row, is_rect) \ vt_screen_restore_color((term)->screen, beg_char_index, beg_row, end_char_index, end_row, is_rect) #define vt_term_copy_region(term, chars, num_chars, beg_char_index, beg_row, end_char_index, \ end_row, is_rect) \ vt_screen_copy_region((term)->screen, chars, num_chars, beg_char_index, beg_row, \ end_char_index, end_row, is_rect) #define vt_term_get_region_size(term, beg_char_index, beg_row, end_char_index, end_row, is_rect) \ vt_screen_get_region_size((term)->screen, beg_char_index, beg_row, end_char_index, end_row, \ is_rect) #define vt_term_get_line_region(term, beg_row, end_char_index, end_row, base_row) \ vt_screen_get_line_region((term)->screen, beg_row, end_char_index, end_row, base_row) #define vt_term_get_word_region(term, beg_char_index, beg_row, end_char_index, end_row, \ base_char_index, base_row) \ vt_screen_get_word_region((term)->screen, beg_char_index, beg_row, end_char_index, end_row, \ base_char_index, base_row) #define vt_term_get_bce_ch(term) vt_screen_get_bce_ch((term)->screen) #define vt_term_write_content(term, fd, conv, clear_at_end, area) \ vt_screen_write_content(term->screen, fd, conv, clear_at_end, area) #define vt_term_cursor_is_rtl(term) vt_screen_cursor_is_rtl((term)->screen) #define vt_term_set_use_multi_col_char(term, flag) \ vt_parser_set_use_multi_col_char((term)->parser, flag) #define vt_term_is_using_multi_col_char(term) \ vt_parser_is_using_multi_col_char((term)->parser) #define vt_term_get_mouse_report_mode(term) vt_parser_get_mouse_report_mode((term)->parser) #define vt_term_want_focus_event(term) vt_parser_want_focus_event((term)->parser) #define vt_term_set_alt_color_mode(term, mode) \ vt_parser_set_alt_color_mode((term)->parser, mode) #define vt_term_get_alt_color_mode(term) vt_parser_get_alt_color_mode((term)->parser) #define vt_term_is_broadcasting(term) vt_parser_is_broadcasting((term)->parser) void vt_term_set_icon_path(vt_term_t *term, const char *path); #define vt_term_window_name(term) vt_get_window_name((term)->parser) #define vt_term_icon_name(term) vt_get_icon_name((term)->parser) #define vt_term_icon_path(term) ((term)->icon_path) #define vt_term_get_uri(term) ((term)->uri) #define vt_term_is_bracketed_paste_mode(term) \ vt_parser_is_bracketed_paste_mode((term)->parser) #define vt_term_set_unicode_policy(term, policy) \ vt_parser_set_unicode_policy((term)->parser, policy) #define vt_term_get_unicode_policy(term) vt_parser_get_unicode_policy((term)->parser) void vt_term_set_bidi_separators(vt_term_t *term, const char *bidi_separators); #define vt_term_get_cmd_line(term) vt_pty_get_cmd_line((term)->pty) #define vt_term_start_config_menu(term, cmd_path, x, y, display) \ vt_start_config_menu((term)->pty, cmd_path, x, y, display) #define vt_term_has_pending_sequence(term) vt_parser_has_pending_sequence((term)->parser) int vt_term_get_config(vt_term_t *term, vt_term_t *output, char *key, int to_menu, int *flag); int vt_term_set_config(vt_term_t *term, char *key, char *value); #define vt_term_exec_cmd(term, cmd) vt_parser_exec_cmd((term)->parser, cmd) #define vt_term_reset(term, level) vt_parser_reset((term)->parser, level) #define vt_term_report_mouse_tracking(term, col, row, button, is_released, key_state, \ button_state) \ vt_parser_report_mouse_tracking((term)->parser, col, row, button, is_released, key_state, \ button_state) #define vt_term_search_init(term, match) vt_screen_search_init((term)->screen, match) #define vt_term_search_final(term) vt_screen_search_final((term)->screen) #define vt_term_search_reset_position(term) vt_screen_search_reset_position((term)->screen) #define vt_term_search_find(term, beg_char_index, beg_row, end_char_index, end_row, regex, \ backward) \ vt_screen_search_find((term)->screen, beg_char_index, beg_row, end_char_index, end_row, regex, \ backward) #define vt_term_blink(term) vt_screen_blink((term)->screen) #define vt_term_has_status_line(term) vt_screen_has_status_line((term)->screen) #define vt_term_get_user_data(term, key) ((term)->user_data) #define vt_term_set_user_data(term, key, val) ((term)->user_data = (val)) #define vt_term_select_drcs(term) vt_parser_select_drcs((term)->parser) #define vt_term_is_visible_cursor(term) vt_parser_is_visible_cursor((term)->parser) #define vt_term_get_cursor_style(term) vt_parser_get_cursor_style((term)->parser) #define vt_term_get_hide_pointer_mode(term) vt_parser_get_hide_pointer_mode((term)->parser) #endif mlterm-3.8.9/vtemu/vt_term_manager.c010064400017600000144000000316651356600660700162330ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_term_manager.h" #include /* sprintf/sscanf */ #include /* fork/exec */ #include #include /* bl_snprintf */ #include /* malloc */ #include #include /* BL_DIGIT_STR */ #include #include /* bl_file_unset_cloexec */ #include /* bl_setenv/bl_unsetenv */ #define MAX_TERMS (MTU * max_terms_multiple) /* Default MAX_TERMS is 32. */ #define MTU (8 * sizeof(*dead_mask)) /* MAX_TERMS unit */ #ifndef BINDIR #define BINDIR "/usr/local/bin" #endif #if 0 #define __DEBUG #endif #if 0 #define INFINIT_RESTART #endif /* --- static variables --- */ static u_int max_terms_multiple; static u_int32_t *dead_mask; /* * 'terms' pointer must not be changed because vt_get_all_terms returns it * directly. * So 'terms' array must be allocated only once. */ static vt_term_t **terms; static u_int num_terms; static char *pty_list; static int zombie_pty; static char *auto_restart_cmd; /* --- static functions --- */ #if !defined(USE_WIN32API) && !defined(DEBUG) static void sig_error(int sig) { u_int count; char env[1024]; size_t len; env[0] = '\0'; len = 0; for (count = 0; count < num_terms; count++) { int master; if ((master = vt_term_get_master_fd(terms[count])) >= 0) { int slave; size_t n; slave = vt_term_get_slave_fd(terms[count]); snprintf(env + len, 1024 - len, "%d %d %d,", master, slave, vt_term_get_child_pid(terms[count])); n = strlen(env + len); if (n + len >= 1024) { env[len] = '\0'; break; } else { len += n; } bl_file_unset_cloexec(master); bl_file_unset_cloexec(slave); } } if (len > 0) { pid_t pid; pid = fork(); if (pid < 0) { return; } if (pid == 0) { /* child process */ for (count = 0; count < num_terms; count++) { vt_term_write_content(terms[count], vt_term_get_slave_fd(terms[count]), terms[count]->parser->cc_conv, 1, WCA_ALL); } exit(0); } bl_setenv("INHERIT_PTY_LIST", env, 1); if (auto_restart_cmd) { execlp(auto_restart_cmd, auto_restart_cmd, NULL); } execl(BINDIR "/mlterm", BINDIR "/mlterm", NULL); bl_error_printf("Failed to restart mlterm.\n"); } exit(1); } #endif static void sig_child(void *p, pid_t pid) { u_int count; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " SIG_CHILD received [PID:%d].\n", pid); #endif if (pid == -1) { /* * Note: * If term->pty is NULL, vt_term_get_child_pid() returns -1. * waitpid() in bl_sig_child.c might return -1. * * (Don't check by "pid < 0" above, because vt_term_get_child_pid() * might return minus value if it is a ssh channel.) */ return; } for (count = 0; count < num_terms; count++) { if (pid == vt_term_get_child_pid(terms[count])) { u_int idx; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " pty %d is dead.\n", count); #endif idx = count / MTU; dead_mask[idx] |= (1 << (count - MTU * idx)); } } } /* --- global functions --- */ int vt_term_manager_init(u_int multiple) { if (multiple > 0) { max_terms_multiple = multiple; } else { max_terms_multiple = 1; } if ((terms = malloc(sizeof(vt_term_t*) * MAX_TERMS)) == NULL) { return 0; } if ((dead_mask = calloc(sizeof(*dead_mask), max_terms_multiple)) == NULL) { goto error1; } if (!vt_term_init()) { goto error2; } bl_add_sig_child_listener(NULL, sig_child); return 1; error2: free(dead_mask); dead_mask = NULL; error1: free(terms); terms = NULL; return 0; } void vt_term_manager_final(void) { int count; #ifdef USE_OT_LAYOUT vt_set_ot_layout_attr(NULL, OT_SCRIPT); vt_set_ot_layout_attr(NULL, OT_FEATURES); #endif bl_remove_sig_child_listener(NULL, sig_child); vt_term_final(); for (count = num_terms - 1; count >= 0; count--) { #if 0 /* * All windows may be invalid before vt_term_manager_final() is called. * Without this vt_term_detach(), if terms[count] is not detached, * pty_listener::pty_closed() which is called in vt_pty_destroy() can * operate invalid window. */ vt_term_detach(terms[count]); #endif vt_term_destroy(terms[count]); } free(terms); free(dead_mask); free(pty_list); free(auto_restart_cmd); } void vt_set_auto_restart_cmd(const char *cmd) { #if !defined(USE_WIN32API) && !defined(DEBUG) char *env; if ( #ifndef INFINIT_RESTART (!(env = getenv("INHERIT_PTY_LIST")) || *env == '\0') && #endif cmd && *cmd) { if (!auto_restart_cmd) { struct sigaction act; #if 0 /* * sa_sigaction which is called instead of sa_handler * if SA_SIGINFO is set to sa_flags is not defined in * some environments. */ act.sa_sigaction = NULL; #endif act.sa_handler = sig_error; sigemptyset(&act.sa_mask); /* Not blocking any signals for child. */ act.sa_flags = SA_NODEFER; /* Not blocking any signals for child. */ sigaction(SIGBUS, &act, NULL); sigaction(SIGSEGV, &act, NULL); sigaction(SIGFPE, &act, NULL); sigaction(SIGILL, &act, NULL); free(auto_restart_cmd); } auto_restart_cmd = strdup(cmd); } else if (auto_restart_cmd) { signal(SIGBUS, SIG_DFL); signal(SIGSEGV, SIG_DFL); signal(SIGFPE, SIG_DFL); signal(SIGILL, SIG_DFL); free(auto_restart_cmd); auto_restart_cmd = NULL; } #endif } vt_term_t *vt_create_term(const char *term_type, u_int cols, u_int rows, u_int tab_size, u_int log_size, vt_char_encoding_t encoding, int is_auto_encoding, int use_auto_detect, int logging_vt_seq, vt_unicode_policy_t policy, int col_size_a, int use_char_combining, int use_multi_col_char, int use_ctl, vt_bidi_mode_t bidi_mode, const char *bidi_separators, int use_dynamic_comb, vt_bs_mode_t bs_mode, vt_vertical_mode_t vertical_mode, int use_local_echo, const char *win_name, const char *icon_name, int use_ansi_colors, vt_alt_color_mode_t alt_color_mode, int use_ot_layout, vt_cursor_style_t cursor_style, int ignore_broadcasted_chars) { #if !defined(USE_WIN32API) && !defined(DEBUG) char *list; char *list_tmp; #endif if (num_terms == MAX_TERMS) { return NULL; } #if !defined(USE_WIN32API) && !defined(DEBUG) if ((list_tmp = getenv("INHERIT_PTY_LIST")) && (list = alloca(strlen(list_tmp) + 1))) { int master; int slave; pid_t child_pid; char *p; strcpy(list, list_tmp); while ((p = bl_str_sep(&list, ","))) { vt_pty_ptr_t pty; if (sscanf(p, "%d %d %d", &master, &slave, &child_pid) == 3) { /* * cols + 1 is for redrawing screen by vt_set_pty_winsize() below. */ if ((pty = vt_pty_new_with(master, slave, child_pid, cols + 1, rows, 0, 0))) { if ((terms[num_terms] = vt_term_new( term_type, cols, rows, tab_size, log_size, encoding, is_auto_encoding, use_auto_detect, logging_vt_seq, policy, col_size_a, use_char_combining, use_multi_col_char, use_ctl, bidi_mode, bidi_separators, use_dynamic_comb, bs_mode, vertical_mode, use_local_echo, win_name, icon_name, use_ansi_colors, alt_color_mode, use_ot_layout, cursor_style, ignore_broadcasted_chars))) { vt_term_plug_pty(terms[num_terms++], pty); vt_set_pty_winsize(pty, cols, rows, 0, 0); continue; } else { vt_pty_destroy(pty); } } close(master); close(slave); } } #ifdef INFINIT_RESTART bl_unsetenv("INHERIT_PTY_LIST"); #endif if (num_terms > 0) { return terms[num_terms - 1]; } } #endif /* * Before modifying terms and num_terms, do vt_close_dead_terms(). */ vt_close_dead_terms(); /* * XXX * If sig_child here... */ if (!(terms[num_terms] = vt_term_new(term_type, cols, rows, tab_size, log_size, encoding, is_auto_encoding, use_auto_detect, logging_vt_seq, policy, col_size_a, use_char_combining, use_multi_col_char, use_ctl, bidi_mode, bidi_separators, use_dynamic_comb, bs_mode, vertical_mode, use_local_echo, win_name, icon_name, use_ansi_colors, alt_color_mode, use_ot_layout, cursor_style, ignore_broadcasted_chars))) { return NULL; } return terms[num_terms++]; } void vt_destroy_term(vt_term_t *term) { u_int count; /* * Before modifying terms and num_terms, do vt_close_dead_terms(). */ vt_close_dead_terms(); /* * XXX * If sig_child here... */ for (count = 0; count < num_terms; count++) { if (terms[count] == term) { terms[count] = terms[--num_terms]; break; } } vt_term_destroy(term); } vt_term_t *vt_get_term(const char *dev) { int count; for (count = 0; count < num_terms; count++) { if (dev == NULL || strcmp(dev, vt_term_get_slave_name(terms[count])) == 0) { return terms[count]; } } return NULL; } vt_term_t *vt_get_detached_term(const char *dev) { int count; for (count = 0; count < num_terms; count++) { if (!vt_term_is_attached(terms[count]) && (dev == NULL || strcmp(dev, vt_term_get_slave_name(terms[count])) == 0)) { return terms[count]; } } return NULL; } vt_term_t *vt_next_term(vt_term_t *term /* is detached */ ) { int count; for (count = 0; count < num_terms; count++) { if (terms[count] == term) { int old; old = count; for (count++; count < num_terms; count++) { if (!vt_term_is_attached(terms[count])) { return terms[count]; } } for (count = 0; count < old; count++) { if (!vt_term_is_attached(terms[count])) { return terms[count]; } } return NULL; } } return NULL; } vt_term_t *vt_prev_term(vt_term_t *term /* is detached */ ) { int count; for (count = 0; count < num_terms; count++) { if (terms[count] == term) { int old; old = count; for (count--; count >= 0; count--) { if (!vt_term_is_attached(terms[count])) { return terms[count]; } } for (count = num_terms - 1; count > old; count--) { if (!vt_term_is_attached(terms[count])) { return terms[count]; } } return NULL; } } return NULL; } /* * Return value: Number of opened terms. Don't trust it after vt_create_term(), * vt_destroy_term() or vt_close_dead_terms() which can change it is called. */ u_int vt_get_all_terms(vt_term_t*** _terms) { if (_terms) { *_terms = terms; } return num_terms; } void vt_close_dead_terms(void) { if (num_terms > 0) { int idx; for (idx = (num_terms - 1) / MTU; idx >= 0; idx--) { if (dead_mask[idx]) { int count; for (count = MTU - 1; count >= 0; count--) { if (dead_mask[idx] & (0x1 << count)) { vt_term_t *term; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " closing dead term %d.\n", count); #endif term = terms[idx * MTU + count]; /* * Update terms and num_terms before * vt_term_destroy, which calls * vt_pty_event_listener::pty_close in which * vt_term_manager can be used. */ terms[idx * MTU + count] = terms[--num_terms]; if (zombie_pty) { vt_term_zombie(term); } else { vt_term_destroy(term); } } } memset(&dead_mask[idx], 0, sizeof(dead_mask[idx])); } } } } char *vt_get_pty_list(void) { int count; char *p; size_t len; free(pty_list); /* The length of pty name is under 50. */ len = (50 + 2) * num_terms; if ((pty_list = malloc(len + 1)) == NULL) { return ""; } p = pty_list; *p = '\0'; for (count = 0; count < num_terms; count++) { bl_snprintf(p, len, "%s:%d;", vt_term_get_slave_name(terms[count]), vt_term_is_attached(terms[count])); len -= strlen(p); p += strlen(p); } return pty_list; } void vt_term_manager_enable_zombie_pty(void) { zombie_pty = 1; } #if defined(__HAIKU__) || defined(__APPLE__) /* only for cocoatouch */ int vt_check_sig_child(void) { if (num_terms > 0) { int idx; for (idx = (num_terms - 1) / MTU; idx >= 0; idx--) { if (dead_mask[idx]) { return 1; } } } return 0; } #endif mlterm-3.8.9/vtemu/vt_term_manager.h010064400017600000144000000032021356600660700162220ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_TERM_MANAGER_H__ #define __VT_TERM_MANAGER_H__ #include "vt_term.h" int vt_term_manager_init(u_int multiple); void vt_term_manager_final(void); void vt_set_auto_restart_cmd(const char *cmd); vt_term_t *vt_create_term(const char *term_type, u_int cols, u_int rows, u_int tab_size, u_int log_size, vt_char_encoding_t encoding, int is_auto_encoding, int use_auto_detect, int logging_vt_seq, vt_unicode_policy_t policy, int col_size_a, int use_char_combining, int use_multi_col_char, int use_ctl, vt_bidi_mode_t bidi_mode, const char *bidi_separators, int use_dynamic_comb, vt_bs_mode_t bs_mode, vt_vertical_mode_t vertical_mode, int use_local_echo, const char *win_name, const char *icon_name, int use_ansi_colors, vt_alt_color_mode_t alt_color_mode, int use_ot_layout, vt_cursor_style_t cursor_style, int ignore_broadcasted_chars); void vt_destroy_term(vt_term_t *term); vt_term_t *vt_get_term(const char *dev); vt_term_t *vt_get_detached_term(const char *dev); vt_term_t *vt_next_term(vt_term_t *term); vt_term_t *vt_prev_term(vt_term_t *term); u_int vt_get_all_terms(vt_term_t ***terms); void vt_close_dead_terms(void); char *vt_get_pty_list(void); void vt_term_manager_enable_zombie_pty(void); #if defined(__HAIKU__) || defined(__APPLE__) /* only for cocoatouch */ int vt_check_sig_child(void); #endif #endif mlterm-3.8.9/vtemu/zmodem.c010064400017600000144000005161251356600660700143530ustar kenusers/* -*- c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */ /* * zmodem.c * * qodem - Qodem Terminal Emulator * * Written 2003-2017 by Kevin Lamonte * * To the extent possible under law, the author(s) have dedicated all * copyright and related and neighboring rights to this software to the * public domain worldwide. This software is distributed without any * warranty. * * You should have received a copy of the CC0 Public Domain Dedication along * with this software. If not, see * . * * Modified 2019- by Araki Ken * (Based on qodem-1.0.0) */ /* * Bugs in the Zmodem protocol: * * 1. ZCOMMAND, huge-ass security hole. * * 2. Stupid arbitrary decisions about when the argument field is big- * endian and when it's little-endian. * * 3. Arbitrary non-control characters CANNOT be escaped making it * impossible to protect against connection closures in telnet, rlogin, * and ssh. * * * Bugs noted in lrzsz implementation: * * 1. A spurious ZRQINIT from sz if we use ZCHALLENGE. * * 2. core from sz if ZRPOS position > file size. * * 3. rz assumes CRC32 on ZSINIT, even if it gets a 16-bit or hex header. * * 4. sz requires a hex ZRPOS on error, not sure why. * * 5. sz requires a hex ZCRC, not sure why. * * */ #include #include #include #include #include #include #include #include #include #include #include #include "zmodem.h" #include /* USE_WIN32API */ #include /* u_int32_t */ #ifndef uint32_t #define uint32_t u_int32_t #endif /** * The supported download protocols. */ typedef enum Q_PROTOCOLS { Q_PROTOCOL_ASCII, /* ASCII */ Q_PROTOCOL_KERMIT, /* Kermit */ Q_PROTOCOL_XMODEM, /* Xmodem */ Q_PROTOCOL_XMODEM_CRC, /* Xmodem CRC */ Q_PROTOCOL_XMODEM_RELAXED, /* Xmodem Relaxed */ Q_PROTOCOL_XMODEM_1K, /* Xmodem-1K */ Q_PROTOCOL_YMODEM, /* Ymodem Batch */ Q_PROTOCOL_ZMODEM, /* Zmodem Batch */ Q_PROTOCOL_XMODEM_1K_G, /* Xmodem-1K/G */ Q_PROTOCOL_YMODEM_G /* Ymodem/G Batch */ } Q_PROTOCOL; /** * The transfer state as exposed to the user in the file transfer dialog * screen. */ typedef enum Q_TRANSFER_STATES { /** * Initial state. */ Q_TRANSFER_STATE_INIT, /** * Waiting for file information. */ Q_TRANSFER_STATE_FILE_INFO, /** * Transferrring a file. */ Q_TRANSFER_STATE_TRANSFER, /** * Completed with a file, maybe waiting for another file info. */ Q_TRANSFER_STATE_FILE_DONE, /** * Transfer aborted, displaying completion screen. */ Q_TRANSFER_STATE_ABORT, /** * Displaying completion screen. */ Q_TRANSFER_STATE_END } Q_TRANSFER_STATE; /** * The data behind the file transfer dialog screen. */ struct q_transfer_stats_struct { Q_TRANSFER_STATE state; Q_PROTOCOL protocol; char * protocol_name; char * filename; char * pathname; char * last_message; unsigned long bytes_total; unsigned long bytes_transfer; unsigned long blocks; unsigned long block_size; unsigned long blocks_transfer; unsigned long error_count; /** * The total bytes to send for a batch. */ unsigned long batch_bytes_total; /** * The amount of bytes sent so far for a batch. */ unsigned long batch_bytes_transfer; time_t batch_start_time; time_t file_start_time; time_t end_time; }; /** * Transfer statistics. Lots of places need to peek into this structure. */ struct q_transfer_stats_struct q_transfer_stats = { Q_TRANSFER_STATE_INIT, Q_PROTOCOL_ASCII, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #if 0 #define DLOG(A) printf A; fflush(NULL) #else #define DLOG(A) #endif #if 0 #define DLOG2(A) printf A; fflush(NULL) #else #define DLOG2(A) #endif #define _(A) A /* Maximum length of any filename */ #define FILENAME_SIZE 256 /* * Maximum length of a message generated for a dialog box (e.g. file transfer * dialog) */ #define DIALOG_MESSAGE_SIZE 128 /* Members of q_status in qodem.h */ static Q_BOOL zmodem_escape_ctrl = Q_FALSE; static Q_BOOL zmodem_zchallenge = Q_FALSE; #define Xfree(X, Y, Z) free(X) #define C_LF 0x0A #define C_CR 0x0D #define C_XON 0x11 #define C_XOFF 0x13 #define C_CAN 0x18 /** * strdup() equivalent that plugs into the Hans-Boehm GC if it is enabled, if * not it just passes through to the default strdup(). * * @param ptr the string to copy * @param file the filename calling this function * @param line the line number at the call point. */ static char * Xstrdup(const char * ptr, const char * file, const int line) { char * local_ptr; #if defined(Q_GC_BOEHM) && defined(HAVE_LIBGC) int length; int i; #endif assert(ptr != NULL); #if defined(Q_GC_BOEHM) && defined(HAVE_LIBGC) length = strlen(ptr) + 1; #ifdef DEBUG local_ptr = (char *) GC_debug_malloc(length, file, line); #else local_ptr = (char *) GC_malloc(length); #endif /* DEBUG */ if (local_ptr != NULL) { for (i = 0; i < length; i++) { local_ptr[i] = ptr[i]; } } #else local_ptr = strdup(ptr); #endif #if 0 /* For debugging: */ fprintf(stderr, "Xstrdup: ptr=%p local_ptr=%p file=%s line=%d\n", ptr, local_ptr, file, line); #endif return local_ptr; } /** * End the file transfer. * * @param new_state the state to switch to after a brief display pause */ static void stop_file_transfer(const Q_TRANSFER_STATE new_state) { zmodem_stop(Q_TRUE); q_transfer_stats.state = new_state; time(&q_transfer_stats.end_time); } /** * Set the exposed filename. Allocates a copy of the string which is freed * when the program state is switched to Q_STATE_CONSOLE. * * @param new_string the new filname */ static void set_transfer_stats_filename(const char * new_string) { #if 0 /* * Do nothing if being set to what it already is. Note this is a pointer * comparison, not a string comparison. */ if (new_string == q_transfer_stats.filename) { return; } if (q_transfer_stats.filename != NULL) { Xfree(q_transfer_stats.filename, __FILE__, __LINE__); } q_transfer_stats.filename = Xstrdup(new_string, __FILE__, __LINE__); #endif } /** * Set the exposed path name. Allocates a copy of the string which is freed * when the program state is switched to Q_STATE_CONSOLE. * * @param new_string the new path name */ static void set_transfer_stats_pathname(const char * new_string) { #if 0 /* * Do nothing if being set to what it already is. Note this is a pointer * comparison, not a string comparison. */ if (new_string == q_transfer_stats.pathname) { return; } if (q_transfer_stats.pathname != NULL) { Xfree(q_transfer_stats.pathname, __FILE__, __LINE__); } q_transfer_stats.pathname = Xstrdup(new_string, __FILE__, __LINE__); #endif } /** * Set the exposed message. Allocates a copy of the string which is freed * when the program state is switched to Q_STATE_CONSOLE. * * @param new_string the new message */ static void set_transfer_stats_last_message(const char * format, ...) { #if 0 char outbuf[DIALOG_MESSAGE_SIZE]; va_list arglist; memset(outbuf, 0, sizeof(outbuf)); va_start(arglist, format); vsprintf((char *) (outbuf + strlen(outbuf)), format, arglist); va_end(arglist); if (q_transfer_stats.last_message != NULL) { Xfree(q_transfer_stats.last_message, __FILE__, __LINE__); } q_transfer_stats.last_message = Xstrdup(outbuf, __FILE__, __LINE__); #endif } /* * Require an ACK every 32 frames on reliable links. */ #define WINDOW_SIZE_RELIABLE 32 /* * Require an ACK every 4 frames on unreliable links. */ #define WINDOW_SIZE_UNRELIABLE 4 /* Data types ----------------------------------------------- */ /* Used to note the start of a packet */ #define ZPAD '*' /* CRC next, frame ends, header packet follows */ #define ZCRCE 'h' /* CRC next, frame continues nonstop */ #define ZCRCG 'i' /* CRC next, frame continues, ZACK expected */ #define ZCRCQ 'j' /* CRC next, ZACK expected, end of frame */ #define ZCRCW 'k' /* Packet types */ #define P_ZRQINIT 0 #define P_ZRINIT 1 #define P_ZSINIT 2 #define P_ZACK 3 #define P_ZFILE 4 #define P_ZSKIP 5 #define P_ZNAK 6 #define P_ZABORT 7 #define P_ZFIN 8 #define P_ZRPOS 9 #define P_ZDATA 10 #define P_ZEOF 11 #define P_ZFERR 12 #define P_ZCRC 13 #define P_ZCHALLENGE 14 #define P_ZCOMPL 15 #define P_ZCAN 16 #define P_ZFREECNT 17 #define P_ZCOMMAND 18 /* Transfer capabilities sent in ZRInit packet */ /* Rx can send and receive true FDX */ #define TX_CAN_FULL_DUPLEX 0x00000001 /* Rx can receive data during disk I/O */ #define TX_CAN_OVERLAP_IO 0x00000002 /* Rx can send a break signal */ #define TX_CAN_BREAK 0x00000004 /* Receiver can decrypt */ #define TX_CAN_DECRYPT 0x00000008 /* Receiver can uncompress */ #define TX_CAN_LZW 0x00000010 /* Receiver can use 32 bit Frame Check */ #define TX_CAN_CRC32 0x00000020 /* Receiver expects ctl chars to be escaped */ #define TX_ESCAPE_CTRL 0x00000040 /* Receiver expects 8th bit to be escaped */ #define TX_ESCAPE_8BIT 0x00000080 /** * The Zmodem protocol state that can encompass multiple file transfers. */ typedef enum { /* Before the first byte is sent */ INIT, /* Transfer complete */ COMPLETE, /* Transfer was aborted due to excessive timeouts or ZCAN */ ABORT, /* Collecting data for a ZFILE, ZSINIT, ZDATA, and ZCOMMAND packet. */ ZDATA, /* * Receiver side */ /* Send ZRINIT */ ZRINIT, /* Waiting for ZFILE or ZSINIT */ ZRINIT_WAIT, /* Send ZCHALLENGE */ ZCHALLENGE, /* Waiting for ZACK */ ZCHALLENGE_WAIT, /* Send ZRPOS */ ZRPOS, /* Waiting for ZDATA */ ZRPOS_WAIT, /* Send ZSKIP */ ZSKIP, /* Send ZCRC */ ZCRC, /* Waiting for ZCRC */ ZCRC_WAIT, /* * Sender side */ /* Send ZRQINIT */ ZRQINIT, /* Waiting for ZRINIT or ZCHALLENGE */ ZRQINIT_WAIT, /* Send ZSINIT */ ZSINIT, /* Waiting for ZACK */ ZSINIT_WAIT, /* Send ZFILE */ ZFILE, /* Waiting for ZSKIP, ZCRC, or ZRPOS */ ZFILE_WAIT, /* Send ZEOF */ ZEOF, /* Waiting for ZRPOS */ ZEOF_WAIT, /* Send ZFIN */ ZFIN, /* Waiting for ZFIN */ ZFIN_WAIT } STATE; /** * The single-file-specific protocol state variables. */ struct ZMODEM_STATUS { /* INIT, COMPLETE, ABORT, etc. */ STATE state; /* State before entering DATA state */ STATE prior_state; /* Send/receive flags */ unsigned long flags; /* If true, use 32-bit CRC */ Q_BOOL use_crc32; /* If true, we are the sender */ Q_BOOL sending; /* Current filename being sent/received */ char * file_name; /* Size of file in bytes */ unsigned int file_size; /* Modification time of file */ time_t file_modtime; /* Current position */ off_t file_position; /* Stream pointer to current file */ FILE * file_stream; /* File CRC32 */ uint32_t file_crc32; /* Block size */ int block_size; /* If true, sent block will ask for ZACK */ Q_BOOL ack_required; /* If true, we are waiting to hear ZACK */ Q_BOOL waiting_for_ack; /* * If true, we are continuously streaming the ZDATA "data subpacket" and * will not need to generate a new packet header. */ Q_BOOL streaming_zdata; /* Timeout normally lasts 10 seconds */ int timeout_length; /* The beginning time for the most recent timeout cycle */ time_t timeout_begin; /* Total number of timeouts before aborting is 5 */ int timeout_max; /* Total number of timeouts so far */ int timeout_count; /* Number of bytes confirmed from the receiver */ int confirmed_bytes; /* * Number of bytes confirmed from the receiver when we dropped the block * size. */ int last_confirmed_bytes; /* True means TCP/IP or error-correcting modem */ Q_BOOL reliable_link; /* File position when the block size was last reduced */ off_t file_position_downgrade; /* When 0, require a ZACK, controls window size */ unsigned blocks_ack_count; /* Number of error blocks */ int consecutive_errors; /* Full pathname to file */ char file_fullname[FILENAME_SIZE]; }; /** * The per-file transfer status. */ static struct ZMODEM_STATUS status = { ABORT, /* Set ABORT by default for zmodem_is_processing() */ INIT, 0, Q_TRUE, Q_FALSE, NULL, 0, 0, 0, NULL, -1, ZMODEM_BLOCK_SIZE, Q_FALSE, Q_FALSE, Q_FALSE, 10, 0, 5, 0, 0, Q_TRUE, 0, 0, 0 }; /* The list of files to upload */ static struct file_info * upload_file_list; /* The current entry in upload_file_list being sent */ static int upload_file_list_i; /* * The path to download to. Note download_path is Xstrdup'd TWICE: once HERE * and once more on the progress dialog. The q_program_state transition to * Q_STATE_CONSOLE is what Xfree's the copy in the progress dialog. This * copy is Xfree'd in zmodem_stop(). */ static char * download_path = NULL; /* Every bit of Zmodem data goes out as packets */ struct zmodem_packet { int type; uint32_t argument; Q_BOOL use_crc32; int crc16; uint32_t crc32; unsigned char data[ZMODEM_MAX_BLOCK_SIZE]; unsigned int data_n; /* * Performance tweak for decode_zdata_bytes to allow it to quickly bail * out during CRC check. */ unsigned char crc_buffer[5]; }; /* Needs to persist across calls to zmodem() */ static struct zmodem_packet packet; /* Internal buffer used to collect a complete packet before processing it */ static unsigned char packet_buffer[ZMODEM_MAX_BLOCK_SIZE]; static unsigned int packet_buffer_n; /* * Internal buffer used to queue a complete outbound packet so that the * top-level code can saturate the link. */ static unsigned char outbound_packet[ZMODEM_MAX_BLOCK_SIZE]; static unsigned int outbound_packet_n; /* Return codes from parse_packet() */ typedef enum { ZM_PP_INVALID, ZM_PP_NODATA, ZM_PP_CRCERROR, ZM_PP_OK } ZM_PARSE_PACKET; #define big_to_little_endian(X) (((X >> 24) & 0xFF) | \ ((X >> 8) & 0xFF00) | \ ((X << 8) & 0xFF0000) | \ ((X << 24) & 0xFF000000)) /* The ZCHALLENGE value we asked for */ static uint32_t zchallenge_value; static int progress_length; /* CRC16 CODE ------------------------------------------------------------- */ /* * KAL - This CRC16 routine was taken verbatim from XYMODEM.DOC. * * This function calculates the CRC used by the XMODEM/CRC Protocol * The first argument is a pointer to the message block. * The second argument is the number of bytes in the message block. * The function returns an integer which contains the CRC. * The low order 16 bits are the coefficients of the CRC. */ static int compute_crc16(int crc, const unsigned char *ptr, int count) { int i; while (--count >= 0) { crc = crc ^ ((int) *ptr++ << 8); for (i = 0; i < 8; ++i) if (crc & 0x8000) crc = (crc << 1) ^ 0x1021; else crc = crc << 1; } return (crc & 0xFFFF); } /* CRC32 CODE ------------------------------------------------------------- */ /* * The following CRC32 code was posted by Colin Plumb in * comp.os.linux.development.system. Google link: * http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&selm=4dr0ab%24o1k%40nyx10.cs.du.edu */ /* * This uses the CRC-32 from IEEE 802 and the FDDI MAC, * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. * * This is, for a slight efficiency win, used in a little-endian bit * order, where the least significant bit of the accumulator (and each * byte of input) corresponds to the highest exponent of x. * E.g. the byte 0x23 is interpreted as x^7+x^6+x^2. For the * most rational output, the computed 32-bit CRC word should be * sent with the low byte (which are the most significant coefficients * from the polynomial) first. If you do this, the CRC of a buffer * that includes a trailing CRC will always be zero. Or, if you * use a trailing invert variation, some fixed value. For this * polynomial, that fixed value is 0x2144df1c. (Leading presets, * be they to 0, -1, or something else, don't matter.) * * Thus, the little-endian hex constant is as follows: * 11111111112222222222333 * 012345678901234567890123456789012 * 111011011011100010000011001000001 * \ /\ /\ /\ /\ /\ /\ /\ /\ * E D B 8 8 3 2 0 * * This technique, while a bit confusing, is widely used in e.g. Zmodem. */ #define CRC32 0xedb88320 /* CRC polynomial */ static uint32_t crc_32_tab[256]; /* * This computes the CRC table quite efficiently, using the fact that * crc_32_tab[i^j] = crc_32_tab[i] ^ crc_32_tab[j]. We start out with * crc_32_tab[0] = 0, j = 128, and then set h to the desired value of * crc_32_tab[j]. Then for each crc_32_tab[i] which is already set (which * includes i = 0, so crc_32_tab[j] will get set), set crc_32_tab[i^j] = * crc_32_tab[i] ^ h. * Then divide j by 2 and repeat until everything is filled in. * The first pass sets crc_32_tab[128]. The second sets crc_32_tab[64] * and crc_32_tab[192]. The third sets entries 32, 96, 160 and 224. * The eighth and last pass sets all the odd-numbered entries. */ static void makecrc(void) { int i, j = 128; uint32_t h = 1; crc_32_tab[0] = 0; do { if (h & 1) h = (h >> 1) ^ CRC32; else h >>= 1; for (i = 0; i < 256; i += j + j) crc_32_tab[i + j] = crc_32_tab[i] ^ h; } while (j >>= 1); } /* * Compute a CRC on the given buffer and length using a static CRC * accumulator. If buf is NULL this initializes the accumulator, * otherwise it updates it to include the additional data and * returns the CRC of the data so far. * * The CRC is computed using preset to -1 and invert. */ static uint32_t compute_crc32(const uint32_t old_crc, const unsigned char *buf, unsigned len) { uint32_t crc; if (buf) { crc = old_crc; while (len--) crc = (crc >> 8) ^ crc_32_tab[(crc ^ *buf++) & 0xff]; return crc ^ 0xffffffff; /* Invert */ } else { return 0xffffffff; /* Preset to -1 */ } } /* CRC32 CODE ------------------------------------------------------------- */ /* ------------------------------------------------------------------------ */ /* Block size adjustment logic -------------------------------------------- */ /* ------------------------------------------------------------------------ */ /** * Move up to a larger block size if things are going better. */ static void block_size_up() { DLOG(("block_size_up(): block_size = %d\n", status.block_size)); /* * After getting a clean bill of health for 8k, move block size up */ if ((status.confirmed_bytes - status.file_position_downgrade) > 8196) { status.block_size *= 2; if (status.block_size > ZMODEM_BLOCK_SIZE) { status.block_size = ZMODEM_BLOCK_SIZE; } } status.last_confirmed_bytes = status.confirmed_bytes; DLOG(("block_size_up(): NEW block size = %d\n", status.block_size)); } /** * Move down to a smaller block size if things are going badly. */ static void block_size_down() { int outstanding_packets = (status.confirmed_bytes - status.last_confirmed_bytes) / status.block_size; DLOG(("block_size_down(): block_size = %d outstanding_packets = %d\n", status.block_size, outstanding_packets)); if (outstanding_packets >= 3) { if (status.block_size > 32) { status.block_size /= 2; status.file_position_downgrade = status.confirmed_bytes; } } if (outstanding_packets >= 10) { if (status.block_size == 32) { /* * Too much line noise, give up */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); set_transfer_stats_last_message(_("LINE NOISE, !@#&*%U")); } } status.blocks_ack_count = WINDOW_SIZE_UNRELIABLE; status.last_confirmed_bytes = status.confirmed_bytes; DLOG(("block_size_down(): NEW block size = %d\n", status.block_size)); } /* ------------------------------------------------------------------------ */ /* Progress dialog -------------------------------------------------------- */ /* ------------------------------------------------------------------------ */ /** * Statistics: reset for a new file. * * @param filename the file being transferred * @param filesize the size of the file (known from either file attributes or * because this is an upload) */ static void stats_new_file(const char * filename, const int filesize) { char * basename_arg; char * dirname_arg; /* * Clear per-file statistics */ q_transfer_stats.blocks_transfer = 0; q_transfer_stats.bytes_transfer = 0; q_transfer_stats.error_count = 0; status.confirmed_bytes = 0; status.last_confirmed_bytes = 0; set_transfer_stats_last_message(""); q_transfer_stats.bytes_total = filesize; q_transfer_stats.blocks = filesize / ZMODEM_BLOCK_SIZE; if ((filesize % ZMODEM_BLOCK_SIZE) > 0) { q_transfer_stats.blocks++; } /* * Note that basename and dirname modify the arguments */ basename_arg = Xstrdup(filename, __FILE__, __LINE__); dirname_arg = Xstrdup(filename, __FILE__, __LINE__); set_transfer_stats_filename(basename(basename_arg)); set_transfer_stats_pathname(dirname(dirname_arg)); Xfree(basename_arg, __FILE__, __LINE__); Xfree(dirname_arg, __FILE__, __LINE__); q_transfer_stats.state = Q_TRANSFER_STATE_TRANSFER; time(&q_transfer_stats.file_start_time); } /** * Statistics: increment the block count. */ static void stats_increment_blocks() { q_transfer_stats.block_size = status.block_size; q_transfer_stats.blocks_transfer = status.file_position / ZMODEM_BLOCK_SIZE; if ((status.file_position % ZMODEM_BLOCK_SIZE) > 0) { q_transfer_stats.blocks_transfer++; } status.consecutive_errors = 0; DLOG(("stats_increment_blocks(): waiting_for_ack = %s ack_required = %s reliable_link = %s confirmed_bytes = %u last_confirmed_bytes = %u block_size = %d blocks_ack_count = %d\n", (status.waiting_for_ack == Q_TRUE ? "true" : "false"), (status.ack_required == Q_TRUE ? "true" : "false"), (status.reliable_link == Q_TRUE ? "true" : "false"), status.confirmed_bytes, status.last_confirmed_bytes, status.block_size, status.blocks_ack_count)); } /** * Statistics: an error was encountered. * * @param format a format string + arguments for emitting to the progress * dialog */ static void stats_increment_errors(const char * format, ...) { char outbuf[DIALOG_MESSAGE_SIZE]; va_list arglist; memset(outbuf, 0, sizeof(outbuf)); va_start(arglist, format); vsprintf((char *) (outbuf + strlen(outbuf)), format, arglist); va_end(arglist); set_transfer_stats_last_message(outbuf); q_transfer_stats.error_count++; status.consecutive_errors++; q_transfer_stats.block_size = status.block_size; /* * Unreliable link is a one-way ticket until the next call to * zmodem_start() . */ status.reliable_link = Q_FALSE; DLOG(("stats_increment_errors(): waiting_for_ack = %s ack_required = %s reliable_link = %s confirmed_bytes = %u last_confirmed_bytes = %u block_size = %d blocks_ack_count = %d\n", (status.waiting_for_ack == Q_TRUE ? "true" : "false"), (status.ack_required == Q_TRUE ? "true" : "false"), (status.reliable_link == Q_TRUE ? "true" : "false"), status.confirmed_bytes, status.last_confirmed_bytes, status.block_size, status.blocks_ack_count)); /* * If too many errors when not in ZDATA, the other end is probably not * even running zmodem. Bail out. */ if ((status.consecutive_errors >= 15) && (status.state != ZDATA)) { set_transfer_stats_last_message(_("LINE NOISE, !@#&*%U")); stop_file_transfer(Q_TRANSFER_STATE_ABORT); status.state = ABORT; } } /** * Initialize a new file to upload. * * @return true if OK, false if the file could not be opened */ static Q_BOOL setup_for_next_file() { char * basename_arg; /* * Reset our dynamic variables */ if (status.file_stream != NULL) { fclose(status.file_stream); } status.file_stream = NULL; if (status.file_name != NULL) { Xfree(status.file_name, __FILE__, __LINE__); } status.file_name = NULL; if (upload_file_list[upload_file_list_i].name == NULL) { /* * Special case: the termination/finish packet */ DLOG(("ZMODEM: No more files (name='%s')\n", upload_file_list[upload_file_list_i].name)); /* * Let's keep all the information the same, just increase the total * bytes. */ q_transfer_stats.batch_bytes_transfer = q_transfer_stats.batch_bytes_total; /* * We're done */ status.state = ZFIN; return Q_TRUE; } /* * Get the file's modification time */ status.file_modtime = upload_file_list[upload_file_list_i].fstats.st_mtime; status.file_size = upload_file_list[upload_file_list_i].fstats.st_size; /* * Open the file */ if ((status.file_stream = fopen(upload_file_list[upload_file_list_i].name, "rb")) == NULL) { DLOG(("ERROR: Unable to open file %s: %s (%d)\n", upload_file_list[upload_file_list_i].name, strerror(errno), errno)); status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); set_transfer_stats_last_message(_("DISK I/O ERROR")); return Q_FALSE; } /* * Note that basename and dirname modify the arguments */ basename_arg = Xstrdup(upload_file_list[upload_file_list_i].name, __FILE__, __LINE__); if (status.file_name != NULL) { Xfree(status.file_name, __FILE__, __LINE__); } status.file_name = Xstrdup(basename(basename_arg), __FILE__, __LINE__); /* * Update the stats */ stats_new_file(upload_file_list[upload_file_list_i].name, upload_file_list[upload_file_list_i].fstats.st_size); /* * Free the copies passed to basename() and dirname() */ Xfree(basename_arg, __FILE__, __LINE__); DLOG(("UPLOAD set up for new file %s (%lu bytes)...\n", upload_file_list[upload_file_list_i].name, (long int) upload_file_list[upload_file_list_i].fstats.st_size)); /* * Update stuff if this is the second file */ if (status.state != ABORT) { /* * Update main status state */ q_transfer_stats.state = Q_TRANSFER_STATE_TRANSFER; /* * We need to send ZFILE now */ status.state = ZFILE; } return Q_TRUE; } /** * Reset the timeout counter. */ static void reset_timer() { time(&status.timeout_begin); } /** * Check for a timeout. * * @return true if a timeout has occurred */ static Q_BOOL check_timeout() { time_t now; time(&now); DLOG(("check_timeout()\n")); if (now - status.timeout_begin >= status.timeout_length) { /* * Timeout */ status.timeout_count++; DLOG(("ZMODEM: Timeout #%d\n", status.timeout_count)); if (status.timeout_count >= status.timeout_max) { stats_increment_errors(_("TOO MANY TIMEOUTS, TRANSFER CANCELLED")); stop_file_transfer(Q_TRANSFER_STATE_ABORT); status.state = ABORT; } else { stats_increment_errors(_("TIMEOUT")); } /* * Reset timeout */ reset_timer(); return Q_TRUE; } /* * No timeout yet */ return Q_FALSE; } /* ------------------------------------------------------------------------ */ /* Encoding layer --------------------------------------------------------- */ /* ------------------------------------------------------------------------ */ /** * Turn a string into hex. * * @param input a buffer with 8-bit bytes * @param input_n the number of bytes in input * @param output the output string of hexademical ASCII characters * @param output_max the maximum number of bytes that can be written to * output */ static void hexify_string(const unsigned char * input, const unsigned int input_n, unsigned char * output, const unsigned int output_max) { char digits[] = "0123456789abcdefg"; unsigned int i; assert(output_max >= input_n * 2); for (i = 0; i < input_n; i++) { output[2 * i] = digits[(input[i] & 0xF0) >> 4]; output[2 * i + 1] = digits[input[i] & 0x0F]; } } /** * Turn a hex string into binary. * * @param input a buffer with hexadecimal ASCII characters * @param input_n the number of bytes in input * @param output the output buffer of 8-bit bytes * @param output_max the maximum number of bytes that can be written to * output * @return true if conversion was successful, false if input is not a valid * hex string */ static Q_BOOL dehexify_string(const unsigned char * input, const unsigned int input_n, unsigned char * output, const unsigned int output_max) { unsigned int i; assert(output_max >= input_n / 2); for (i = 0; i < input_n; i++) { int ch = tolower(input[i]); int j = i / 2; if ((ch >= '0') && (ch <= '9')) { output[j] = ch - '0'; } else if ((ch >= 'a') && (ch <= 'f')) { output[j] = ch - 'a' + 0x0A; } else { /* * Invalid hex string */ return Q_FALSE; } output[j] = output[j] << 4; i++; ch = tolower(input[i]); if ((ch >= '0') && (ch <= '9')) { output[j] |= ch - '0'; } else if ((ch >= 'a') && (ch <= 'f')) { output[j] |= ch - 'a' + 0x0A; } else { /* * Invalid hex string */ return Q_FALSE; } } /* * All OK */ return Q_TRUE; } /* ------------------------------------------------------------------------ */ /* Bytes layer ------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ /** * Turn escaped ZDATA bytes into regular bytes, copying to output. * * The CRC escape sequence bytes are copied to crc_buffer which must be at * least 5 bytes long: 1 byte for CRC escape character, 4 bytes for CRC * data. * * The input buffer will be shifted down to handle multiple packets streaming * together. * * @param input the encoded bytes from the remote side * @param input_n the number of bytes in input_n * @param output a buffer to contain the decoded bytes * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer * @param crc_buffer a buffer to contain the CRC bytes */ static Q_BOOL decode_zdata_bytes(unsigned char * input, unsigned int * input_n, unsigned char * output, unsigned int * output_n, const unsigned int output_max, unsigned char * crc_buffer) { int i; /* input iterator */ int j; /* for doing_crc case */ Q_BOOL doing_crc = Q_FALSE; Q_BOOL done = Q_FALSE; unsigned char crc_type = 0; DLOG(("decode_zdata_bytes(): input_n = %d output_n = %d output_max = %d data: ", *input_n, *output_n, output_max)); for (i = 0; i < *input_n; i++) { DLOG2(("%02x ", (input[i] & 0xFF))); } DLOG2(("\n")); /* * Worst-case scenario: input is twice the output size */ assert((output_max * 2) >= (*input_n)); /* * We need to quickly scan the input and bail out if it too short. * * The first check is to look for a CRC escape of some kind, if that is * missing we are done. */ for (i = 0; (i < *input_n) && (done == Q_FALSE); i++) { if (input[i] == C_CAN) { /* * Point past the CAN */ i++; if (i == *input_n) { DLOG(("decode_zdata_bytes: incomplete (C_CAN)\n")); return Q_FALSE; } switch (input[i]) { case ZCRCE: case ZCRCG: case ZCRCQ: case ZCRCW: /* * The CRC escape is here, we can run the big loop */ goto decode_zdata_bytes_big_loop; } } } /* * The CRC escape is missing, so we need to bail out now. */ DLOG(("decode_zdata_bytes: incomplete (no CRC escape)\n")); return Q_FALSE; decode_zdata_bytes_big_loop: *output_n = 0; j = 0; for (i = 0; (i < *input_n) && (done == Q_FALSE); i++) { if (input[i] == C_CAN) { /* * Point past the CAN */ i++; if (i == *input_n) { /* * Uh-oh, missing last byte */ DLOG(("decode_zdata_bytes: incomplete (C_CAN)\n")); return Q_FALSE; } if (input[i] == ZCRCE) { if (doing_crc == Q_TRUE) { /* * WOAH! CRC escape within a CRC escape */ return Q_FALSE; } /* * CRC escape, switch to crc collection */ doing_crc = Q_TRUE; crc_type = input[i]; i--; } else if (input[i] == ZCRCG) { if (doing_crc == Q_TRUE) { /* * WOAH! CRC escape within a CRC escape */ return Q_FALSE; } /* * CRC escape, switch to crc collection */ doing_crc = Q_TRUE; crc_type = input[i]; i--; } else if (input[i] == ZCRCQ) { if (doing_crc == Q_TRUE) { /* * WOAH! CRC escape within a CRC escape */ return Q_FALSE; } /* * CRC escape, switch to crc collection */ doing_crc = Q_TRUE; crc_type = input[i]; i--; } else if (input[i] == ZCRCW) { if (doing_crc == Q_TRUE) { /* * WOAH! CRC escape within a CRC escape */ return Q_FALSE; } /* * CRC escape, switch to crc collection */ doing_crc = Q_TRUE; crc_type = input[i]; i--; } else if (input[i] == 'l') { /* * Escaped control character: 0x7f */ if (doing_crc == Q_TRUE) { crc_buffer[j] = 0x7F; j++; } else { output[*output_n] = 0x7F; *output_n = *output_n + 1; } } else if (input[i] == 'm') { /* * Escaped control character: 0xff */ if (doing_crc == Q_TRUE) { crc_buffer[j] = 0xFF; j++; } else { output[*output_n] = 0xFF; *output_n = *output_n + 1; } } else if ((input[i] & 0x40) != 0) { /* * Escaped control character: CAN m OR 0x40 */ if (doing_crc == Q_TRUE) { crc_buffer[j] = input[i] & 0xBF; j++; } else { output[*output_n] = input[i] & 0xBF; *output_n = *output_n + 1; } } else if (input[i] == C_CAN) { /* * Real CAN, cancel the transfer */ status.state = ABORT; set_transfer_stats_last_message( _("TRANSFER CANCELLED BY SENDER")); stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_FALSE; } else { /* * Should never get here */ } } else { /* * If we're doing the CRC part, put the data elsewhere */ if (doing_crc == Q_TRUE) { crc_buffer[j] = input[i]; j++; } else { /* * I ought to ignore any unencoded control characters when * encoding was requested at this point here. However, * encoding control characters is broken anyway in lrzsz so I * won't bother with a further check. If you want actually * reliable transfer over not-8-bit-clean links, use Kermit * instead. */ output[*output_n] = input[i]; *output_n = *output_n + 1; } } if (doing_crc == Q_TRUE) { if ((packet.use_crc32 == Q_TRUE) && (j == 5)) { /* * Done */ done = Q_TRUE; } if ((packet.use_crc32 == Q_FALSE) && (j == 3)) { /* * Done */ done = Q_TRUE; } } } /* for (i=0; i= 0x80) && (ch < 0xA0)) { /* * 8bit control char, always encode */ encode_char = Q_TRUE; } else if (((ch & 0x80) != 0) && (status.flags & TX_ESCAPE_8BIT)) { /* * 8bit char, encode only if requested */ encode_char = Q_TRUE; } break; } if (encode_char == Q_TRUE) { /* * Encode */ encode_byte_map[ch] = ch | 0x40; } else if (ch == 0x7F) { /* * Escaped control character: 0x7f */ encode_byte_map[ch] = 'l'; } else if (ch == 0xFF) { /* * Escaped control character: 0xff */ encode_byte_map[ch] = 'm'; } else { /* * Regular character */ encode_byte_map[ch] = ch; } } DLOG(("setup_encode_byte_map():\n")); DLOG(("---- \n")); for (ch = 0; ch < 256; ch++) { DLOG(("From %02x --> To %02x\n", (int) ch, (int) encode_byte_map[ch])); } DLOG(("---- \n")); } /** * Turn one byte into up to two escaped bytes, copying to output. The output * buffer must be big enough to contain all the data. * * @param ch the byte to convert * @param output a buffer to contain the encoded byte * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer */ static void encode_byte(const unsigned char ch, unsigned char * output, unsigned int * output_n, const unsigned int output_max) { unsigned char new_ch = encode_byte_map[ch]; /* * Check for space */ assert(*output_n + 2 <= output_max); if (new_ch != ch) { /* * Encode */ output[*output_n] = C_CAN; *output_n = *output_n + 1; output[*output_n] = new_ch; *output_n = *output_n + 1; } else { /* * Regular character */ output[*output_n] = ch; *output_n = *output_n + 1; } } /** * Turn regular bytes into escaped bytes, copying to output. The output * buffer must be big enough to contain all the data. * * @param output a buffer to contain the encoded byte * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer * @param crc_type ZCRCE, ZCRCG, ZCRCQ, or ZCRCW */ static void encode_zdata_bytes(unsigned char * output, unsigned int * output_n, const unsigned int output_max, const unsigned char crc_type) { unsigned int i; /* input iterator */ unsigned int j; /* CRC32 iterator */ int crc_16; uint32_t crc_32; Q_BOOL doing_crc = Q_FALSE; unsigned int crc_length = 0; unsigned char ch; unsigned char crc_buffer[4]; DLOG(("encode_zdata_bytes(): packet.type = %d packet.use_crc32 = %s packet.data_n = %d output_n = %d output_max = %d data: ", packet.type, (packet.use_crc32 == Q_TRUE ? "true" : "false"), packet.data_n, *output_n, output_max)); for (i = 0; i < packet.data_n; i++) { DLOG2(("%02x ", (packet.data[i] & 0xFF))); } DLOG2(("\n")); for (i = 0; ; i++) { if (doing_crc == Q_FALSE) { if (i == packet.data_n) { /* * Add the link escape sequence */ output[*output_n] = C_CAN; *output_n = *output_n + 1; output[*output_n] = crc_type; *output_n = *output_n + 1; /* * Compute the CRC */ if ((packet.use_crc32 == Q_TRUE) && (packet.type != P_ZSINIT)) { crc_length = 4; crc_32 = compute_crc32(0, NULL, 0); /* * Another case of *strange* CRC behavior... */ for (j = 0; j < packet.data_n; j++) { crc_32 = ~compute_crc32(crc_32, packet.data + j, 1); } crc_32 = ~compute_crc32(crc_32, &crc_type, 1); crc_32 = ~crc_32; DLOG(("encode_zdata_bytes(): DATA CRC32: %08x\n", crc_32)); /* * Little-endian */ crc_buffer[0] = (unsigned char) ( crc_32 & 0xFF); crc_buffer[1] = (unsigned char) ((crc_32 >> 8) & 0xFF); crc_buffer[2] = (unsigned char) ((crc_32 >> 16) & 0xFF); crc_buffer[3] = (unsigned char) ((crc_32 >> 24) & 0xFF); } else { /* * 16-bit CRC */ crc_length = 2; crc_16 = 0; crc_16 = compute_crc16(crc_16, packet.data, packet.data_n); crc_16 = compute_crc16(crc_16, &crc_type, 1); DLOG(("encode_zdata_bytes(): DATA CRC16: %04x\n", crc_16)); /* * Big-endian */ crc_buffer[0] = (unsigned char) ((crc_16 >> 8) & 0xFF); crc_buffer[1] = (unsigned char) ( crc_16 & 0xFF); } doing_crc = Q_TRUE; i = -1; continue; } else { ch = packet.data[i]; } } else { if (i >= crc_length) { break; } ch = crc_buffer[i]; } /* * Encode the byte */ encode_byte(ch, output, output_n, output_max); } /* for (i = 0; i < packet.data_n; i++) */ /* * One type of packet is terminated "special" */ if (crc_type == ZCRCW) { output[*output_n] = C_XON; *output_n = *output_n + 1; } DLOG(("encode_zdata_bytes(): i = %d *output_n = %d data: ", i, *output_n)); for (i = 0; i < *output_n; i++) { DLOG2(("%02x ", (output[i] & 0xFF))); } DLOG2(("\n")); } /* ------------------------------------------------------------------------ */ /* Packet layer ----------------------------------------------------------- */ /* ------------------------------------------------------------------------ */ #define HEX_PACKET_LENGTH 20 /** * Build a Zmodem packet. * * @param type the packet type * @param argument a 32-bit argument * @param data_packet the buffer to write the packet to * @param data_packet_n the size of data_packet * @param data_packet_max the maximum size of data_packet */ static void build_packet(const int type, const long argument, unsigned char * data_packet, unsigned int * data_packet_n, const int data_packet_max) { int crc_16; unsigned char crc_16_hex[4]; uint32_t crc_32; unsigned char header[10]; Q_BOOL do_hex; int i; char * type_string; switch (type) { case P_ZRQINIT: type_string = "ZRQINIT"; break; case P_ZRINIT: type_string = "ZRINIT"; break; case P_ZSINIT: type_string = "ZSINIT"; break; case P_ZACK: type_string = "ZACK"; break; case P_ZFILE: type_string = "ZFILE"; break; case P_ZSKIP: type_string = "ZSKIP"; break; case P_ZNAK: type_string = "ZNAK"; break; case P_ZABORT: type_string = "ZABORT"; break; case P_ZFIN: type_string = "ZFIN"; break; case P_ZRPOS: type_string = "ZRPOS"; break; case P_ZDATA: type_string = "ZDATA"; break; case P_ZEOF: type_string = "ZEOF"; break; case P_ZFERR: type_string = "ZFERR"; break; case P_ZCRC: type_string = "ZCRC"; break; case P_ZCHALLENGE: type_string = "ZCHALLENGE"; break; case P_ZCOMPL: type_string = "ZCOMPL"; break; case P_ZCAN: type_string = "ZCAN"; break; case P_ZFREECNT: type_string = "ZFREECNT"; break; case P_ZCOMMAND: type_string = "ZCOMMAND"; break; default: type_string = "Invalid type"; } DLOG(("build_packet(): type = %s (%d) argument = %08lx\n", type_string, type, argument)); /* * Initialize the packet */ packet.type = type; packet.use_crc32 = status.use_crc32; packet.data_n = 0; /* * Copy type to first header byte */ header[0] = type; switch (type) { case P_ZRPOS: case P_ZEOF: case P_ZCRC: case P_ZCOMPL: case P_ZFREECNT: case P_ZSINIT: /* * Little endian order */ header[4] = (argument >> 24) & 0xFF; header[3] = (argument >> 16) & 0xFF; header[2] = (argument >> 8) & 0xFF; header[1] = argument & 0xFF; break; default: /* * Everything else is in big endian order */ header[1] = (argument >> 24) & 0xFF; header[2] = (argument >> 16) & 0xFF; header[3] = (argument >> 8) & 0xFF; header[4] = argument & 0xFF; break; } switch (type) { case P_ZRQINIT: case P_ZRINIT: case P_ZSINIT: case P_ZCHALLENGE: /* * ZCHALLENGE comes before the CRC32 negotiation, so it must use hex * packets. The other packets are defined by the standard to be hex. */ case P_ZRPOS: do_hex = Q_TRUE; break; default: if ((status.flags & TX_ESCAPE_CTRL) || (status.flags & TX_ESCAPE_8BIT) ) { do_hex = Q_TRUE; } else { do_hex = Q_FALSE; } break; } /* * OK, so we can get seriously out of sync with rz -- it doesn't bother * checking to see if ZSINIT is CRC32 or not. So we have to see what it * expects and encode appropriately. */ if ((type == P_ZSINIT) && (status.sending == Q_TRUE) && (status.use_crc32 == Q_TRUE) ) { do_hex = Q_FALSE; } /* * A bug in sz: it sometimes loses the ZCRC even though it reads the * bytes. */ if ((type == P_ZCRC) && (status.sending == Q_FALSE)) { do_hex = Q_TRUE; } if (do_hex == Q_TRUE) { /* * Hex must be 16-bit CRC, override the default setting */ packet.use_crc32 = Q_FALSE; /* * Hex packets */ data_packet[0] = ZPAD; data_packet[1] = ZPAD; data_packet[2] = C_CAN; data_packet[3] = 'B'; hexify_string(header, 5, &data_packet[4], HEX_PACKET_LENGTH - 10); *data_packet_n = *data_packet_n + HEX_PACKET_LENGTH; /* * Hex packets always use 16-bit CRC */ crc_16 = compute_crc16(0, header, 5); crc_16_hex[0] = (crc_16 >> 8) & 0xFF; crc_16_hex[1] = crc_16 & 0xFF; hexify_string(crc_16_hex, 2, &data_packet[14], HEX_PACKET_LENGTH - 14); data_packet[18] = C_CR; /* * lrzsz flips the high bit here. Why?? */ /* data_packet[19] = C_LF; */ data_packet[19] = C_LF | 0x80; switch (type) { case P_ZFIN: case P_ZACK: break; default: /* * Append XON to most hex packets */ data_packet[(*data_packet_n)] = C_XON; *data_packet_n = *data_packet_n + 1; break; } } else { Q_BOOL altered_encode_byte_map = Q_FALSE; uint32_t old_flags = status.flags; if (type == P_ZSINIT) { /* * Special case: lrzsz needs control characters escaped in the * ZSINIT. */ if (!(status.flags & TX_ESCAPE_CTRL)) { altered_encode_byte_map = Q_TRUE; /* * Update the encode map */ status.flags |= TX_ESCAPE_CTRL; setup_encode_byte_map(); } } /* * Binary packets */ data_packet[0] = ZPAD; data_packet[1] = C_CAN; if (status.use_crc32 == Q_TRUE) { data_packet[2] = 'C'; } else { data_packet[2] = 'A'; } /* * Set initial length */ *data_packet_n = *data_packet_n + 3; /* * Encode the argument field */ for (i = 0; i < 5; i++) { encode_byte((unsigned char) (header[i] & 0xFF), data_packet, data_packet_n, data_packet_max); } if (packet.use_crc32 == Q_TRUE) { crc_32 = compute_crc32(0, NULL, 0); crc_32 = compute_crc32(crc_32, header, 5); /* * Little-endian */ encode_byte((unsigned char) ( crc_32 & 0xFF), data_packet, data_packet_n, data_packet_max); encode_byte((unsigned char) ((crc_32 >> 8) & 0xFF), data_packet, data_packet_n, data_packet_max); encode_byte((unsigned char) ((crc_32 >> 16) & 0xFF), data_packet, data_packet_n, data_packet_max); encode_byte((unsigned char) ((crc_32 >> 24) & 0xFF), data_packet, data_packet_n, data_packet_max); } else { crc_16 = compute_crc16(0, header, 5); encode_byte((unsigned char) ((crc_16 >> 8) & 0xFF), data_packet, data_packet_n, data_packet_max); encode_byte((unsigned char) ( crc_16 & 0xFF), data_packet, data_packet_n, data_packet_max); } if (altered_encode_byte_map == Q_TRUE) { /* * Restore encode_byte_map and flags */ status.flags = old_flags; setup_encode_byte_map(); } } /* * Make sure we're still OK */ assert(*data_packet_n <= data_packet_max); } /** * Parse a Zmodem packet. * * @param input the bytes from the remote side * @param input_n the number of bytes in input_n * @param discard the number of bytes that were consumed by the input * @return a parse packet return code (OK, CRC error, etc.) */ static ZM_PARSE_PACKET parse_packet(const unsigned char * input, const int input_n, int * discard) { char * type_string; int begin = 0; unsigned char crc_header[5]; uint32_t crc_32; int crc_16; Q_BOOL has_data = Q_FALSE; int i; Q_BOOL got_can = Q_FALSE; unsigned char ch; unsigned char hex_buffer[4]; DLOG(("parse_packet()\n")); /* * Clear packet */ memset(&packet, 0, sizeof(struct zmodem_packet)); /* * Find the start of the packet */ while (input[begin] != ZPAD) { /* * Strip non-ZPAD characters */ begin++; if (begin >= input_n) { /* * Throw away what's here, we're still looking for a packet * beginning. */ *discard = begin; return ZM_PP_NODATA; } } /* * Throw away up to the packet beginning */ *discard = begin; while (input[begin] == ZPAD) { /* * Strip ZPAD characters */ begin++; if (begin >= input_n) { return ZM_PP_NODATA; } } /* * Pull into fields */ if (input[begin] != C_CAN) { *discard = *discard + 1; return ZM_PP_INVALID; } begin++; if (begin >= input_n) { return ZM_PP_NODATA; } if (input[begin] == 'A') { /* * CRC-16 */ if (input_n - begin < 8) { return ZM_PP_NODATA; } packet.use_crc32 = Q_FALSE; packet.argument = 0; packet.crc16 = 0; begin += 1; for (i = 0; i < 7; i++, begin++) { if (begin >= input_n) { return ZM_PP_NODATA; } if (input[begin] == C_CAN) { /* * Escape control char */ got_can = Q_TRUE; i--; continue; } if (got_can == Q_TRUE) { got_can = Q_FALSE; if (input[begin] == 'l') { /* * Escaped control character: 0x7f */ ch = 0x7F; } else if (input[begin] == 'm') { /* * Escaped control character: 0xff */ ch = 0xFF; } else if ((input[begin] & 0x40) != 0) { /* * Escaped control character: CAN m OR 0x40 */ ch = input[begin] & 0xBF; } else { /* * Should never get here */ return ZM_PP_INVALID; } } else { ch = input[begin]; } if (i == 0) { /* * Type */ packet.type = ch; crc_header[0] = packet.type; } else if (i < 5) { /* * Argument */ packet.argument |= (ch << (32 - (8 * i))); crc_header[i] = ch; } else { /* * CRC */ packet.crc16 |= (ch << (16 - (8 * (i - 4)))); } } } else if (input[begin] == 'B') { /* * CRC-16 HEX */ begin++; if (input_n - begin < 14 + 2) { return ZM_PP_NODATA; } packet.use_crc32 = Q_FALSE; /* * Dehexify */ memset(hex_buffer, 0, sizeof(hex_buffer)); if (dehexify_string(&input[begin], 2, hex_buffer, sizeof(hex_buffer)) == Q_FALSE) { return ZM_PP_INVALID; } packet.type = hex_buffer[0]; memset(hex_buffer, 0, sizeof(hex_buffer)); if (dehexify_string(&input[begin + 2], 8, hex_buffer, sizeof(hex_buffer)) == Q_FALSE) { return ZM_PP_INVALID; } packet.argument = ((hex_buffer[0] & 0xFF) << 24) | ((hex_buffer[1] & 0xFF) << 16) | ((hex_buffer[2] & 0xFF) << 8) | (hex_buffer[3] & 0xFF); memset(hex_buffer, 0, sizeof(hex_buffer)); if (dehexify_string(&input[begin + 10], 4, hex_buffer, sizeof(hex_buffer)) == Q_FALSE) { return ZM_PP_INVALID; } packet.crc16 = ((hex_buffer[0] & 0xFF) << 8) | (hex_buffer[1] & 0xFF); /* * Point to end */ begin += 14; /* * Copy header to crc_header */ crc_header[0] = packet.type; crc_header[1] = (unsigned char) ((packet.argument >> 24) & 0xFF); crc_header[2] = (unsigned char) ((packet.argument >> 16) & 0xFF); crc_header[3] = (unsigned char) ((packet.argument >> 8) & 0xFF); crc_header[4] = (unsigned char) ( packet.argument & 0xFF); /* * More special-case junk: sz sends 0d 8a at the end of each hex * header. */ begin += 2; /* * sz also sends XON at the end of each hex header except ZFIN and * ZACK. */ switch (packet.type) { case P_ZFIN: case P_ZACK: break; default: if (input_n - begin < 1) { return ZM_PP_NODATA; } begin++; break; } } else if (input[begin] == 'C') { /* * CRC-32 */ if (input_n - begin < 10) { return ZM_PP_NODATA; } packet.use_crc32 = Q_TRUE; packet.argument = 0; packet.crc32 = 0; /* * Loop through the type, argument, and crc values, unescaping * control characters along the way */ begin += 1; for (i = 0; i < 9; i++, begin++) { if (begin >= input_n) { return ZM_PP_NODATA; } if (input[begin] == C_CAN) { /* * Escape control char */ got_can = Q_TRUE; i--; continue; } if (got_can == Q_TRUE) { got_can = Q_FALSE; if (input[begin] == 'l') { /* * Escaped control character: 0x7f */ ch = 0x7F; } else if (input[begin] == 'm') { /* * Escaped control character: 0xff */ ch = 0xFF; } else if ((input[begin] & 0x40) != 0) { /* * Escaped control character: CAN m OR 0x40 */ ch = input[begin] & 0xBF; } else { /* * Should never get here */ return ZM_PP_NODATA; } } else { ch = input[begin]; } if (i == 0) { /* * Type */ packet.type = ch; crc_header[0] = packet.type; } else if (i < 5) { /* * Argument */ packet.argument |= (ch << (32 - (8 * i))); crc_header[i] = ch; } else { /* * CRC - in little-endian form */ packet.crc32 |= (ch << (8 * (i - 5))); } } } else { /* * Invalid packet type */ *discard = *discard + 1; return ZM_PP_INVALID; } /* * Type */ switch (packet.type) { case P_ZRQINIT: type_string = "ZRQINIT"; break; case P_ZRINIT: type_string = "ZRINIT"; break; case P_ZSINIT: type_string = "ZSINIT"; break; case P_ZACK: type_string = "ZACK"; break; case P_ZFILE: type_string = "ZFILE"; break; case P_ZSKIP: type_string = "ZSKIP"; break; case P_ZNAK: type_string = "ZNAK"; break; case P_ZABORT: type_string = "ZABORT"; break; case P_ZFIN: type_string = "ZFIN"; break; case P_ZRPOS: type_string = "ZRPOS"; break; case P_ZDATA: type_string = "ZDATA"; break; case P_ZEOF: type_string = "ZEOF"; break; case P_ZFERR: type_string = "ZFERR"; break; case P_ZCRC: type_string = "ZCRC"; break; case P_ZCHALLENGE: type_string = "ZCHALLENGE"; break; case P_ZCOMPL: type_string = "ZCOMPL"; break; case P_ZCAN: type_string = "ZCAN"; break; case P_ZFREECNT: type_string = "ZFREECNT"; break; case P_ZCOMMAND: type_string = "ZCOMMAND"; break; default: DLOG(("parse_packet(): INVALID PACKET TYPE %d\n", packet.type)); return ZM_PP_INVALID; } /* * Figure out if the argument is supposed to be flipped */ switch (packet.type) { case P_ZRPOS: case P_ZEOF: case P_ZCRC: case P_ZCOMPL: case P_ZFREECNT: /* * Swap the packet argument around */ packet.argument = big_to_little_endian(packet.argument); break; default: break; } if (packet.use_crc32 == Q_TRUE) { DLOG(("parse_packet(): CRC32 type = %s (%d) argument=%08x crc=%08x\n", type_string, packet.type, packet.argument, packet.crc32)); } else { DLOG(("parse_packet(): CRC16 type = %s (%d) argument=%08x crc=%04x\n", type_string, packet.type, packet.argument, packet.crc16)); } /* * Check CRC */ if (packet.use_crc32 == Q_TRUE) { crc_32 = compute_crc32(0, NULL, 0); crc_32 = compute_crc32(crc_32, crc_header, 5); if (crc_32 != packet.crc32) { DLOG(("parse_packet(): CRC ERROR (given=%08x computed=%08x)\n", packet.crc32, crc_32)); stats_increment_errors(_("CRC ERROR")); return ZM_PP_CRCERROR; } } else { crc_16 = compute_crc16(0, crc_header, 5); if (crc_16 != packet.crc16) { DLOG(("parse_packet(): CRC ERROR (given=%04x computed=%04x)\n", packet.crc16, crc_16)); stats_increment_errors(_("CRC ERROR")); return ZM_PP_CRCERROR; } } DLOG(("parse_packet(): CRC OK\n")); /* * Pull data for certain packet types */ switch (packet.type) { case P_ZSINIT: case P_ZFILE: case P_ZDATA: case P_ZCOMMAND: /* * Packet data will follow */ has_data = Q_TRUE; break; default: break; } /* * Discard what's been processed */ *discard = begin; if (has_data == Q_TRUE) { status.prior_state = status.state; status.state = ZDATA; packet.data_n = 0; packet.crc16 = 0; packet.crc32 = compute_crc32(0, NULL, 0); } /* * All OK */ return ZM_PP_OK; } /* ------------------------------------------------------------------------ */ /* Top-level states ------------------------------------------------------- */ /* ------------------------------------------------------------------------ */ /** * Receive: ZCHALLENGE * * @param output a buffer to write bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer * @return true if we are done reading input and are ready to send bytes to * the remote side */ static Q_BOOL receive_zchallenge(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { uint32_t options; FILE * dev_random; DLOG(("receive_zchallenge()\n")); /* * Build a random value for ZCHALLENGE using /dev/random */ dev_random = fopen("/dev/random", "r"); if (dev_random == NULL) { /* * /dev/random isn't here, or isn't readable. Use random() instead, * even though it probably sucks. */ #ifdef USE_WIN32API zchallenge_value = rand(); #else zchallenge_value = random(); #endif } else { fread(&zchallenge_value, sizeof(uint32_t), 1, dev_random); fclose(dev_random); } DLOG(("receive_zchallenge() VALUE = %08x\n", zchallenge_value)); options = zchallenge_value; build_packet(P_ZCHALLENGE, options, output, output_n, output_max); status.state = ZCHALLENGE_WAIT; /* * Discard input bytes */ packet_buffer_n = 0; /* * Process through the new state */ return Q_FALSE; } /** * Receive: ZCHALLENGE_WAIT * * @param output a buffer to write bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer * @return true if we are done reading input and are ready to send bytes to * the remote side */ static Q_BOOL receive_zchallenge_wait(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { ZM_PARSE_PACKET rc_pp; uint32_t options = 0; int discard; DLOG(("receive_zchallenge_wait()\n")); if (packet_buffer_n > 0) { rc_pp = parse_packet(packet_buffer, packet_buffer_n, &discard); /* * Take the bytes off the stream */ if (discard > 0) { memmove(packet_buffer, packet_buffer + discard, packet_buffer_n - discard); packet_buffer_n -= discard; } if ((rc_pp == ZM_PP_CRCERROR) || (rc_pp == ZM_PP_INVALID)) { DLOG(("receive_zchallenge_wait(): ERROR garbled header\n")); stats_increment_errors(_("GARBLED HEADER")); packet_buffer_n = 0; build_packet(P_ZNAK, options, output, output_n, output_max); return Q_TRUE; } if (rc_pp == ZM_PP_NODATA) { return Q_TRUE; } if (rc_pp == ZM_PP_OK) { if (packet.type == P_ZACK) { /* * Verify the value returned */ DLOG(("receive_zchallenge_wait() argument = %08x correct = %08x\n", packet.argument, zchallenge_value)); if (packet.argument == zchallenge_value) { set_transfer_stats_last_message(_("ZCHALLENGE -- OK")); /* * I'd love to wait a second here so the user can see the * successful ZCHALLENGE response on the transfer * screen... */ /* * Send the ZRINIT */ set_transfer_stats_last_message("ZRINIT"); status.state = ZRINIT; packet.crc16 = 0; packet.crc32 = compute_crc32(0, NULL, 0); return Q_FALSE; } else { DLOG(("receive_zchallenge_wait(): ERROR zchallenge error\n")); stats_increment_errors(_("ZCHALLENGE -- ERROR")); status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } else if (packet.type == P_ZNAK) { DLOG(("receive_zchallenge_wait(): ERROR ZNAK\n")); /* * Re-send */ stats_increment_errors("ZNAK"); status.state = ZCHALLENGE; } else if (packet.type == P_ZRQINIT) { DLOG(("receive_zchallenge_wait(): ERROR ZRQINIT\n")); /* * Re-send, but don't count as an error */ set_transfer_stats_last_message("ZRQINIT"); status.state = ZCHALLENGE; } else { /* * Sender isn't Zmodem compliant, abort. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } /* * Process through the new state */ return Q_FALSE; } if (check_timeout() == Q_TRUE) { status.state = ZCHALLENGE; return Q_FALSE; } /* * No data, done */ return Q_TRUE; } /** * Receive: ZCRC * * @param output a buffer to write bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer * @return true if we are done reading input and are ready to send bytes to * the remote side */ static Q_BOOL receive_zcrc(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { /* * Buffer for reading the file */ unsigned char file_buffer[1]; size_t file_buffer_n; /* * Save the original file position */ off_t original_position = status.file_position; int total_bytes = 0; DLOG(("receive_zcrc() ENTER\n")); /* * Reset crc32 */ status.file_crc32 = compute_crc32(0, NULL, 0); /* * Seek to beginning of file */ fseek(status.file_stream, 0, SEEK_SET); while (!feof(status.file_stream)) { file_buffer_n = fread(file_buffer, 1, sizeof(file_buffer), status.file_stream); total_bytes += file_buffer_n; /* * I think I have a different CRC function from lrzsz... I have to * negate both here and below to get the same value. */ status.file_crc32 = ~compute_crc32(status.file_crc32, file_buffer, file_buffer_n); } /* * Seek back to the original location */ fseek(status.file_stream, original_position, SEEK_SET); status.file_crc32 = ~status.file_crc32; DLOG(("receive_zcrc() total_bytes = %d on-disk CRC32 = %08lx\n", total_bytes, (unsigned long) status.file_crc32)); build_packet(P_ZCRC, total_bytes, output, output_n, output_max); status.state = ZCRC_WAIT; packet_buffer_n = 0; return Q_FALSE; } /** * Receive: ZCRC_WAIT * * @param output a buffer to write bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer * @return true if we are done reading input and are ready to send bytes to * the remote side */ static Q_BOOL receive_zcrc_wait(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { ZM_PARSE_PACKET rc_pp; struct stat fstats; int i; int rc; uint32_t options = 0; int discard; DLOG(("receive_zcrc_wait()\n")); if (packet_buffer_n > 0) { rc_pp = parse_packet(packet_buffer, packet_buffer_n, &discard); /* * Take the bytes off the stream */ if (discard > 0) { memmove(packet_buffer, packet_buffer + discard, packet_buffer_n - discard); packet_buffer_n -= discard; } if ((rc_pp == ZM_PP_CRCERROR) || (rc_pp == ZM_PP_INVALID)) { DLOG(("receive_zcrc_wait(): ERROR garbled header\n")); stats_increment_errors(_("GARBLED HEADER")); packet_buffer_n = 0; build_packet(P_ZNAK, options, output, output_n, output_max); return Q_TRUE; } if (rc_pp == ZM_PP_NODATA) { return Q_TRUE; } if (rc_pp == ZM_PP_OK) { if (packet.type == P_ZCRC) { /* * Verify the value returned */ DLOG(("receive_zcrc_wait() argument = %08x correct = %08lx\n", packet.argument, (unsigned long) status.file_crc32)); if (packet.argument == status.file_crc32) { /* * We're working on the same file, check its length to * see if we should send ZRPOS or ZSKIP. */ if (status.file_size == status.file_position) { DLOG(("receive_zcrc_wait(): got file, switch to ZSKIP\n")); status.state = ZSKIP; } else { DLOG(("receive_zcrc_wait(): crash recovery, switch to ZRPOS\n")); status.state = ZRPOS; } } else { /* * This is a different file, rename it */ for (i = 0; ; i++) { /* * Add a numeric suffix and see if the file doesn't * exist. If so, we can use that filename. */ sprintf(status.file_fullname, "%s/%s.%04d", download_path, status.file_name, i); rc = stat(status.file_fullname, &fstats); if (rc < 0) { if (errno == ENOENT) { /* * We found a free filename, break out and * try to create it. */ DLOG(("receive_zcrc_wait(): prevent overwrite, switch to ZRPOS, new filename = %s\n", status.file_fullname)); break; } else { status.state = ABORT; set_transfer_stats_last_message( _("DISK I/O ERROR")); stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } } /* for (i = 0; ; i++) */ status.file_position = 0; status.file_stream = fopen(status.file_fullname, "w+b"); if (status.file_stream == NULL) { status.state = ABORT; set_transfer_stats_last_message( _("CANNOT CREATE FILE")); stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } /* * Seek to the end */ fseek(status.file_stream, 0, SEEK_END); /* * Update progress display */ stats_new_file(status.file_fullname, status.file_size); /* * Ready for ZRPOS now */ status.state = ZRPOS; } /* * At this point we have switched to ZRPOS or ZSKIP, either * with the original filename (crash recovery) or a new one * (different file). */ } else if (packet.type == P_ZNAK) { DLOG(("receive_zcrc_wait(): ERROR ZNAK\n")); stats_increment_errors("ZNAK"); status.state = ZCRC; } else if (packet.type == P_ZFILE) { DLOG(("receive_zcrc_wait(): ZFILE sender does not understand ZCRC, move to crash recovery (even though this may corrupt the file)\n")); stats_increment_errors("Sender does not understand ZCRC!"); status.state = ZRPOS; } else { /* * Sender isn't Zmodem compliant, abort. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } /* * Process through the new state */ return Q_FALSE; } if (check_timeout() == Q_TRUE) { status.state = ZCRC; return Q_FALSE; } /* * No data, done */ return Q_TRUE; } /** * Receive: ZRINIT * * @param output a buffer to write bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer * @return true if we are done reading input and are ready to send bytes to * the remote side */ static Q_BOOL receive_zrinit(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { uint32_t options; DLOG(("receive_zrinit()\n")); options = TX_CAN_FULL_DUPLEX | TX_CAN_OVERLAP_IO; if (status.use_crc32 == Q_TRUE) { options |= TX_CAN_CRC32; } if (zmodem_escape_ctrl == Q_TRUE) { options |= TX_ESCAPE_CTRL; } status.flags = options; build_packet(P_ZRINIT, options, output, output_n, output_max); status.state = ZRINIT_WAIT; packet_buffer_n = 0; return Q_FALSE; } /** * Receive: ZRINIT_WAIT * * @param output a buffer to write bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer * @return true if we are done reading input and are ready to send bytes to * the remote side */ static Q_BOOL receive_zrinit_wait(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { ZM_PARSE_PACKET rc_pp; int discard; uint32_t options = 0; DLOG(("receive_zrinit_wait()\n")); if (packet_buffer_n > 0) { rc_pp = parse_packet(packet_buffer, packet_buffer_n, &discard); /* * Take the bytes off the stream */ if (discard > 0) { memmove(packet_buffer, packet_buffer + discard, packet_buffer_n - discard); packet_buffer_n -= discard; } if ((rc_pp == ZM_PP_CRCERROR) || (rc_pp == ZM_PP_INVALID)) { DLOG(("receive_zrinit_wait(): ERROR garbled header\n")); stats_increment_errors(_("GARBLED HEADER")); packet_buffer_n = 0; build_packet(P_ZNAK, options, output, output_n, output_max); return Q_TRUE; } if (rc_pp == ZM_PP_NODATA) { return Q_TRUE; } if (rc_pp == ZM_PP_OK) { if (packet.type == P_ZFIN) { /* * Last file has come down, we're done */ set_transfer_stats_last_message("ZFIN"); /* * All done. */ options = 0; build_packet(P_ZFIN, options, output, output_n, output_max); /* * Waiting for the Over-and-Out */ status.state = ZFIN_WAIT; } else if (packet.type == P_ZRQINIT) { /* * Sender has repeated its ZRQINIT, re-send the ZRINIT * response. */ set_transfer_stats_last_message("ZRINIT"); status.state = ZRINIT; packet.crc16 = 0; packet.crc32 = compute_crc32(0, NULL, 0); } else if (packet.type == P_ZSINIT) { set_transfer_stats_last_message("ZSINIT"); /* * See what options were specified */ if (packet.argument & TX_ESCAPE_CTRL) { status.flags |= TX_ESCAPE_CTRL; DLOG(("receive_zrinit_wait() ZSINIT TX_ESCAPE_CTRL\n")); } if (packet.argument & TX_ESCAPE_8BIT) { status.flags |= TX_ESCAPE_8BIT; DLOG(("receive_zrinit_wait() ZSINIT TX_ESCAPE_8BIT\n")); } DLOG(("receive_zrinit_wait() ZSINIT state = %d\n", status.state)); /* * Update the encode map */ setup_encode_byte_map(); /* * ZACK the ZSINIT */ options = 0; build_packet(P_ZACK, options, output, output_n, output_max); } else if (packet.type == P_ZCOMMAND) { /* * Be compliant with the co-called standard, but emit a * warning because NO ONE should ever use ZCOMMAND. */ set_transfer_stats_last_message( _("ERROR: ZCOMMAND NOT SUPPORTED")); } else if (packet.type == P_ZFILE) { set_transfer_stats_last_message("ZFILE"); /* * Record the prior state and switch to data processing */ status.prior_state = ZRINIT_WAIT; status.state = ZDATA; packet.data_n = 0; packet.crc16 = 0; packet.crc32 = compute_crc32(0, NULL, 0); } else if (packet.type == P_ZNAK) { DLOG(("receive_zrinit_wait(): ERROR ZNAK\n")); stats_increment_errors("ZNAK"); if (status.prior_state == ZSKIP) { /* * Special case: send a ZSKIP back instead of a ZRINIT if * we asked for a ZSKIP the last time. */ status.state = ZSKIP; } else { status.state = ZRINIT; } } else { /* * Sender isn't Zmodem compliant, abort. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } /* * Process through the new state */ return Q_FALSE; } if (check_timeout() == Q_TRUE) { if (status.prior_state == ZSKIP) { /* * Special case: send a ZSKIP back instead of a ZRINIT if we * asked for a ZSKIP the last time. */ status.state = ZSKIP; } else { status.state = ZRINIT; } return Q_FALSE; } /* * No data, done */ return Q_TRUE; } /** * Receive: ZRPOS * * @param output a buffer to write bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer * @return true if we are done reading input and are ready to send bytes to * the remote side */ static Q_BOOL receive_zrpos(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { uint32_t options; DLOG(("receive_zrpos()\n")); options = status.file_position; build_packet(P_ZRPOS, options, output, output_n, output_max); status.state = ZRPOS_WAIT; DLOG(("receive_zrpos(): ZRPOS file_position = %ld\n", status.file_position)); packet_buffer_n = 0; return Q_FALSE; } /** * Receive: ZRPOS_WAIT * * @param output a buffer to write bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer * @return true if we are done reading input and are ready to send bytes to * the remote side */ static Q_BOOL receive_zrpos_wait(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { ZM_PARSE_PACKET rc_pp; int discard; uint32_t options = 0; struct utimbuf utime_buffer; DLOG(("receive_zrpos_wait()\n")); if (packet_buffer_n > 0) { rc_pp = parse_packet(packet_buffer, packet_buffer_n, &discard); /* * Take the bytes off the stream */ if (discard > 0) { memmove(packet_buffer, packet_buffer + discard, packet_buffer_n - discard); packet_buffer_n -= discard; } if ((rc_pp == ZM_PP_CRCERROR) || (rc_pp == ZM_PP_INVALID)) { if (status.prior_state != ZRPOS_WAIT) { /* * Only send ZNAK when we aren't in ZDATA mode */ DLOG(("receive_zrpos_wait(): ERROR garbled header\n")); stats_increment_errors(_("GARBLED HEADER")); packet_buffer_n = 0; build_packet(P_ZNAK, options, output, output_n, output_max); return Q_TRUE; } else { /* * Keep processing the buffer until we get ZM_PP_NODATA */ return Q_FALSE; } } if (rc_pp == ZM_PP_NODATA) { return Q_TRUE; } if (rc_pp == ZM_PP_OK) { if (packet.type == P_ZEOF) { DLOG(("receive_zrpos_wait() ZEOF bytes = %ud file size = %ld\n", packet.argument, status.file_position)); q_transfer_stats.state = Q_TRANSFER_STATE_FILE_DONE; set_transfer_stats_last_message("ZEOF"); /* * Check file length and ack */ if (status.file_position == packet.argument) { /* * All ok */ fclose(status.file_stream); /* * Set access and modification times */ utime_buffer.actime = status.file_modtime; utime_buffer.modtime = status.file_modtime; utime(status.file_fullname, &utime_buffer); assert(status.file_name != NULL); Xfree(status.file_name, __FILE__, __LINE__); status.file_name = NULL; status.file_stream = NULL; options = 0; build_packet(P_ZRINIT, options, output, output_n, output_max); set_transfer_stats_last_message("ZRINIT"); /* * ZEOF will be followed by ZFIN or ZFILE, let * receive_zrinit_wait() figure it out. */ status.state = ZRINIT_WAIT; } else { /* * The sender claims that the file size is different from * the actual size they sent. We will send an error and * try to recover. */ DLOG(("receive_zrpos_wait(): ERROR BAD FILE POSITION FROM SENDER\n")); stats_increment_errors(_("BAD FILE POSITION FROM SENDER")); status.state = ZRPOS; } } else if (packet.type == P_ZDATA) { set_transfer_stats_last_message("ZDATA"); /* * Record the prior state and switch to data processing */ status.prior_state = ZRPOS_WAIT; status.state = ZDATA; packet.data_n = 0; packet.crc16 = 0; packet.crc32 = compute_crc32(0, NULL, 0); } else if (packet.type == P_ZNAK) { DLOG(("receive_zrpos_wait(): ERROR ZNAK\n")); stats_increment_errors("ZNAK"); status.state = ZRPOS; } else { /* * Sender isn't Zmodem compliant, abort. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } /* * Process through the new state */ return Q_FALSE; } if (check_timeout() == Q_TRUE) { status.state = ZRPOS; return Q_FALSE; } /* * No data, done */ return Q_TRUE; } /** * Receive: ZFILE * * @return true if we are done reading input and are ready to send bytes to * the remote side */ static Q_BOOL receive_zfile() { int filesleft; long totalbytesleft; mode_t permissions; struct stat fstats; Q_BOOL need_new_file = Q_FALSE; int i; int rc; Q_BOOL file_exists = Q_FALSE; DLOG(("receive_zfile()\n")); /* * Break out ZFILE data */ /* * filename */ status.file_name = Xstrdup((char *) packet.data, __FILE__, __LINE__); /* * size, mtime, umask, files left, total left */ sscanf((char *) packet.data + strlen((char *) packet.data) + 1, "%u %lo %o 0 %d %ld", (unsigned int *) &status.file_size, &status.file_modtime, (int *) &permissions, &filesleft, &totalbytesleft); /* * It so happens we can't use the permissions mask. Forsberg didn't * encode it in a standard way. */ DLOG(("receive_zfile(): ZFILE name: %s\n", status.file_name)); DLOG(("receive_zfile(): ZFILE size: %u mtime: %s umask: %04o\n", status.file_size, ctime(&status.file_modtime), permissions)); DLOG(("receive_zfile(): ZFILE filesleft: %d totalbytesleft: %ld\n", filesleft, totalbytesleft)); /* * Open the file */ sprintf(status.file_fullname, "%s/%s", download_path, status.file_name); rc = stat(status.file_fullname, &fstats); if (rc < 0) { if (errno == ENOENT) { /* * Creating the file, so go straight to ZRPOS */ status.file_position = 0; DLOG(("receive_zfile(): new file, switch to ZRPOS\n")); set_transfer_stats_last_message("ZRPOS"); status.state = ZRPOS; } else { status.state = ABORT; set_transfer_stats_last_message(_("DISK I/O ERROR")); stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } else { file_exists = Q_TRUE; status.file_position = fstats.st_size; /* * Check if we need to ZSKIP or ZCRC this file */ if (status.file_size < status.file_position) { /* * Uh-oh, this is obviously a new file because it is smaller than * the file on disk. */ need_new_file = Q_TRUE; } else if (status.file_size == status.file_position) { /* * Hmm, we have a file on disk already. We'll open the file, but * switch to ZCRC and see if we should ZSKIP the file based on * its CRC value. */ DLOG(("receive_zfile(): existing file, switch to ZCRC\n")); set_transfer_stats_last_message("ZCRC"); status.state = ZCRC; } else if (status.file_size > 0) { /* * Looks like a crash recovery case */ DLOG(("receive_zfile(): filename exists, might need crash recovery, switch to ZCRC\n")); set_transfer_stats_last_message("ZCRC"); status.state = ZCRC; } else { /* * 0-length file, so we can switch directly to ZRPOS. */ DLOG(("receive_zfile(): 0-length file, switch to ZRPOS\n")); set_transfer_stats_last_message("ZRPOS"); status.state = ZRPOS; } } if (need_new_file == Q_TRUE) { /* * Guarantee we get a new file */ file_exists = Q_FALSE; for (i = 0; ; i++) { /* * Change the filename */ sprintf(status.file_fullname, "%s/%s.%04d", download_path, status.file_name, i); rc = stat(status.file_fullname, &fstats); if (rc < 0) { if (errno == ENOENT) { /* * Creating the file, so go straight to ZRPOS */ status.file_position = 0; DLOG(("receive_zfile(): prevent overwrite, switch to ZRPOS, new filename = %s\n", status.file_fullname)); status.state = ZRPOS; break; } else { status.state = ABORT; set_transfer_stats_last_message(_("DISK I/O ERROR")); stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } } /* for (i = 0 ; ; i++) */ } /* if (need_new_file == Q_TRUE) */ if (file_exists == Q_TRUE) { status.file_stream = fopen(status.file_fullname, "r+b"); } else { status.file_stream = fopen(status.file_fullname, "w+b"); } if (status.file_stream == NULL) { status.state = ABORT; set_transfer_stats_last_message(_("CANNOT CREATE FILE")); stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } /* * Seek to the end */ fseek(status.file_stream, 0, SEEK_END); /* * Update progress display */ stats_new_file(status.file_fullname, status.file_size); q_transfer_stats.bytes_transfer = status.file_position; /* * Process through the new state */ return Q_FALSE; } /** * Receive: ZDATA * * @param output a buffer to write bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer * @return true if we are done reading input and are ready to send bytes to * the remote side */ static Q_BOOL receive_zdata(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { Q_BOOL end_of_packet; Q_BOOL acknowledge; Q_BOOL crc_ok = Q_FALSE; uint32_t options; int crc16; uint32_t crc32; unsigned int i; DLOG(("receive_zdata(): DATA state=%d prior_state=%d packet.data_n=%d\n", status.state, status.prior_state, packet.data_n)); /* * First, decode the bytes for escaped control characters */ if (decode_zdata_bytes (packet_buffer, &packet_buffer_n, packet.data + packet.data_n, &packet.data_n, sizeof(packet.data) - packet.data_n, packet.crc_buffer) == Q_FALSE) { /* * Not enough data available, wait for more */ /* * Trash the partial data in packet.data. */ if (packet_buffer_n > 0) { packet.data_n = 0; } return Q_TRUE; } /* * See what kind of CRC escape was requested */ if (packet.crc_buffer[0] == ZCRCG) { /* * CRC escape: not end of packet, no acknowledgement required */ end_of_packet = Q_FALSE; acknowledge = Q_FALSE; } else if (packet.crc_buffer[0] == ZCRCE) { /* * CRC escape: end of packet, no acknowledgement required */ end_of_packet = Q_TRUE; acknowledge = Q_FALSE; } else if (packet.crc_buffer[0] == ZCRCW) { /* * CRC escape: end of packet, acknowledgement required */ end_of_packet = Q_TRUE; acknowledge = Q_TRUE; } else if (packet.crc_buffer[0] == ZCRCQ) { /* * CRC escape: not end of packet, acknowledgement required */ end_of_packet = Q_FALSE; acknowledge = Q_TRUE; } else { /* * Sender isn't Zmodem compliant, abort. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } /* * Check the crc */ /* * Copy the CRC escape byte onto the end of packet.data */ packet.data[packet.data_n] = packet.crc_buffer[0]; if (packet.use_crc32 == Q_TRUE) { /* * 32-bit CRC */ packet.crc32 = compute_crc32(0, NULL, 0); packet.crc32 = compute_crc32(packet.crc32, packet.data, packet.data_n + 1); /* * Little-endian */ crc32 = ((packet.crc_buffer[4] & 0xFF) << 24) | ((packet.crc_buffer[3] & 0xFF) << 16) | ((packet.crc_buffer[2] & 0xFF) << 8) | (packet.crc_buffer[1] & 0xFF); DLOG(("receive_zdata(): DATA CRC32: given %08x\n", crc32)); DLOG(("receive_zdata(): DATA CRC32: computed %08x\n", packet.crc32)); if (crc32 == packet.crc32) { /* * CRC OK */ crc_ok = Q_TRUE; } } else { /* * 16-bit CRC */ packet.crc16 = compute_crc16(packet.crc16, packet.data, packet.data_n + 1); crc16 = ((packet.crc_buffer[1] & 0xFF) << 8) | (packet.crc_buffer[2] & 0xFF); DLOG(("receive_zdata(): DATA CRC16: given %04x\n", crc16)); DLOG(("receive_zdata(): DATA CRC16: computed %04x\n", packet.crc16)); if (crc16 == packet.crc16) { /* * CRC OK */ crc_ok = Q_TRUE; } } if (crc_ok == Q_TRUE) { DLOG(("receive_zdata(): DATA CRC: OK\n")); if (status.prior_state == ZRPOS_WAIT) { DLOG(("receive_zdata(): WRITE TO FILE %d BYTES\n", packet.data_n)); /* * Write the packet to file */ fwrite(packet.data, 1, packet.data_n, status.file_stream); fflush(status.file_stream); /* * Increment count */ status.file_position += packet.data_n; status.block_size = packet.data_n; q_transfer_stats.bytes_transfer += packet.data_n; stats_increment_blocks(); packet.data_n = 0; packet.crc16 = 0; packet.crc32 = compute_crc32(0, NULL, 0); if (acknowledge == Q_TRUE) { DLOG(("receive_zdata(): ZACK required\n")); options = big_to_little_endian(status.file_position); build_packet(P_ZACK, options, output, output_n, output_max); } if (end_of_packet == Q_TRUE) { DLOG(("receive_zdata(): PACKET EOF\n")); status.state = ZRPOS_WAIT; return Q_FALSE; } } } else { /* * CRC error */ DLOG(("receive_zdata(): CRC ERROR\n")); if (status.prior_state == ZRPOS_WAIT) { /* * CRC error in the packet */ stats_increment_errors(_("CRC ERROR")); /* * Send ZRPOS */ packet_buffer_n = 0; options = status.file_position; build_packet(P_ZRPOS, options, output, output_n, output_max); status.state = ZRPOS_WAIT; DLOG(("receive_zdata(): send ZRPOS file_position = %ld\n", status.file_position)); return Q_TRUE; } else if (status.prior_state == ZRINIT_WAIT) { /* * CRC error in the packet */ stats_increment_errors(_("CRC ERROR")); /* * Send ZNAK */ packet_buffer_n = 0; options = 0; build_packet(P_ZNAK, options, output, output_n, output_max); status.state = ZRINIT_WAIT; DLOG(("receive_zdata(): send ZNAK, back to zrinit to get filename\n")); return Q_TRUE; } else { /* * Some other state. This is a coding error. Save a log message, */ DLOG(("receive_zdata(): CRC error, but in incorrect protocol state!\n")); } } DLOG(("receive_zdata(): DATA (post-processed): ")); for (i = 0; i < packet.data_n; i++) { DLOG2(("%02x ", (packet.data[i] & 0xFF))); } DLOG2(("\n")); /* * Figure out the next state to transition to */ if (status.prior_state == ZRINIT_WAIT) { switch (packet.type) { case P_ZFILE: status.state = ZFILE; break; case P_ZSINIT: status.state = ZRINIT_WAIT; /* * Send ZACK */ options = 0; build_packet(P_ZACK, options, output, output_n, output_max); return Q_TRUE; case P_ZCOMMAND: status.state = ZRINIT_WAIT; /* * Send ZCOMPL, assume it failed */ options = 1; build_packet(P_ZCOMPL, options, output, output_n, output_max); return Q_TRUE; default: status.state = ZDATA; break; } } else { /* * We came here from ZRPOS_WAIT */ status.state = ZDATA; } /* * Process through the new state */ return Q_FALSE; } /** * Receive: ZSKIP * * @param output a buffer to write bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum size of the output buffer * @return true if we are done reading input and are ready to send bytes to * the remote side */ static Q_BOOL receive_zskip(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { uint32_t options = 0; struct utimbuf utime_buffer; DLOG(("receive_zskip()\n")); /* * Close existing file handle, reset file fields... */ fclose(status.file_stream); /* * Set access and modification times */ utime_buffer.actime = status.file_modtime; utime_buffer.modtime = status.file_modtime; utime(status.file_fullname, &utime_buffer); assert(status.file_name != NULL); Xfree(status.file_name, __FILE__, __LINE__); status.file_name = NULL; status.file_stream = NULL; /* * Send out ZSKIP packet */ build_packet(P_ZSKIP, options, output, output_n, output_max); /* * Update progress display */ q_transfer_stats.state = Q_TRANSFER_STATE_FILE_DONE; set_transfer_stats_last_message("ZSKIP"); /* * ZSKIP will be followed immediately by another ZFILE, which is handled * in receive_zrinit_wait(). */ status.prior_state = ZSKIP; status.state = ZRINIT_WAIT; packet_buffer_n = 0; return Q_FALSE; } /** * Receive a file via the Zmodem protocol. * * @param input the bytes from the remote side * @param input_n the number of bytes in input_n * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static void zmodem_receive(unsigned char * input, unsigned int input_n, unsigned char * output, unsigned int * output_n, const unsigned int output_max) { Q_BOOL done; /* * DLOG(("zmodem_receive() NOISE ON\n")); * static int noise = 0; * noise++; * if (noise > 30) { * noise = 0; * input[0] = 0xaa; * } */ unsigned int i; DLOG(("zmodem_receive() START packet_buffer_n = %d packet_buffer = ", packet_buffer_n)); for (i = 0; i < packet_buffer_n; i++) { DLOG2(("%02x ", (packet_buffer[i] & 0xFF))); } DLOG2(("\n")); done = Q_FALSE; while (done == Q_FALSE) { /* * Add input_n to packet_buffer */ if (input_n > sizeof(packet_buffer) - packet_buffer_n) { memcpy(packet_buffer + packet_buffer_n, input, sizeof(packet_buffer) - packet_buffer_n); memmove(input, input + sizeof(packet_buffer) - packet_buffer_n, input_n - (sizeof(packet_buffer) - packet_buffer_n)); input_n -= (sizeof(packet_buffer) - packet_buffer_n); packet_buffer_n = sizeof(packet_buffer); } else { memcpy(packet_buffer + packet_buffer_n, input, input_n); packet_buffer_n += input_n; input_n = 0; } switch (status.state) { case INIT: /* * This state is where everyone begins. Start with ZCHALLENGE or * ZRINIT. */ if (zmodem_zchallenge == Q_TRUE) { set_transfer_stats_last_message("ZCHALLENGE"); status.state = ZCHALLENGE; } else { set_transfer_stats_last_message("ZRINIT"); status.state = ZRINIT; packet.crc16 = 0; packet.crc32 = compute_crc32(0, NULL, 0); } break; case ZCHALLENGE: done = receive_zchallenge(output, output_n, output_max); break; case ZCHALLENGE_WAIT: done = receive_zchallenge_wait(output, output_n, output_max); break; case ZCRC: done = receive_zcrc(output, output_n, output_max); break; case ZCRC_WAIT: done = receive_zcrc_wait(output, output_n, output_max); break; case ZRINIT: done = receive_zrinit(output, output_n, output_max); break; case ZRINIT_WAIT: done = receive_zrinit_wait(output, output_n, output_max); break; case ZRPOS: done = receive_zrpos(output, output_n, output_max); break; case ZRPOS_WAIT: done = receive_zrpos_wait(output, output_n, output_max); break; case ZFILE: done = receive_zfile(); break; case ZSKIP: done = receive_zskip(output, output_n, output_max); break; case ZDATA: done = receive_zdata(output, output_n, output_max); break; case ZFIN_WAIT: DLOG(("zmodem_receive(): ZFIN\n")); /* * NOP */ done = Q_TRUE; status.state = COMPLETE; /* * Update transfer stats */ set_transfer_stats_last_message(_("SUCCESS")); stop_file_transfer(Q_TRANSFER_STATE_END); time(&q_transfer_stats.end_time); break; case ABORT: case COMPLETE: /* * NOP */ done = Q_TRUE; break; case ZFILE_WAIT: case ZSINIT: case ZSINIT_WAIT: case ZRQINIT: case ZRQINIT_WAIT: case ZFIN: case ZEOF: case ZEOF_WAIT: /* * Receive should NEVER see these states */ abort(); break; } /* switch (status.state) */ DLOG(("zmodem_receive(): done = %s\n", (done == Q_TRUE ? "true" : "false"))); } /* while (done == Q_FALSE) */ DLOG(("zmodem_receive() END packet_buffer_n = %d packet_buffer = ", packet_buffer_n)); for (i = 0; i < packet_buffer_n; i++) { DLOG2(("%02x ", (packet_buffer[i] & 0xFF))); } DLOG2(("\n")); } /** * Send: ZRQINIT * * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static Q_BOOL send_zrqinit(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { uint32_t options; DLOG(("send_zrqinit()\n")); options = 0; build_packet(P_ZRQINIT, options, output, output_n, output_max); status.state = ZRQINIT_WAIT; packet_buffer_n = 0; return Q_FALSE; } /** * Send: ZRQINIT_WAIT * * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static Q_BOOL send_zrqinit_wait(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { ZM_PARSE_PACKET rc_pp; int discard; uint32_t options = 0; DLOG(("send_zrqinit_wait()\n")); if (packet_buffer_n > 0) { rc_pp = parse_packet(packet_buffer, packet_buffer_n, &discard); /* * Take the bytes off the stream */ if (discard > 0) { DLOG(("send_zrqinit_wait(): packet_buffer_n = %d discard = %d\n", packet_buffer_n, discard)); memmove(packet_buffer, packet_buffer + discard, packet_buffer_n - discard); packet_buffer_n -= discard; } if ((rc_pp == ZM_PP_CRCERROR) || (rc_pp == ZM_PP_INVALID)) { DLOG(("send_zrqinit_wait(): ERROR garbled header\n")); stats_increment_errors(_("GARBLED HEADER")); packet_buffer_n = 0; build_packet(P_ZNAK, options, output, output_n, output_max); return Q_TRUE; } if (rc_pp == ZM_PP_NODATA) { return Q_TRUE; } if (rc_pp == ZM_PP_OK) { if (packet.type == P_ZRINIT) { set_transfer_stats_last_message("ZRINIT"); /* * See what options were specified */ if (packet.argument & TX_ESCAPE_CTRL) { status.flags |= TX_ESCAPE_CTRL; DLOG(("send_zrqinit_wait() ZRINIT TX_ESCAPE_CTRL\n")); } if (packet.argument & TX_ESCAPE_8BIT) { status.flags |= TX_ESCAPE_8BIT; DLOG(("send_zrqinit_wait() ZRINIT TX_ESCAPE_8BIT\n")); } if (packet.argument & TX_CAN_FULL_DUPLEX) { status.flags |= TX_CAN_FULL_DUPLEX; DLOG(("send_zrqinit_wait() ZRINIT TX_CAN_FULL_DUPLEX\n")); } if (packet.argument & TX_CAN_OVERLAP_IO) { status.flags |= TX_CAN_OVERLAP_IO; DLOG(("send_zrqinit_wait() ZRINIT TX_CAN_OVERLAP_IO\n")); } if (packet.argument & TX_CAN_BREAK) { status.flags |= TX_CAN_BREAK; DLOG(("send_zrqinit_wait() ZRINIT TX_CAN_BREAK\n")); } if (packet.argument & TX_CAN_DECRYPT) { status.flags |= TX_CAN_DECRYPT; DLOG(("send_zrqinit_wait() ZRINIT TX_CAN_DECRYPT\n")); } if (packet.argument & TX_CAN_LZW) { status.flags |= TX_CAN_LZW; DLOG(("send_zrqinit_wait() ZRINIT TX_CAN_LZW\n")); } /* * zmodem_start(..., Z_CRC16) fails to send a file by this. * If this is not commented out, use Z_CRC32 all the time. */ #if 0 if (packet.argument & TX_CAN_CRC32) { status.flags |= TX_CAN_CRC32; DLOG(("send_zrqinit_wait() ZRINIT TX_CAN_CRC32\n")); status.use_crc32 = Q_TRUE; } #endif /* * Update the encode map */ setup_encode_byte_map(); /* * Now switch to ZSINIT */ status.state = ZSINIT; } else if (packet.type == P_ZCHALLENGE) { /* * Respond to ZCHALLENGE, remain in ZRINIT_WAIT */ options = packet.argument; build_packet(P_ZACK, options, output, output_n, output_max); } else if (packet.type == P_ZNAK) { DLOG(("send_zrqinit_wait(): ERROR ZNAK\n")); stats_increment_errors("ZNAK"); status.state = ZRQINIT; } else { /* * Sender isn't Zmodem compliant, abort. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } /* * Process through the new state */ return Q_FALSE; } if (check_timeout() == Q_TRUE) { status.state = ZRQINIT; return Q_FALSE; } /* * No data, done */ return Q_TRUE; } /** * Send: ZSINIT * * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static Q_BOOL send_zsinit(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { uint32_t options; DLOG(("send_zsinit()\n")); /* * Escape ctrl characters by default, but not 8bit characters */ if (((status.flags & TX_ESCAPE_CTRL) == 0) && (zmodem_escape_ctrl == Q_TRUE)) { options = TX_ESCAPE_CTRL; build_packet(P_ZSINIT, options, output, output_n, output_max); status.state = ZSINIT_WAIT; set_transfer_stats_last_message("ZSINIT"); /* * This is where I could put an attention string */ /* * snprintf(packet.data, sizeof(packet.data) - 1, "SOMETHING HERE"); */ packet.data[0] = 0x0; packet.data_n = strlen((char *) packet.data) + 1; /* * Make sure we continue to use the right CRC */ packet.use_crc32 = Q_FALSE; /* * Now encode */ encode_zdata_bytes(output, output_n, output_max, ZCRCW); } else { /* * Head straight into file upload */ set_transfer_stats_last_message("ZFILE"); status.state = ZFILE; } packet_buffer_n = 0; return Q_FALSE; } /** * Send: ZSINIT_WAIT * * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static Q_BOOL send_zsinit_wait(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { ZM_PARSE_PACKET rc_pp; int discard; uint32_t options = 0; DLOG(("send_zsinit_wait()\n")); if (packet_buffer_n > 0) { rc_pp = parse_packet(packet_buffer, packet_buffer_n, &discard); /* * Take the bytes off the stream */ if (discard > 0) { memmove(packet_buffer, packet_buffer + discard, packet_buffer_n - discard); packet_buffer_n -= discard; } if ((rc_pp == ZM_PP_CRCERROR) || (rc_pp == ZM_PP_INVALID)) { DLOG(("send_zsinit_wait(): ERROR garbled header\n")); stats_increment_errors(_("GARBLED HEADER")); packet_buffer_n = 0; build_packet(P_ZNAK, options, output, output_n, output_max); return Q_TRUE; } if (rc_pp == ZM_PP_NODATA) { return Q_TRUE; } if (rc_pp == ZM_PP_OK) { if (packet.type == P_ZACK) { set_transfer_stats_last_message("ZACK"); /* * I'd love to wait a full second here... */ /* * Switch to ZFILE */ set_transfer_stats_last_message("ZFILE"); status.state = ZFILE; } else if (packet.type == P_ZNAK) { DLOG(("send_zsinit_wait(): ERROR ZNAK\n")); stats_increment_errors("ZNAK"); status.state = ZSINIT; } else { /* * Sender isn't Zmodem compliant, abort. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } /* * Process through the new state */ return Q_FALSE; } if (check_timeout() == Q_TRUE) { status.state = ZSINIT; return Q_FALSE; } /* * No data, done */ return Q_TRUE; } /** * Send: ZFILE * * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static Q_BOOL send_zfile(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { uint32_t options; DLOG(("send_zfile()\n")); /* * Send header for the next file */ options = 0; build_packet(P_ZFILE, options, output, output_n, output_max); status.state = ZFILE_WAIT; /* * Put together the filename info */ snprintf((char *) packet.data, sizeof(packet.data) - 1, "%s %d %lo 0 0 1 %d", status.file_name, status.file_size, status.file_modtime, status.file_size); /* * Include the NUL terminator */ packet.data_n = strlen((char *) packet.data) + 1; packet.data[strlen(status.file_name)] = 0x00; /* * Make sure we continue to use the right CRC */ packet.use_crc32 = status.use_crc32; /* * Now encode the filename */ encode_zdata_bytes(output, output_n, output_max, ZCRCW); packet_buffer_n = 0; return Q_FALSE; } /** * Send: ZFILE_WAIT * * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static Q_BOOL send_zfile_wait(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { ZM_PARSE_PACKET rc_pp; int discard; uint32_t options = 0; DLOG(("send_zfile_wait()\n")); if (packet_buffer_n > 0) { rc_pp = parse_packet(packet_buffer, packet_buffer_n, &discard); /* * Take the bytes off the stream */ if (discard > 0) { memmove(packet_buffer, packet_buffer + discard, packet_buffer_n - discard); packet_buffer_n -= discard; } if ((rc_pp == ZM_PP_CRCERROR) || (rc_pp == ZM_PP_INVALID)) { DLOG(("send_zfile_wait(): ERROR garbled header\n")); stats_increment_errors(_("GARBLED HEADER")); packet_buffer_n = 0; build_packet(P_ZNAK, options, output, output_n, output_max); return Q_TRUE; } if (rc_pp == ZM_PP_NODATA) { return Q_TRUE; } if (rc_pp == ZM_PP_OK) { if (packet.type == P_ZRPOS) { set_transfer_stats_last_message("ZRPOS"); DLOG(("send_zfile_wait() ZRPOS packet.argument = %u status.file_size = %u\n", (uint32_t) packet.argument, (uint32_t) status.file_size)); /* * Sanity check the file size */ if (packet.argument > status.file_size) { /* * The receiver lied to me, so screw them. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } /* * Seek to the desired location */ status.file_position = packet.argument; fseek(status.file_stream, status.file_position, SEEK_SET); /* * Send the ZDATA start */ options = big_to_little_endian(status.file_position); build_packet(P_ZDATA, options, output, output_n, output_max); status.prior_state = ZFILE_WAIT; status.state = ZDATA; status.ack_required = Q_FALSE; } else if (packet.type == P_ZNAK) { DLOG(("send_zfile_wait(): ERROR ZNAK\n")); stats_increment_errors("ZNAK"); status.state = ZFILE; } else if (packet.type == P_ZCRC) { int total_bytes = 0; /* * Buffer for reading the file */ unsigned char file_buffer[1]; size_t file_buffer_n; /* * Save the original file position */ off_t original_position = status.file_position; /* * Receiver wants the file CRC between 0 and packet.argument */ set_transfer_stats_last_message("ZCRC"); /* * Reset crc32 */ status.file_crc32 = compute_crc32(0, NULL, 0); /* * Seek to beginning of file */ fseek(status.file_stream, 0, SEEK_SET); while ((!feof(status.file_stream)) && (total_bytes < packet.argument) ) { file_buffer_n = fread(file_buffer, 1, sizeof(file_buffer), status.file_stream); total_bytes += file_buffer_n; /* * I think I have a different CRC function from lrzsz... * I have to negate both here and below to get the same * value. */ status.file_crc32 = ~compute_crc32(status.file_crc32, file_buffer, file_buffer_n); } status.file_crc32 = ~status.file_crc32; /* * Seek back to the original location */ fseek(status.file_stream, original_position, SEEK_SET); DLOG(("send_zfile_wait() respond to ZCRC total_bytes = %d on-disk CRC32 = %08lx\n", total_bytes, (unsigned long) status.file_crc32)); /* * Send it as a ZCRC */ options = status.file_crc32; build_packet(P_ZCRC, options, output, output_n, output_max); } else if (packet.type == P_ZSKIP) { /* * Skip this file */ set_transfer_stats_last_message("ZSKIP"); /* * Increase the total batch transfer */ q_transfer_stats.batch_bytes_transfer += status.file_size; q_transfer_stats.state = Q_TRANSFER_STATE_FILE_DONE; set_transfer_stats_last_message("ZRINIT"); fclose(status.file_stream); assert(status.file_name != NULL); Xfree(status.file_name, __FILE__, __LINE__); status.file_name = NULL; status.file_stream = NULL; /* * Setup for the next file. */ upload_file_list_i++; setup_for_next_file(); } else { /* * Sender isn't Zmodem compliant, abort. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } /* * Process through the new state */ return Q_FALSE; } if (check_timeout() == Q_TRUE) { status.state = ZFILE; return Q_FALSE; } /* * No data, done */ return Q_TRUE; } /** * Send: ZDATA * * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static Q_BOOL send_zdata(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { ZM_PARSE_PACKET rc_pp; uint32_t options = 0; int discard; int rc; Q_BOOL last_block = Q_FALSE; Q_BOOL use_spare_packet = Q_FALSE; Q_BOOL got_error = Q_FALSE; DLOG(("send_zdata(): DATA state=%d prior_state=%d packet.data_n=%d\n", status.state, status.prior_state, packet.data_n)); DLOG(("send_zdata(): waiting_for_ack = %s ack_required = %s reliable_link = %s confirmed_bytes = %u last_confirmed_bytes = %u block_size = %d blocks_ack_count = %d\n", (status.waiting_for_ack == Q_TRUE ? "true" : "false"), (status.ack_required == Q_TRUE ? "true" : "false"), (status.reliable_link == Q_TRUE ? "true" : "false"), status.confirmed_bytes, status.last_confirmed_bytes, status.block_size, status.blocks_ack_count)); /* * Check the input buffer first */ if (packet_buffer_n > 0) { rc_pp = parse_packet(packet_buffer, packet_buffer_n, &discard); /* * Take the bytes off the stream */ if (discard > 0) { memmove(packet_buffer, packet_buffer + discard, packet_buffer_n - discard); packet_buffer_n -= discard; } if ((rc_pp == ZM_PP_CRCERROR) || (rc_pp == ZM_PP_INVALID)) { DLOG(("send_zdata(): ERROR garbled header\n")); stats_increment_errors(_("GARBLED HEADER")); packet_buffer_n = 0; build_packet(P_ZNAK, options, output, output_n, output_max); return Q_TRUE; } if (rc_pp == ZM_PP_NODATA) { return Q_TRUE; } if (rc_pp == ZM_PP_OK) { if (packet.type == P_ZSKIP) { DLOG(("send_zdata() ZSKIP\n")); /* * This is the proper way to skip a file - head to ZEOF */ /* * Send an empty ZCRCW on recovery */ outbound_packet_n = 0; *output_n = 0; /* * Make sure we continue to use the right CRC */ packet.use_crc32 = status.use_crc32; /* * Encode directly to output */ encode_zdata_bytes(output, output_n, output_max, ZCRCW); /* * Send ZEOF */ set_transfer_stats_last_message("ZEOF"); status.state = ZEOF; /* * Process through the new state */ return Q_FALSE; } if (packet.type == P_ZRPOS) { DLOG(("send_zdata() ZRPOS\n")); if (status.ack_required == Q_FALSE) { /* * This is the first ZRPOS that indicates an error. */ DLOG(("send_zdata(): ERROR ZRPOS\n")); stats_increment_errors(_("CRC ERROR")); /* * Send a ZCRCW. That part is handled below. */ status.ack_required = Q_TRUE; status.waiting_for_ack = Q_FALSE; /* * Throw away everything that is still in the buffer so * we can start with the empty ZCRCW packet. */ *output_n = 0; outbound_packet_n = 0; status.streaming_zdata = Q_FALSE; packet_buffer_n = 0; got_error = Q_TRUE; } else { /* * lrz will send a second ZRPOS, but Hyperterm does not * when the user hits 'Skip file'. I'm not sure which is * really correct, so handle both cases gracefully. */ status.ack_required = Q_FALSE; status.waiting_for_ack = Q_FALSE; DLOG(("send_zdata(): 2nd ZRPOS in reponse to ZCRCW\n")); } DLOG(("send_zdata(): ZRPOS reposition to %u, file size is %u\n", (uint32_t) packet.argument, (uint32_t) status.file_size)); if (packet.argument <= status.file_size) { /* * Record the confirmed bytes and use them to change * block size as needed. */ status.confirmed_bytes = packet.argument; if (got_error == Q_TRUE) { block_size_down(); if (status.state == ABORT) { DLOG(("Transfer was cancelled, bye!\n")); return Q_TRUE; } } /* * Seek to the desired location */ status.file_position = packet.argument; fseek(status.file_stream, status.file_position, SEEK_SET); DLOG(("send_zdata() ZRPOS new file position: %lu\n", status.file_position)); /* * Update the progress display */ q_transfer_stats.bytes_transfer = status.file_position; /* * Send the ZDATA start. */ options = big_to_little_endian(status.file_position); build_packet(P_ZDATA, options, output, output_n, output_max); } else if (packet.argument > status.file_size) { /* * The receiver lied to me, so screw them. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } else if (packet.type == P_ZACK) { DLOG(("send_zdata() ZACK\n")); /* * See how much they acked */ status.ack_required = Q_FALSE; status.waiting_for_ack = Q_FALSE; /* * Seek to the desired location */ DLOG(("send_zdata() ZACK original file position: %lu\n", status.file_position)); /* * Hyperterm lies to me when the user clicks 'Skip file' */ if (big_to_little_endian(packet.argument) > status.file_size) { DLOG(("send_zdata() ZACK RECEIVER LIED ABOUT FILE POSITION\n")); /* * Treat this as ZEOF */ set_transfer_stats_last_message("ZEOF"); status.state = ZEOF; return Q_FALSE; } status.file_position = big_to_little_endian(packet.argument); /* * Normal case: file position is somewhere within the file */ fseek(status.file_stream, status.file_position, SEEK_SET); DLOG(("send_zdata() ZACK new file position: %lu\n", status.file_position)); /* * Record the confirmed bytes and use them to change block * size as needed. */ status.confirmed_bytes = status.file_position; block_size_up(); if (status.file_position == status.file_size) { /* * Yippee, done */ /* * Send ZEOF */ set_transfer_stats_last_message("ZEOF"); status.state = ZEOF; return Q_FALSE; } else { /* * Update the progress display */ q_transfer_stats.bytes_transfer = status.file_position; /* * Check to see if we need to begin a new frame or just * keep running with this one. */ if (status.streaming_zdata == Q_FALSE) { DLOG(("send_zdata() Send new ZDATA start at file position %lu\n", status.file_position)); /* * Send the ZDATA start */ options = big_to_little_endian(status.file_position); build_packet(P_ZDATA, options, output, output_n, output_max); status.streaming_zdata = Q_TRUE; } } } else if (packet.type == P_ZNAK) { DLOG(("send_zdata(): ERROR ZNAK\n")); stats_increment_errors("ZNAK"); /* * Technically ZNAK on ZDATA is a protocol error. I am * choosing to re-send starting from the last ack'd position * hoping for a recovery, but it would be just as valid to * cancel the transfer here. */ status.state = ZRPOS; } else { /* * Sender isn't Zmodem compliant, abort. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } } else { /* * No input data, see if we are waiting on the other side */ if (status.waiting_for_ack == Q_TRUE) { /* * We are waiting for a new ZRPOS, check timeout */ if (check_timeout() == Q_TRUE) { /* * Resend the ZCRCW for recovery */ status.ack_required = Q_TRUE; status.waiting_for_ack = Q_FALSE; } else { /* * No timeout, exit out */ return Q_TRUE; } } } /* if (packet_buffer_n > 0) */ if ((status.waiting_for_ack == Q_FALSE) && (status.ack_required == Q_FALSE)) { /* * Send more data if it's available (or we are right at the end) AND * there is room in the output buffer. */ if (((!feof(status.file_stream)) || (ftell(status.file_stream) == status.file_size)) && (outbound_packet_n == 0) ) { if (output_max - *output_n < (2 * status.block_size)) { /* * There isn't enough space in output, instead put the data * in outbound_packet where it will be queued for later. */ DLOG(("send_zdata(): switch to outbound_packet\n")); use_spare_packet = Q_TRUE; assert(outbound_packet_n == 0); } set_transfer_stats_last_message("ZDATA"); DLOG(("send_zdata(): read %d bytes from file\n", status.block_size)); rc = fread(packet.data, 1, status.block_size, status.file_stream); if (rc < 0) { status.state = ABORT; set_transfer_stats_last_message(_("DISK I/O ERROR")); stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } else if ((rc < status.block_size) || (rc == 0)) { /* * Last packet, woo! */ last_block = Q_TRUE; status.file_position = status.file_size; q_transfer_stats.bytes_transfer = status.file_size; } else { status.file_position += status.block_size; q_transfer_stats.bytes_transfer += status.block_size; } packet.data_n = rc; /* * Increment count */ stats_increment_blocks(); if (use_spare_packet == Q_TRUE) { assert(outbound_packet_n == 0); if (last_block == Q_TRUE) { /* * ZCRCW on last block */ /* * Make sure we continue to use the right CRC */ packet.use_crc32 = status.use_crc32; encode_zdata_bytes(outbound_packet, &outbound_packet_n, sizeof(outbound_packet), ZCRCW); status.waiting_for_ack = Q_TRUE; } else { /* * Check window size */ status.blocks_ack_count--; if (status.blocks_ack_count == 0) { DLOG(("send_zdata(): Require a ZACK via ZCRCQ \n")); /* * Require a ZACK via ZCRCQ */ if (status.reliable_link == Q_TRUE) { status.blocks_ack_count = WINDOW_SIZE_RELIABLE; } else { status.blocks_ack_count = WINDOW_SIZE_UNRELIABLE; } status.waiting_for_ack = Q_TRUE; status.streaming_zdata = Q_TRUE; /* * Make sure we continue to use the right CRC */ packet.use_crc32 = status.use_crc32; encode_zdata_bytes(outbound_packet, &outbound_packet_n, sizeof(outbound_packet), ZCRCQ); } else { DLOG(("send_zdata(): Keep streaming with ZCRCG \n")); /* * ZCRCG otherwise */ /* * Make sure we continue to use the right CRC */ packet.use_crc32 = status.use_crc32; encode_zdata_bytes(outbound_packet, &outbound_packet_n, sizeof(outbound_packet), ZCRCG); } } } else { if (last_block == Q_TRUE) { /* * ZCRCW on last block */ /* * Make sure we continue to use the right CRC */ packet.use_crc32 = status.use_crc32; encode_zdata_bytes(output, output_n, output_max, ZCRCW); status.waiting_for_ack = Q_TRUE; } else { /* * Check window size */ status.blocks_ack_count--; if (status.blocks_ack_count == 0) { DLOG(("send_zdata(): Require a ZACK via ZCRCQ \n")); /* * Require a ZACK via ZCRCQ */ if (status.reliable_link == Q_TRUE) { status.blocks_ack_count = WINDOW_SIZE_RELIABLE; } else { status.blocks_ack_count = WINDOW_SIZE_UNRELIABLE; } status.waiting_for_ack = Q_TRUE; status.streaming_zdata = Q_TRUE; /* * Make sure we continue to use the right CRC */ packet.use_crc32 = status.use_crc32; encode_zdata_bytes(output, output_n, output_max, ZCRCQ); } else { DLOG(("send_zdata(): Keep streaming with ZCRCG \n")); /* * ZCRCG otherwise */ /* * Make sure we continue to use the right CRC */ packet.use_crc32 = status.use_crc32; encode_zdata_bytes(output, output_n, output_max, ZCRCG); } } } } /* if ((!feof(status.file_stream)) && (outbound_packet_n == 0)) */ } else if ((status.ack_required == Q_TRUE) && (status.waiting_for_ack == Q_FALSE) ) { DLOG(("send_zdata(): Send empty ZCRCW on recovery \n")); /* * Send empty ZCRCW on recovery */ packet.data_n = 0; if ((outbound_packet_n > 0) && (sizeof(outbound_packet) - outbound_packet_n > 32) ) { /* * Encode to the other buffer */ /* * Make sure we continue to use the right CRC */ packet.use_crc32 = status.use_crc32; encode_zdata_bytes(outbound_packet, &outbound_packet_n, sizeof(outbound_packet), ZCRCW); status.waiting_for_ack = Q_TRUE; } else if (output_max - *output_n > 32) { /* * Encode directly to output */ /* * Make sure we continue to use the right CRC */ packet.use_crc32 = status.use_crc32; encode_zdata_bytes(output, output_n, output_max, ZCRCW); status.waiting_for_ack = Q_TRUE; } } /* * Force the queue to fill up on this call. */ if (use_spare_packet == Q_TRUE) { return Q_FALSE; } /* * I either sent some data out, or I can't do anything else */ return Q_TRUE; } /** * Send: ZEOF * * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static Q_BOOL send_zeof(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { uint32_t options; DLOG(("send_zeof()\n")); options = status.file_size; build_packet(P_ZEOF, options, output, output_n, output_max); status.state = ZEOF_WAIT; packet_buffer_n = 0; return Q_FALSE; } /** * Send: ZEOF_WAIT * * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static Q_BOOL send_zeof_wait(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { ZM_PARSE_PACKET rc_pp; uint32_t options = 0; int discard; DLOG(("send_zeof_wait()\n")); /* * Check the input buffer first */ if (packet_buffer_n > 0) { rc_pp = parse_packet(packet_buffer, packet_buffer_n, &discard); /* * Take the bytes off the stream */ if (discard > 0) { memmove(packet_buffer, packet_buffer + discard, packet_buffer_n - discard); packet_buffer_n -= discard; } if ((rc_pp == ZM_PP_CRCERROR) || (rc_pp == ZM_PP_INVALID)) { DLOG(("send_zeof_wait(): ERROR garbled header\n")); stats_increment_errors(_("GARBLED HEADER")); packet_buffer_n = 0; build_packet(P_ZNAK, options, output, output_n, output_max); return Q_TRUE; } if (rc_pp == ZM_PP_NODATA) { return Q_TRUE; } if (rc_pp == ZM_PP_OK) { if (packet.type == P_ZRINIT) { /* * Yippee, done */ DLOG(("send_zeof_wait() ZRINIT\n")); /* * Increase the total batch transfer */ q_transfer_stats.batch_bytes_transfer += status.file_size; q_transfer_stats.state = Q_TRANSFER_STATE_FILE_DONE; set_transfer_stats_last_message("ZRINIT"); fclose(status.file_stream); assert(status.file_name != NULL); Xfree(status.file_name, __FILE__, __LINE__); status.file_name = NULL; status.file_stream = NULL; /* * Setup for the next file. */ upload_file_list_i++; setup_for_next_file(); } else if (packet.type == P_ZNAK) { DLOG(("send_zeof_wait(): ERROR ZNAK\n")); stats_increment_errors("ZNAK"); status.state = ZEOF; } else { /* * Sender isn't Zmodem compliant, abort. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } /* * Process through the new state */ return Q_FALSE; } if (check_timeout() == Q_TRUE) { status.state = ZEOF; return Q_FALSE; } /* * No data, done */ return Q_TRUE; } /** * Send: ZFIN * * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static Q_BOOL send_zfin(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { uint32_t options; DLOG(("send_zfin()\n")); options = 0; build_packet(P_ZFIN, options, output, output_n, output_max); status.state = ZFIN_WAIT; packet_buffer_n = 0; return Q_FALSE; } /** * Send: ZFIN_WAIT * * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static Q_BOOL send_zfin_wait(unsigned char * output, unsigned int * output_n, const unsigned int output_max) { ZM_PARSE_PACKET rc_pp; int discard; uint32_t options = 0; DLOG(("send_zfin_wait()\n")); if (packet_buffer_n > 0) { rc_pp = parse_packet(packet_buffer, packet_buffer_n, &discard); /* * Take the bytes off the stream */ if (discard > 0) { memmove(packet_buffer, packet_buffer + discard, packet_buffer_n - discard); packet_buffer_n -= discard; } if ((rc_pp == ZM_PP_CRCERROR) || (rc_pp == ZM_PP_INVALID)) { DLOG(("send_zfin_wait(): ERROR garbled header\n")); stats_increment_errors(_("GARBLED HEADER")); packet_buffer_n = 0; build_packet(P_ZNAK, options, output, output_n, output_max); return Q_TRUE; } if (rc_pp == ZM_PP_NODATA) { return Q_TRUE; } if (rc_pp == ZM_PP_OK) { if (packet.type == P_ZFIN) { DLOG(("send_zfin_wait(): ZFIN, sending Over-and-Out\n")); /* * Send Over-and-Out */ output[0] = 'O'; output[1] = 'O'; *output_n = 2; /* * Now switch to COMPLETE */ status.state = COMPLETE; set_transfer_stats_last_message(_("SUCCESS")); stop_file_transfer(Q_TRANSFER_STATE_END); time(&q_transfer_stats.end_time); } else if (packet.type == P_ZNAK) { DLOG(("send_zfin_wait(): ERROR ZNAK\n")); stats_increment_errors("ZNAK"); status.state = ZFIN; } else if (packet.type == P_ZRINIT) { DLOG(("send_zfin_wait(): ERROR ZRINIT\n")); stats_increment_errors("ZRINIT"); status.state = ZFIN; } else { /* * Sender isn't Zmodem compliant, abort. */ status.state = ABORT; stop_file_transfer(Q_TRANSFER_STATE_ABORT); return Q_TRUE; } } /* * Process through the new state */ return Q_FALSE; } if (check_timeout() == Q_TRUE) { status.state = ZFIN; return Q_FALSE; } /* * No data, done */ return Q_TRUE; } /** * Send a file via the Zmodem protocol. * * @param input the bytes from the remote side * @param input_n the number of bytes in input_n * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ static void zmodem_send(unsigned char * input, unsigned int input_n, unsigned char * output, unsigned int * output_n, const unsigned int output_max) { unsigned int i; Q_BOOL done; static int can_count = 0; done = Q_FALSE; while (done == Q_FALSE) { DLOG(("zmodem_send() START input_n = %d output_n = %d\n", input_n, *output_n)); DLOG(("zmodem_send() START packet_buffer_n = %d packet_buffer = ", packet_buffer_n)); for (i = 0; i < packet_buffer_n; i++) { DLOG2(("%02x ", (packet_buffer[i] & 0xFF))); } DLOG2(("\n")); /* * Add input_n to packet_buffer */ if (input_n > sizeof(packet_buffer) - packet_buffer_n) { memcpy(packet_buffer + packet_buffer_n, input, sizeof(packet_buffer) - packet_buffer_n); memmove(input, input + sizeof(packet_buffer) - packet_buffer_n, input_n - (sizeof(packet_buffer) - packet_buffer_n)); input_n -= (sizeof(packet_buffer) - packet_buffer_n); packet_buffer_n = sizeof(packet_buffer); } else { memcpy(packet_buffer + packet_buffer_n, input, input_n); packet_buffer_n += input_n; input_n = 0; } /* * Scan for 4 consecutive C_CANs */ for (i = 0; i < packet_buffer_n; i++) { if (packet_buffer[i] != C_CAN) { can_count = 0; } else { can_count++; } if (can_count >= 4) { /* * Receiver has killed the transfer */ status.state = ABORT; set_transfer_stats_last_message( _("TRANSFER CANCELLED BY RECEIVER")); stop_file_transfer(Q_TRANSFER_STATE_ABORT); } } if (outbound_packet_n > 0) { /* * Dispatch whatever is in outbound_packet */ int n = output_max - *output_n; if (n > outbound_packet_n) { n = outbound_packet_n; } DLOG(("zmodem_send() dispatch only %d bytes outbound_packet\n", n)); DLOG(("zmodem_send() output_max %d output_n %d n %d\n", output_max, *output_n, n)); DLOG(("zmodem_send() outbound_packet: %d bytes: ", outbound_packet_n)); for (i = 0; i < outbound_packet_n; i++) { DLOG2(("%02x ", (outbound_packet[i] & 0xFF))); } DLOG2(("\n")); if (n > 0) { memcpy(output + *output_n, outbound_packet, n); memmove(outbound_packet, outbound_packet + n, outbound_packet_n - n); outbound_packet_n -= n; *output_n += n; } /* * Do nothing else */ done = Q_TRUE; } else { switch (status.state) { case INIT: /* * This state is where everyone begins. Start with ZRQINIT */ status.state = ZRQINIT; set_transfer_stats_last_message("ZRQINIT"); break; case ZSINIT: done = send_zsinit(output, output_n, output_max); break; case ZSINIT_WAIT: done = send_zsinit_wait(output, output_n, output_max); break; case ZRQINIT: done = send_zrqinit(output, output_n, output_max); break; case ZRQINIT_WAIT: done = send_zrqinit_wait(output, output_n, output_max); break; case ZFILE: done = send_zfile(output, output_n, output_max); break; case ZFILE_WAIT: done = send_zfile_wait(output, output_n, output_max); break; case ZDATA: done = send_zdata(output, output_n, output_max); break; case ZEOF: done = send_zeof(output, output_n, output_max); break; case ZEOF_WAIT: done = send_zeof_wait(output, output_n, output_max); break; case ZFIN: done = send_zfin(output, output_n, output_max); break; case ZFIN_WAIT: done = send_zfin_wait(output, output_n, output_max); break; case ABORT: case COMPLETE: /* * NOP */ done = Q_TRUE; break; case ZCRC: case ZCRC_WAIT: case ZRINIT: case ZRINIT_WAIT: case ZRPOS: case ZRPOS_WAIT: case ZCHALLENGE: case ZCHALLENGE_WAIT: case ZSKIP: /* * Send should NEVER see these states */ abort(); break; } /* switch (status.state) */ } DLOG(("zmodem_send(): done = %s\n", (done == Q_TRUE ? "true" : "false"))); } /* while (done == Q_FALSE) */ /* * DLOG(("zmodem_send() NOISE\n")); * static int noise = 0; * noise++; * if (noise > 30) { * noise = 0; * output[0] = 0xaa; * } */ DLOG(("zmodem_send() END packet_buffer_n = %d packet_buffer = ", packet_buffer_n)); for (i = 0; i < packet_buffer_n; i++) { DLOG2(("%02x ", (packet_buffer[i] & 0xFF))); } DLOG2(("\n")); } /** * Process raw bytes from the remote side through the transfer protocol. See * also protocol_process_data(). * * @param input the bytes from the remote side * @param input_n the number of bytes in input_n * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ void zmodem(unsigned char * input, const unsigned int input_n, unsigned char * output, unsigned int * output_n, const unsigned int output_max) { unsigned int i; /* * Check my input arguments */ assert(input_n >= 0); assert(input != NULL); assert(output != NULL); assert(*output_n >= 0); assert(output_max > ZMODEM_MAX_BLOCK_SIZE); if ((status.state == ABORT) || (status.state == COMPLETE)) { return; } DLOG(("ZMODEM: state = %d input_n = %d output_n = %d\n", status.state, input_n, *output_n)); DLOG(("ZMODEM: %d input bytes: ", input_n)); for (i = 0; i < input_n; i++) { DLOG2(("%02x ", (input[i] & 0xFF))); } DLOG2(("\n")); if (input_n > 0) { /* * Something was sent to me, so reset timeout */ reset_timer(); } if (status.sending == Q_FALSE) { zmodem_receive(input, input_n, output, output_n, output_max); } else { zmodem_send(input, input_n, output, output_n, output_max); } DLOG(("ZMODEM: %d output bytes: ", *output_n)); for (i = 0; i < *output_n; i++) { DLOG2(("%02x ", (output[i] & 0xFF))); } DLOG2(("\n")); /* * Reset the timer if we sent something */ if (*output_n > 0) { reset_timer(); } } /** * Setup for a new file transfer session. * * @param file_list list of files to upload, or NULL if this will be a * download. * @param pathname the path to save downloaded files to * @param send if true, this is an upload: file_list must be valid and * pathname is ignored. If false, this is a download: file_list must be NULL * and pathname will be used. * @param in_flavor the type of Zmodem transfer to perform * @return true if successful */ Q_BOOL zmodem_start(struct file_info * file_list, const char * pathname, const Q_BOOL send, const ZMODEM_FLAVOR in_flavor, int progress_len) { int i; /* * If I got here, then I know that all the files in file_list exist. * forms.c ensures the files are all readable by me. */ /* * Verify that file_list is set when send is true */ if (send == Q_TRUE) { assert(file_list != NULL); } else { assert(file_list == NULL); } /* * Assume we don't start up successfully */ status.state = ABORT; upload_file_list = file_list; upload_file_list_i = 0; DLOG(("ZMODEM: START flavor = %d pathname = \'%s\'\n", in_flavor, pathname)); if (upload_file_list != NULL) { for (i = 0; upload_file_list[i].name != NULL; i++) { DLOG(("upload_file_list[%d] = '%s'\n", i, upload_file_list[i].name)); } } status.sending = send; if (send == Q_TRUE) { /* * Set up for first file */ if (setup_for_next_file() == Q_FALSE) { return Q_FALSE; } } else { /* * Save download path */ download_path = Xstrdup(pathname, __FILE__, __LINE__); set_transfer_stats_filename(""); set_transfer_stats_pathname(pathname); } if (in_flavor == Z_CRC32) { makecrc(); if (send != Q_TRUE) { /* * We aren't allowed to send in CRC32 unless the receiver asks * for it. */ status.use_crc32 = Q_TRUE; } } else { status.use_crc32 = Q_FALSE; } status.state = INIT; /* * Set block size */ q_transfer_stats.block_size = ZMODEM_BLOCK_SIZE; status.confirmed_bytes = 0; status.last_confirmed_bytes = 0; status.consecutive_errors = 0; /* * Set the window size */ status.reliable_link = Q_TRUE; status.blocks_ack_count = WINDOW_SIZE_RELIABLE; status.streaming_zdata = Q_FALSE; /* * Clear the last message */ set_transfer_stats_last_message(""); /* * Clear the packet buffer */ packet_buffer_n = 0; outbound_packet_n = 0; /* * Setup timer */ reset_timer(); status.timeout_count = 0; /* * Initialize the encode map */ setup_encode_byte_map(); progress_length = progress_len; DLOG(("ZMODEM: START OK\n")); return Q_TRUE; } /** * Stop the file transfer. Note that this function is only called in * stop_file_transfer() and save_partial is always true. However it is left * in for API completeness. * * @param save_partial if true, save any partially-downloaded files. */ void zmodem_stop(const Q_BOOL save_partial) { char notify_message[DIALOG_MESSAGE_SIZE]; DLOG(("ZMODEM: STOP\n")); if ((save_partial == Q_TRUE) || (status.sending == Q_TRUE)) { if (status.file_stream != NULL) { fflush(status.file_stream); fclose(status.file_stream); } } else { if (status.file_stream != NULL) { fclose(status.file_stream); if (unlink(status.file_name) < 0) { snprintf(notify_message, sizeof(notify_message), _("Error deleting file \"%s\": %s\n"), status.file_name, strerror(errno)); #if 0 notify_form(notify_message, 0); #endif } } } status.file_stream = NULL; if (status.file_name != NULL) { Xfree(status.file_name, __FILE__, __LINE__); } status.file_name = NULL; if (download_path != NULL) { Xfree(download_path, __FILE__, __LINE__); } download_path = NULL; } void zmodem_cancel(void) { /* See stop_file_transfer() */ zmodem_stop(Q_FALSE); q_transfer_stats.state = Q_TRANSFER_STATE_ABORT; time(&q_transfer_stats.end_time); #if 0 set_transfer_stats_last_message(_("USER CANCELS")); #endif status.state = ABORT; /* for zmodem_is_processing */ status.file_size = 0; status.file_position = 0; /* * This flag is not cleared and used at the next zmodem_start(), and * zmodem() waits for ACK unexpectedly. (This results in unexpected * delay in transferring data.) */ status.waiting_for_ack = Q_FALSE; } Q_BOOL zmodem_is_processing(int *progress_cur, int *progress_len) { *progress_len = progress_length; if (status.state == COMPLETE) { *progress_cur = progress_length; return Q_FALSE; } if (status.file_size > 0 && status.file_position < status.file_size) { *progress_cur = status.file_position * progress_length / status.file_size; } else { *progress_cur = 0; } if (status.state == ABORT) { return Q_FALSE; } else { return Q_TRUE; } } #if 0 void main(void) { unsigned char input[4096]; unsigned char output[ZMODEM_MAX_BLOCK_SIZE + 1]; unsigned int len; zmodem_start(NULL, "download", Q_FALSE, Z_CRC16); input[0] = '\0'; zmodem(input, 0, output, &len, sizeof(output)); printf("%d\n", len); unsigned int i; for (i = 0; i < len; i++) { printf("%c", output[i]); } printf("\n"); } #endif #if 0 void main(void) { unsigned char input[4096]; unsigned char output[ZMODEM_MAX_BLOCK_SIZE + 1]; unsigned int len; static struct file_info info[2]; info[0].name = "/home/ken/.signature"; stat("/home/ken/.signature", &info[0].fstats); info[1].name = NULL; zmodem_start(info, "download", Q_TRUE, Z_CRC16); input[0] = '\0'; zmodem(input, 0, output, &len, sizeof(output)); printf("%d\n", len); unsigned int i; for (i = 0; i < len; i++) { printf("%c", output[i]); } printf("\n"); } #endif mlterm-3.8.9/vtemu/vt_termcap.c010064400017600000144000000321041356600660700152120ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "vt_termcap.h" #include /* strchr */ #include /* strdup */ #include /* free */ #include #include #include typedef enum str_field { TC_DELETE, TC_BACKSPACE, TC_HOME, TC_END, TC_F1, TC_F2, TC_F3, TC_F4, TC_F5, MAX_TERMCAP_STR_FIELDS } str_field_t; typedef enum bool_field { TC_BCE, MAX_TERMCAP_BOOL_FIELDS } bool_field_t; typedef struct str_field_table { char *name; str_field_t field; } str_field_table_t; typedef struct bool_field_table { char *name; bool_field_t field; } bool_field_table_t; typedef struct vt_termcap { char *name; char *str_fields[MAX_TERMCAP_STR_FIELDS]; int8_t bool_fields[MAX_TERMCAP_BOOL_FIELDS]; } vt_termcap_t; /* --- static variables --- */ static vt_termcap_t *entries; static u_int num_entries; static str_field_table_t str_field_table[] = { { "kD", TC_DELETE, }, { "kb", TC_BACKSPACE, }, { "kh", TC_HOME, }, { "@7", TC_END, }, /* "\x1bOP" in xterm(279), but doc/term/mlterm.ti defined "\x1b[11~" from before. */ { "k1", TC_F1, }, /* "\x1bOQ" in xterm(279), but doc/term/mlterm.ti defined "\x1b[12~" from before. */ { "k2", TC_F2, }, /* "\x1bOR" in xterm(279), but doc/term/mlterm.ti defined "\x1b[13~" from before. */ { "k3", TC_F3, }, /* "\x1bOS" in xterm(279), but doc/term/mlterm.ti defined "\x1b[14~" from before. */ { "k4", TC_F4, }, /* Requested by Andi Cristian Serbanescu (1 Nov 2012) */ { "k5", TC_F5, }, }; static bool_field_table_t bool_field_table[] = { { "ut", TC_BCE, }, }; static char *tc_file = "mlterm/termcap"; /* --- static functions --- */ static int entry_init(vt_termcap_t *termcap, const char *name) { memset(termcap, 0, sizeof(vt_termcap_t)); termcap->name = strdup(name); return 1; } static int entry_final(vt_termcap_t *termcap) { int count; free(termcap->name); for (count = 0; count < MAX_TERMCAP_STR_FIELDS; count++) { free(termcap->str_fields[count]); } return 1; } static int parse_termcap_db(vt_termcap_t *termcap, char *termcap_db) { char *field; int count; while ((field = bl_str_sep(&termcap_db, ":"))) { char *key; char *value; key = bl_str_sep(&field, "="); if ((value = field) == NULL) { for (count = 0; count < MAX_TERMCAP_BOOL_FIELDS; count++) { if (strcmp(key, bool_field_table[count].name) == 0) { termcap->bool_fields[bool_field_table[count].field] = 1; break; } } } else { for (count = 0; count < MAX_TERMCAP_STR_FIELDS; count++) { if (strcmp(key, str_field_table[count].name) == 0) { if ((value = bl_str_unescape(value))) { free(termcap->str_fields[str_field_table[count].field]); termcap->str_fields[str_field_table[count].field] = value; } break; } } } } return 1; } static vt_termcap_t *search_termcap(const char *name) { int count; for (count = 0; count < num_entries; count++) { const char *p1; const char *p2; p1 = entries[count].name; while (*p1) { p2 = name; while (*p1 && *p2 && *p1 != '|' && *p1 == *p2) { p1++; p2++; } if (*p1 == '|' || *p1 == '\0') { return &entries[count]; } else { if ((p1 = strchr(p1, '|')) == NULL) { break; } p1++; } } } return NULL; } static int read_conf(char *filename) { bl_file_t *from; char *line; size_t len; char *termcap_db; size_t db_len; if (!(from = bl_file_open(filename, "r"))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " %s couldn't be opened.\n", filename); #endif return 0; } termcap_db = NULL; db_len = 0; while ((line = bl_file_get_line(from, &len))) { void *p; if (len == 0 || *line == '#') { /* empty line or comment out */ continue; } while (*line == ' ' || *line == '\t') { line++; len--; } /* + 1 is for NULL terminator */ if ((p = realloc(termcap_db, db_len + len + 1)) == NULL) { free(termcap_db); bl_file_close(from); return 0; } termcap_db = p; strncpy(&termcap_db[db_len], line, len); db_len += len; if (termcap_db[db_len - 1] == '\\') { db_len--; } else { vt_termcap_t *termcap; char *field; char *db_p; termcap_db[db_len] = '\0'; db_p = termcap_db; if ((field = bl_str_sep(&db_p, ":"))) { if ((termcap = search_termcap(field))) { #if 0 entry_final(termcap); entry_init(termcap, field); #endif parse_termcap_db(termcap, db_p); } else if ((p = realloc(entries, sizeof(vt_termcap_t) * (num_entries + 1)))) { entries = p; termcap = &entries[num_entries]; if (entry_init(termcap, field) && parse_termcap_db(termcap, db_p)) { num_entries++; } } } db_len = 0; } } free(termcap_db); bl_file_close(from); return 1; } static int termcap_init(void) { char *rcpath; if ((entries = malloc(sizeof(vt_termcap_t))) == NULL) { return 0; } if (!entry_init(entries, "*")) { return 0; } entries[0].bool_fields[TC_BCE] = 1; num_entries = 1; if ((rcpath = bl_get_sys_rc_path(tc_file))) { if (!read_conf(rcpath)) { #if defined(__ANDROID__) #define MAX_DB_LEN_IDX 2 const char *db[] = { "k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~", "ut", "kh=\E[7~:@7=\E[8~:k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~:ut", "kb=^H:kD=^?:k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~", }; const char *names[] = { "mlterm", "xterm", "rxvt", "kterm", }; void *p; char *buf; if ((p = realloc(entries, sizeof(vt_termcap_t) * (sizeof(db) / sizeof(db[0]) + 1))) && (buf = alloca(strlen(db[MAX_DB_LEN_IDX]) + 1))) { size_t count; entries = p; num_entries = sizeof(db) / sizeof(db[0]) + 1; for (count = 0; count < sizeof(db) / sizeof(db[0]); count++) { entry_init(entries + count + 1, names[count]); strcpy(buf, db[count]); parse_termcap_db(entries + count + 1, buf); } } #endif } free(rcpath); } if ((rcpath = bl_get_user_rc_path(tc_file))) { read_conf(rcpath); free(rcpath); } return 1; } /* --- global functions --- */ vt_termcap_t *vt_termcap_get(const char *name) { vt_termcap_t *termcap; if (entries == NULL) { if (!termcap_init()) { return NULL; } } if ((termcap = search_termcap(name))) { return termcap; } /* '*' */ return entries; } void vt_termcap_final(void) { int count; for (count = 0; count < num_entries; count++) { entry_final(&entries[count]); } free(entries); } int vt_termcap_set_key_seq(vt_termcap_t *termcap, vt_special_key_t key, const char *str) { str_field_t field; if (key == SPKEY_DELETE) { field = TC_DELETE; } else if (key == SPKEY_BACKSPACE) { field = TC_BACKSPACE; } else { return 0; } free(termcap->str_fields[field]); termcap->str_fields[field] = strdup(str); return 1; } int vt_termcap_bce_is_enabled(vt_termcap_t *termcap) { return termcap->bool_fields[TC_BCE]; } char *vt_termcap_special_key_to_seq(vt_termcap_t *termcap, vt_special_key_t key, int modcode, int is_app_keypad, int is_app_cursor_keys, int is_app_escape, int modify_cursor_keys, int modify_function_keys) { static char escseq[10]; char *seq; char intermed_ch; char final_ch; int param; switch (key) { case SPKEY_DELETE: if (modcode || !(seq = termcap->str_fields[TC_DELETE])) { intermed_ch = '['; param = 3; final_ch = '~'; break; } else { return seq; } case SPKEY_BACKSPACE: if (!(seq = termcap->str_fields[TC_BACKSPACE])) { seq = "\x7f"; } return seq; case SPKEY_ESCAPE: if (is_app_escape) { return "\x1bO["; } else { return "\x1b"; } case SPKEY_END: if (modcode || !is_app_cursor_keys || !(seq = termcap->str_fields[TC_END])) { intermed_ch = (is_app_cursor_keys && !modcode) ? 'O' : '['; param = modcode ? 1 : 0; final_ch = 'F'; break; } else { return seq; } case SPKEY_HOME: if (modcode || !is_app_cursor_keys || !(seq = termcap->str_fields[TC_HOME])) { intermed_ch = (is_app_cursor_keys && !modcode) ? 'O' : '['; param = modcode ? 1 : 0; final_ch = 'H'; break; } else { return seq; } case SPKEY_BEGIN: intermed_ch = '['; param = modcode ? 1 : 0; final_ch = 'E'; break; case SPKEY_ISO_LEFT_TAB: intermed_ch = '['; param = 0; final_ch = 'Z'; modcode = 0; break; default: if (key <= SPKEY_KP_F4) { if (is_app_keypad) { char final_chs[] = { 'j', /* MULTIPLY */ 'k', /* ADD */ 'l', /* SEPARATOR */ 'm', /* SUBTRACT */ 'n', /* DELETE */ 'o', /* DIVIDE */ 'q', /* END */ 'w', /* HOME */ 'u', /* BEGIN */ 'x', /* UP */ 'r', /* DOWN */ 'v', /* RIGHT */ 't', /* LEFT */ 'p', /* INSERT */ 'y', /* PRIOR */ 's', /* NEXT */ 'P', /* F1 */ 'Q', /* F2 */ 'R', /* F3 */ 'S', /* F4 */ }; intermed_ch = 'O'; param = 0; final_ch = final_chs[key - SPKEY_KP_MULTIPLY]; } else { if (key <= SPKEY_KP_DIVIDE) { return NULL; } else if (key <= SPKEY_KP_BEGIN) { key += (SPKEY_END - SPKEY_KP_END); } else if (key <= SPKEY_KP_LEFT) { key += (SPKEY_UP - SPKEY_KP_UP); } else if (key == SPKEY_KP_INSERT) { key = SPKEY_INSERT; } else if (key <= SPKEY_KP_F4) { key += (SPKEY_PRIOR - SPKEY_KP_PRIOR); } else { return NULL; } return vt_termcap_special_key_to_seq(termcap, key, modcode, is_app_keypad, is_app_cursor_keys, is_app_escape, modify_cursor_keys, modify_function_keys); } } else if (key <= SPKEY_LEFT) { intermed_ch = (is_app_cursor_keys && !modcode) ? 'O' : '['; param = modcode ? 1 : 0; final_ch = (key - SPKEY_UP) + 'A'; } else if (key <= SPKEY_NEXT) { intermed_ch = '['; param = (key - SPKEY_FIND) + 1; final_ch = '~'; } else if (key <= SPKEY_F5) { if (modcode || !(seq = termcap->str_fields[TC_F1 + key - SPKEY_F1])) { if (key == SPKEY_F5) { intermed_ch = '['; param = 15; final_ch = '~'; } else { /* PQRS */ if (modcode) { intermed_ch = '['; param = 1; } else { intermed_ch = 'O'; param = 0; } final_ch = (key - SPKEY_F1) + 'P'; } } else { return seq; } } else /* if( key <= SPKEY_F37) */ { char params[] = { /* F6 - F15 */ 17, 18, 19, 20, 21, 23, 24, 25, 26, 28, /* F16 - F25 */ 29, 31, 32, 33, 34, 42, 43, 44, 45, 46, /* F26 - F35 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, /* F36 - F37 */ 57, 58, }; intermed_ch = '['; final_ch = '~'; param = params[key - SPKEY_F6]; } } if (modcode) /* ESC Ps ; Ps */ { if ('A' <= final_ch && final_ch <= 'H') { /* cursor keys */ if (0 <= modify_cursor_keys && modify_cursor_keys <= 1) { goto obsolete_format; } else if (modify_cursor_keys == 3) { goto private_format; } } else if (SPKEY_IS_FKEY(key)) { if (modify_function_keys == 3) { goto private_format; } else if ('P' <= final_ch && final_ch <= 'S') { /* F1-F4 keys */ if (modify_function_keys == 0) { intermed_ch = 'O'; goto obsolete_format; } else if (modify_function_keys == 1) { goto obsolete_format; } } } while (1) { bl_snprintf(escseq, sizeof(escseq), "\x1b%c%d;%d%c", intermed_ch, param, modcode, final_ch); break; obsolete_format: bl_snprintf(escseq, sizeof(escseq), "\x1b%c%d%c", intermed_ch, modcode, final_ch); break; private_format: bl_snprintf(escseq, sizeof(escseq), "\x1b%c>%d;%d%c", intermed_ch, param, modcode, final_ch); break; } } else if (param) /* ESC Ps */ { bl_snprintf(escseq, sizeof(escseq), "\x1b%c%d%c", intermed_ch, param, final_ch); } else /* ESC */ { bl_snprintf(escseq, sizeof(escseq), "\x1b%c%c", intermed_ch, final_ch); } return escseq; } mlterm-3.8.9/vtemu/vt_termcap.h010064400017600000144000000035531356600660700152250ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_TERMCAP_H__ #define __VT_TERMCAP_H__ #include typedef enum vt_special_key { SPKEY_DELETE = 0, SPKEY_BACKSPACE, SPKEY_ESCAPE, SPKEY_END, SPKEY_HOME, SPKEY_BEGIN, SPKEY_ISO_LEFT_TAB, SPKEY_KP_MULTIPLY, SPKEY_KP_ADD, SPKEY_KP_SEPARATOR, SPKEY_KP_SUBTRACT, SPKEY_KP_DELETE, SPKEY_KP_DIVIDE, SPKEY_KP_END, SPKEY_KP_HOME, SPKEY_KP_BEGIN, SPKEY_KP_UP, SPKEY_KP_DOWN, SPKEY_KP_RIGHT, SPKEY_KP_LEFT, SPKEY_KP_INSERT, SPKEY_KP_PRIOR, SPKEY_KP_NEXT, SPKEY_KP_F1, SPKEY_KP_F2, SPKEY_KP_F3, SPKEY_KP_F4, SPKEY_UP, SPKEY_DOWN, SPKEY_RIGHT, SPKEY_LEFT, SPKEY_FIND, SPKEY_INSERT, SPKEY_EXECUTE, SPKEY_SELECT, SPKEY_PRIOR, SPKEY_NEXT, SPKEY_F1, SPKEY_F2, SPKEY_F3, SPKEY_F4, SPKEY_F5, SPKEY_F6, SPKEY_F7, SPKEY_F8, SPKEY_F9, SPKEY_F10, SPKEY_F11, SPKEY_F12, SPKEY_F13, SPKEY_F14, SPKEY_F15, SPKEY_F16, SPKEY_F17, SPKEY_F18, SPKEY_F19, SPKEY_F20, SPKEY_F21, SPKEY_F22, SPKEY_F23, SPKEY_F24, SPKEY_F25, SPKEY_F26, SPKEY_F27, SPKEY_F28, SPKEY_F29, SPKEY_F30, SPKEY_F31, SPKEY_F32, SPKEY_F33, SPKEY_F34, SPKEY_F35, SPKEY_F36, SPKEY_F37 } vt_special_key_t; typedef struct vt_termcap *vt_termcap_ptr_t; #define SPKEY_IS_FKEY(key) ((key) >= SPKEY_F1) vt_termcap_ptr_t vt_termcap_get(const char *name); void vt_termcap_final(); int vt_termcap_set_key_seq(vt_termcap_ptr_t termcap, vt_special_key_t key, const char *str); int vt_termcap_bce_is_enabled(vt_termcap_ptr_t termcap); char *vt_termcap_special_key_to_seq(vt_termcap_ptr_t termcap, vt_special_key_t key, int modcode, int is_app_keypad, int is_app_cursor_keys, int is_app_escape, int modify_cursor_keys, int modify_function_keys); #endif mlterm-3.8.9/vtemu/zmodem.h010064400017600000144000000066611356600660700143570ustar kenusers/* * zmodem.h * * qodem - Qodem Terminal Emulator * * Written 2003-2017 by Kevin Lamonte * * To the extent possible under law, the author(s) have dedicated all * copyright and related and neighboring rights to this software to the * public domain worldwide. This software is distributed without any * warranty. * * You should have received a copy of the CC0 Public Domain Dedication along * with this software. If not, see * . * * Modified 2019- by Araki Ken * (Based on qodem-1.0.0) */ #ifndef __ZMODEM_H__ #define __ZMODEM_H__ /* Includes --------------------------------------------------------------- */ #include #ifdef __cplusplus extern "C" { #endif /* Defines ---------------------------------------------------------------- */ /** * view_directory() and batch_entry_window() need to return both the file * name and size, so we have a struct to combine these. */ struct file_info { char * name; struct stat fstats; }; /** * The flavors of Zmodem that are supported. */ typedef enum { Z_CRC16, /* Zmodem 16-bit CRC */ Z_CRC32 /* Zmodem 32-bit CRC */ } ZMODEM_FLAVOR; #define Q_BOOL int #define Q_FALSE 0 #define Q_TRUE 1 /* * Technically, Zmodem maxes at 1024 bytes, but each byte might be * CRC-escaped to twice its size. Then we've got the CRC escape itself to * include. */ #define ZMODEM_BLOCK_SIZE 1024 #define ZMODEM_MAX_BLOCK_SIZE (2 * (ZMODEM_BLOCK_SIZE + 4 + 1)) /* Globals ---------------------------------------------------------------- */ /* Functions -------------------------------------------------------------- */ /** * Process raw bytes from the remote side through the transfer protocol. See * also protocol_process_data(). * * @param input the bytes from the remote side * @param input_n the number of bytes in input_n * @param output a buffer to contain the bytes to send to the remote side * @param output_n the number of bytes that this function wrote to output * @param output_max the maximum number of bytes this function may write to * output */ extern void zmodem(unsigned char * input, const unsigned int input_n, unsigned char * output, unsigned int * output_n, const unsigned int output_max); /** * Setup for a new file transfer session. * * @param file_list list of files to upload, or NULL if this will be a * download. * @param pathname the path to save downloaded files to * @param send if true, this is an upload: file_list must be valid and * pathname is ignored. If false, this is a download: file_list must be NULL * and pathname will be used. * @param in_flavor the type of Zmodem transfer to perform * @param progress_len the length of progress bar. * @return true if successful */ extern Q_BOOL zmodem_start(struct file_info * file_list, const char * pathname, const Q_BOOL send, const ZMODEM_FLAVOR in_flavor, int progress_len); /** * Stop the file transfer. Note that this function is only called in * stop_file_transfer() and save_partial is always true. However it is left * in for API completeness. * * @param save_partial if true, save any partially-downloaded files. */ extern void zmodem_stop(const Q_BOOL save_partial); extern void zmodem_cancel(void); extern Q_BOOL zmodem_is_processing(int *progress_cur, int *progress_len); #ifdef __cplusplus } #endif #endif /* __ZMODEM_H__ */ mlterm-3.8.9/vtemu/vt_transfer.c010064400017600000144000000075471356600660700154200ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include #include #include #include #include #include "zmodem.h" #ifndef LIBDIR #define TRANSFERLIB_DIR "/usr/local/lib/mlterm/" #else #define TRANSFERLIB_DIR LIBDIR "/mlterm/" #endif /* --- static variables --- */ static int zmodem_mode; static struct file_info zmodem_info[2]; static void (*dl_zmodem)(unsigned char *, const unsigned int, unsigned char *, unsigned int *, const unsigned int); static Q_BOOL (*dl_zmodem_start)(struct file_info *, const char *, const Q_BOOL, const ZMODEM_FLAVOR, int); static Q_BOOL (*dl_zmodem_cancel)(void); static Q_BOOL (*dl_zmodem_is_processing)(int *, int *); static int is_tried; #ifndef NO_DYNAMIC_LOAD_TRANSFER static bl_dl_handle_t handle; #endif static int progress_prev = -1; /* --- static functions --- */ static int load_library(void) { is_tried = 1; #ifndef NO_DYNAMIC_LOAD_TRANSFER if (!(handle = bl_dl_open(TRANSFERLIB_DIR, "zmodem")) && !(handle = bl_dl_open("", "zmodem"))) { bl_error_printf("ZMODEM: Could not load.\n"); return 0; } bl_dl_close_at_exit(handle); dl_zmodem = bl_dl_func_symbol(handle, "zmodem"); dl_zmodem_start = bl_dl_func_symbol(handle, "zmodem_start"); dl_zmodem_cancel = bl_dl_func_symbol(handle, "zmodem_cancel"); dl_zmodem_is_processing = bl_dl_func_symbol(handle, "zmodem_is_processing"); #else dl_zmodem = zmodem; dl_zmodem_start = zmodem_start; dl_zmodem_cancel = zmodem_cancel; dl_zmodem_is_processing = zmodem_is_processing; #endif return 1; } static void reset(void) { zmodem_mode = 0; free(zmodem_info[0].name); zmodem_info[0].name = NULL; progress_prev = -1; } /* --- global functions --- */ int vt_transfer_start(/* vt_transfer_type_t type, */ char *send_file /* allocated by the caller */, const char *save_dir, int is_crc32, int progress_len) { Q_BOOL ret; if (zmodem_mode || (is_tried ? (dl_zmodem_start == NULL) : !load_library())) { return 0; } if (send_file) { zmodem_info[0].name = send_file; stat(send_file, &zmodem_info[0].fstats); ret = (*dl_zmodem_start)(zmodem_info, save_dir, Q_TRUE, is_crc32 ? Z_CRC32 : Z_CRC16, progress_len); } else { char *p; size_t len = strlen(save_dir); if ((p = alloca(len + 2))) { memcpy(p, save_dir, len); strcpy(p + len, "/"); bl_mkdir_for_file(p, 0700); } ret = (*dl_zmodem_start)(NULL, save_dir, Q_FALSE, is_crc32 ? Z_CRC32 : Z_CRC16, progress_len); } if (ret) { zmodem_mode = 1; return 1; } else { free(zmodem_info[0].name); zmodem_info[0].name = NULL; return 0; } } void vt_transfer_cancel(void) { (*dl_zmodem_cancel)(); reset(); } void vt_transfer_data(u_char *input, const u_int input_n, u_char *output, u_int *output_n, const u_int output_max) { #if 0 if (input_n > 0) { FILE *fp = fopen("zmodem.log", "a"); u_int i; fprintf(fp, "INPUT %d\n", input_n); for (i = 0; i < input_n; i++) { fprintf(fp, "%c", input[i]); } fprintf(fp, "\n"); fclose(fp); } #endif (*dl_zmodem)(input, input_n, output, output_n, output_max); #if 0 if (*output_n > 0) { FILE *fp = fopen("zmodem.log", "a"); u_int i; fprintf(fp, "OUTPUT %d\n", *output_n); for (i = 0; i < *output_n; i++) { fprintf(fp, "%c", output[i]); } fprintf(fp, "\n"); fclose(fp); } #endif } int vt_transfer_get_state(int *progress_cur, int *progress_len) { if ((*dl_zmodem_is_processing)(progress_cur, progress_len)) { if (progress_prev < *progress_cur) { progress_prev = *progress_cur; return 1; } else { return -1; } } else { reset(); return 0; } } mlterm-3.8.9/vtemu/vt_transfer.h010064400017600000144000000007471356600660700154200ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __VT_TRANSFER_H__ #define __VT_TRANSFER_H__ #include int vt_transfer_start(char *send_file, const char *save_dir, int is_crc32, int progress_len); void vt_transfer_cancel(void); void vt_transfer_data(u_char *input, const u_int input_n, u_char *output, u_int *output_n, const u_int output_max); int vt_transfer_get_state(int *progress_cur, int *progress_len); #endif mlterm-3.8.9/vtemu/Makefile.in010064400017600000144000000050741356600660700147550ustar kenuserstop_builddir = .. top_srcdir = @top_srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ libexecdir = @libexecdir@ CC = @CC@ LIBTOOL = @LIBTOOL@ INSTALL = @INSTALL@ BINDIR = $(DESTDIR)$(bindir) LIBDIR = $(DESTDIR)$(libdir) VPATH = $(top_srcdir)/vtemu # @FRIBIDI_CFLAGS@ and @IND_CFLAGS@ are for NO_DYNAMIC_LOAD_CTL. CFLAGS = $(CFLAGS_LOCAL) @DEB_CFLAGS@ @POBL_CFLAGS@ @MEF_CFLAGS@ @SSH2_CFLAGS@ \ @UTMP_CFLAGS@ @FRIBIDI_CFLAGS@ @IND_CFLAGS@ @CTL_CFLAGS@ @VT52_CFLAGS@ \ @IMAGE_CFLAGS@ @TOOLS_CFLAGS@ @OT_LAYOUT_CFLAGS@ @CFLAGS@ \ @VT_NORM_CFLAGS@ @CPPFLAGS@ \ -I/usr/local/include -DLIBEXECDIR=\"$(libexecdir)\" -DBINDIR=\"$(bindir)\" \ -DLIBDIR=\"$(libdir)\" OBJ_CORE = vt_char.o vt_str.o vt_line.o vt_model.o vt_ot_layout.o @VT_NORM_OBJ@ @CTL_LOADER_OBJ@ OBJ = vt_char_encoding.o vt_color.o vt_edit.o vt_edit_util.o vt_edit_scroll.o \ vt_cursor.o vt_logical_visual.o vt_logs.o vt_screen.o vt_shape.o \ vt_str_parser.o vt_term.o vt_parser.o vt_term_manager.o \ vt_bidi.o vt_iscii.o vt_config_menu.o vt_config_proto.o vt_drcs.o \ vt_pty.o vt_termcap.o vt_line_shape.o cygfile.o vt_transfer.o @VT_PTY_OBJ@ LIBNAME = libmlterm LIBTOOL_CC = $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) all : @LMLTERM_CORE@ $(LIBNAME).a libzmodem.la debug : @LMLTERM_CORE@ $(LIBNAME).a $(LIBNAME).a : $(OBJ) $(LIBTOOL_LINK) -o $(LIBNAME).a $(OBJ:.o=.lo) $(LIBNAME)_core.a : $(OBJ_CORE) $(LIBTOOL_LINK) -o $(LIBNAME)_core.a $(OBJ_CORE:.o=.lo) $(LIBNAME)_core.la : $(OBJ_CORE) $(LIBTOOL_LINK) -o $(LIBNAME)_core.la $(OBJ_CORE:.o=.lo) \ @NO_UNDEFINED_FLAG@ -rpath $(libdir) -avoid-version @LPOBL@ $(LIBS) $(LIBNAME)_coreotl.la : $(OBJ_CORE) $(LIBTOOL_LINK) -o $(LIBNAME)_coreotl.la $(OBJ_CORE:.o=.lo) \ @NO_UNDEFINED_FLAG@ -rpath $(libdir) -avoid-version @LPOBL@ $(LIBS) libzmodem.la : zmodem.o $(LIBTOOL_LINK) -o libzmodem.la zmodem.lo \ @NO_UNDEFINED_FLAG@ -rpath $(libdir)/mlterm -module -avoid-version install : $(LIBDIR) if test "`echo @LMLTERM_CORE@|grep .la`" != "" ; then \ $(LIBTOOL_INSTALL) @LMLTERM_CORE@ $(LIBDIR) ; \ fi $(LIBTOOL_INSTALL) libzmodem.la $(LIBDIR)/mlterm uninstall : rm -f $(LIBDIR)/*mlterm_core*.* $(LIBDIR) : mkdir -p $(LIBDIR) clean : rm -rf $(OBJ) $(OBJ:.o=.lo) $(OBJ_CORE) $(OBJ_CORE:.o=.lo) mlterm.o mlterm.lo \ zmodem.o zmodem.lo .libs *.a *.la distclean: clean rm -f Makefile wc : find . -name "*.[ch]" -a \! -name "test_*" | xargs wc -l .SUFFIXES : .c.o .m.o : $(LIBTOOL_CC) -c $< .c.o : $(LIBTOOL_CC) -c $< mlterm-3.8.9/vtemu/cygfile.c010064400017600000144000000024341356600660700144730ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #if defined(__CYGWIN__) || defined(__MSYS__) #include #include #include /* bl_conv_to_win32_path */ /* --- global functions --- */ HANDLE cygfopen(const char *path, const char *mode) { char winpath[MAX_PATH]; HANDLE file; if (bl_conv_to_win32_path(path, winpath, sizeof(winpath)) < 0) { return NULL; } if (*mode == 'a') { file = CreateFileA(winpath, FILE_APPEND_DATA, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } else /* if( *mode == 'w') */ { file = CreateFileA(winpath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); } if (file == INVALID_HANDLE_VALUE) { return NULL; } else { return file; } } int cygfclose(HANDLE file) { CloseHandle(file); return 0; } size_t cygfwrite(const void *ptr, size_t size, size_t nmemb, HANDLE file) { DWORD written; if (WriteFile(file, ptr, size * nmemb, &written, NULL)) { return written; } else { return 0; } } #ifdef __DEBUG void main(void) { HANDLE file = cygfopen("test.log", "w"); cygfwrite("aaa\n", 1, 4, file); cygfclose(file); file = cygfopen("test.log", "a"); cygfwrite("bbb\n", 1, 4, file); cygfclose(file); } #endif #endif mlterm-3.8.9/uitoolkit004075500017600000144000000000001356600660700135115ustar kenusersmlterm-3.8.9/uitoolkit/xlib004075500017600000144000000000001356600660700144475ustar kenusersmlterm-3.8.9/uitoolkit/xlib/ui_xim.h010064400017600000144000000016321356600660700161700ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_XIM_H__ #define __UI_XIM_H__ #include #include #include "../ui_window.h" typedef struct ui_xim { XIM im; char *name; char *locale; ef_parser_t *parser; vt_char_encoding_t encoding; ui_window_t **xic_wins; u_int num_xic_wins; } ui_xim_t; int ui_xim_init(int use_xim); int ui_xim_final(void); int ui_xim_display_opened(Display *display); int ui_xim_display_closed(Display *display); int ui_add_xim_listener(ui_window_t *win, char *xim_name, char *xim_locale); int ui_remove_xim_listener(ui_window_t *win); XIMStyle ui_xim_get_style(ui_window_t *win); XIC ui_xim_create_ic(ui_window_t *win, XIMStyle selected_style, XVaNestedList preedit_attr); char *ui_get_xim_name(ui_window_t *win); char *ui_get_xim_locale(ui_window_t *win); char *ui_get_default_xim_name(void); #endif mlterm-3.8.9/uitoolkit/xlib/ui_color.c010064400017600000144000000127471356600660700165150ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_color.h" #include /* memcpy,strcmp */ #include /* sscanf */ #include #include #include #include /* --- static functions --- */ static void native_color_to_xcolor(ui_color_t *xcolor, XColor *ncolor) { xcolor->pixel = ncolor->pixel; xcolor->red = (ncolor->red >> 8) & 0xff; xcolor->green = (ncolor->green >> 8) & 0xff; xcolor->blue = (ncolor->blue >> 8) & 0xff; xcolor->alpha = 0xff; } static int alloc_closest_xcolor_pseudo(ui_display_t *disp, int red, /* 0 to 0xffff */ int green, /* 0 to 0xffff */ int blue, /* 0 to 0xffff */ ui_color_t *ret_xcolor) { XColor *all_colors; /* colors exist in the shared color map */ XColor closest_color; int closest_index = -1; u_long min_diff = 0xffffffff; u_long diff; int diff_r, diff_g, diff_b; int ncells = disp->visual->map_entries; int i; /* FIXME: When visual class is StaticColor, should not be return? */ if (!disp->visual->class == PseudoColor && !disp->visual->class == GrayScale) { return 0; } if ((all_colors = malloc(ncells * sizeof(XColor))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc() failed.\n"); #endif return 0; } /* get all colors from default colormap */ for (i = 0; i < ncells; i++) { all_colors[i].pixel = i; } XQueryColors(disp->display, disp->colormap, all_colors, ncells); red >>= 8; green >>= 8; blue >>= 8; /* find the closest color */ for (i = 0; i < ncells; i++) { diff_r = red - (all_colors[i].red >> 8); diff_g = green - (all_colors[i].green >> 8); diff_b = blue - (all_colors[i].blue >> 8); diff = COLOR_DISTANCE(diff_r, diff_g, diff_b); if (diff < min_diff) { min_diff = diff; closest_index = i; /* no one may notice the difference (4[2^3/2]*4*9+4*4*30+4*4) */ if (diff < COLOR_DISTANCE_THRESHOLD) { break; } } } if (closest_index == -1) /* unable to find closest color */ { closest_color.red = 0; closest_color.green = 0; closest_color.blue = 0; } else { closest_color.red = all_colors[closest_index].red; closest_color.green = all_colors[closest_index].green; closest_color.blue = all_colors[closest_index].blue; } closest_color.flags = DoRed | DoGreen | DoBlue; free(all_colors); if (!XAllocColor(disp->display, disp->colormap, &closest_color)) { return 0; } ret_xcolor->pixel = closest_color.pixel; ret_xcolor->red = (closest_color.red >> 8) & 0xff; ret_xcolor->green = (closest_color.green >> 8) & 0xff; ret_xcolor->blue = (closest_color.blue >> 8) & 0xff; ret_xcolor->alpha = 0xff; return 1; } /* --- global functions --- */ int ui_load_named_xcolor(ui_display_t *disp, ui_color_t *xcolor, char *name) { XColor near; XColor exact; u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; if (vt_color_parse_rgb_name(&red, &green, &blue, &alpha, name)) { return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, alpha); } if (!XAllocNamedColor(disp->display, disp->colormap, name, &near, &exact)) { /* try to find closest color */ if (XParseColor(disp->display, disp->colormap, name, &exact)) { return alloc_closest_xcolor_pseudo(disp, exact.red, exact.green, exact.blue, xcolor); } else { return 0; } } native_color_to_xcolor(xcolor, &near); return 1; } int ui_load_rgb_xcolor(ui_display_t *disp, ui_color_t *xcolor, u_int8_t red, u_int8_t green, u_int8_t blue, u_int8_t alpha) { if (disp->depth == 32) { xcolor->red = red; xcolor->green = green; xcolor->blue = blue; xcolor->alpha = alpha; /* XXX */ xcolor->pixel = (alpha << 24) | (((u_int)red * (u_int)alpha / 256) << 16) | (((u_int)green * (u_int)alpha / 256) << 8) | (((u_int)blue * (u_int)alpha / 256)); } else { XColor ncolor; ncolor.red = (red << 8) + red; ncolor.green = (green << 8) + green; ncolor.blue = (blue << 8) + blue; ncolor.flags = 0; if (!XAllocColor(disp->display, disp->colormap, &ncolor)) { /* try to find closest color */ return alloc_closest_xcolor_pseudo(disp, ncolor.red, ncolor.green, ncolor.blue, xcolor); } native_color_to_xcolor(xcolor, &ncolor); } return 1; } void ui_unload_xcolor(ui_display_t *disp, ui_color_t *xcolor) { #if 0 u_long pixel[1]; pixel[0] = xcolor->pixel; XFreeColors(disp->display, disp->colormap, pixel, 1, 0); #endif } void ui_get_xcolor_rgba(u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_int8_t *alpha /* can be NULL */, ui_color_t *xcolor) { *red = xcolor->red; *green = xcolor->green; *blue = xcolor->blue; if (alpha) { *alpha = xcolor->alpha; } } int ui_xcolor_fade(ui_display_t *disp, ui_color_t *xcolor, u_int fade_ratio) { u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; ui_get_xcolor_rgba(&red, &green, &blue, &alpha, xcolor); #if 0 bl_msg_printf("Fading R%d G%d B%d => ", red, green, blue); #endif red = (red * fade_ratio) / 100; green = (green * fade_ratio) / 100; blue = (blue * fade_ratio) / 100; ui_unload_xcolor(disp, xcolor); #if 0 bl_msg_printf("R%d G%d B%d\n", red, green, blue); #endif return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, alpha); } mlterm-3.8.9/uitoolkit/xlib/ui_connect_dialog.c010064400017600000144000000125251356600660700203410ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ /* Note that protocols except ssh aren't supported if USE_LIBSSH2 is defined. */ #ifdef USE_LIBSSH2 #include "../ui_connect_dialog.h" #include /* sprintf */ #include /* alloca */ #include /* strdup */ #include #include /* USE_WIN32API */ #include #include #include #define LINESPACE 10 #define BEGENDSPACE 8 #define CLEAR_DRAW 1 #define DRAW 2 #define DRAW_EXPOSE 3 /* --- global functions --- */ int ui_connect_dialog(char **uri, /* Should be free'ed by those who call this. */ char **pass, /* Same as uri. If pass is not input, "" is set. */ char **exec_cmd, /* Same as uri. If exec_cmd is not input, NULL is set. */ char **privkey, /* in/out */ int *x11_fwd, /* in/out */ char *display_name, Window parent_window, char *def_server /* (@)(:)(:). */ ) { Display *display; int screen; Window window; GC gc; XFontStruct *font; u_int width; u_int height; u_int ncolumns; char *title; char *password; size_t pass_len; int ret; if (!(title = alloca((ncolumns = 20 + strlen(def_server))))) { return 0; } sprintf(title, "Enter password for %s", def_server); if (!(display = XOpenDisplay(display_name))) { return 0; } screen = DefaultScreen(display); gc = DefaultGC(display, screen); if (!(font = XLoadQueryFont(display, "-*-r-normal-*-*-*-*-*-c-*-iso8859-1"))) { XCloseDisplay(display); return 0; } XSetFont(display, gc, font->fid); width = font->max_bounds.width * ncolumns + BEGENDSPACE; height = (font->ascent + font->descent + LINESPACE) * 2; if (!(window = XCreateSimpleWindow( display, DefaultRootWindow(display), (DisplayWidth(display, screen) - width) / 2, (DisplayHeight(display, screen) - height) / 2, width, height, 0, BlackPixel(display, screen), WhitePixel(display, screen)))) { XFreeFont(display, font); XCloseDisplay(display); return 0; } XStoreName(display, window, title); XSetIconName(display, window, title); XSelectInput(display, window, KeyReleaseMask | ExposureMask | StructureNotifyMask); XMapWindow(display, window); ret = 0; password = strdup(""); pass_len = 1; while (1) { XEvent ev; int redraw = 0; XWindowEvent(display, window, KeyReleaseMask | ExposureMask | StructureNotifyMask, &ev); if (ev.type == KeyRelease) { char buf[10]; void *p; size_t len; if ((len = XLookupString(&ev.xkey, buf, sizeof(buf), NULL, NULL)) > 0) { if (buf[0] == 0x08) /* Backspace */ { if (pass_len > 1) { password[--pass_len] = '\0'; redraw = CLEAR_DRAW; } } else if (buf[0] == 0x1b) { break; } else if (isprint((int)buf[0])) { if (!(p = realloc(password, (pass_len += len)))) { break; } memcpy((password = p) + pass_len - len - 1, buf, len); password[pass_len - 1] = '\0'; redraw = DRAW; } else { /* Exit loop successfully. */ ret = 1; break; } } } else if (ev.type == Expose) { redraw = DRAW_EXPOSE; } else if (ev.type == MapNotify) { XSetInputFocus(display, window, RevertToPointerRoot, CurrentTime); } if (redraw) { XPoint points[5]; points[0].x = BEGENDSPACE / 2; points[0].y = font->ascent + font->descent + LINESPACE; points[1].x = width - BEGENDSPACE / 2; points[1].y = font->ascent + font->descent + LINESPACE; points[2].x = width - BEGENDSPACE / 2; points[2].y = (font->ascent + font->descent) * 2 + LINESPACE * 3 / 2; points[3].x = BEGENDSPACE / 2; points[3].y = (font->ascent + font->descent) * 2 + LINESPACE * 3 / 2; points[4].x = BEGENDSPACE / 2; points[4].y = font->ascent + font->descent + LINESPACE; if (redraw == DRAW_EXPOSE) { XDrawString(display, window, gc, BEGENDSPACE / 2, font->ascent + LINESPACE / 2, title, strlen(title)); XDrawLines(display, window, gc, points, 5, CoordModeOrigin); } else if (redraw == CLEAR_DRAW) { XClearArea(display, window, points[0].x + 1, points[0].y + 1, points[2].x - points[0].x - 1, points[2].y - points[0].y - 1, False); } if (password) { char *input; size_t count; if (!(input = alloca(pass_len - 1))) { break; } for (count = 0; count < pass_len - 1; count++) { input[count] = '*'; } XDrawString(display, window, gc, BEGENDSPACE / 2 + font->max_bounds.width / 2, font->ascent * 2 + font->descent + LINESPACE * 3 / 2, input, BL_MIN(pass_len - 1, ncolumns - 1)); } } } XDestroyWindow(display, window); XFreeFont(display, font); XCloseDisplay(display); if (ret && (*uri = strdup(def_server))) { *pass = password; *exec_cmd = NULL; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Connecting to %s %s\n", *uri, *pass); #endif } else { free(password); } return ret; } #endif mlterm-3.8.9/uitoolkit/xlib/ui_decsp_font.c010064400017600000144000000160771356600660700175230ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_decsp_font.h" #include /* memset */ #include /* malloc */ /* --- global functions --- */ ui_decsp_font_t *ui_decsp_font_new(Display *display, u_int width, u_int height, u_int ascent) { ui_decsp_font_t *font; char gray_bits[] = {0x11, 0x44}; Window win; u_int glyph_width; u_int glyph_height; GC gc; Pixmap gray; XPoint pts[4]; int count; if ((font = malloc(sizeof(ui_decsp_font_t))) == NULL) { return NULL; } font->width = width; font->height = height; font->ascent = ascent; glyph_width = width; glyph_height = height; win = DefaultRootWindow(display); gray = XCreateBitmapFromData(display, win, gray_bits, 8, 2); gc = XCreateGC(display, gray, 0, NULL); XSetForeground(display, gc, 0); XSetFillStyle(display, gc, FillSolid); memset(font->glyphs, 0, sizeof(font->glyphs)); for (count = 1; count < sizeof(font->glyphs) / sizeof(font->glyphs[0]); count++) { /* * Glyph map * * None , Used , Used , None , None , None , None , None , * None , None , None , Used , Used , Used , Used , Used , * Used , Used , Used , Used , Used , Used , Used , Used , * Used , Used , None , None , None , None , Used , None , */ if (count <= 0x02 || (0x0b <= count && count <= 0x19) || count == 0x1e) { font->glyphs[count] = XCreatePixmap(display, win, width, height, 1); XFillRectangle(display, font->glyphs[count], gc, 0, 0, width, height); } } XSetForeground(display, gc, 1); XSetLineAttributes(display, gc, (glyph_width >> 3) + 1, LineSolid, CapProjecting, JoinMiter); pts[0].x = glyph_width / 2; pts[0].y = 0; pts[1].x = 0; pts[1].y = glyph_height / 2; pts[2].x = glyph_width / 2; pts[2].y = glyph_height; pts[3].x = glyph_width; pts[3].y = glyph_height / 2; XFillPolygon(display, font->glyphs[0x01], gc, pts, 4, Nonconvex, CoordModeOrigin); XSetFillStyle(display, gc, FillStippled); XSetStipple(display, gc, gray); XFillRectangle(display, font->glyphs[0x02], gc, 0, 0, width, height); XSetFillStyle(display, gc, FillSolid); XDrawLine(display, font->glyphs[0x0b], gc, 0, glyph_height / 2, glyph_width / 2, glyph_height / 2); XDrawLine(display, font->glyphs[0x0b], gc, glyph_width / 2, 0, glyph_width / 2, glyph_height / 2); XDrawLine(display, font->glyphs[0x0c], gc, 0, glyph_height / 2, glyph_width / 2, glyph_height / 2); XDrawLine(display, font->glyphs[0x0c], gc, glyph_width / 2, glyph_height / 2, glyph_width / 2, glyph_height); XDrawLine(display, font->glyphs[0x0d], gc, glyph_width / 2, glyph_height / 2, glyph_width, glyph_height / 2); XDrawLine(display, font->glyphs[0x0d], gc, glyph_width / 2, glyph_height / 2, glyph_width / 2, glyph_height); XDrawLine(display, font->glyphs[0x0e], gc, glyph_width / 2, glyph_height / 2, glyph_width, glyph_height / 2); XDrawLine(display, font->glyphs[0x0e], gc, glyph_width / 2, 0, glyph_width / 2, glyph_height / 2); XDrawLine(display, font->glyphs[0x0f], gc, 0, glyph_height / 2, glyph_width, glyph_height / 2); XDrawLine(display, font->glyphs[0x0f], gc, glyph_width / 2, 0, glyph_width / 2, glyph_height); XDrawLine(display, font->glyphs[0x10], gc, 0, 0, glyph_width, 0); XDrawLine(display, font->glyphs[0x11], gc, 0, glyph_height / 4, glyph_width, glyph_height / 4); XDrawLine(display, font->glyphs[0x12], gc, 0, glyph_height / 2, glyph_width, glyph_height / 2); XDrawLine(display, font->glyphs[0x13], gc, 0, glyph_height * 3 / 4, glyph_width, glyph_height * 3 / 4); XDrawLine(display, font->glyphs[0x14], gc, 0, glyph_height, glyph_width, glyph_height); XDrawLine(display, font->glyphs[0x15], gc, glyph_width / 2, glyph_height / 2, glyph_width, glyph_height / 2); XDrawLine(display, font->glyphs[0x15], gc, glyph_width / 2, 0, glyph_width / 2, glyph_height); XDrawLine(display, font->glyphs[0x16], gc, 0, glyph_height / 2, glyph_width / 2, glyph_height / 2); XDrawLine(display, font->glyphs[0x16], gc, glyph_width / 2, 0, glyph_width / 2, glyph_height); XDrawLine(display, font->glyphs[0x17], gc, 0, glyph_height / 2, glyph_width, glyph_height / 2); XDrawLine(display, font->glyphs[0x17], gc, glyph_width / 2, 0, glyph_width / 2, glyph_height / 2); XDrawLine(display, font->glyphs[0x18], gc, 0, glyph_height / 2, glyph_width, glyph_height / 2); XDrawLine(display, font->glyphs[0x18], gc, glyph_width / 2, glyph_height / 2, glyph_width / 2, glyph_height); XDrawLine(display, font->glyphs[0x19], gc, glyph_width / 2, 0, glyph_width / 2, glyph_height); XDrawLine(display, font->glyphs[0x1e], gc, glyph_width / 2 - 1, glyph_height / 2, glyph_width / 2 + 1, glyph_height / 2); XDrawLine(display, font->glyphs[0x1e], gc, glyph_width / 2, glyph_height / 2 - 1, glyph_width / 2, glyph_height / 2 + 1); XFreePixmap(display, gray); XFreeGC(display, gc); return font; } void ui_decsp_font_destroy(ui_decsp_font_t *font, Display *display) { int count; for (count = 0; count < sizeof(font->glyphs) / sizeof(font->glyphs[0]); count++) { if (font->glyphs[count]) { XFreePixmap(display, font->glyphs[count]); } } free(font); } void ui_decsp_font_draw_string(ui_decsp_font_t *font, Display *display, Drawable drawable, GC gc, int x, int y, u_char *str, u_int len) { int count; int cache = -1; /* to avoid replace clip mask every time */ y -= font->ascent; /* original y is not used */ for (count = 0; count < len; count++) { if (*str < 0x20 && font->glyphs[*str]) { XSetClipOrigin(display, gc, x, y); if (cache != *str) { XSetClipMask(display, gc, font->glyphs[*str]); cache = *str; } XFillRectangle(display, drawable, gc, x, y, font->width, font->height); } else { /* XXX handle '#'? */ XSetClipMask(display, gc, None); cache = -1; XDrawRectangle(display, drawable, gc, x, y, font->width - 1, font->height - 1); } x += font->width; str++; } XSetClipMask(display, gc, None); } void ui_decsp_font_draw_image_string(ui_decsp_font_t *font, Display *display, Drawable drawable, GC gc, int x, int y, u_char *str, u_int len) { u_int count; y -= font->ascent; /* original y is not used */ for (count = 0; count < len; count++) { if (*str < 0x20 && font->glyphs[*str]) { XCopyPlane(display, font->glyphs[*str], drawable, gc, 0, 0, font->width, font->height, x, y, 1); } else { /* XXX handle '#'? */ XGCValues gcv; u_long fg; u_long bg; if (!XGetGCValues(display, gc, GCBackground | GCForeground, &gcv)) { return; } fg = gcv.foreground; bg = gcv.background; XSetForeground(display, gc, bg); XFillRectangle(display, drawable, gc, x, y, font->width, font->height); XSetForeground(display, gc, fg); XDrawRectangle(display, drawable, gc, x, y, font->width - 1, font->height - 1); } x += font->width; str++; } } mlterm-3.8.9/uitoolkit/xlib/ui_decsp_font.h010064400017600000144000000014251356600660700175170ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_DECSP_FONT_H__ #define __UI_DECSP_FONT_H__ #include "../ui.h" typedef struct ui_decsp_font { Pixmap glyphs[0x20]; u_int width; u_int height; u_int ascent; } ui_decsp_font_t; ui_decsp_font_t *ui_decsp_font_new(Display *display, u_int width, u_int height, u_int ascent); void ui_decsp_font_destroy(ui_decsp_font_t *vtgr, Display *display); void ui_decsp_font_draw_string(ui_decsp_font_t *vtgr, Display *display, Drawable drawable, GC gc, int x, int y, u_char *str, u_int len); void ui_decsp_font_draw_image_string(ui_decsp_font_t *font, Display *display, Drawable drawable, GC gc, int x, int y, u_char *str, u_int len); #endif mlterm-3.8.9/uitoolkit/xlib/ui_display.c010064400017600000144000000324571356600660700170440ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_display.h" #include /* memset/memcpy */ #include #include #include /* strdup */ #include /* bl_file_set_cloexec */ #include #include "../ui_window.h" #include "../ui_picture.h" #include "../ui_imagelib.h" #include "ui_xim.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static u_int num_displays; static ui_display_t **displays; static int (*default_error_handler)(Display *, XErrorEvent *); /* --- static functions --- */ #ifdef __DEBUG static int error_handler(Display *display, XErrorEvent *event) { char buffer[1024]; XGetErrorText(display, event->error_code, buffer, 1024); bl_msg_printf("%s\n", buffer); abort(); return 1; } static int ioerror_handler(Display *display) { bl_error_printf("X IO Error.\n"); abort(); return 1; } #else /* __DEBUG */ static int error_handler(Display *display, XErrorEvent *event) { /* * If is included for 'X_OpenFont', typedef of BOOL and INT32 * is conflicted in (included from and * (included from ). */ if (event->error_code == 2 /* BadValue */ && event->request_code == 45 /* X_OpenFont */) { /* * XXX Hack * If BadValue error happens in XLoad(Query)Font function, * mlterm doesn't stop. */ bl_msg_printf("XLoad(Query)Font failed.\n"); /* ignored anyway */ return 0; } else if (default_error_handler) { return (*default_error_handler)(display, event); } else { exit(1); return 1; } } #endif #ifdef USE_ALERT_DIALOG #define LINESPACE 20 #define BEGENDSPACE 20 static int dialog_cb(bl_dialog_style_t style, const char *msg) { Display *display; int screen; Window window; GC gc; XFontStruct *font; u_int width; u_int height; u_int len; char title[] = "** Warning **"; if (style != BL_DIALOG_ALERT) { return -1; } len = strlen(msg); if (!(display = XOpenDisplay(""))) { return -1; } screen = DefaultScreen(display); gc = DefaultGC(display, screen); if (!(font = XLoadQueryFont(display, "-*-r-normal-*-*-*-*-*-c-*-iso8859-1"))) { XCloseDisplay(display); return -1; } XSetFont(display, gc, font->fid); width = font->max_bounds.width * BL_MAX(len, sizeof(title) - 1) + BEGENDSPACE; height = (font->ascent + font->descent) * 2 + LINESPACE; if (!(window = XCreateSimpleWindow(display, DefaultRootWindow(display), (DisplayWidth(display, screen) - width) / 2, (DisplayHeight(display, screen) - height) / 2, width, height, 0, BlackPixel(display, screen), WhitePixel(display, screen)))) { XFreeFont(display, font); XCloseDisplay(display); return -1; } /* * Not only ButtonReleaseMask but also ButtonPressMask is necessary to * receive ButtonRelease event correctly. */ XSelectInput(display, window, KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|ExposureMask|StructureNotifyMask); XMapWindow(display, window); while (1) { XEvent ev; XWindowEvent(display, window, KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|ExposureMask|StructureNotifyMask, &ev); if (ev.type == KeyRelease || ev.type == ButtonRelease || ev.type == ClientMessage) { break; } else if (ev.type == Expose) { XDrawString(display, window, gc, BEGENDSPACE / 2, font->ascent + LINESPACE / 2, title, sizeof(title) - 1); XDrawString(display, window, gc, BEGENDSPACE / 2, font->ascent * 2 + font->descent + LINESPACE / 2, msg, len); } else if (ev.type == MapNotify) { XSetInputFocus(display, window, RevertToPointerRoot, CurrentTime); } } XDestroyWindow(display, window); XFreeFont(display, font); XCloseDisplay(display); return 1; } #endif static ui_display_t *open_display(char *name, u_int depth) { ui_display_t *disp; XVisualInfo vinfo; if ((disp = calloc(1, sizeof(ui_display_t))) == NULL) { return NULL; } if ((disp->display = XOpenDisplay(name)) == NULL) { bl_error_printf("Couldn't open display %s.\n", name); goto error1; } /* set close-on-exec flag on the socket connected to X. */ bl_file_set_cloexec(XConnectionNumber(disp->display)); disp->name = DisplayString(disp->display); disp->screen = DefaultScreen(disp->display); disp->my_window = DefaultRootWindow(disp->display); disp->width = DisplayWidth(disp->display, disp->screen); disp->height = DisplayHeight(disp->display, disp->screen); if (depth && XMatchVisualInfo(disp->display, disp->screen, depth, TrueColor, &vinfo) && vinfo.visual != DefaultVisual(disp->display, disp->screen)) { XSetWindowAttributes s_attr; Window win; disp->depth = depth; disp->visual = vinfo.visual; disp->colormap = XCreateColormap(disp->display, disp->my_window, vinfo.visual, AllocNone); s_attr.background_pixel = BlackPixel(disp->display, disp->screen); s_attr.border_pixel = BlackPixel(disp->display, disp->screen); s_attr.colormap = disp->colormap; win = XCreateWindow(disp->display, disp->my_window, 0, 0, 1, 1, 0, disp->depth, InputOutput, disp->visual, CWColormap | CWBackPixel | CWBorderPixel, &s_attr); if ((disp->gc = ui_gc_new(disp->display, win)) == NULL) { goto error2; } XDestroyWindow(disp->display, win); } else { disp->depth = DefaultDepth(disp->display, disp->screen); disp->visual = DefaultVisual(disp->display, disp->screen); disp->colormap = DefaultColormap(disp->display, disp->screen); if ((disp->gc = ui_gc_new(disp->display, None)) == NULL) { goto error2; } } disp->modmap.map = XGetModifierMapping(disp->display); default_error_handler = XSetErrorHandler(error_handler); #ifdef __DEBUG XSetIOErrorHandler(ioerror_handler); XSynchronize(disp->display, True); #endif ui_xim_display_opened(disp->display); ui_picture_display_opened(disp->display); #ifdef DEBUG bl_debug_printf("X connection opened.\n"); #endif return disp; error2: XCloseDisplay(disp->display); error1: free(disp); return NULL; } static void close_display(ui_display_t *disp) { u_int count; ui_gc_destroy(disp->gc); if (disp->modmap.map) { XFreeModifiermap(disp->modmap.map); } for (count = 0; count < (sizeof(disp->cursors) / sizeof(disp->cursors[0])); count++) { if (disp->cursors[count]) { XFreeCursor(disp->display, disp->cursors[count]); } } for (count = 0; count < disp->num_roots; count++) { ui_window_unmap(disp->roots[count]); ui_window_final(disp->roots[count]); } free(disp->roots); ui_xim_display_closed(disp->display); ui_picture_display_closed(disp->display); XCloseDisplay(disp->display); free(disp); } /* --- global functions --- */ ui_display_t *ui_display_open(char *disp_name, u_int depth) { int count; ui_display_t *disp; void *p; for (count = 0; count < num_displays; count++) { if (strcmp(displays[count]->name, disp_name) == 0) { return displays[count]; } } #ifdef USE_ALERT_DIALOG /* Callback should be set before bl_dialog() is called. */ bl_dialog_set_callback(dialog_cb); #endif if ((disp = open_display(disp_name, depth)) == NULL) { return NULL; } if ((p = realloc(displays, sizeof(ui_display_t *) * (num_displays + 1))) == NULL) { ui_display_close(disp); return NULL; } displays = p; displays[num_displays++] = disp; return disp; } void ui_display_close(ui_display_t *disp) { u_int count; for (count = 0; count < num_displays; count++) { if (displays[count] == disp) { close_display(displays[count]); displays[count] = displays[--num_displays]; #ifdef DEBUG bl_debug_printf("X connection closed.\n"); #endif return; } } } void ui_display_close_all(void) { while (num_displays > 0) { close_display(displays[--num_displays]); } free(displays); displays = NULL; } ui_display_t **ui_get_opened_displays(u_int *num) { *num = num_displays; return displays; } int ui_display_fd(ui_display_t *disp) { return XConnectionNumber(disp->display); } int ui_display_show_root(ui_display_t *disp, ui_window_t *root, int x, int y, int hint, char *app_name, Window parent_window) { void *p; if ((p = realloc(disp->roots, sizeof(ui_window_t *) * (disp->num_roots + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } disp->roots = p; root->disp = disp; root->parent = NULL; if (parent_window) { root->parent_window = parent_window; } else { root->parent_window = disp->my_window; } root->gc = disp->gc; root->x = x; root->y = y; if (app_name) { root->app_name = app_name; } /* * root is added to disp->roots before ui_window_show() because * ui_display_get_group_leader() is called in ui_window_show(). */ disp->roots[disp->num_roots++] = root; ui_window_show(root, hint); return 1; } int ui_window_reset_group(ui_window_t *win); /* defined in xlib/ui_window.c */ int ui_display_remove_root(ui_display_t *disp, ui_window_t *root) { u_int count; for (count = 0; count < disp->num_roots; count++) { if (disp->roots[count] == root) { /* Don't switching on or off screen in exiting. */ ui_window_unmap(root); ui_window_final(root); disp->num_roots--; if (count == disp->num_roots) { disp->roots[count] = NULL; } else { disp->roots[count] = disp->roots[disp->num_roots]; if (count == 0) { /* Group leader is changed. */ #if 0 bl_debug_printf(BL_DEBUG_TAG " Changing group_leader -> %x\n", disp->roots[0]->my_window); #endif for (count = 0; count < disp->num_roots; count++) { ui_window_reset_group(disp->roots[count]); } } } return 1; } } return 0; } void ui_display_idling(ui_display_t *disp) { int count; for (count = 0; count < disp->num_roots; count++) { ui_window_idling(disp->roots[count]); } } int ui_display_receive_next_event(ui_display_t *disp) { XEvent event; int count; do { XNextEvent(disp->display, &event); if (!XFilterEvent(&event, None)) { for (count = 0; count < disp->num_roots; count++) { ui_window_receive_event(disp->roots[count], &event); } } } while (XEventsQueued(disp->display, QueuedAfterReading)); return 1; } void ui_display_sync(ui_display_t *disp) { if (XEventsQueued(disp->display, QueuedAlready)) { ui_display_receive_next_event(disp); } XFlush(disp->display); } /* * Folloing functions called from ui_window.c */ int ui_display_own_selection(ui_display_t *disp, ui_window_t *win) { if (disp->selection_owner) { ui_display_clear_selection(disp, disp->selection_owner); } disp->selection_owner = win; return 1; } int ui_display_clear_selection(ui_display_t *disp, /* NULL means all selection owner windows. */ ui_window_t *win) { if (disp == NULL) { u_int count; for (count = 0; count < num_displays; count++) { ui_display_clear_selection(displays[count], displays[count]->selection_owner); } return 1; } if (disp->selection_owner == NULL || disp->selection_owner != win) { return 0; } if (disp->selection_owner->selection_cleared) { (*disp->selection_owner->selection_cleared)(disp->selection_owner); } disp->selection_owner = NULL; return 1; } XModifierKeymap *ui_display_get_modifier_mapping(ui_display_t *disp) { return disp->modmap.map; } void ui_display_update_modifier_mapping(ui_display_t *disp, u_int serial) { if (serial != disp->modmap.serial) { if (disp->modmap.map) { XFreeModifiermap(disp->modmap.map); } disp->modmap.map = XGetModifierMapping(disp->display); disp->modmap.serial = serial; } } Cursor ui_display_get_cursor(ui_display_t *disp, u_int shape) { int idx; /* * XXX * cursor[0] == XC_xterm / cursor[1] == XC_left_ptr / cursor[2] == XC_nil * Mlterm uses only these shapes. */ if (shape == XC_xterm) { idx = 0; } else if (shape == XC_left_ptr) { idx = 1; } else if (shape == XC_nil) { idx = 2; } else { return None; } if (!disp->cursors[idx]) { if (idx == 2) { XFontStruct *font; XColor dummy; if (!(font = XLoadQueryFont(disp->display, "nil2")) && !(font = XLoadQueryFont(disp->display, "fixed"))) { return None; } disp->cursors[idx] = XCreateGlyphCursor(disp->display, font->fid, font->fid, 'X', ' ', &dummy, &dummy); XFreeFont(disp->display, font); } else { disp->cursors[idx] = XCreateFontCursor(disp->display, shape); } } return disp->cursors[idx]; } XVisualInfo *ui_display_get_visual_info(ui_display_t *disp) { XVisualInfo vinfo_template; int nitems; vinfo_template.visualid = XVisualIDFromVisual(disp->visual); /* Return pointer to the first element of VisualInfo list. */ return XGetVisualInfo(disp->display, VisualIDMask, &vinfo_template, &nitems); } XID ui_display_get_group_leader(ui_display_t *disp) { if (disp->num_roots > 0) { return disp->roots[0]->my_window; } else { return None; } } mlterm-3.8.9/uitoolkit/xlib/ui_display.h010064400017600000144000000004311356600660700170340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_DISPLAY_H__ #define ___UI_DISPLAY_H__ #include "../ui_display.h" Cursor ui_display_get_cursor(ui_display_t *disp, u_int shape); XVisualInfo *ui_display_get_visual_info(ui_display_t *disp); #endif mlterm-3.8.9/uitoolkit/xlib/ui_dnd.c010064400017600000144000000550371356600660700161430ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ /** @file * @brief X Drag and Drop protocol support */ #ifndef DISABLE_XDND #include "../ui_window.h" #include "../ui_dnd.h" #include #include #include #include #include #include #include #include #define SUCCESS 0 #define FAILURE -1 /* XXX: should we cache this atom for decrease round-trip? */ #define XA_DND_STORE(display) (XInternAtom(display, "MLTERM_DND", False)) /* following define should be consistent with the counterpart in ui_window.c */ #define XA_INCR(display) (XInternAtom(display, "INCR", False)) /* For now, we need a pointer to this structure in the ui_window_t * to keep track of DND. It should be removed someday ...*/ typedef struct ui_dnd_context { Window source; Atom waiting_atom; int is_incr; ef_parser_t *parser; ef_conv_t *conv; Atom action; } ui_dnd_context_t; typedef struct dnd_parser { char *atomname; int (*parser)(ui_window_t *, u_char *, int); } dnd_parser_t; #ifdef BL_DEBUG static void TEST_dnd(ui_display_t *disp); #endif /********************** parsers **********************************/ /* XXX: to properly support DnD spec v5, parsers should accept "codeset"*/ static int parse_text_unicode(ui_window_t *win, u_char *src, int len) { int filled_len; ef_parser_t *parser; ef_conv_t *conv; u_char conv_buf[512] = {0}; if (!(win->utf_selection_notified)) return FAILURE; if ((conv = win->dnd->conv) && (parser = win->dnd->parser) && (win->dnd->is_incr)) { if (len == 0) { /* the incr session was finished */ (conv->destroy)(conv); win->dnd->conv = NULL; (parser->destroy)(parser); win->dnd->parser = NULL; #ifdef DEBUG bl_debug_printf("freed parser/converter\n"); #endif return SUCCESS; } #ifdef DEBUG bl_debug_printf("recycling parser/converter %d, %p, %p\n", win->dnd->is_incr, conv, parser); #endif } else { if (win->dnd->conv) (win->dnd->conv->destroy)(win->dnd->conv); if (win->dnd->parser) (win->dnd->parser->destroy)(win->dnd->parser); if (!(conv = ef_utf8_conv_new())) return FAILURE; if (!(parser = ef_utf16_parser_new())) { (conv->destroy)(conv); return FAILURE; } /* initialize the parser's endian. */ (parser->init)(parser); if ((src[0] == 0xFF || src[0] == 0xFE) && (src[1] == 0xFF || src[1] == 0xFE) && (src[0] != src[1])) { /* src sequence seems to have a valid BOM and * * should initialize parser correctly */ } else { /* try to set parser state depending on your machine's endianess by sending BOM */ /* XXX: it's not spec comformant and someteime fails */ u_int16_t BOM[] = {0xFEFF}; (parser->set_str)(parser, (u_char *)BOM, 2); (parser->next_char)(parser, NULL); } } (parser->set_str)(parser, src, len); /* conversion from utf16 -> utf8. */ while (!parser->is_eos) { filled_len = (conv->convert)(conv, conv_buf, sizeof(conv_buf), parser); if (filled_len == 0) break; (*win->utf_selection_notified)(win, conv_buf, filled_len); } if (win->dnd->is_incr) { /* keep pointers to parser/converter to use them for next event */ win->dnd->parser = parser; win->dnd->conv = conv; } else { (conv->destroy)(conv); win->dnd->conv = NULL; (parser->destroy)(parser); win->dnd->parser = NULL; } return SUCCESS; } static void unescape(u_char *src) { u_char *dst; int c; dst = src; while (*src) { if (*src == '%' && sscanf(src, "%%%2x", &c) == 1) { *(dst++) = c; src += 3; } else { *(dst++) = *(src++); } } *dst = '\0'; } static int parse_text_uri_list(ui_window_t *win, u_char *src, int len) { u_char *pos; u_char *end; if (len <= 0) return FAILURE; pos = src; end = src + len; while (pos < end) { u_char *delim; /* * According to RFC, 0x0d is the delimiter. */ if ((delim = strchr(pos, 0x0d))) { *delim++ = '\0'; } else { delim = end; } if (pos + 7 < end && strncmp((char *)pos, "file://", 7) == 0) { /* * Skip "file:". * But if pos == 'file://'(with no trailing bytes), not skipped * by checking pos + 7 < end because it doesn't conform to * "file://..." format. */ pos += 7; } unescape(pos); /* XdndActionMove == Shift+DnD */ if (win->dnd->action == XInternAtom(win->disp->display, "XdndActionMove", False) && win->set_xdnd_config) { (*win->set_xdnd_config)(win, NULL, "scp", pos); } else if (win->utf_selection_notified) { (*win->utf_selection_notified)(win, pos, strlen(pos)); } else { return FAILURE; } /* skip trailing 0x0A */ pos = delim + 1; } return SUCCESS; } static int parse_compound_text(ui_window_t *win, u_char *src, int len) { if (!(win->xct_selection_notified)) return FAILURE; (*win->xct_selection_notified)(win, src, len); return SUCCESS; } static int parse_utf8_string(ui_window_t *win, u_char *src, int len) { if (!(win->utf_selection_notified)) return FAILURE; (*win->utf_selection_notified)(win, src, len); return SUCCESS; } static int parse_mlterm_config(ui_window_t *win, u_char *src, int len) { char *value; if (len <= 0) return FAILURE; if (!(win->set_xdnd_config)) return FAILURE; value = strchr((char *)src, '='); if (!value) return FAILURE; *value = 0; #ifdef DEBUG bl_debug_printf("conf key %s val %s\n", src, value); #endif (*win->set_xdnd_config)(win, NULL, /* dev */ (char *)src, /* key */ value + 1 /* value */); return SUCCESS; } static int parse_app_color(ui_window_t *win, u_char *src, int len) { u_int16_t *r, *g, *b; u_char buffer[25]; r = (u_int16_t *)src; g = r + 1; b = r + 2; sprintf((char *)buffer, "bg_color=#%02x%02x%02x", (*r) >> 8, (*g) >> 8, (*b) >> 8); #ifdef DEBUG bl_debug_printf("bgcolor: %s\n", buffer); #endif parse_mlterm_config(win, buffer, strlen(buffer)); return SUCCESS; } static int parse_prop_bgimage(ui_window_t *win, u_char *src, int len) { char *head; char tail; if (len <= 0) return FAILURE; if (!(win->set_xdnd_config)) return FAILURE; tail = src[len - 1]; src[len - 1] = 0; if ((head = strstr((char *)src, "file://"))) { /* format should be file:/// */ memmove(src, head + 7, len - 6 - ((char *)src - head)); src[strlen((char *)src)] = tail; src[strlen((char *)src)] = 0; if (!(head = strstr((char *)src, "/"))) return FAILURE; /* and should be localhost and safely ignored.*/ src = (u_char *)head; /* remove trailing garbage */ if ((head = strstr((char *)src, "\r"))) *head = 0; if ((head = strstr((char *)src, "\n"))) *head = 0; } else { /* other schemas (like "http" --call wget?) may be supported here */ } #ifdef DEBUG bl_debug_printf("bgimage: %s\n", src); #endif (*win->set_xdnd_config)(win, NULL, /* dev */ "wall_picture", /* key */ (char *)src /* value */); return SUCCESS; } #ifdef DEBUG static int parse_debug(ui_window_t *win, u_char *src, int len) { int i; bl_debug_printf(">%s<\n", (char *)src); for (i = 0; (i < 100) && (i < len); i++) bl_debug_printf("\n%d %x", i, src[i]); return SUCCESS; } #endif /* new mime type and parser pair should be added into this table */ static dnd_parser_t dnd_parsers[] = {{"text/x-mlterm.config", parse_mlterm_config}, {"UTF8_STRING", parse_utf8_string}, {"COMPOUND_TEXT", parse_compound_text}, {"TEXT", parse_utf8_string}, {"application/x-color", parse_app_color}, {"property/bgimage", parse_prop_bgimage}, {"x-special/gnome-reset-background", parse_prop_bgimage}, {"text/uri-list", parse_text_uri_list}, {"text/unicode", parse_text_unicode}, {"text/plain", parse_utf8_string}, /* nobody would use following... {"GIMP_PATTERN" , parse_utf8_string } , {"GIMP_BRUSH" , parse_utf8_string } , {"GIMP_GRADIENT" , parse_utf8_string } , {"GIMP_IMAGEFILE" , parse_utf8_string } , */ {NULL, NULL}}; /************************** static functions *************************/ static int ignore_badwin(Display *display, XErrorEvent *event) { char buffer[1024]; XGetErrorText(display, event->error_code, buffer, 1024); bl_error_printf("%s\n", buffer); switch (event->error_code) { case BadWindow: return 1; default: abort(); /* Not reached. */ return 0; } } static void set_badwin_handler(int flag) { static XErrorHandler old; if (flag) { if (!old) old = XSetErrorHandler(ignore_badwin); } else { if (old) { XSetErrorHandler(old); old = NULL; } } } static int finalize_context(ui_window_t *win) { if (!(win->dnd)) return FAILURE; if (win->dnd->conv) (win->dnd->conv->destroy)(win->dnd->conv); if (win->dnd->parser) (win->dnd->parser->destroy)(win->dnd->parser); free(win->dnd); win->dnd = NULL; return SUCCESS; } /* seek atom array and return the index */ static int is_pref(Atom type, Atom *atom_list, int num) { int i; for (i = 0; i < num; i++) if (atom_list[i] == type) return i; return FAILURE; } /**send a accept/reject message to the dnd sender *\param win mlterm window */ static void reply(ui_window_t *win) { XClientMessageEvent msg; msg.type = ClientMessage; msg.display = win->disp->display; msg.format = 32; msg.window = win->dnd->source; msg.message_type = XInternAtom(win->disp->display, "XdndStatus", False); msg.data.l[0] = win->my_window; if (win->dnd->waiting_atom) { msg.data.l[1] = 0x1 | 0x2; /* accept the drop | use [2][3] */ msg.data.l[2] = 0; msg.data.l[3] = 0; msg.data.l[4] = win->dnd->action; } else { msg.data.l[1] = 0; msg.data.l[2] = 0; msg.data.l[3] = 0; msg.data.l[4] = 0; } set_badwin_handler(1); XSendEvent(win->disp->display, msg.window, False, 0, (XEvent *)&msg); set_badwin_handler(0); } /**send finish message to dnd sender *\param win mlterm window */ static int finish(ui_window_t *win) { XClientMessageEvent msg; if (!(win->dnd)) return FAILURE; if (!(win->dnd->source)) return FAILURE; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "saying good bye\n"); #endif msg.message_type = XInternAtom(win->disp->display, "XdndFinished", False); msg.data.l[0] = win->my_window; /* setting bit 0 means success */ msg.data.l[1] = 1; msg.data.l[2] = win->dnd->action; msg.type = ClientMessage; msg.format = 32; msg.window = win->dnd->source; msg.display = win->disp->display; set_badwin_handler(1); XSendEvent(win->disp->display, win->dnd->source, False, 0, (XEvent *)&msg); set_badwin_handler(0); win->dnd->source = 0; return SUCCESS; } /**parse dnd data and send them to the pty *\param win mlterm window *\param atom type of data *\param src data from dnd (src is prop_return of XGetWindowProperty() which *always allocated * one extra byte in prop_return and sets it to zero. So src[len] is always *NULL.) *\param len size of data in bytes */ static int parse(ui_window_t *win, u_char *src, int len) { dnd_parser_t *proc_entry; if (!src) return FAILURE; if (!(win->dnd)) return FAILURE; if (!(win->dnd->waiting_atom)) return FAILURE; if (win->dnd->action == XInternAtom(win->disp->display, "XdndActionMove", False)) { return parse_text_uri_list(win, src, len); } for (proc_entry = dnd_parsers; proc_entry->atomname; proc_entry++) { if ((win->dnd->waiting_atom) == XInternAtom(win->disp->display, proc_entry->atomname, False)) break; } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "processing as %s\n", proc_entry->atomname); #endif if (proc_entry->parser) return (proc_entry->parser)(win, src, len); return FAILURE; } /* i is used as an index for an array of atom. * i = -1 means "nothing" * * returned value is the atom found and NOT THE INDEX * and 0 means "nothing" */ static Atom choose_atom(ui_window_t *win, Atom *atom_list, int num) { dnd_parser_t *proc_entry; int i; #ifdef DEBUG char *atom_name; for (i = 0; i < num; i++) { if (!atom_list[i]) break; atom_name = XGetAtomName(win->disp->display, atom_list[i]); if (atom_name) { bl_debug_printf(BL_DEBUG_TAG "candidate #%d: %s\n", i, atom_name); XFree(atom_name); } } #endif i = -1; for (proc_entry = dnd_parsers; i < 0 && proc_entry->atomname; proc_entry++) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "ckecking against : %s\n", proc_entry->atomname); #endif i = is_pref(XInternAtom(win->disp->display, proc_entry->atomname, False), atom_list, num); } if (i < 0) return (Atom)0; /* 0 would never be used for Atom */ #ifdef DEBUG atom_name = XGetAtomName(win->disp->display, atom_list[i]); if (atom_name) { bl_debug_printf(BL_DEBUG_TAG "accepted: %s(%d)\n", atom_name, atom_list[i]); XFree(atom_name); } #endif return atom_list[i]; } /**set/reset the window's dnd awareness *\param win mlterm window *\param flag awareness is set when true */ static void awareness(ui_window_t *win, int version) { set_badwin_handler(1); XChangeProperty(win->disp->display, win->my_window, XInternAtom(win->disp->display, "XdndAware", False), XA_ATOM, 32, PropModeReplace, (u_char *)(&version), 1); set_badwin_handler(0); } static int enter(ui_window_t *win, XEvent *event) { Atom to_wait; /* more than 3 type is available? */ if (event->xclient.data.l[1] & 0x01) { Atom act_type; int act_format; unsigned long nitems, left; Atom *dat; int result; set_badwin_handler(1); result = XGetWindowProperty(win->disp->display, event->xclient.data.l[0], XInternAtom(win->disp->display, "XdndTypeList", False), 0L, 1024L, False, XA_ATOM, &act_type, &act_format, &nitems, &left, (u_char **)(&dat)); set_badwin_handler(0); if (result != Success) return FAILURE; if (act_type != None) { to_wait = choose_atom(win, dat, nitems); } else { to_wait = None; } XFree(dat); } else { /* less than 3 candidates */ to_wait = choose_atom(win, (Atom *)(event->xclient.data.l + 2), 3); } if (!(to_wait)) { finalize_context(win); return FAILURE; } if (!win->dnd && !(win->dnd = calloc(1, sizeof(ui_dnd_context_t)))) { return FAILURE; } win->dnd->source = event->xclient.data.l[0]; win->dnd->waiting_atom = to_wait; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "choosed atom:%d on %p\n", to_wait, win->dnd); #endif return SUCCESS; } static int position(ui_window_t *win, XEvent *event) { if (!(win->dnd)) return FAILURE; if (win->dnd->source != event->xclient.data.l[0]) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "WID mismatched.\n"); #endif finalize_context(win); return FAILURE; } win->dnd->action = event->xclient.data.l[4]; reply(win); return SUCCESS; } static int drop(ui_window_t *win, XEvent *event) { if (!(win->dnd)) return FAILURE; if (win->dnd->source != event->xclient.data.l[0]) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "WID mismatched.\n"); #endif finalize_context(win); return FAILURE; } /* data request */ set_badwin_handler(1); XConvertSelection(win->disp->display, XInternAtom(win->disp->display, "XdndSelection", False), win->dnd->waiting_atom, /* mime type */ XA_DND_STORE(win->disp->display), win->my_window, event->xclient.data.l[2]); set_badwin_handler(0); return SUCCESS; } static int incr(ui_window_t *win, XEvent *event) { u_long bytes_after; XTextProperty ct; int result; if (!(win->dnd)) return FAILURE; /* remember that it's an incremental transfer */ win->dnd->is_incr = 1; /* dummy read to determine data length */ set_badwin_handler(1); result = XGetWindowProperty(win->disp->display, event->xproperty.window, event->xproperty.atom, 0, 0, False, AnyPropertyType, &ct.encoding, &ct.format, &ct.nitems, &bytes_after, &ct.value); set_badwin_handler(0); if (result != Success) return FAILURE; /* ignore when ct.encoding != XA_INCR */ if (ct.encoding != XA_INCR(win->disp->display)) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "ignored.\n"); #endif if (ct.value) XFree(ct.value); return FAILURE; } set_badwin_handler(1); result = XGetWindowProperty(win->disp->display, event->xproperty.window, event->xproperty.atom, 0, bytes_after, False, AnyPropertyType, &ct.encoding, &ct.format, &ct.nitems, &bytes_after, &ct.value); set_badwin_handler(0); if (result != Success) return FAILURE; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "INCR: %d\n", ct.nitems); #endif /* * (man XGetWindowProperty) * XGetWindowProperty always allocates one extra byte in prop_return (even * if the property is zero length) and sets it to zero so that simple * properties consisting of characters do not have to be copied into yet * another string before use. */ parse(win, ct.value, ct.nitems); if (ct.nitems == 0) { /* all data have been received */ #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "terminating.\n"); #endif finish(win); finalize_context(win); } if (ct.value) XFree(ct.value); /* This delete will trigger the next update*/ set_badwin_handler(1); XDeleteProperty(win->disp->display, event->xproperty.window, event->xproperty.atom); set_badwin_handler(0); return SUCCESS; } static int selection(ui_window_t *win, XEvent *event) { u_long bytes_after; XTextProperty ct; int seg = 0; int result; if (!(win->dnd)) return FAILURE; /* dummy read to determine data length */ set_badwin_handler(1); result = XGetWindowProperty(win->disp->display, event->xselection.requestor, event->xselection.property, 0, 0, False, AnyPropertyType, &ct.encoding, &ct.format, &ct.nitems, &bytes_after, &ct.value); set_badwin_handler(0); if (result != Success) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "couldn't get property. \n"); #endif finalize_context(win); return FAILURE; } if (ct.value) XFree(ct.value); if (ct.encoding == XA_INCR(win->disp->display)) return SUCCESS; while (bytes_after > 0) { set_badwin_handler(1); result = XGetWindowProperty(win->disp->display, event->xselection.requestor, event->xselection.property, seg / 4, 4096, False, AnyPropertyType, &ct.encoding, &ct.format, &ct.nitems, &bytes_after, &ct.value); set_badwin_handler(0); if (result != Success) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "couldn't get property. \n"); #endif finalize_context(win); return FAILURE; } parse(win, ct.value, ct.nitems); XFree(ct.value); seg += ct.nitems; } finish(win); finalize_context(win); return SUCCESS; } /*****************************************************************************/ /* XFilterEvent(event, w) analogue */ /* return 0 if the event should be processed in the mlterm mail loop */ /* return 1 if nothing to be done is left for the event */ int ui_dnd_filter_event(XEvent *event, ui_window_t *win) { BL_TESTIT_ONCE(dnd, (win->disp)); switch (event->type) { /* case CreateNotify:*/ case MapNotify: /* CreateNotifyEvent seems to be lost somewhere... */ awareness(win, 5); return 0; case SelectionNotify: if (event->xselection.property != XA_DND_STORE(win->disp->display)) return 0; selection(win, event); set_badwin_handler(1); XDeleteProperty(win->disp->display, event->xselection.requestor, event->xselection.property); set_badwin_handler(0); break; case ClientMessage: if (event->xclient.message_type == XInternAtom(win->disp->display, "XdndEnter", False)) { enter(win, event); } else if (event->xclient.message_type == XInternAtom(win->disp->display, "XdndPosition", False)) { position(win, event); } else if (event->xclient.message_type == XInternAtom(win->disp->display, "XdndDrop", False)) { drop(win, event); } else if (event->xclient.data.l[0] == (XInternAtom(win->disp->display, "WM_DELETE_WINDOW", False))) { finalize_context(win); /* the event should also be processed in main loop */ return 0; } else { return 0; } break; case PropertyNotify: if (event->xproperty.atom != XA_DND_STORE(win->disp->display)) return 0; if (event->xproperty.state == PropertyDelete) { /* ignore delete notify */ return 1; } incr(win, event); break; case DestroyNotify: finalize_context(win); return 0; default: return 0; } /* the event was processed. mlterm main loop don't have to know about it*/ return 1; } #ifdef BL_DEBUG #include static void TEST_parse_text_uri_list_utf_selection_notified(ui_window_t *win, u_char *data, size_t len) { static int count; u_char *urls[] = { "http://hoge.com/foo.bar", "http://abcdefg", "/hijklmn", }; data[len] = '\0'; assert(strcmp(urls[count], data) == 0); count++; } static void TEST_parse_text_uri_list(ui_display_t *disp) { ui_window_t win; ui_dnd_context_t dnd; u_char *urls[] = { "http://hoge.com/foo.bar", "http://abcdefg\r\nfile:///hijklmn", }; u_char buf[100]; int count; memset(&win, 0, sizeof(win)); /* disp is used for XInternAtom(win->disp->display, "XdndActionMove", False) */ win.disp = disp; win.utf_selection_notified = TEST_parse_text_uri_list_utf_selection_notified; memset(&dnd, 0, sizeof(dnd)); win.dnd = &dnd; for (count = 0; count < sizeof(urls) / sizeof(urls[0]); count++) { strcpy(buf, urls[count]); parse_text_uri_list(&win, buf, strlen(urls[count])); } } static void TEST_dnd(ui_display_t *disp) { TEST_parse_text_uri_list(disp); bl_msg_printf("PASS X DnD test.\n"); } #endif #endif /* DISABLE_XDND */ mlterm-3.8.9/uitoolkit/xlib/ui_font.c010064400017600000144000001055741356600660700163460ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_font.h" #include #include /* bl_snprintf */ #include /* alloca */ #include /* bl_str_sep/bl_str_to_int/memset/strncasecmp */ #include /* DIGIT_STR_LEN */ #include /* bl_get_lang() */ #include #include #include /* vt_is_msb_set */ #include "ui_type_loader.h" #include "ui_decsp_font.h" #define FOREACH_FONT_ENCODINGS(csinfo, font_encoding_p) \ for ((font_encoding_p) = (csinfo)->encoding_names; \ (font_encoding_p) < \ (csinfo)->encoding_names + \ sizeof((csinfo)->encoding_names) / sizeof((csinfo)->encoding_names[0]) && \ *(font_encoding_p); \ (font_encoding_p)++) #define DIVIDE_ROUNDING(a, b) (((int)((a)*10 + (b)*5)) / ((int)((b)*10))) #define DIVIDE_ROUNDINGUP(a, b) (((int)((a)*10 + (b)*10 - 1)) / ((int)((b)*10))) #if 0 #define __DEBUG #endif typedef struct cs_info { ef_charset_t cs; /* default encodings. */ char *encoding_names[2]; } cs_info_t; /* --- static variables --- */ /* * If this table is changed, ui_font_config.c:cs_table and * mc_font.c:cs_info_table * shoule be also changed. */ static cs_info_t cs_info_table[] = { { ISO10646_UCS4_1, { "iso10646-1", NULL, }, }, { DEC_SPECIAL, { "iso8859-1", NULL, }, }, { ISO8859_1_R, { "iso8859-1", NULL, }, }, { ISO8859_2_R, { "iso8859-2", NULL, }, }, { ISO8859_3_R, { "iso8859-3", NULL, }, }, { ISO8859_4_R, { "iso8859-4", NULL, }, }, { ISO8859_5_R, { "iso8859-5", NULL, }, }, { ISO8859_6_R, { "iso8859-6", NULL, }, }, { ISO8859_7_R, { "iso8859-7", NULL, }, }, { ISO8859_8_R, { "iso8859-8", NULL, }, }, { ISO8859_9_R, { "iso8859-9", NULL, }, }, { ISO8859_10_R, { "iso8859-10", NULL, }, }, { TIS620_2533, { "tis620.2533-1", "tis620.2529-1", }, }, { ISO8859_13_R, { "iso8859-13", NULL, }, }, { ISO8859_14_R, { "iso8859-14", NULL, }, }, { ISO8859_15_R, { "iso8859-15", NULL, }, }, { ISO8859_16_R, { "iso8859-16", NULL, }, }, /* * XXX * The encoding of TCVN font is iso8859-1, and its font family is .VnTime or * .VnTimeH... How to deal with it ? */ { TCVN5712_3_1993, { NULL, NULL, }, }, { ISCII_ASSAMESE, { NULL, NULL, }, }, { ISCII_BENGALI, { NULL, NULL, }, }, { ISCII_GUJARATI, { NULL, NULL, }, }, { ISCII_HINDI, { NULL, NULL, }, }, { ISCII_KANNADA, { NULL, NULL, }, }, { ISCII_MALAYALAM, { NULL, NULL, }, }, { ISCII_ORIYA, { NULL, NULL, }, }, { ISCII_PUNJABI, { NULL, NULL, }, }, { ISCII_TAMIL, { NULL, NULL, }, }, { ISCII_TELUGU, { NULL, NULL, }, }, { VISCII, { "viscii-1", NULL, }, }, { KOI8_R, { "koi8-r", NULL, }, }, { KOI8_U, { "koi8-u", NULL, }, }, #if 0 /* * XXX * KOI8_T, GEORGIAN_PS and CP125X charset can be shown by unicode font only. */ { KOI8_T, { NULL, NULL, }, }, { GEORGIAN_PS, { NULL, NULL, }, }, { CP1250, { NULL, NULL, }, }, { CP1251, { NULL, NULL, }, }, { CP1252, { NULL, NULL, }, }, { CP1253, { NULL, NULL, }, }, { CP1254, { NULL, NULL, }, }, { CP1255, { NULL, NULL, }, }, { CP1256, { NULL, NULL, }, }, { CP1257, { NULL, NULL, }, }, { CP1258, { NULL, NULL, }, }, { CP874, { NULL, NULL, }, }, #endif { JISX0201_KATA, { "jisx0201.1976-0", NULL, }, }, { JISX0201_ROMAN, { "jisx0201.1976-0", NULL, }, }, { JISC6226_1978, { "jisx0208.1978-0", "jisx0208.1983-0", }, }, { JISX0208_1983, { "jisx0208.1983-0", "jisx0208.1990-0", }, }, { JISX0208_1990, { "jisx0208.1990-0", "jisx0208.1983-0", }, }, { JISX0212_1990, { "jisx0212.1990-0", NULL, }, }, { JISX0213_2000_1, { "jisx0213.2000-1", "jisx0208.1983-0", }, }, { JISX0213_2000_2, { "jisx0213.2000-2", NULL, }, }, { KSC5601_1987, { "ksc5601.1987-0", "ksx1001.1997-0", }, }, #if 0 /* * XXX * UHC and JOHAB fonts are not used at the present time. * see vt_vt100_parser.c:vt_parse_vt100_sequence(). */ { UHC, { NULL, NULL, }, }, { JOHAB, { "johabsh-1", /* "johabs-1" , */ "johab-1", }, }, #endif { GB2312_80, { "gb2312.1980-0", NULL, }, }, { GBK, { "gbk-0", NULL, }, }, { BIG5, { "big5.eten-0", "big5.hku-0", }, }, { HKSCS, { "big5hkscs-0", "big5-0", }, }, { CNS11643_1992_1, { "cns11643.1992-1", "cns11643.1992.1-0", }, }, { CNS11643_1992_2, { "cns11643.1992-2", "cns11643.1992.2-0", }, }, { CNS11643_1992_3, { "cns11643.1992-3", "cns11643.1992.3-0", }, }, { CNS11643_1992_4, { "cns11643.1992-4", "cns11643.1992.4-0", }, }, { CNS11643_1992_5, { "cns11643.1992-5", "cns11643.1992.5-0", }, }, { CNS11643_1992_6, { "cns11643.1992-6", "cns11643.1992.6-0", }, }, { CNS11643_1992_7, { "cns11643.1992-7", "cns11643.1992.7-0", }, }, }; static int compose_dec_special_font; static int use_point_size_for_fc; static double dpi_for_fc; /* --- static functions --- */ static cs_info_t *get_cs_info(ef_charset_t cs) { int count; for (count = 0; count < sizeof(cs_info_table) / sizeof(cs_info_t); count++) { if (cs_info_table[count].cs == cs) { return &cs_info_table[count]; } } #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " not supported cs(%x).\n", cs); #endif return NULL; } #if !defined(NO_DYNAMIC_LOAD_TYPE) static void xft_unset_font(ui_font_t *font) { void (*func)(ui_font_t *); if (!(func = ui_load_type_xft_func(UI_UNSET_FONT))) { return; } (*func)(font); } #elif defined(USE_TYPE_XFT) void xft_unset_font(ui_font_t *font); #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) static void cairo_unset_font(ui_font_t *font) { void (*func)(ui_font_t *); if (!(func = ui_load_type_cairo_func(UI_UNSET_FONT))) { return; } (*func)(font); } #elif defined(USE_TYPE_CAIRO) void cairo_unset_font(ui_font_t *font); #endif static int set_decsp_font(ui_font_t *font) { /* * freeing font->xfont or font->xft_font */ #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) if (font->xft_font) { xft_unset_font(font); } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if (font->cairo_font) { cairo_unset_font(font); } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) if (font->xfont) { XFreeFont(font->display, font->xfont); font->xfont = NULL; } #endif if ((font->decsp_font = ui_decsp_font_new(font->display, font->width, font->height, font->ascent)) == NULL) { return 0; } /* decsp_font is impossible to draw double with. */ font->double_draw_gap = 0; /* decsp_font is always fixed pitch. */ font->is_proportional = 0; return 1; } #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) static u_int xcore_calculate_char_width(Display *display, XFontStruct *xfont, u_int32_t ch) { int width; if (ch < 0x100) { u_char c; c = ch; width = XTextWidth(xfont, &c, 1); } else { XChar2b c[2]; width = XTextWidth16(xfont, c, ui_convert_ucs4_to_utf16(c, ch) / 2); } if (width < 0) { /* Some (indic) fonts could return minus value as text width. */ return 0; } else { return width; } } static int parse_xfont_name(char **font_xlfd, char **percent, /* NULL can be returned. */ char *font_name /* Don't specify NULL. Broken in this function */ ) { /* * XFont format. * [Font XLFD](:[Percentage]) */ /* bl_str_sep() never returns NULL because font_name isn't NULL. */ *font_xlfd = bl_str_sep(&font_name, ":"); /* may be NULL */ *percent = font_name; return 1; } static XFontStruct *load_xfont_intern(Display *display, char *fontname, size_t max_len, const char *family, const char *weight, const char *slant, const char *width, const char *additional, u_int fontsize, const char *spacing, const char *encoding) { bl_snprintf(fontname, max_len, "-*-%s-%s-%s-%s-%s-%d-*-*-*-%s-*-%s", family, weight, slant, width, additional, fontsize, spacing, encoding); #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " loading %s.\n", fontname); #endif return XLoadQueryFont(display, fontname); } static XFontStruct *load_xfont(Display *display, const char *family, const char *weight, const char *slant, const char *width, u_int fontsize, const char *spacing, const char *encoding) { XFontStruct *xfont; char *fontname; size_t max_len; /* "+ 19" means the num of '-' , '*'(18byte) and null chars. */ max_len = strlen(family) + 7 /* unifont */ + strlen(weight) + strlen(slant) + strlen(width) + 2 /* lang */ + DIGIT_STR_LEN(fontsize) + strlen(spacing) + strlen(encoding) + 19; if ((fontname = alloca(max_len)) == NULL) { return NULL; } if ((xfont = load_xfont_intern(display, fontname, max_len, family, weight, slant, width, "*", fontsize, spacing, encoding))) { return xfont; } if (strcmp(encoding, "iso10646-1") == 0 && strcmp(family, "biwidth") == 0) { /* XFree86 Unicode font */ if ((xfont = load_xfont_intern(display, fontname, max_len, "*", weight, slant, width, bl_get_lang(), fontsize, spacing, encoding))) { return xfont; } if (strcmp(bl_get_lang(), "ja") != 0 && (xfont = load_xfont_intern(display, fontname, max_len, "*", weight, slant, width, "ja", fontsize, spacing, encoding))) { return xfont; } /* GNU Unifont (-gnu-unifont) */ return load_xfont_intern(display, fontname, max_len, "unifont", weight, slant, width, "*", fontsize, spacing, encoding); } return NULL; } static int xcore_set_font(ui_font_t *font, const char *fontname, u_int fontsize, u_int col_width, /* if usascii font wants to be set , 0 will be set */ int use_medium_for_bold, u_int letter_space) { XFontStruct *xfont; u_int cols; char *weight; char *slant; char *width; char *family; cs_info_t *csinfo; char **font_encoding_p; u_int percent; int count; int num_spacings; char *spacings[] = {"c", "m", "p"}; if ((csinfo = get_cs_info(FONT_CS(font->id))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " get_cs_info(cs %x(id %x)) failed.\n", FONT_CS(font->id), font->id); #endif return 0; } if (fontname) { char *p; char *font_xlfd; char *percent_str; if ((p = alloca(strlen(fontname) + 1)) == NULL) { return 0; } strcpy(p, fontname); if (parse_xfont_name(&font_xlfd, &percent_str, p)) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " loading %s font (%s percent).\n", font_xlfd, percent_str); #endif while (1) { if (!(xfont = XLoadQueryFont(font->display, font_xlfd))) { char *xlfd; if ((xlfd = bl_str_replace(font_xlfd, "-bold-", "-medium-"))) { xfont = XLoadQueryFont(font->display, xlfd); free(xlfd); } if (!xfont) { bl_msg_printf("Font %s couldn't be loaded.\n", font_xlfd); break; } font->double_draw_gap = 1; } else { font->double_draw_gap = use_medium_for_bold; } if (percent_str == NULL || !bl_str_to_uint(&percent, percent_str)) { percent = 0; } goto font_found; } } } /* * searching apropriate font by using font info. */ #ifdef __DEBUG bl_debug_printf("font for id %x will be loaded.\n", font->id); #endif font->double_draw_gap = 0; percent = 0; if (font->id & FONT_BOLD) { weight = "bold"; } else { weight = "medium"; } if (font->id & FONT_ITALIC) { slant = "i"; } else { slant = "r"; } width = "normal"; if ((font->id & FONT_FULLWIDTH) && (FONT_CS(font->id) == ISO10646_UCS4_1)) { family = "biwidth"; num_spacings = sizeof(spacings) / sizeof(spacings[0]); } else { family = "fixed"; num_spacings = 1; } for (count = 0; ; count++) { FOREACH_FONT_ENCODINGS(csinfo, font_encoding_p) { int idx; for (idx = 0; idx < num_spacings; idx++) { if ((xfont = load_xfont(font->display, family, weight, slant, width, fontsize, spacings[idx], *font_encoding_p))) { goto font_found; } } } if (count == 0) { width = "*"; family = "*"; num_spacings = sizeof(spacings) / sizeof(spacings[0]); } else if (count == 1) { slant = "*"; } else if (count == 2) { weight = "*"; if (font->id & FONT_BOLD) { /* no bold font is found. */ font->double_draw_gap = 1; } } else { break; } } return 0; font_found: font->xfont = xfont; font->height = xfont->ascent + xfont->descent; font->ascent = xfont->ascent; /* * calculating actual font glyph width. */ font->is_proportional = 0; font->width = xfont->max_bounds.width; if (xfont->max_bounds.width != xfont->min_bounds.width) { if (FONT_CS(font->id) == ISO10646_UCS4_1 || FONT_CS(font->id) == TIS620_2533) { if (font->id & FONT_FULLWIDTH) { /* * XXX * At the present time , all full width unicode fonts * (which may include both half width and full width * glyphs) are regarded as fixed. * Since I don't know what chars to be compared to * determine font proportion and width. */ } else { /* * XXX * A font including combining (0-width) glyphs or both half and * full width glyphs. * In this case , whether the font is proportional or not * cannot be determined by comparing min_bounds and max_bounds, * so if `i' and `W' chars have different width , the font is * regarded as proportional (and `W' width is used as font->width). */ u_int w_width; u_int i_width; if ((w_width = xcore_calculate_char_width(font->display, font->xfont, 'W')) == 0) { font->is_proportional = 1; } else if ((i_width = xcore_calculate_char_width(font->display, font->xfont, 'i')) == 0 || w_width != i_width) { font->is_proportional = 1; font->width = w_width; } else { font->width = w_width; } } } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " max font width(%d) and min one(%d) are mismatched.\n", xfont->max_bounds.width, xfont->min_bounds.width); #endif font->is_proportional = 1; } } font->x_off = 0; if (font->id & FONT_FULLWIDTH) { cols = 2; } else { cols = 1; } if (col_width == 0) { /* standard(usascii) font */ if (percent > 0) { u_int ch_width; if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ ch_width = DIVIDE_ROUNDING(fontsize * percent, 100); } else { ch_width = DIVIDE_ROUNDING(fontsize * percent, 200); } if (font->width != ch_width) { font->is_proportional = 1; if (!font->is_var_col_width && font->width < ch_width) { /* * If width(2) of '1' doesn't match ch_width(4) * x_off = (4-2)/2 = 1. * It means that starting position of drawing '1' is 1 * as follows. * * 0123 * +----+ * | ** | * | * | * | * | * +----+ */ font->x_off = (ch_width - font->width) / 2; } font->width = ch_width; } } else if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ font->is_proportional = 1; font->x_off = font->width / 2; font->width *= 2; } /* letter_space is ignored in variable column width mode. */ if (!font->is_var_col_width && letter_space > 0) { font->is_proportional = 1; font->width += letter_space; font->x_off += (letter_space / 2); } } else { /* not a standard(usascii) font */ /* * XXX hack * forcibly conforming non standard font width to standard font width. */ if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ if (font->width != col_width) { bl_msg_printf( "Font(id %x) width(%d) is not matched with " "standard width(%d).\n", font->id, font->width, col_width); font->is_proportional = 1; /* is_var_col_width is always false if is_vertical is true. */ if (/* ! font->is_var_col_width && */ font->width < col_width) { font->x_off = (col_width - font->width) / 2; } font->width = col_width; } } else { if (font->width != col_width * cols) { bl_msg_printf( "Font(id %x) width(%d) is not matched with " "standard width(%d).\n", font->id, font->width, col_width * cols); font->is_proportional = 1; if (!font->is_var_col_width && font->width < col_width * cols) { font->x_off = (col_width * cols - font->width) / 2; } font->width = col_width * cols; } } } /* * checking if font width/height/ascent member is sane. */ if (font->width == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " font width is 0.\n"); #endif font->is_proportional = 1; /* XXX this may be inaccurate. */ font->width = DIVIDE_ROUNDINGUP(fontsize * cols, 2); } if (font->height == 0) { /* XXX this may be inaccurate. */ font->height = fontsize; } if (font->ascent == 0) { /* XXX this may be inaccurate. */ font->ascent = fontsize; } /* * set_decsp_font() is called after dummy font is loaded to get font metrics. * Since dummy font encoding is "iso8859-1", loading rarely fails. */ if (compose_dec_special_font && FONT_CS(font->id) == DEC_SPECIAL) { return set_decsp_font(font); } return 1; } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) static u_int xft_calculate_char_width(ui_font_t *font, u_int32_t ch /* US-ASCII or Unicode */ ) { int (*func)(ui_font_t *, u_int32_t); if (!(func = ui_load_type_xft_func(UI_CALCULATE_CHAR_WIDTH))) { return 0; } return (*func)(font, ch); } static int xft_set_font(ui_font_t *font, const char *fontname, u_int fontsize, u_int col_width, /* if usascii font wants to be set , 0 will be set. */ u_int letter_space, int aa_opt, /* 0 = default , 1 = enable , -1 = disable */ int use_point_size, double dpi) { int (*func)(ui_font_t *, const char *, u_int, u_int, u_int, int, int, double); if (!(func = ui_load_type_xft_func(UI_SET_FONT))) { return 0; } return (*func)(font, fontname, fontsize, col_width, letter_space, aa_opt, use_point_size, dpi); } static int xft_set_ot_font(ui_font_t *font) { int (*func)(ui_font_t *); if (!(func = ui_load_type_xft_func(UI_SET_OT_FONT))) { return 0; } return (*func)(font); } static u_int xft_convert_text_to_glyphs(ui_font_t *font, u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features) { int (*func)(ui_font_t *, u_int32_t *, u_int, int8_t *, u_int8_t *, u_int32_t *, u_int32_t *, u_int, const char *, const char *); if (!(func = ui_load_type_xft_func(UI_CONVERT_TEXT_TO_GLYPHS))) { return 0; } return (*func)(font, shaped, shaped_len, offsets, widths, cmapped, src, src_len, script, features); } #elif defined(USE_TYPE_XFT) u_int xft_calculate_char_width(ui_font_t *font, u_int32_t ch); int xft_set_font(ui_font_t *font, const char *fontname, u_int fontsize, u_int col_width, u_int letter_space, int aa_opt, int use_point_size, double dpi); int xft_set_ot_font(ui_font_t *font); #define xft_convert_text_to_glyphs(font, shaped, shaped_len, offsets, widths, cmapped, src, \ src_len, script, features) \ ft_convert_text_to_glyphs(font, shaped, shaped_len, offsets, widths, cmapped, src, src_len, \ script, features) u_int ft_convert_text_to_glyphs(ui_font_t *font, u_int32_t *shaped, int8_t *, u_int8_t *, u_int shaped_len, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features); #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) static u_int cairo_calculate_char_width(ui_font_t *font, u_int32_t ch /* US-ASCII or Unicode */ ) { int (*func)(ui_font_t *, u_int32_t); if (!(func = ui_load_type_cairo_func(UI_CALCULATE_CHAR_WIDTH))) { return 0; } return (*func)(font, ch); } static int cairo_set_font(ui_font_t *font, const char *fontname, u_int fontsize, u_int col_width, /* if usascii font wants to be set , 0 will be set. */ u_int letter_space, int aa_opt, /* 0 = default , 1 = enable , -1 = disable */ int use_point_size, double dpi) { int (*func)(ui_font_t *, const char *, u_int, u_int, u_int, int, int, double); if (!(func = ui_load_type_cairo_func(UI_SET_FONT))) { return 0; } return (*func)(font, fontname, fontsize, col_width, letter_space, aa_opt, use_point_size, dpi); } static int cairo_set_ot_font(ui_font_t *font) { int (*func)(ui_font_t *); if (!(func = ui_load_type_cairo_func(UI_SET_OT_FONT))) { return 0; } return (*func)(font); } static u_int cairo_convert_text_to_glyphs(ui_font_t *font, u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features) { int (*func)(ui_font_t *, u_int32_t *, u_int, int8_t *, u_int8_t *, u_int32_t *, u_int32_t *, u_int, const char *, const char *); if (!(func = ui_load_type_cairo_func(UI_CONVERT_TEXT_TO_GLYPHS))) { return 0; } return (*func)(font, shaped, shaped_len, offsets, widths, cmapped, src, src_len, script, features); } #elif defined(USE_TYPE_CAIRO) u_int cairo_calculate_char_width(ui_font_t *font, u_int32_t ch); int cairo_set_font(ui_font_t *font, const char *fontname, u_int fontsize, u_int col_width, u_int letter_space, int aa_opt, int use_point_size, double dpi); int cairo_set_ot_font(ui_font_t *font); #define cairo_convert_text_to_glyphs(font, shaped, shaped_len, offsets, widths, cmapped, src, \ src_len, script, features) \ ft_convert_text_to_glyphs(font, shaped, shaped_len, offsets, widths, cmapped, src, src_len, \ script, features) #ifndef USE_TYPE_XFT u_int ft_convert_text_to_glyphs(ui_font_t *font, u_int32_t *shaped, int8_t *offsets, u_int8_t *widths, u_int shaped_len, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features); #endif #endif static u_int calculate_char_width(ui_font_t *font, u_int32_t ch, ef_charset_t cs) { #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) if (font->xft_font) { if (cs != US_ASCII && !IS_ISCII(cs)) { if (!(ch = ui_convert_to_xft_ucs4(ch, cs))) { return 0; } } return xft_calculate_char_width(font, ch); } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if (font->cairo_font) { if (cs != US_ASCII && !IS_ISCII(cs)) { if (!(ch = ui_convert_to_xft_ucs4(ch, cs))) { return 0; } } return cairo_calculate_char_width(font, ch); } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) if (font->xfont) { return xcore_calculate_char_width(font->display, font->xfont, ch); } #endif #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " couldn't calculate correct font width.\n"); #endif return 0; } /* --- global functions --- */ void ui_compose_dec_special_font(void) { compose_dec_special_font = 1; } ui_font_t *ui_font_new( Display *display, vt_font_t id, int size_attr, ui_type_engine_t type_engine, ui_font_present_t font_present, /* FONT_VAR_WIDTH is never set if FONT_VERTICAL is set. */ const char *fontname, u_int fontsize, u_int col_width, int use_medium_for_bold, u_int letter_space /* ignored in variable column width mode. */ ) { ui_font_t *font; if ((font = calloc(1, sizeof(ui_font_t))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc() failed.\n"); #endif return NULL; } font->display = display; font->id = id; if (font_present & FONT_VAR_WIDTH) { font->is_var_col_width = 1; } else if (IS_ISCII(FONT_CS(font->id))) { /* * For exampe, 'W' width and 'l' width of OR-TTSarala font for ISCII_ORIYA * are the same by chance, though it is actually a proportional font. */ font->is_var_col_width = font->is_proportional = 1; } if (font_present & FONT_VERTICAL) { font->is_vertical = 1; } if (size_attr >= DOUBLE_HEIGHT_TOP) { fontsize *= 2; col_width *= 2; } switch (type_engine) { default: return NULL; #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) case TYPE_XFT: if (!xft_set_font(font, fontname, fontsize, col_width, letter_space, (font_present & FONT_AA) == FONT_AA ? 1 : ((font_present & FONT_NOAA) == FONT_NOAA ? -1 : 0), use_point_size_for_fc, dpi_for_fc)) { free(font); return NULL; } break; #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) case TYPE_CAIRO: if (!cairo_set_font(font, fontname, fontsize, col_width, letter_space, (font_present & FONT_AA) == FONT_AA ? 1 : ((font_present & FONT_NOAA) == FONT_NOAA ? -1 : 0), use_point_size_for_fc, dpi_for_fc)) { free(font); return NULL; } break; #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) case TYPE_XCORE: if (font_present & FONT_AA) { return NULL; } else if (!xcore_set_font(font, fontname, fontsize, col_width, use_medium_for_bold, letter_space)) { if (size_attr >= DOUBLE_HEIGHT_TOP && xcore_set_font(font, fontname, fontsize / 2, col_width, use_medium_for_bold, letter_space)) { goto end; } free(font); return NULL; } goto end; #endif } /* * set_decsp_font() is called after dummy xft/cairo font is loaded to get font * metrics. * Since dummy font encoding is "iso8859-1", loading rarely fails. */ /* XXX dec specials must always be composed for now */ if (/* compose_dec_special_font && */ FONT_CS(font->id) == DEC_SPECIAL) { set_decsp_font(font); } #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) end: #endif if (size_attr == DOUBLE_WIDTH) { if (type_engine == TYPE_CAIRO) { font->x_off *= 2; } else { font->x_off += (font->width / 2); font->is_proportional = 1; font->is_var_col_width = 0; } font->width *= 2; } font->size_attr = size_attr; if (font->is_proportional && !font->is_var_col_width) { bl_msg_printf("Characters (cs %x) are drawn *one by one* to arrange column width.\n", FONT_CS(font->id)); } #ifdef DEBUG ui_font_dump(font); #endif return font; } void ui_font_destroy(ui_font_t *font) { #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) if (font->xft_font) { xft_unset_font(font); } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if (font->cairo_font) { cairo_unset_font(font); } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) if (font->xfont) { XFreeFont(font->display, font->xfont); font->xfont = NULL; } #endif if (font->decsp_font) { ui_decsp_font_destroy(font->decsp_font, font->display); font->decsp_font = NULL; } free(font); } u_int ui_calculate_char_width(ui_font_t *font, u_int32_t ch, ef_charset_t cs, int *draw_alone) { if (draw_alone) { *draw_alone = 0; } if (font->is_proportional) { if (font->is_var_col_width) { /* Returned value can be 0 if iscii font is used. */ return calculate_char_width(font, ch, cs); } if (draw_alone) { *draw_alone = 1; } } else if (draw_alone && cs == ISO10646_UCS4_1 /* ISO10646_UCS4_1_V is always proportional */ #ifdef USE_OT_LAYOUT && (!font->use_ot_layout /* || ! font->ot_font */) #endif ) { if (((ef_get_ucs_property(ch) & EF_AWIDTH) || /* * The width of U+2590 and U+2591 is narrow in EastAsianWidth-6.3.0 * but the glyphs in GNU Unifont are full-width unexpectedly. */ ch == 0x2590 || ch == 0x2591)) { if (calculate_char_width(font, ch, cs) != font->width) { *draw_alone = 1; } } } return font->width; } char **ui_font_get_encoding_names(ef_charset_t cs) { cs_info_t *info; if ((info = get_cs_info(cs))) { return info->encoding_names; } else { return NULL; } } void ui_font_use_point_size(int use) { use_point_size_for_fc = use; } int ui_font_has_ot_layout_table(ui_font_t *font) { #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if (font->cairo_font) { #ifdef USE_OT_LAYOUT if (!font->ot_font) { if (font->ot_font_not_found) { return 0; } if (!cairo_set_ot_font(font)) { font->ot_font_not_found = 1; return 0; } } #endif return 1; } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) if (font->xft_font) { #ifdef USE_OT_LAYOUT if (!font->ot_font) { if (font->ot_font_not_found) { return 0; } if (!xft_set_ot_font(font)) { font->ot_font_not_found = 1; return 0; } } #endif return 1; } #endif return 0; } u_int ui_convert_text_to_glyphs(ui_font_t *font, /* always has ot_font */ u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features) { #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if (font->cairo_font) { return cairo_convert_text_to_glyphs(font, shaped, shaped_len, offsets, widths, cmapped, src, src_len, script, features); } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) if (font->xft_font) { return xft_convert_text_to_glyphs(font, shaped, shaped_len, offsets, widths, cmapped, src, src_len, script, features); } #endif return 0; } /* For mlterm-libvte */ void ui_font_set_dpi_for_fc(double dpi) { dpi_for_fc = dpi; } #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO) static int use_cp932_ucs_for_xft = 0; static u_int32_t convert_to_ucs4(u_int32_t ch, ef_charset_t cs) { if (IS_ISO10646_UCS4(cs) /* || cs == ISO10646_UCS2_1 */) { return ch; } else { ef_char_t non_ucs; ef_char_t ucs4; non_ucs.size = CS_SIZE(cs); non_ucs.property = 0; non_ucs.cs = cs; ef_int_to_bytes(non_ucs.ch, non_ucs.size, ch); if (vt_is_msb_set(cs)) { u_int count; for (count = 0; count < non_ucs.size; count++) { non_ucs.ch[count] &= 0x7f; } } if (ef_map_to_ucs4(&ucs4, &non_ucs)) { return ef_char_to_int(&ucs4); } else { return 0; } } } void ui_use_cp932_ucs_for_xft(void) { use_cp932_ucs_for_xft = 1; } /* * used only for xft or cairo. */ u_int32_t ui_convert_to_xft_ucs4(u_int32_t ch, ef_charset_t cs /* US_ASCII and ISO8859_1_R is not accepted */ ) { if (cs == US_ASCII || cs == ISO8859_1_R) { return 0; } else if (use_cp932_ucs_for_xft && cs == JISX0208_1983) { if (ch == 0x2140) { return 0xff3c; } else if (ch == 0x2141) { return 0xff5e; } else if (ch == 0x2142) { return 0x2225; } else if (ch == 0x215d) { return 0xff0d; } else if (ch == 0x2171) { return 0xffe0; } else if (ch == 0x2172) { return 0xffe1; } else if (ch == 0x224c) { return 0xffe2; } } return convert_to_ucs4(ch, cs); } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) /* Return written size */ size_t ui_convert_ucs4_to_utf16(u_char *dst, /* 4 bytes. Big endian. */ u_int32_t src) { #if 0 bl_debug_printf(BL_DEBUG_TAG "%.8x => ", src); #endif if (src < 0x10000) { dst[0] = (src >> 8) & 0xff; dst[1] = src & 0xff; return 2; } else if (src < 0x110000) { /* surrogate pair */ u_char c; src -= 0x10000; c = (u_char)(src / (0x100 * 0x400)); src -= (c * 0x100 * 0x400); dst[0] = c + 0xd8; c = (u_char)(src / 0x400); src -= (c * 0x400); dst[1] = c; c = (u_char)(src / 0x100); src -= (c * 0x100); dst[2] = c + 0xdc; dst[3] = (u_char)src; #if 0 bl_msg_printf("%.2x%.2x%.2x%.2x\n", dst[0], dst[1], dst[2], dst[3]); #endif return 4; } return 0; } #endif #ifdef DEBUG void ui_font_dump(ui_font_t *font) { #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) bl_msg_printf("Font id %x: XFont %p ", font->id, font->xfont); #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) bl_msg_printf("Font id %x: XftFont %p ", font->id, font->xft_font); #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) bl_msg_printf("Font id %x: CairoFont %p ", font->id, font->cairo_font); #endif bl_msg_printf("(width %d, height %d, ascent %d, x_off %d, gap %d)", font->width, font->height, font->ascent, font->x_off, font->double_draw_gap); if (font->is_proportional) { bl_msg_printf(" (proportional)"); } if (font->is_var_col_width) { bl_msg_printf(" (var col width)"); } if (font->is_vertical) { bl_msg_printf(" (vertical)"); } if (font->double_draw_gap) { bl_msg_printf(" (double drawing)"); } bl_msg_printf("\n"); } #endif mlterm-3.8.9/uitoolkit/xlib/ui_gc.c010064400017600000144000000041121356600660700157530ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_gc.h" #include /* malloc */ #include "../ui_color.h" /* --- global functions --- */ ui_gc_t *ui_gc_new(Display *display, Drawable drawable) { ui_gc_t *gc; XGCValues gc_value; if ((gc = calloc(1, sizeof(ui_gc_t))) == NULL) { return NULL; } gc->display = display; if (drawable) { /* Default value of GC. */ gc->fg_color = 0xff000000; gc->bg_color = 0xffffffff; /* Overwriting default value (1) of backgrond and foreground colors. */ gc_value.foreground = gc->fg_color; gc_value.background = gc->bg_color; gc_value.graphics_exposures = True; gc->gc = XCreateGC(gc->display, drawable, GCForeground | GCBackground | GCGraphicsExposures, &gc_value); } else { gc->gc = DefaultGC(display, DefaultScreen(display)); XGetGCValues(display, gc->gc, GCForeground | GCBackground, &gc_value); gc->fg_color = gc_value.foreground; gc->bg_color = gc_value.background; } return gc; } void ui_gc_destroy(ui_gc_t *gc) { if ((gc->gc != DefaultGC(gc->display, DefaultScreen(gc->display)))) { XFreeGC(gc->display, gc->gc); } free(gc); } void ui_gc_set_fg_color(ui_gc_t *gc, u_long fg_color) { /* Cooperate with ui_window_copy_area(). */ if (gc->mask) { XSetClipMask(gc->display, gc->gc, None); gc->mask = None; } if (fg_color != gc->fg_color) { XSetForeground(gc->display, gc->gc, fg_color); gc->fg_color = fg_color; } } void ui_gc_set_bg_color(ui_gc_t *gc, u_long bg_color) { /* Cooperate with ui_window_copy_area(). */ if (gc->mask) { XSetClipMask(gc->display, gc->gc, None); gc->mask = None; } if (bg_color != gc->bg_color) { XSetBackground(gc->display, gc->gc, bg_color); gc->bg_color = bg_color; } } void ui_gc_set_fid(ui_gc_t *gc, Font fid) { /* XXX Lazy skip (maybe harmless) */ #if 0 if (gc->mask) { XSetClipMask(gc->display, gc->gc, None); gc->mask = None; } #endif if (gc->fid != fid) { XSetFont(gc->display, gc->gc, fid); gc->fid = fid; } } mlterm-3.8.9/uitoolkit/xlib/ui_imagelib.c010064400017600000144000001270561356600660700171500ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ /** @file * @brief image handling functions using gdk-pixbuf */ #ifndef NO_IMAGE #include "../ui_imagelib.h" /* * might not include internally in some environments * (e.g. open window in Solaris 2.6), so is necessary. * SF Bug 350944. */ #include #include /* XInternAtom */ #include #include /* memcpy */ #include /* sscanf */ #ifdef BUILTIN_IMAGELIB #include #endif /* BUILTIN_IMAGELIB */ #ifdef DLOPEN_LIBM #include /* dynamically loading pow */ #else #include /* pow */ #endif #include #include /* u_int32_t/u_int16_t */ #include /* SSIZE_MAX */ #include #include /* strdup */ #include /* DIGIT_STR_LEN */ #include #include /* BL_LIBEXECDIR */ #include "ui_display.h" /* ui_display_get_visual_info */ /* * 'data' which is malloc'ed for XCreateImage() in pixbuf_to_ximage_truecolor() * is free'ed in XDestroyImage(). */ #ifdef BL_DEBUG static void destroy_image(XImage *image) { bl_mem_remove(image->data, __FILE__, __LINE__, __FUNCTION__); XDestroyImage(image); } #undef XDestroyImage #define XDestroyImage(image) destroy_image(image) #endif #if 1 #define USE_FS #endif #if 0 #define ENABLE_CARD2PIXBUF #endif #if (GDK_PIXBUF_MAJOR < 2) #define g_object_ref(pixbuf) gdk_pixbuf_ref(pixbuf) #define g_object_unref(pixbuf) gdk_pixbuf_unref(pixbuf) #endif /* Trailing "/" is appended in value_table_refresh(). */ #ifndef LIBMDIR #define LIBMDIR "/lib" #endif #if 0 #define __DEBUG #endif #define PIXEL_RED(pixel, rgbinfo) \ ((((pixel) & (rgbinfo).r_mask) >> (rgbinfo).r_offset) << (rgbinfo).r_limit) #define PIXEL_BLUE(pixel, rgbinfo) \ ((((pixel) & (rgbinfo).b_mask) >> (rgbinfo).b_offset) << (rgbinfo).b_limit) #define PIXEL_GREEN(pixel, rgbinfo) \ ((((pixel) & (rgbinfo).g_mask) >> (rgbinfo).g_offset) << (rgbinfo).g_limit) #define RGB_TO_PIXEL(r, g, b, rgbinfo) \ (((((r) >> (rgbinfo).r_limit) << (rgbinfo).r_offset) & (rgbinfo).r_mask) | \ ((((g) >> (rgbinfo).g_limit) << (rgbinfo).g_offset) & (rgbinfo).g_mask) | \ ((((b) >> (rgbinfo).b_limit) << (rgbinfo).b_offset) & (rgbinfo).b_mask)) #if 1 #define BUILTIN_SIXEL #endif typedef struct rgb_info { u_long r_mask; u_long g_mask; u_long b_mask; u_int r_limit; u_int g_limit; u_int b_limit; u_int r_offset; u_int g_offset; u_int b_offset; } rgb_info_t; /* --- static variables --- */ static int display_count = 0; /* --- static functions --- */ #include "../../common/c_imagelib.c" static Status get_drawable_size(Display *display, Drawable drawable, u_int *width, u_int *height) { Window root; int x; int y; u_int border; u_int depth; return XGetGeometry(display, drawable, &root, &x, &y, width, height, &border, &depth); } /* returned cmap shuold be freed by the caller */ static int fetch_colormap(ui_display_t *disp, XColor **color_list) { int num_cells, i; num_cells = disp->visual->map_entries; if ((*color_list = calloc(num_cells, sizeof(XColor))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG "couldn't allocate color table\n"); #endif return 0; } for (i = 0; i < num_cells; i++) { ((*color_list)[i]).pixel = i; } XQueryColors(disp->display, disp->colormap, *color_list, num_cells); return num_cells; } /* Get an background pixmap from _XROOTMAP_ID */ static Pixmap root_pixmap(ui_display_t *disp) { Atom id; int act_format; u_long nitems; u_long bytes_after; u_char *prop; Pixmap pixmap; if (!(id = XInternAtom(disp->display, "_XROOTPMAP_ID", False))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " _XROOTPMAP_ID atom is not available.\n"); #endif return None; } if (XGetWindowProperty(disp->display, disp->my_window, id, 0, 1, False, XA_PIXMAP, &id, &act_format, &nitems, &bytes_after, &prop) != Success || !prop) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " Failed to read prop\n"); #endif return None; } pixmap = *((Drawable *)prop); XFree(prop); return pixmap; } static void rgb_info_init(XVisualInfo *vinfo, rgb_info_t *rgb) { rgb->r_mask = vinfo->red_mask; rgb->g_mask = vinfo->green_mask; rgb->b_mask = vinfo->blue_mask; rgb->r_offset = lsb(rgb->r_mask); rgb->g_offset = lsb(rgb->g_mask); rgb->b_offset = lsb(rgb->b_mask); rgb->r_limit = 8 + rgb->r_offset - msb(rgb->r_mask); rgb->g_limit = 8 + rgb->g_offset - msb(rgb->g_mask); rgb->b_limit = 8 + rgb->b_offset - msb(rgb->b_mask); } static void value_table_refresh(u_char *value_table, /* 256 bytes */ ui_picture_modifier_t *mod) { int i, tmp; double real_gamma, real_brightness, real_contrast; static double (*pow_func)(double, double); real_gamma = (double)(mod->gamma) / 100; real_contrast = (double)(mod->contrast) / 100; real_brightness = (double)(mod->brightness) / 100; if (!pow_func) { #ifdef DLOPEN_LIBM bl_dl_handle_t handle; if ((!(handle = bl_dl_open(LIBMDIR "/", "m")) && !(handle = bl_dl_open("", "m"))) || !(pow_func = bl_dl_func_symbol(handle, "pow"))) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to load pow in " LIBMDIR "/libm.so\n"); #endif if (handle) { bl_dl_close(handle); } /* * gamma, contrast and brightness options are ignored. * (alpha option still survives.) */ for (i = 0; i < 256; i++) { value_table[i] = i; } return; } #else /* DLOPEN_LIBM */ pow_func = pow; #endif /* BUILTIN_IMAGELIB */ } for (i = 0; i < 256; i++) { tmp = real_contrast * (255 * (*pow_func)(((double)i + 0.5) / 255, real_gamma) - 128) + 128 * real_brightness; if (tmp >= 255) { break; } else if (tmp < 0) { value_table[i] = 0; } else { value_table[i] = tmp; } } for (; i < 256; i++) { value_table[i] = 255; } } static int modify_pixmap(ui_display_t *disp, Pixmap src_pixmap, Pixmap dst_pixmap /* Can be same as src_pixmap */, u_int width, u_int height, ui_picture_modifier_t *pic_mod /* Mustn't be normal */ ) { u_char value_table[256]; u_int x, y; XImage *image; u_char r, g, b; u_long pixel; if ((image = XGetImage(disp->display, src_pixmap, 0, 0, width, height, AllPlanes, ZPixmap)) == NULL) { return 0; } value_table_refresh(value_table, pic_mod); if (disp->visual->class == TrueColor) { XVisualInfo *vinfo; rgb_info_t rgbinfo; if (!(vinfo = ui_display_get_visual_info(disp))) { XDestroyImage(image); return 0; } rgb_info_init(vinfo, &rgbinfo); XFree(vinfo); for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixel = XGetPixel(image, x, y); r = PIXEL_RED(pixel, rgbinfo); g = PIXEL_GREEN(pixel, rgbinfo); b = PIXEL_BLUE(pixel, rgbinfo); r = (value_table[r] * (255 - pic_mod->alpha) + pic_mod->blend_red * pic_mod->alpha) / 255; g = (value_table[g] * (255 - pic_mod->alpha) + pic_mod->blend_green * pic_mod->alpha) / 255; b = (value_table[b] * (255 - pic_mod->alpha) + pic_mod->blend_blue * pic_mod->alpha) / 255; XPutPixel(image, x, y, RGB_TO_PIXEL(r, g, b, rgbinfo) | (disp->depth == 32 ? 0xff000000 : 0)); } } } else /* if( disp->visual->class == PseudoColor) */ { XColor *color_list; int num_cells; if ((num_cells = fetch_colormap(disp, &color_list)) == 0) { XDestroyImage(image); return 0; } for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { if ((pixel = XGetPixel(image, x, y)) >= num_cells) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Pixel %x is illegal.\n", pixel); #endif continue; } r = color_list[pixel].red >> 8; g = color_list[pixel].green >> 8; b = color_list[pixel].blue >> 8; r = (value_table[r] * (255 - pic_mod->alpha) + pic_mod->blend_red * pic_mod->alpha) / 255; g = (value_table[g] * (255 - pic_mod->alpha) + pic_mod->blend_green * pic_mod->alpha) / 255; b = (value_table[b] * (255 - pic_mod->alpha) + pic_mod->blend_blue * pic_mod->alpha) / 255; XPutPixel(image, x, y, closest_color_index(color_list, num_cells, r, g, b)); } } free(color_list); } XPutImage(disp->display, dst_pixmap, disp->gc->gc, image, 0, 0, 0, 0, width, height); XDestroyImage(image); return 1; } #if defined(BUILTIN_IMAGELIB) || defined(BUILTIN_SIXEL) #ifndef BUILTIN_IMAGELIB #define CARD_HEAD_SIZE 0 #include "../../common/c_sixel.c" #endif static int load_sixel(ui_display_t *disp, char *path, Pixmap *pixmap, Pixmap *mask, /* Can be NULL */ u_int *width, /* Can be NULL */ u_int *height /* Can be NULL */ ) { XImage *image; u_int32_t *data; u_int32_t *in; u_char *out; u_int w; u_int h; u_int x; u_int y; XVisualInfo *vinfo; rgb_info_t rgbinfo; int bytes_per_pixel; GC mask_gc; XGCValues gcv; if (disp->depth < 16 || !(data = in = out = load_sixel_from_file(path, &w, &h))) { return 0; } vinfo = ui_display_get_visual_info(disp); rgb_info_init(vinfo, &rgbinfo); XFree(vinfo); if (disp->depth == 16) { bytes_per_pixel = 2; } else { bytes_per_pixel = 4; } if (mask) { *mask = None; } for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { u_int32_t pixel; #ifdef GDK_PIXBUF_VERSION if (mask && ((u_char *)in)[3] <= 0x7f) #else if (mask && in[0] <= 0x7fffffff) #endif { if (*mask == None) { *mask = XCreatePixmap(disp->display, ui_display_get_group_leader(disp), w, h, 1); mask_gc = XCreateGC(disp->display, *mask, 0, &gcv); XSetForeground(disp->display, mask_gc, 1); XFillRectangle(disp->display, *mask, mask_gc, 0, 0, w, h); XSetForeground(disp->display, mask_gc, 0); } XDrawPoint(disp->display, *mask, mask_gc, x, y); } #ifdef GDK_PIXBUF_VERSION pixel = RGB_TO_PIXEL(((u_char *)in)[0], ((u_char *)in)[1], ((u_char *)in)[2], rgbinfo); #else pixel = RGB_TO_PIXEL((in[0] >> 16) & 0xff, (in[0] >> 8) & 0xff, in[0] & 0xff, rgbinfo); #endif if (bytes_per_pixel == 2) { *((u_int16_t *)out) = pixel; } else /* if( bytes_per_pixel == 4) */ { *((u_int32_t *)out) = (pixel | (in[0] & 0xff000000)); } in++; out += bytes_per_pixel; } } if (mask && *mask) { XFreeGC(disp->display, mask_gc); } image = XCreateImage(disp->display, disp->visual, disp->depth, ZPixmap, 0, data, w, h, /* in case depth isn't multiple of 8 */ bytes_per_pixel * 8, w * bytes_per_pixel); *pixmap = XCreatePixmap(disp->display, ui_display_get_group_leader(disp), w, h, disp->depth); XPutImage(disp->display, *pixmap, disp->gc->gc, image, 0, 0, 0, 0, w, h); XDestroyImage(image); if (width) { *width = w; } if (height) { *height = h; } return 1; } #endif /* BUILTIN_SIXEL */ #ifdef BUILTIN_IMAGELIB /* create GdkPixbuf from the specified file path. * * The returned pixbuf should be unrefed by the caller. * Don't modify returned pixbuf since the pixbuf * is stored in the cache and may be reused. * This function is not reentrant. */ static GdkPixbuf *load_file(char *path, /* If NULL is specified, cache is cleared. */ u_int width, /* 0 == image width */ u_int height, /* 0 == image height */ int keep_aspect, GdkInterpType scale_type) { static char *name = NULL; static GdkPixbuf *orig_cache = NULL; static GdkPixbuf *scaled_cache = NULL; GdkPixbuf *pixbuf; if (!path) { /* free caches */ if (orig_cache) { g_object_unref(orig_cache); orig_cache = NULL; } if (scaled_cache) { g_object_unref(scaled_cache); scaled_cache = NULL; } return NULL; } if (name == NULL || strcmp(name, path) != 0) { /* create new pixbuf */ if (!(pixbuf = gdk_pixbuf_new_from(path))) { return NULL; } /* XXX Don't cache ~/.mlterm/[pty name].six, [pty name].rgs and anim-*.gif */ if (!strstr(path, "mlterm/") || strstr(path, "mlterm/macro")) { #ifdef __DEBUG bl_warn_printf(BL_DEBUG_TAG " adding a pixbuf to cache(%s)\n", path); #endif /* Replace cache */ free(name); name = strdup(path); if (orig_cache) { g_object_unref(orig_cache); } orig_cache = pixbuf; if (scaled_cache) /* scaled_cache one is not vaild now */ { g_object_unref(scaled_cache); scaled_cache = NULL; } } } else { #ifdef __DEBUG bl_warn_printf(BL_DEBUG_TAG " using the pixbuf from cache\n"); #endif pixbuf = orig_cache; } /* loading from file/cache ends here */ if (width == 0) { width = gdk_pixbuf_get_width(pixbuf); } if (height == 0) { height = gdk_pixbuf_get_height(pixbuf); } if (keep_aspect) { u_int w = height * gdk_pixbuf_get_width(pixbuf) / gdk_pixbuf_get_height(pixbuf); if (w < width) { width = w; } else { u_int h = width * gdk_pixbuf_get_height(pixbuf) / gdk_pixbuf_get_width(pixbuf); if (h < height) { height = h; } } } /* It is necessary to scale orig_cache if width/height don't correspond. */ if ((width != gdk_pixbuf_get_width(pixbuf)) || (height != gdk_pixbuf_get_height(pixbuf))) { if (pixbuf != orig_cache) { /* Non-cached image */ GdkPixbuf *scaled_pixbuf; scaled_pixbuf = gdk_pixbuf_scale_simple(pixbuf, width, height, scale_type); g_object_unref(pixbuf); return scaled_pixbuf; } /* Old cached scaled_cache pixbuf became obsolete if width/height is changed */ else if (scaled_cache && gdk_pixbuf_get_width(scaled_cache) == width && gdk_pixbuf_get_height(scaled_cache) == height) { #ifdef __DEBUG bl_warn_printf(BL_DEBUG_TAG " using the scaled_cache pixbuf(%u x %u) from cache\n", width, height); #endif pixbuf = scaled_cache; } else { if (!(pixbuf = gdk_pixbuf_scale_simple(pixbuf, width, height, scale_type))) { return NULL; } #ifdef __DEBUG bl_warn_printf(BL_DEBUG_TAG " adding a scaled pixbuf to cache(%u x %u)\n", width, height); #endif if (scaled_cache) { g_object_unref(scaled_cache); } scaled_cache = pixbuf; } } /* scaling ends here */ if (pixbuf == scaled_cache || pixbuf == orig_cache) { /* Add reference count of the cache. */ g_object_ref(pixbuf); } return pixbuf; } #ifdef ENABLE_CARD2PIXBUF /* create a pixbuf from an array of cardinals */ static GdkPixbuf *create_pixbuf_from_cardinals(u_int32_t *cardinal, int req_width, int req_height) { GdkPixbuf *pixbuf; GdkPixbuf *scaled; int rowstride; u_char *line; u_char *pixel; int width, height; int x, y; width = cardinal[0]; height = cardinal[1]; if ((pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height)) == NULL) { return NULL; } rowstride = gdk_pixbuf_get_rowstride(pixbuf); line = gdk_pixbuf_get_pixels(pixbuf); cardinal += 2; for (y = 0; y < height; y++) { pixel = line; for (x = 0; x < width; x++) { /* ARGB -> RGBA conversion */ pixel[2] = (*cardinal) & 0xff; pixel[1] = ((*cardinal) >> 8) & 0xff; pixel[0] = ((*cardinal) >> 16) & 0xff; pixel[3] = ((*cardinal) >> 24) & 0xff; cardinal++; pixel += 4; } line += rowstride; } if (req_width == 0) { req_width = width; } if (req_height == 0) { req_height = height; } if ((req_width != width) || (req_height != height)) { scaled = gdk_pixbuf_scale_simple(pixbuf, req_width, req_height, GDK_INTERP_TILES); } else { scaled = NULL; } if (scaled) { g_object_unref(pixbuf); return scaled; } else { return pixbuf; } } #endif /* ENABLE_CARD2PIXBUF */ static int pixbuf_to_pixmap_pseudocolor(ui_display_t *disp, GdkPixbuf *pixbuf, Pixmap pixmap) { int width, height, rowstride; u_int bytes_per_pixel; int x, y; int num_cells; #ifdef USE_FS char *diff_next; char *diff_cur; char *temp; #endif /* USE_FS */ u_char *line; u_char *pixel; XColor *color_list; int closest; int diff_r, diff_g, diff_b; int ret_val = 0; if ((num_cells = fetch_colormap(disp, &color_list)) == 0) { return 0; } width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); #ifdef USE_FS if ((diff_cur = calloc(1, width * 3)) == NULL) { goto error1; } if ((diff_next = calloc(1, width * 3)) == NULL) { goto error2; } #endif /* USE_FS */ bytes_per_pixel = (gdk_pixbuf_get_has_alpha(pixbuf)) ? 4 : 3; rowstride = gdk_pixbuf_get_rowstride(pixbuf); line = gdk_pixbuf_get_pixels(pixbuf); for (y = 0; y < height; y++) { pixel = line; #ifdef USE_FS closest = closest_color_index(color_list, num_cells, pixel[0] - diff_cur[0], pixel[1] - diff_cur[1], pixel[2] - diff_cur[2]); diff_r = (color_list[closest].red >> 8) - pixel[0]; diff_g = (color_list[closest].green >> 8) - pixel[1]; diff_b = (color_list[closest].blue >> 8) - pixel[2]; diff_cur[3 * 1 + 0] += diff_r / 2; diff_cur[3 * 1 + 1] += diff_g / 2; diff_cur[3 * 1 + 2] += diff_b / 2; /* initialize next line */ diff_next[3 * 0 + 0] = diff_r / 4; diff_next[3 * 0 + 1] = diff_g / 4; diff_next[3 * 0 + 2] = diff_b / 4; diff_next[3 * 1 + 0] = diff_r / 4; diff_next[3 * 1 + 1] = diff_g / 4; diff_next[3 * 1 + 2] = diff_b / 4; #else closest = closest_color_index(color_list, num_cells, pixel[0], pixel[1], pixel[2]); #endif /* USE_FS */ XSetForeground(disp->display, disp->gc->gc, closest); XDrawPoint(disp->display, pixmap, disp->gc->gc, 0, y); pixel += bytes_per_pixel; for (x = 1; x < width - 2; x++) { #ifdef USE_FS closest = closest_color_index(color_list, num_cells, pixel[0] - diff_cur[3 * x + 0], pixel[1] - diff_cur[3 * x + 1], pixel[2] - diff_cur[3 * x + 2]); diff_r = (color_list[closest].red >> 8) - pixel[0]; diff_g = (color_list[closest].green >> 8) - pixel[1]; diff_b = (color_list[closest].blue >> 8) - pixel[2]; diff_cur[3 * (x + 1) + 0] += diff_r / 2; diff_cur[3 * (x + 1) + 1] += diff_g / 2; diff_cur[3 * (x + 1) + 2] += diff_b / 2; diff_next[3 * (x - 1) + 0] += diff_r / 8; diff_next[3 * (x - 1) + 1] += diff_g / 8; diff_next[3 * (x - 1) + 2] += diff_b / 8; diff_next[3 * (x + 0) + 0] += diff_r / 8; diff_next[3 * (x + 0) + 1] += diff_g / 8; diff_next[3 * (x + 0) + 2] += diff_b / 8; /* initialize next line */ diff_next[3 * (x + 1) + 0] = diff_r / 4; diff_next[3 * (x + 1) + 1] = diff_g / 4; diff_next[3 * (x + 1) + 2] = diff_b / 4; #else closest = closest_color_index(color_list, num_cells, pixel[0], pixel[1], pixel[2]); #endif /* USE_FS */ XSetForeground(disp->display, disp->gc->gc, closest); XDrawPoint(disp->display, pixmap, disp->gc->gc, x, y); pixel += bytes_per_pixel; } #ifdef USE_FS closest = closest_color_index(color_list, num_cells, pixel[0] - diff_cur[3 * x + 0], pixel[1] - diff_cur[3 * x + 1], pixel[2] - diff_cur[3 * x + 2]); diff_r = (color_list[closest].red >> 8) - pixel[0]; diff_g = (color_list[closest].green >> 8) - pixel[1]; diff_b = (color_list[closest].blue >> 8) - pixel[2]; diff_next[3 * (x - 1) + 0] += diff_r / 4; diff_next[3 * (x - 1) + 1] += diff_g / 4; diff_next[3 * (x - 1) + 2] += diff_b / 4; diff_next[3 * (x + 0) + 0] += diff_r / 4; diff_next[3 * (x + 0) + 1] += diff_g / 4; diff_next[3 * (x + 0) + 2] += diff_b / 4; temp = diff_cur; diff_cur = diff_next; diff_next = temp; #else closest = closest_color_index(color_list, num_cells, pixel[0], pixel[1], pixel[2]); #endif /* USE_FS */ XSetForeground(disp->display, disp->gc->gc, closest); XDrawPoint(disp->display, pixmap, disp->gc->gc, x, y); line += rowstride; } ret_val = 1; #ifdef USE_FS error2: free(diff_cur); free(diff_next); #endif /* USE_FS */ error1: free(color_list); return ret_val; } static XImage *pixbuf_to_ximage_truecolor(ui_display_t *disp, GdkPixbuf *pixbuf) { XVisualInfo *vinfo; rgb_info_t rgbinfo; u_int x, y; u_int width, height, rowstride, bytes_per_pixel; u_char *line; XImage *image; char *data; if (!(vinfo = ui_display_get_visual_info(disp))) { return NULL; } rgb_info_init(vinfo, &rgbinfo); XFree(vinfo); width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); /* Set num of bytes per pixel of display (necessarily 4 or 2 in TrueColor). */ bytes_per_pixel = disp->depth > 16 ? 4 : 2; if (width > SSIZE_MAX / bytes_per_pixel / height || /* integer overflow */ !(data = malloc(width * height * bytes_per_pixel))) { return NULL; } if (!(image = XCreateImage(disp->display, disp->visual, disp->depth, ZPixmap, 0, data, width, height, /* in case depth isn't multiple of 8 */ bytes_per_pixel * 8, width * bytes_per_pixel))) { free(data); return NULL; } /* set num of bytes per pixel of pixbuf */ bytes_per_pixel = (gdk_pixbuf_get_has_alpha(pixbuf)) ? 4 : 3; rowstride = gdk_pixbuf_get_rowstride(pixbuf); line = gdk_pixbuf_get_pixels(pixbuf); for (y = 0; y < height; y++) { u_char *pixel; pixel = line; for (x = 0; x < width; x++) { XPutPixel(image, x, y, RGB_TO_PIXEL(pixel[0], pixel[1], pixel[2], rgbinfo) | (disp->depth == 32 ? 0xff000000 : 0)); pixel += bytes_per_pixel; } line += rowstride; } return image; } static int pixbuf_to_pixmap(ui_display_t *disp, GdkPixbuf *pixbuf, Pixmap pixmap) { if (disp->visual->class == TrueColor) { XImage *image; if ((image = pixbuf_to_ximage_truecolor(disp, pixbuf))) { XPutImage(disp->display, pixmap, disp->gc->gc, image, 0, 0, 0, 0, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); XDestroyImage(image); return 1; } else { return 0; } } else /* if( disp->visual->class == PseudoColor) */ { return pixbuf_to_pixmap_pseudocolor(disp, pixbuf, pixmap); } } static int pixbuf_to_pixmap_and_mask(ui_display_t *disp, GdkPixbuf *pixbuf, Pixmap pixmap, Pixmap *mask /* Created in this function. */ ) { if (!pixbuf_to_pixmap(disp, pixbuf, pixmap)) { return 0; } if (gdk_pixbuf_get_has_alpha(pixbuf)) { int x, y; int width, height, rowstride; u_char *line; u_char *pixel; GC mask_gc; XGCValues gcv; int has_tp; width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); /* * DefaultRootWindow should not be used because depth and visual * of DefaultRootWindow don't always match those of mlterm window. * Use ui_display_get_group_leader instead. */ *mask = XCreatePixmap(disp->display, ui_display_get_group_leader(disp), width, height, 1); mask_gc = XCreateGC(disp->display, *mask, 0, &gcv); XSetForeground(disp->display, mask_gc, 0); XFillRectangle(disp->display, *mask, mask_gc, 0, 0, width, height); XSetForeground(disp->display, mask_gc, 1); line = gdk_pixbuf_get_pixels(pixbuf); rowstride = gdk_pixbuf_get_rowstride(pixbuf); has_tp = 0; for (y = 0; y < height; y++) { pixel = line + 3; for (x = 0; x < width; x++) { if (*pixel > 127) { XDrawPoint(disp->display, *mask, mask_gc, x, y); } else { has_tp = 1; } pixel += 4; } line += rowstride; } XFreeGC(disp->display, mask_gc); if (!has_tp) { /* mask is not necessary. */ XFreePixmap(disp->display, *mask); *mask = None; } } else { /* no mask */ *mask = None; } return 1; } static XImage *compose_truecolor(ui_display_t *disp, GdkPixbuf *pixbuf, Pixmap pixmap) { XVisualInfo *vinfo; rgb_info_t rgbinfo; XImage *image; int x, y; int width, height, rowstride; u_char *line; u_char *pixel; u_char r, g, b; u_long pixel2; width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); if (!(vinfo = ui_display_get_visual_info(disp))) { return NULL; } rgb_info_init(vinfo, &rgbinfo); XFree(vinfo); if (!(image = XGetImage(disp->display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap))) { return NULL; } rowstride = gdk_pixbuf_get_rowstride(pixbuf); line = gdk_pixbuf_get_pixels(pixbuf); for (y = 0; y < height; y++) { pixel = line; for (x = 0; x < width; x++) { pixel2 = XGetPixel(image, x, y); r = PIXEL_RED(pixel2, rgbinfo); g = PIXEL_BLUE(pixel2, rgbinfo); b = PIXEL_GREEN(pixel2, rgbinfo); r = (r * (256 - pixel[3]) + pixel[0] * pixel[3]) >> 8; g = (g * (256 - pixel[3]) + pixel[1] * pixel[3]) >> 8; b = (b * (256 - pixel[3]) + pixel[2] * pixel[3]) >> 8; XPutPixel(image, x, y, RGB_TO_PIXEL(r, g, b, rgbinfo) | (disp->depth == 32 ? 0xff000000 : 0)); pixel += 4; } line += rowstride; } return image; } static XImage *compose_pseudocolor(ui_display_t *disp, GdkPixbuf *pixbuf, Pixmap pixmap) { XImage *image; int x, y, num_cells; int width, height, rowstride; u_int r, g, b; u_char *line; u_char *pixel; u_long pixel2; XColor *color_list; if ((num_cells = fetch_colormap(disp, &color_list)) == 0) { return NULL; } width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); if (!(image = XGetImage(disp->display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap))) { free(color_list); return NULL; } rowstride = gdk_pixbuf_get_rowstride(pixbuf); line = gdk_pixbuf_get_pixels(pixbuf); for (y = 0; y < height; y++) { pixel = line; for (x = 0; x < width; x++) { if ((pixel2 = XGetPixel(image, x, y)) >= num_cells) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Pixel %x is illegal.\n", pixel2); #endif continue; } r = color_list[pixel2].red >> 8; g = color_list[pixel2].green >> 8; b = color_list[pixel2].blue >> 8; r = (r * (256 - pixel[3]) + pixel[0] * pixel[3]) >> 8; g = (g * (256 - pixel[3]) + pixel[1] * pixel[3]) >> 8; b = (b * (256 - pixel[3]) + pixel[2] * pixel[3]) >> 8; XPutPixel(image, x, y, closest_color_index(color_list, num_cells, r, g, b)); pixel += 4; } line += rowstride; } free(color_list); return image; } static int compose_to_pixmap(ui_display_t *disp, GdkPixbuf *pixbuf, Pixmap pixmap) { XImage *image; if (disp->visual->class == TrueColor) { image = compose_truecolor(disp, pixbuf, pixmap); } else /* if( disp->visual->class == PseudoColor) */ { image = compose_pseudocolor(disp, pixbuf, pixmap); } if (!image) { return 0; } XPutImage(disp->display, pixmap, disp->gc->gc, image, 0, 0, 0, 0, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); XDestroyImage(image); return 1; } static int modify_image(GdkPixbuf *pixbuf, ui_picture_modifier_t *pic_mod /* Mustn't be normal */ ) { int x, y; int width, height, rowstride, bytes_per_pixel; u_char *line; u_char *pixel; u_char value_table[256]; value_table_refresh(value_table, pic_mod); bytes_per_pixel = (gdk_pixbuf_get_has_alpha(pixbuf)) ? 4 : 3; width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); rowstride = gdk_pixbuf_get_rowstride(pixbuf); line = gdk_pixbuf_get_pixels(pixbuf); for (y = 0; y < height; y++) { pixel = line; line += rowstride; for (x = 0; x < width; x++) { /* * XXX * keeps neither hue nor saturation. * MUST be replaced by another better color model(CIE Yxy? lab?) */ pixel[0] = (value_table[pixel[0]] * (255 - pic_mod->alpha) + pic_mod->blend_red * pic_mod->alpha) / 255; pixel[1] = (value_table[pixel[1]] * (255 - pic_mod->alpha) + pic_mod->blend_green * pic_mod->alpha) / 255; pixel[2] = (value_table[pixel[2]] * (255 - pic_mod->alpha) + pic_mod->blend_blue * pic_mod->alpha) / 255; /* alpha plane is not changed */ pixel += bytes_per_pixel; } } return 1; } #else /* BUILTIN_IMAGELIB */ #ifdef NO_TOOLS #define load_file(disp, path, width, height, keep_aspect, pic_mod, pixmap, mask) (0) #define create_cardinals_from_file(path, width, height) (NULL) #else /* NO_TOOLS */ static pid_t exec_mlimgloader(int *read_fd, Window window, u_int width, u_int height, char *path, char *dst, char *opt) { int fds[2]; pid_t pid; if (!path || !*path || pipe(fds) == -1) { return -1; } if ((pid = fork()) == -1) { close(fds[0]); close(fds[1]); return -1; } if (pid == 0) { /* child process */ char *args[8]; char win_str[DIGIT_STR_LEN(Window) + 1]; char width_str[DIGIT_STR_LEN(u_int) + 1]; char height_str[DIGIT_STR_LEN(u_int) + 1]; args[0] = BL_LIBEXECDIR("mlterm") "/mlimgloader"; sprintf(win_str, "%lu", window); args[1] = win_str; sprintf(width_str, "%u", width); args[2] = width_str; sprintf(height_str, "%u", height); args[3] = height_str; args[4] = path; args[5] = dst; args[6] = opt; args[7] = NULL; close(fds[0]); if (dup2(fds[1], STDOUT_FILENO) != -1) { execv(args[0], args); } bl_msg_printf("Failed to exec %s.\n", args[0]); exit(1); } close(fds[1]); *read_fd = fds[0]; return pid; } static int load_file(ui_display_t *disp, char *path, u_int *width, u_int *height, int keep_aspect, ui_picture_modifier_t *pic_mod, Pixmap *pixmap, Pixmap *mask /* Can be NULL */ ) { int read_fd; char pix_str[DIGIT_STR_LEN(Pixmap) + 1 + DIGIT_STR_LEN(Pixmap) + 1]; Pixmap pixmap_tmp; Pixmap mask_tmp; ssize_t size; if (exec_mlimgloader(&read_fd, ui_display_get_group_leader(disp), *width, *height, path, "pixmap", keep_aspect ? "-a" : NULL) == -1) { return 0; } if ((size = read(read_fd, pix_str, sizeof(pix_str) - 1)) <= 0) { goto error; } pix_str[size] = '\0'; if (sscanf(pix_str, "%lu %lu", &pixmap_tmp, &mask_tmp) != 2) { goto error; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Receiving pixmap %lu %lu\n", pixmap_tmp, mask_tmp); #endif if (*width == 0 || *height == 0 || keep_aspect) { get_drawable_size(disp->display, pixmap_tmp, width, height); } *pixmap = XCreatePixmap(disp->display, ui_display_get_group_leader(disp), *width, *height, disp->depth); if (!ui_picture_modifier_is_normal(pic_mod)) { modify_pixmap(disp, pixmap_tmp, *pixmap, *width, *height, pic_mod); } else { XCopyArea(disp->display, pixmap_tmp, *pixmap, disp->gc->gc, 0, 0, *width, *height, 0, 0); } if (mask) { if (mask_tmp) { GC mask_gc; XGCValues gcv; *mask = XCreatePixmap(disp->display, ui_display_get_group_leader(disp), *width, *height, 1); mask_gc = XCreateGC(disp->display, *mask, 0, &gcv); XCopyArea(disp->display, mask_tmp, *mask, mask_gc, 0, 0, *width, *height, 0, 0); XFreeGC(disp->display, mask_gc); } else { *mask = None; } } XSync(disp->display, False); close(read_fd); /* child process exited by this. pixmap_tmp is alive until here. */ return 1; error: close(read_fd); return 0; } static u_int32_t *create_cardinals_from_file(char *path, u_int32_t width, u_int32_t height) { int read_fd; u_int32_t *cardinal; ssize_t size; if (exec_mlimgloader(&read_fd, None, width, height, path, "stdout", NULL) == -1) { return 0; } if (read(read_fd, &width, sizeof(u_int32_t)) != sizeof(u_int32_t) || read(read_fd, &height, sizeof(u_int32_t)) != sizeof(u_int32_t)) { cardinal = NULL; } else if ((cardinal = malloc((size = (width * height + 2) * sizeof(u_int32_t))))) { u_char *p; ssize_t n_rd; cardinal[0] = width; cardinal[1] = height; size -= (sizeof(u_int32_t) * 2); p = &cardinal[2]; while ((n_rd = read(read_fd, p, size)) > 0) { p += n_rd; size -= n_rd; } if (size > 0) { free(cardinal); cardinal = NULL; } } close(read_fd); #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " %s(w %d h %d) is loaded.\n", path, width, height); #endif return cardinal; } #endif /* NO_TOOLS */ #endif /* BUILTIN_IMAGELIB */ /* --- global functions --- */ void ui_imagelib_display_opened(Display *display) { #if GDK_PIXBUF_MAJOR >= 2 if (display_count == 0) { g_type_init(); } #endif /*GDK_PIXBUF_MAJOR*/ /* Want _XROOTPIAMP_ID changed events. */ XSelectInput(display, DefaultRootWindow(display), PropertyChangeMask); display_count++; } void ui_imagelib_display_closed(Display *display) { display_count--; if (display_count == 0) { #ifdef BUILTIN_IMAGELIB /* drop pixbuf cache */ load_file(NULL, 0, 0, 0, 0); #endif } } /** Load an image from the specified file. *\param win mlterm window. *\param path File full path. *\param pic_mod picture modifier. * *\return Pixmap to be used as a window's background. */ Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, ui_picture_modifier_t *pic_mod) { #ifdef BUILTIN_IMAGELIB GdkPixbuf *pixbuf; #else u_int width; u_int height; #endif Pixmap pixmap; if (!path || !*path) { return None; } if (strncmp(path, "pixmap:", 7) == 0 && sscanf(path + 7, "%lu", &pixmap) == 1) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " pixmap:%lu is used.\n", pixmap); #endif return pixmap; } #ifdef BUILTIN_IMAGELIB if (!(pixbuf = load_file(path, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), 0, GDK_INTERP_BILINEAR))) { return None; } if (!ui_picture_modifier_is_normal(pic_mod)) { /* pixbuf which load_file() returned is cached, so don't modify it. */ GdkPixbuf *p; p = gdk_pixbuf_copy(pixbuf); g_object_unref(pixbuf); if ((pixbuf = p) == NULL) { return None; } if (!modify_image(pixbuf, pic_mod)) { g_object_unref(pixbuf); return None; } } if (gdk_pixbuf_get_has_alpha(pixbuf) && (pixmap = ui_imagelib_get_transparent_background(win, NULL))) { if (!compose_to_pixmap(win->disp, pixbuf, pixmap)) { goto error; } } else { pixmap = XCreatePixmap(win->disp->display, win->my_window, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), win->disp->depth); if (!pixbuf_to_pixmap(win->disp, pixbuf, pixmap)) { goto error; } } g_object_unref(pixbuf); return pixmap; error: XFreePixmap(win->disp->display, pixmap); g_object_unref(pixbuf); return None; #else /* BUILTIN_IMAGELIB */ width = ACTUAL_WIDTH(win); height = ACTUAL_HEIGHT(win); if (load_file(win->disp, path, &width, &height, 0, pic_mod, &pixmap, NULL)) { return pixmap; } else { return None; } #endif /* BUILTIN_IMAGELIB */ } /* defined in xlib/ui_window.c */ int ui_window_get_visible_geometry(ui_window_t *win, int *x, int *y, int *my_x, int *my_y, u_int *width, u_int *height); /** Create an pixmap from root window *\param win window structure *\param pic_mod picture modifier * *\return Newly allocated Pixmap (or None in the case of failure) */ Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modifier_t *pic_mod) { int x; int y; int pix_x; int pix_y; u_int width; u_int height; Pixmap root; Pixmap pixmap; u_int root_width; u_int root_height; if (!(root = root_pixmap(win->disp))) { return None; } if (!ui_window_get_visible_geometry(win, &x, &y, &pix_x, &pix_y, &width, &height)) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " ui_window_get_visible_geometry failed.\n"); #endif return None; } /* The pixmap to be returned */ pixmap = XCreatePixmap(win->disp->display, win->my_window, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), win->disp->depth); get_drawable_size(win->disp->display, root, &root_width, &root_height); if (win->disp->depth != DefaultDepth(win->disp->display, DefaultScreen(win->disp->display))) { u_int bytes_per_pixel; XImage *image = NULL; char *data = NULL; XImage *image2; XVisualInfo vinfo_template; int nitems; XVisualInfo *vinfo; rgb_info_t rgbinfo; rgb_info_t rgbinfo2; u_int _x; u_int _y; /* Set num of bytes per pixel of display (necessarily 4 or 2 in TrueColor). */ bytes_per_pixel = win->disp->depth > 16 ? 4 : 2; if (win->disp->visual->class != TrueColor || !(image = XGetImage(win->disp->display, root, x, y, width, height, AllPlanes, ZPixmap)) || width > SSIZE_MAX / bytes_per_pixel / height || !(data = malloc(width * height * bytes_per_pixel)) || !(image2 = XCreateImage(win->disp->display, win->disp->visual, win->disp->depth, ZPixmap, 0, data, width, height, /* in case depth isn't multiple of 8 */ bytes_per_pixel * 8, width * bytes_per_pixel))) { XFreePixmap(win->disp->display, pixmap); if (image) { XDestroyImage(image); } if (data) { free(data); } return None; } vinfo_template.visualid = XVisualIDFromVisual(DefaultVisual(win->disp->display, DefaultScreen(win->disp->display))); vinfo = XGetVisualInfo(win->disp->display, VisualIDMask, &vinfo_template, &nitems); rgb_info_init(vinfo, &rgbinfo); XFree(vinfo); vinfo = ui_display_get_visual_info(win->disp); rgb_info_init(vinfo, &rgbinfo2); XFree(vinfo); for (_y = 0; _y < height; _y++) { for (_x = 0; _x < width; _x++) { u_long pixel; pixel = XGetPixel(image, _x, _y); XPutPixel(image2, _x, _y, (win->disp->depth == 32 ? 0xff000000 : 0) | RGB_TO_PIXEL(PIXEL_RED(pixel, rgbinfo), PIXEL_GREEN(pixel, rgbinfo), PIXEL_BLUE(pixel, rgbinfo), rgbinfo2)); } } XPutImage(win->disp->display, pixmap, win->disp->gc->gc, image2, 0, 0, 0, 0, width, height); XDestroyImage(image); XDestroyImage(image2); } else if (root_width < win->disp->width || root_height < win->disp->height) { GC gc; gc = XCreateGC(win->disp->display, win->my_window, 0, NULL); x %= root_width; y %= root_height; /* Some WM (WindowMaker etc) need tiling... sigh.*/ XSetTile(win->disp->display, gc, root); XSetTSOrigin(win->disp->display, gc, -x, -y); XSetFillStyle(win->disp->display, gc, FillTiled); /* XXX not correct with virtual desktop? */ XFillRectangle(win->disp->display, pixmap, gc, pix_x, pix_y, width, height); XFreeGC(win->disp->display, gc); } else { XCopyArea(win->disp->display, root, pixmap, win->gc->gc, x, y, width, height, pix_x, pix_y); } if (!ui_picture_modifier_is_normal(pic_mod)) { if (!modify_pixmap(win->disp, pixmap, pixmap, width, height, pic_mod)) { XFreePixmap(win->disp->display, pixmap); return None; } } return pixmap; } /** Load an image from the specified file with alpha plane. A pixmap and a mask *are returned. *\param display connection to the X server. *\param path File full path. *\param cardinal Returns pointer to a data structure for the extended WM hint *spec. *\param pixmap Returns an image pixmap for the old WM hint. *\param mask Returns a mask bitmap for the old WM hint. *\param width Pointer to the desired width. If *width is 0, the returned image *would not be scaled and *width would be overwritten by its width. *\param height Pointer to the desired height. *height can be 0. *(see "width" 's description) * *\return Success => 1, Failure => 0 */ int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) { u_int dst_height, dst_width; #ifdef BUILTIN_IMAGELIB GdkPixbuf *pixbuf; #endif dst_width = *width; dst_height = *height; #if defined(BUILTIN_IMAGELIB) || defined(BUILTIN_SIXEL) if (!cardinal && strcasecmp(path + strlen(path) - 4, ".six") == 0 && dst_width == 0 && dst_height == 0 && load_sixel(disp, path, pixmap, mask, width, height)) { return 1; } #endif #ifdef BUILTIN_IMAGELIB if (path) { /* create a pixbuf from the file and create a cardinal array */ if (!(pixbuf = load_file(path, dst_width, dst_height, keep_aspect, GDK_INTERP_BILINEAR))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG "couldn't load pixbuf\n"); #endif return 0; } if (cardinal) { if (!(*cardinal = create_cardinals_from_pixbuf(pixbuf))) { g_object_unref(pixbuf); return 0; } } } else { #ifdef ENABLE_CARD2PIXBUF if (!cardinal || !*cardinal) { return 0; } /* create a pixbuf from the cardinal array */ if (!(pixbuf = create_pixbuf_from_cardinals(*cardinal, dst_width, dst_height))) #endif { return 0; } } dst_width = gdk_pixbuf_get_width(pixbuf); dst_height = gdk_pixbuf_get_height(pixbuf); /* * Create the Icon pixmap & mask to be used in WMHints. * Note that none as a result is acceptable. * Pixmaps can't be cached since the last pixmap may be freed by someone... */ if (pixmap) { /* * DefaultRootWindow should not be used because depth and visual * of DefaultRootWindow don't always match those of mlterm window. * Use ui_display_get_group_leader instead. */ *pixmap = XCreatePixmap(disp->display, ui_display_get_group_leader(disp), dst_width, dst_height, disp->depth); if (mask) { if (!pixbuf_to_pixmap_and_mask(disp, pixbuf, *pixmap, mask)) { g_object_unref(pixbuf); goto error; } } else { if (!pixbuf_to_pixmap(disp, pixbuf, *pixmap)) { g_object_unref(pixbuf); goto error; } } } g_object_unref(pixbuf); #else /* BUILTIN_IMAGELIB */ if (!path) { /* cardinals => pixbuf is not supported. */ return 0; } if (!load_file(disp, path, &dst_width, &dst_height, keep_aspect, NULL, pixmap, mask)) { return 0; } if (cardinal) { if (!(*cardinal = create_cardinals_from_file(path, dst_width, dst_height))) { goto error; } } #endif /* BUILTIN_IMAGELIB */ if (*width == 0 || *height == 0 || keep_aspect) { *width = dst_width; *height = dst_height; } return 1; error: XFreePixmap(disp->display, *pixmap); return 0; } Pixmap ui_imagelib_pixbuf_to_pixmap(ui_window_t *win, ui_picture_modifier_t *pic_mod, GdkPixbufPtr pixbuf) { #ifdef BUILTIN_IMAGELIB Pixmap pixmap; GdkPixbuf *target; if (!ui_picture_modifier_is_normal(pic_mod)) { if ((target = gdk_pixbuf_copy(pixbuf)) == NULL) { return None; } modify_image(target, pic_mod); } else { target = pixbuf; } pixmap = XCreatePixmap(win->disp->display, win->my_window, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), win->disp->depth); if (pixbuf_to_pixmap(win->disp, target, pixmap)) { return pixmap; } if (target != pixbuf) { g_object_unref(target); } XFreePixmap(win->disp->display, pixmap); #endif /* BUILTIN_IMAGELIB */ return None; } void ui_destroy_image(Display *display, Pixmap pixmap) { XFreePixmap(display, pixmap); } #endif /* NO_IMAGE */ mlterm-3.8.9/uitoolkit/xlib/ui_selection_encoding.c010064400017600000144000000034061356600660700212220ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_selection_encoding.h" #include /* NULL */ #include #include #include /* --- static varaiables --- */ static ef_parser_t *utf_parser; /* leaked */ static ef_parser_t *parser; /* leaked */ static ef_conv_t *utf_conv; /* leaked */ static ef_conv_t *conv; /* leaked */ #ifdef USE_XLIB static int big5_buggy; #endif /* --- global functions --- */ #ifdef USE_XLIB void ui_set_big5_selection_buggy(int buggy) { big5_buggy = buggy; } #endif ef_parser_t *ui_get_selection_parser(int utf) { if (utf) { if (!utf_parser) { if (!(utf_parser = vt_char_encoding_parser_new(VT_UTF8))) { return NULL; } } return utf_parser; } else { if (!parser) { if (!(parser = ef_xct_parser_new())) { return NULL; } } return parser; } } ef_conv_t *ui_get_selection_conv(int utf) { if (utf) { if (!utf_conv) { if (!(utf_conv = vt_char_encoding_conv_new(VT_UTF8))) { return NULL; } } return utf_conv; } else { if (!conv) { #ifdef USE_XLIB if (big5_buggy) { if (!(conv = ef_xct_big5_buggy_conv_new())) { return NULL; } } else #endif { if (!(conv = ef_xct_conv_new())) { return NULL; } } } return conv; } } #if 0 void ui_selection_encoding_final(void) { if (utf_parser) { (*utf_parser->destroy)(utf_parser); utf_parser = NULL; } if (parser) { (*parser->destroy)(parser); parser = NULL; } if (utf_conv) { (*utf_conv->destroy)(utf_conv); utf_conv = NULL; } if (conv) { (*conv->destroy)(conv); conv = NULL; } } #endif mlterm-3.8.9/uitoolkit/xlib/ui_type_loader.c010064400017600000144000000040711356600660700176750ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_type_loader.h" #ifndef NO_DYNAMIC_LOAD_TYPE #include /* NULL */ #include #include #ifndef LIBDIR #define TYPELIB_DIR "/usr/local/lib/mlterm/" #else #define TYPELIB_DIR LIBDIR "/mlterm/" #endif /* --- global functions --- */ void *ui_load_type_xft_func(ui_type_id_t id) { static void **func_table; static int is_tried; if (!is_tried) { bl_dl_handle_t handle; is_tried = 1; if ((!(handle = bl_dl_open(TYPELIB_DIR, "type_xft")) && !(handle = bl_dl_open("", "type_xft")))) { bl_error_printf("xft: Could not load.\n"); return NULL; } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Loading libtype_xft.so\n"); #endif bl_dl_close_at_exit(handle); func_table = bl_dl_func_symbol(handle, "ui_type_xft_func_table"); if ((u_int32_t)func_table[TYPE_API_COMPAT_CHECK] != TYPE_API_COMPAT_CHECK_MAGIC) { bl_dl_close(handle); func_table = NULL; bl_error_printf("Incompatible type engine API.\n"); return NULL; } } if (func_table) { return func_table[id]; } else { return NULL; } } void *ui_load_type_cairo_func(ui_type_id_t id) { static void **func_table; static int is_tried; if (!is_tried) { bl_dl_handle_t handle; is_tried = 1; if ((!(handle = bl_dl_open(TYPELIB_DIR, "type_cairo")) && !(handle = bl_dl_open("", "type_cairo")))) { bl_error_printf("cairo: Could not load.\n"); return NULL; } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Loading libtype_cairo.so\n"); #endif bl_dl_close_at_exit(handle); func_table = bl_dl_func_symbol(handle, "ui_type_cairo_func_table"); if ((u_int32_t)func_table[TYPE_API_COMPAT_CHECK] != TYPE_API_COMPAT_CHECK_MAGIC) { bl_dl_close(handle); func_table = NULL; bl_error_printf("Incompatible type engine API.\n"); return NULL; } } if (func_table) { return func_table[id]; } else { return NULL; } } #endif /* NO_DYNAMIC_LOAD_TYPE */ mlterm-3.8.9/uitoolkit/xlib/ui_type_loader.h010064400017600000144000000015121356600660700176770ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_TYPE_LOADER_H__ #define __UI_TYPE_LOADER_H__ #include "../ui_font.h" #include "../ui_window.h" typedef enum ui_type_id { TYPE_API_COMPAT_CHECK, UI_WINDOW_SET_TYPE, UI_WINDOW_DRAW_STRING8, UI_WINDOW_DRAW_STRING32, UI_WINDOW_RESIZE, UI_SET_FONT, UI_UNSET_FONT, UI_CALCULATE_CHAR_WIDTH, UI_WINDOW_SET_CLIP, UI_WINDOW_UNSET_CLIP, UI_SET_OT_FONT, UI_CONVERT_TEXT_TO_GLYPHS, MAX_TYPE_FUNCS, } ui_type_id_t; #define TYPE_API_VERSION 0x01 #define TYPE_API_COMPAT_CHECK_MAGIC \ (((TYPE_API_VERSION & 0x0f) << 28) | ((sizeof(ui_font_t) & 0xff) << 20) | \ ((sizeof(ui_window_t) & 0xff) << 12)) void *ui_load_type_xft_func(ui_type_id_t id); void *ui_load_type_cairo_func(ui_type_id_t id); #endif mlterm-3.8.9/uitoolkit/xlib/ui_window.c010064400017600000144000002764631356600660700167150ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ /* * Functions designed and implemented by Minami Hirokazu(minami@mistfall.net) * are: * - XDND support * - Extended Window Manager Hint(Icon) support */ #include "../ui_window.h" #include /* abs */ #include /* memset/memcpy */ #include /* getpid */ #include /* for XSizeHints */ #include #include #include /* realloc/free */ #include /* BL_MAX */ #include /* bl_usleep */ #include /* bl_get_codeset() */ #include "../ui_xic.h" #include "../ui_picture.h" #ifndef DISABLE_XDND #include "../ui_dnd.h" #endif #include "ui_type_loader.h" #include "ui_display.h" /* ui_display_get_cursor */ #include "ui_decsp_font.h" /* * Atom macros. * Not cached because Atom may differ on each display */ #define XA_CLIPBOARD(display) (XInternAtom(display, "CLIPBOARD", False)) #define XA_COMPOUND_TEXT(display) (XInternAtom(display, "COMPOUND_TEXT", False)) #define XA_TARGETS(display) (XInternAtom(display, "TARGETS", False)) #ifdef DEBUG #define XA_MULTIPLE(display) (XInternAtom(display, "MULTIPLE", False)) #endif #define XA_TEXT(display) (XInternAtom(display, "TEXT", False)) #define XA_UTF8_STRING(display) (XInternAtom(display, "UTF8_STRING", False)) #define XA_BMP(display) (XInternAtom(display, "image/bmp", False)) #define XA_NONE(display) (XInternAtom(display, "NONE", False)) #define XA_SELECTION(display) (XInternAtom(display, "MLTERM_SELECTION", False)) #define XA_DELETE_WINDOW(display) (XInternAtom(display, "WM_DELETE_WINDOW", False)) #define XA_TAKE_FOCUS(display) (XInternAtom(display, "WM_TAKE_FOCUS", False)) #define XA_INCR(display) (XInternAtom(display, "INCR", False)) #define XA_XROOTPMAP_ID(display) (XInternAtom(display, "_XROOTPMAP_ID", False)) #define XA_XSETROOT_ID(display) (XInternAtom(display, "_XSETROOT_ID", False)) #define XA_WM_CLIENT_LEADER(display) (XInternAtom(display, "WM_CLIENT_LEADER", False)) /* * Extended Window Manager Hint support */ #define XA_NET_WM_ICON(display) (XInternAtom(display, "_NET_WM_ICON", False)) #define XA_NET_WM_PID(display) (XInternAtom(display, "_NET_WM_PID", False)) /* * Motif Window Manager Hint (for borderless window) */ #define XA_MWM_INFO(display) (XInternAtom(display, "_MOTIF_WM_INFO", True)) #define XA_MWM_HINTS(display) (XInternAtom(display, "_MOTIF_WM_HINTS", True)) #define IS_INHERIT_TRANSPARENT(win) \ (use_inherit_transparent && ui_picture_modifier_is_normal((win)->pic_mod)) /* win->width is not multiples of (win)->width_inc if window is maximized. */ #define RIGHT_MARGIN(win) \ ((win)->width_inc ? ((win)->width - (win)->min_width) % (win)->width_inc : 0) #define BOTTOM_MARGIN(win) \ ((win)->height_inc ? ((win)->height - (win)->min_height) % (win)->height_inc : 0) typedef struct { u_int32_t flags; u_int32_t functions; u_int32_t decorations; int32_t inputMode; u_int32_t status; } MWMHints_t; #define MWM_HINTS_DECORATIONS (1L << 1) #define MAX_CLICK 3 /* max is triple click */ #define restore_fg_color(win) ui_gc_set_fg_color((win)->gc, (win)->fg_color.pixel) #define restore_bg_color(win) ui_gc_set_bg_color((win)->gc, (win)->bg_color.pixel) #if 0 #define __DEBUG #endif /* --- static variables --- */ static int click_interval = 250; /* millisecond, same as xterm. */ /* ParentRelative isn't used for transparency by default */ static int use_inherit_transparent = 0; static int use_clipboard = 1; static int use_urgent_bell = 0; static struct { u_int8_t h_type[2]; u_int8_t h_size[4]; u_int8_t h_res1[2]; u_int8_t h_res2[2]; u_int8_t h_offbits[4]; u_int8_t i_size[4]; u_int8_t i_width[4]; u_int8_t i_height[4]; u_int8_t i_planes[2]; u_int8_t i_bitcount[2]; u_int8_t i_compression[4]; u_int8_t i_sizeimage[4]; u_int8_t i_xpelspermeter[4]; u_int8_t i_ypelspermeter[4]; u_int8_t i_clrused[4]; u_int8_t i_clrimportant[4]; u_char data[1]; } * sel_bmp; static size_t sel_bmp_size; /* --- static functions --- */ static int locale_is_utf8(void) { char *p = bl_get_codeset(); if ((*(p++) & ~0x20) == 'U' && (*(p++) & ~0x20) == 'T' && (*(p++) & ~0x20) == 'F' && p[(*p == '-' || *p == '_')] == '8') { return 1; } else { return 0; } } static void urgent_bell(ui_window_t *win, int on) { if (use_urgent_bell && (!win->is_focused || !on)) { #ifndef XUrgencyHint #define XUrgencyHint (1L << 8) /* not defined in X11R5 */ #endif XWMHints *hints; win = ui_get_root_window(win); if ((hints = XGetWMHints(win->disp->display, win->my_window))) { if (on) { hints->flags |= XUrgencyHint; } else { hints->flags &= ~XUrgencyHint; } XSetWMHints(win->disp->display, win->my_window, hints); XFree(hints); } } } static void clear_margin_area(ui_window_t *win) { u_int right_margin; u_int bottom_margin; right_margin = RIGHT_MARGIN(win); bottom_margin = BOTTOM_MARGIN(win); if (win->hmargin > 0) { XClearArea(win->disp->display, win->my_window, 0, 0, win->hmargin, ACTUAL_HEIGHT(win), 0); } if (win->hmargin + right_margin > 0) { XClearArea(win->disp->display, win->my_window, win->width - right_margin + win->hmargin, 0, win->hmargin + right_margin, ACTUAL_HEIGHT(win), 0); } if (win->vmargin > 0) { XClearArea(win->disp->display, win->my_window, win->hmargin, 0, win->width - right_margin, win->vmargin, 0); } if (win->vmargin + bottom_margin > 0) { XClearArea(win->disp->display, win->my_window, win->hmargin, win->height - bottom_margin + win->vmargin, win->width - right_margin, win->vmargin + bottom_margin, 0); } } /* Only used for set_transparent|update_modified_transparent */ static int set_transparent_picture(ui_window_t *win, Pixmap pixmap) { /* * !! Notice !! * This must be done before ui_window_set_wall_picture() because * ui_window_set_wall_picture() doesn't do anything if is_transparent * flag is on. */ win->is_transparent = 0; if (!ui_window_set_wall_picture(win, pixmap, 1)) { win->pic_mod = NULL; return 0; } win->is_transparent = 1; return 1; } /* Only used for set_transparent */ static int update_transparent_picture(ui_window_t *win) { ui_picture_t *pic; if (!(pic = ui_acquire_bg_picture(win, win->pic_mod, "root"))) { goto error1; } if (!set_transparent_picture(win, pic->pixmap)) { goto error2; } ui_release_picture(pic); return 1; error2: ui_release_picture(pic); error1: win->is_transparent = 0; /* win->pic_mod = NULL is done in set_transparent. */ return 0; } static int unset_transparent(ui_window_t *win) { /* * XXX * If previous mode is not modified transparent, * ParentRelative mode of parent windows should be unset. */ /* * !! Notice !! * this must be done before ui_window_unset_wall_picture() because * ui_window_unset_wall_picture() doesn't do anything if is_transparent * flag is on. */ win->is_transparent = 0; win->pic_mod = NULL; return ui_window_unset_wall_picture(win, 1); } static int set_transparent(ui_window_t *win) { Window parent; if (!IS_INHERIT_TRANSPARENT(win)) { /* * XXX * If previous mode is not modified transparent, * ParentRelative mode of parent windows should be unset. */ /* win->is_transparent is set appropriately in update_transparent_picture(). */ if (update_transparent_picture(win)) { return 1; } else { bl_msg_printf( "_XROOTPMAP_ID is not found." " Trying ParentRelative for transparency instead.\n"); if (!ui_picture_modifier_is_normal(win->pic_mod)) { bl_msg_printf( "(brightness, contrast, gamma and alpha " "options are ignored)\n"); win->pic_mod = NULL; } use_inherit_transparent = 1; } } /* * It is not necessary to set ParentRelative more than once, so * this function should be used as follows. * if( ! IS_INHERIT_TRANSPARENT(win) || ! win->wall_picture_is_set) * { * set_transparent( win) ; * } */ /* * Root - Window A - Window C * - Window B - Window D * - Window E * If Window C is set_transparent(), C -> A -> Root are set ParentRelative. * Window B,D and E are not set ParentRelative. */ while (win->parent) { /* win->is_transparent is set appropriately in set_transparent() */ set_transparent_picture(win, ParentRelative); win = win->parent; } set_transparent_picture(win, ParentRelative); parent = win->my_window; while (1) { Window root; Window *list; u_int n; XWindowAttributes attr; if (!XQueryTree(win->disp->display, parent, &root, &parent, &list, &n)) { break; } XFree(list); if (!parent || parent == root) { break; } if (XGetWindowAttributes(win->disp->display, parent, &attr) && attr.depth == win->disp->depth) { XSetWindowBackgroundPixmap(win->disp->display, parent, ParentRelative); } else { break; } } return 1; } static void notify_focus_in_to_children(ui_window_t *win) { u_int count; if (!win->is_focused && win->inputtable > 0) { win->is_focused = 1; if (win->window_focused) { (*win->window_focused)(win); } ui_xic_set_focus(win); } for (count = 0; count < win->num_children; count++) { notify_focus_in_to_children(win->children[count]); } } static void notify_focus_out_to_children(ui_window_t *win) { u_int count; if (win->is_focused) { win->is_focused = 0; if (win->window_unfocused) { (*win->window_unfocused)(win); } ui_xic_unset_focus(win); } for (count = 0; count < win->num_children; count++) { notify_focus_out_to_children(win->children[count]); } } static void notify_configure_to_children(ui_window_t *win) { u_int count; if (win->is_transparent) { if (!IS_INHERIT_TRANSPARENT(win) || !win->wall_picture_is_set) { #ifdef __DEBUG bl_debug_printf("configure notify for transparency\n"); #endif set_transparent(win); } else if (win->window_exposed) { clear_margin_area(win); (*win->window_exposed)(win, 0, 0, win->width, win->height); } #if 0 else { clear_margin_area(win); ui_window_clear_all(win); } #endif } for (count = 0; count < win->num_children; count++) { notify_configure_to_children(win->children[count]); } } static void notify_reparent_to_children(ui_window_t *win) { u_int count; if (win->is_transparent) { /* Parent window is changed. => Reset transparent. */ #ifdef __DEBUG bl_debug_printf("reparent notify for transparency\n"); #endif set_transparent(win); } for (count = 0; count < win->num_children; count++) { notify_reparent_to_children(win->children[count]); } } static void notify_property_to_children(ui_window_t *win) { u_int count; if (win->is_transparent) { /* Background image of desktop is changed. */ if (!IS_INHERIT_TRANSPARENT(win)) { #ifdef __DEBUG bl_debug_printf("property notify for transparency\n"); #endif set_transparent(win); } } for (count = 0; count < win->num_children; count++) { notify_property_to_children(win->children[count]); } } static int is_descendant_window(ui_window_t *win, Window window) { u_int count; if (win->my_window == window) { return 1; } for (count = 0; count < win->num_children; count++) { if (is_descendant_window(win->children[count], window)) { return 1; } } return 0; } static int is_in_the_same_window_family(ui_window_t *win, Window window) { return is_descendant_window(ui_get_root_window(win), window); } static u_int total_min_width(ui_window_t *win) { u_int count; u_int min_width; min_width = win->min_width + win->hmargin * 2 + RIGHT_MARGIN(win); for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_WIDTH)) { min_width += total_min_width(win->children[count]); } } return min_width; } static u_int total_min_height(ui_window_t *win) { u_int count; u_int min_height; min_height = win->min_height + win->vmargin * 2 + BOTTOM_MARGIN(win); for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_HEIGHT)) { min_height += total_min_height(win->children[count]); } } return min_height; } static u_int total_width_inc(ui_window_t *win) { u_int count; u_int width_inc; width_inc = win->width_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_WIDTH)) { width_inc += total_width_inc(win->children[count]); } } return width_inc; } static u_int total_height_inc(ui_window_t *win) { u_int count; u_int height_inc; height_inc = win->height_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_HEIGHT)) { height_inc += total_height_inc(win->children[count]); } } return height_inc; } static u_int max_width_inc(ui_window_t *win) { u_int count; u_int width_inc; width_inc = win->width_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_WIDTH)) { u_int sub_inc; /* * XXX * we should calculate least common multiple of width_inc and sub_inc. */ if ((sub_inc = total_width_inc(win->children[count])) > width_inc) { width_inc = sub_inc; } } } return width_inc; } static u_int max_height_inc(ui_window_t *win) { u_int count; u_int height_inc; height_inc = win->height_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_HEIGHT)) { u_int sub_inc; /* * XXX * we should calculate least common multiple of width_inc and sub_inc. */ if ((sub_inc = max_height_inc(win->children[count])) > height_inc) { height_inc = sub_inc; } } } return height_inc; } static XID reset_client_leader(ui_window_t *root) { u_long leader; if ((leader = ui_display_get_group_leader(root->disp)) == None) { leader = root->my_window; } XChangeProperty(root->disp->display, root->my_window, XA_WM_CLIENT_LEADER(root->disp->display), XA_WINDOW, 32, PropModeReplace, (unsigned char *)(&leader), 1); return leader; } static void convert_to_decsp_font_index(u_char *str, u_int len) { while (len != 0) { if (*str == 0x5f) { *str = 0x7f; } else if (0x5f < *str && *str < 0x7f) { (*str) -= 0x5f; } len--; str++; } } static void scroll_region(ui_window_t *win, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y) { XCopyArea(win->disp->display, win->my_window, win->my_window, win->gc->gc, src_x + win->hmargin, src_y + win->vmargin, width, height, dst_x + win->hmargin, dst_y + win->vmargin); while (win->wait_copy_area_response) { XEvent ev; XWindowEvent(win->disp->display, win->my_window, ExposureMask, &ev); if (ev.type == GraphicsExpose) { /* * GraphicsExpose caused by the previous XCopyArea is * processed *after* XCopyArea above to avoid following problem. * * - : GraphicsExpose Area * * (X Window screen) (vt_term_t) * aaaaaaaaaa aaaaaaaaaa * bbbbbbbbbb bbbbbbbbbb * cccccccccc cccccccccc * 1||(CA) 1|| * \/ \/ * bbbbbbbbbb bbbbbbbbbb * cccccccccc cccccccccc * ---------- dddddddddd * 2|| * \/ * bbbbbbbbbb 3(GE) cccccccccc * cccccccccc <===== dddddddddd * eeeeeeeeee eeeeeeeeee * 4||(CA) * \/ * cccccccccc * eeeeeeeeee * eeeeeeeeee */ ev.xgraphicsexpose.x += (dst_x - src_x); ev.xgraphicsexpose.y += (dst_y - src_y); } ui_window_receive_event(win, &ev); } win->wait_copy_area_response = 1; } static int send_selection(ui_window_t *win, XSelectionRequestEvent *req_ev, u_char *sel_data, size_t sel_len, Atom sel_type, int sel_format) { XEvent res_ev; res_ev.xselection.type = SelectionNotify; res_ev.xselection.display = req_ev->display; res_ev.xselection.requestor = req_ev->requestor; res_ev.xselection.selection = req_ev->selection; res_ev.xselection.target = req_ev->target; res_ev.xselection.time = req_ev->time; if (sel_data == NULL) { res_ev.xselection.property = None; } else { if (req_ev->property == None) { /* An obsolete client may fill None as a property. * Try to deal with them by using 'target' instead. */ req_ev->property = req_ev->target; } if (req_ev->property != None) { XChangeProperty(win->disp->display, req_ev->requestor, req_ev->property, sel_type, sel_format, PropModeReplace, sel_data, sel_len); } res_ev.xselection.property = req_ev->property; } XSendEvent(win->disp->display, res_ev.xselection.requestor, False, 0, &res_ev); return 1; } static int right_shift(u_long mask) { int shift = 0; int count = 8; if (mask == 0) { return 0; } while ((mask & 1) == 0) { mask >>= 1; shift++; } while ((mask & 1) == 1) { mask >>= 1; count--; } if (count > 0) { shift -= count; } return shift; } static void reset_input_focus(ui_window_t *win) { u_int count; if (win->inputtable) { win->inputtable = -1; } else { win->inputtable = 0; } for (count = 0; count < win->num_children; count++) { reset_input_focus(win->children[count]); } } static void ensure_input_focus(ui_window_t *win) { u_int count; if (win->inputtable > 0) { if (!win->is_focused) { XSetInputFocus(win->disp->display, win->my_window, RevertToParent, CurrentTime); } } else { for (count = 0; count < win->num_children; count++) { ensure_input_focus(win->children[count]); } } } static int get_num_inputtables(ui_window_t *win) { u_int count; int num = (win->inputtable != 0) ? 1 : 0; for (count = 0; count < win->num_children; count++) { num += get_num_inputtables(win->children[count]); } return num; } #if !defined(NO_DYNAMIC_LOAD_TYPE) static void ui_window_set_use_xft(ui_window_t *win, int use_xft) { void (*func)(ui_window_t *, int); if (!(func = ui_load_type_xft_func(UI_WINDOW_SET_TYPE))) { return; } (*func)(win, use_xft); } static void ui_window_xft_draw_string8(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, size_t len) { void (*func)(ui_window_t *, ui_font_t *, ui_color_t *, int, int, u_char *, size_t); if (!(func = ui_load_type_xft_func(UI_WINDOW_DRAW_STRING8))) { return; } (*func)(win, font, fg_color, x, y, str, len); } static void ui_window_xft_draw_string32(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, /* FcChar32 */ u_int32_t *str, size_t len) { void (*func)(ui_window_t *, ui_font_t *, ui_color_t *, int, int, /* FcChar32 */ u_int32_t *, size_t); if (!(func = ui_load_type_xft_func(UI_WINDOW_DRAW_STRING32))) { return; } return (*func)(win, font, fg_color, x, y, str, len); } static void xft_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height) { void (*func)(ui_window_t *, int, int, u_int, u_int); if (!(func = ui_load_type_xft_func(UI_WINDOW_SET_CLIP))) { return; } (*func)(win, x, y, width, height); } static void xft_unset_clip(ui_window_t *win) { void (*func)(ui_window_t *); if (!(func = ui_load_type_xft_func(UI_WINDOW_UNSET_CLIP))) { return; } (*func)(win); } static void ui_window_set_use_cairo(ui_window_t *win, int use_cairo) { void (*func)(ui_window_t *, int); if (!(func = ui_load_type_cairo_func(UI_WINDOW_SET_TYPE))) { return; } (*func)(win, use_cairo); } static void ui_window_cairo_draw_string8(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, size_t len) { void (*func)(ui_window_t *, ui_font_t *, ui_color_t *, int, int, u_char *, size_t); if (!(func = ui_load_type_cairo_func(UI_WINDOW_DRAW_STRING8))) { return; } (*func)(win, font, fg_color, x, y, str, len); } static void ui_window_cairo_draw_string32(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, /* FcChar32 */ u_int32_t *str, size_t len) { void (*func)(ui_window_t *, ui_font_t *, ui_color_t *, int, int, /* FcChar32 */ u_int32_t *, size_t); if (!(func = ui_load_type_cairo_func(UI_WINDOW_DRAW_STRING32))) { return; } (*func)(win, font, fg_color, x, y, str, len); } static void cairo_resize(ui_window_t *win) { void (*func)(ui_window_t *); if (!(func = ui_load_type_cairo_func(UI_WINDOW_RESIZE))) { return; } (*func)(win); } static void cairo_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height) { void (*func)(ui_window_t *, int, int, u_int, u_int); if (!(func = ui_load_type_cairo_func(UI_WINDOW_SET_CLIP))) { return; } (*func)(win, x, y, width, height); } static void cairo_unset_clip(ui_window_t *win) { void (*func)(ui_window_t *); if (!(func = ui_load_type_cairo_func(UI_WINDOW_UNSET_CLIP))) { return; } (*func)(win); } #else /* NO_DYNAMIC_LOAD_TYPE */ #ifdef USE_TYPE_XFT void ui_window_set_use_xft(ui_window_t *win, int use_xft); void ui_window_xft_draw_string8(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, size_t len); void ui_window_xft_draw_string32(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_int32_t *str, size_t len); void xft_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height); void xft_unset_clip(ui_window_t *win); #endif #ifdef USE_TYPE_CAIRO void ui_window_set_use_cairo(ui_window_t *win, int use_cairo); void ui_window_cairo_draw_string8(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, size_t len); void ui_window_cairo_draw_string32(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_int32_t *str, size_t len); void cairo_resize(ui_window_t *win); void cairo_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height); void cairo_unset_clip(ui_window_t *win); #endif #endif /* NO_DYNAMIC_LOAD_TYPE */ /* --- global functions --- */ int ui_window_init(ui_window_t *win, u_int width, u_int height, u_int min_width, /* width_inc * 1 must be added to if width_inc > 0 */ u_int min_height, /* height_inc * 1 must be added to if height_inc > 0 */ u_int width_inc, u_int height_inc, u_int hmargin, u_int vmargin, int create_gc, int inputtable) { memset(win, 0, sizeof(ui_window_t)); win->fg_color.pixel = 0xff000000; win->fg_color.alpha = 0xff; memset(&win->bg_color, 0xff, sizeof(win->bg_color)); win->event_mask = ExposureMask | FocusChangeMask | PropertyChangeMask; /* If wall picture is set, scrollable will be 0. */ win->is_scrollable = 1; #if 0 /* * is_focus member shoule be 0 by default in order to call * XSetICFocus(ui_xic_set_focus) in startup FocusIn event. * If XSetICFocus() is not called, KeyPress event is discarded * in XFilterEvent. */ win->is_focused = 0; #endif win->inputtable = inputtable; /* This flag will map window automatically in ui_window_show() */ win->is_mapped = 1; win->create_gc = create_gc; win->width = width; win->height = height; win->min_width = min_width; win->min_height = min_height; win->width_inc = width_inc; win->height_inc = height_inc; win->sizehint_flag = SIZEHINT_WIDTH|SIZEHINT_HEIGHT; win->hmargin = hmargin; win->vmargin = vmargin; win->prev_clicked_button = -1; win->app_name = "mlterm"; /* Can be changed in ui_display_show_root(). */ return 1; } void ui_window_final(ui_window_t *win) { u_int count; #ifdef DEBUG bl_debug_printf("[deleting child windows]\n"); ui_window_dump_children(win); #endif for (count = 0; count < win->num_children; count++) { ui_window_final(win->children[count]); } free(win->children); if (win->my_window) { ui_display_clear_selection(win->disp, win); ui_xic_deactivate(win); /* Delete cairo/xft. */ ui_window_set_type_engine(win, TYPE_XCORE); XDestroyWindow(win->disp->display, win->my_window); if (win->create_gc) { ui_gc_destroy(win->gc); } } else { /* ui_window_show() is not called yet. */ } if (win->window_finalized) { (*win->window_finalized)(win); } } /* * Call this function in window_realized event at first. */ void ui_window_set_type_engine(ui_window_t *win, ui_type_engine_t type_engine) { #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) if ((win->xft_draw != NULL) != (type_engine == TYPE_XFT)) { ui_window_set_use_xft(win, (type_engine == TYPE_XFT)); } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if ((win->cairo_draw != NULL) != (type_engine == TYPE_CAIRO)) { ui_window_set_use_cairo(win, (type_engine == TYPE_CAIRO)); } #endif } void ui_window_add_event_mask(ui_window_t *win, long event_mask) { #if 0 if (event_mask & ButtonMotionMask) { event_mask &= ~ButtonMotionMask; event_mask |= (Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask); } #endif win->event_mask |= event_mask; if (win->my_window) { XSelectInput(win->disp->display, win->my_window, win->event_mask); } } void ui_window_remove_event_mask(ui_window_t *win, long event_mask) { #if 0 if (event_mask & ButtonMotionMask) { event_mask &= ~ButtonMotionMask; event_mask |= (Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask); } #endif win->event_mask &= ~event_mask; if (win->my_window) { XSelectInput(win->disp->display, win->my_window, win->event_mask); } } void ui_window_ungrab_pointer(ui_window_t *win) { XUngrabPointer(win->disp->display, CurrentTime); } int ui_window_set_wall_picture(ui_window_t *win, Pixmap pic, int do_expose) { u_int count; if (win->is_transparent) { /* * unset transparent before setting wall picture ! */ return 0; } XSetWindowBackgroundPixmap(win->disp->display, win->my_window, pic); win->wall_picture_is_set = 1; win->is_scrollable = 0; if (do_expose) { clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } #if 0 else { ui_window_clear_all(win); } #endif } for (count = 0; count < win->num_children; count++) { ui_window_set_wall_picture(win->children[count], ParentRelative, do_expose); } return 1; } int ui_window_unset_wall_picture(ui_window_t *win, int do_expose) { u_int count; /* * win->wall_picture_is_set == 0 doesn't mean that following codes * to disable wall picture is already processed. * e.g.) If ui_window_unset_transparent() is called after * ui_window_set_transparent() before my_window is created, * XSetWindowBackground() which is not called in ui_window_set_bg_color() * (because is_transparent flag is set by ui_window_set_transparent()) * is never called in startup by checking win->wall_picture_is_set as follows. */ #if 0 if (!win->wall_picture_is_set) { /* already unset */ return 1; } #endif if (win->is_transparent) { /* * transparent background is not a wall picture :) * this case is regarded as not using a wall picture. */ return 1; } XSetWindowBackgroundPixmap(win->disp->display, win->my_window, None); XSetWindowBackground(win->disp->display, win->my_window, win->bg_color.pixel); win->wall_picture_is_set = 0; win->is_scrollable = 1; if (do_expose) { clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } #if 0 else { ui_window_clear_all(win); } #endif } for (count = 0; count < win->num_children; count++) { ui_window_unset_wall_picture(win->children[count], do_expose); } return 1; } /* * This function is possible to be called before my_window is created. * (because ui_screen_t doesn't contain transparent flag.) */ int ui_window_set_transparent( ui_window_t *win, /* Transparency is applied to all children recursively */ ui_picture_modifier_t *pic_mod) { u_int count; win->pic_mod = pic_mod; if (win->my_window == None) { /* * If Window is not still created , actual drawing is delayed and * ReparentNotify event will do transparent processing automatically after * ui_window_show(). */ win->is_transparent = 1; } else { set_transparent(win); } for (count = 0; count < win->num_children; count++) { ui_window_set_transparent(win->children[count], win->pic_mod); } return 1; } /* * This function is possible to be called before my_window is created. * (because ui_screen_t doesn't contain transparent flag.) */ int ui_window_unset_transparent(ui_window_t *win) { u_int count; if (win->my_window == None) { win->is_transparent = 0; } else if (win->is_transparent) { unset_transparent(win); clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } #if 0 else { ui_window_clear_all(win); } #endif } for (count = 0; count < win->num_children; count++) { ui_window_unset_transparent(win->children[count]); } return 1; } /* * Cursor is not changeable after ui_window_show(). */ void ui_window_set_cursor(ui_window_t *win, u_int cursor_shape) { if (win->my_window == None) { win->cursor_shape = cursor_shape; } else { Cursor cursor; if ((cursor = ui_display_get_cursor(win->disp, (win->cursor_shape = cursor_shape)))) { XDefineCursor(win->disp->display, win->my_window, cursor); } } } int ui_window_set_fg_color(ui_window_t *win, ui_color_t *fg_color) { if (win->fg_color.pixel == fg_color->pixel) { return 0; } win->fg_color = *fg_color; return 1; } int ui_window_set_bg_color(ui_window_t *win, ui_color_t *bg_color) { if (win->bg_color.pixel == bg_color->pixel) { return 0; } win->bg_color = *bg_color; if (!win->is_transparent && !win->wall_picture_is_set) { XSetWindowBackground(win->disp->display, win->my_window, win->bg_color.pixel); clear_margin_area(win); } return 1; } int ui_window_add_child(ui_window_t *win, ui_window_t *child, int x, int y, int map) { void *p; if ((p = realloc(win->children, sizeof(*win->children) * (win->num_children + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } win->children = p; child->parent = win; child->x = x + win->hmargin; child->y = y + win->vmargin; if (!(child->is_mapped = map) && child->inputtable > 0) { child->inputtable = -1; } win->children[win->num_children++] = child; return 1; } int ui_window_remove_child(ui_window_t *win, ui_window_t *child) { u_int count; for (count = 0; count < win->num_children; count++) { if (win->children[count] == child) { child->parent = NULL; win->children[count] = win->children[--win->num_children]; return 1; } } return 0; } ui_window_t *ui_get_root_window(ui_window_t *win) { while (win->parent != NULL) { win = win->parent; } return win; } GC ui_window_get_fg_gc(ui_window_t *win) { /* Reset */ restore_fg_color(win); #if 0 restore_bg_color(win); #endif return win->gc->gc; } GC ui_window_get_bg_gc(ui_window_t *win) { ui_gc_set_fg_color((win)->gc, (win)->bg_color.pixel); #if 0 ui_gc_set_bg_color((win)->gc, (win)->fg_color.pixel); #endif return win->gc->gc; } /* * If win->parent(_window) is None, specify XValue|YValue as 'hint' to locate * window at win->x/win->y. */ int ui_window_show(ui_window_t *win, int hint) { u_int count; XSetWindowAttributes s_attr; if (win->my_window) { /* already shown */ return 0; } if (win->parent) { win->disp = win->parent->disp; win->gc = win->parent->gc; win->parent_window = win->parent->my_window; } if (hint & XNegative) { win->x += (win->disp->width - ACTUAL_WIDTH(win)); } if (hint & YNegative) { win->y += (win->disp->height - ACTUAL_HEIGHT(win)); } s_attr.background_pixel = win->bg_color.pixel; s_attr.border_pixel = win->fg_color.pixel; s_attr.colormap = win->disp->colormap; #if 1 win->my_window = XCreateWindow(win->disp->display, win->parent_window, win->x, win->y, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), 0, win->disp->depth, InputOutput, win->disp->visual, CWBackPixel | CWBorderPixel | CWColormap, &s_attr); #else win->my_window = XCreateSimpleWindow(win->disp->display, win->parent_window, win->x, win->y, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), 0, win->fg_color.pixel, win->bg_color.pixel); #endif if (win->create_gc) { ui_gc_t *gc; if ((gc = ui_gc_new(win->disp->display, win->my_window)) == NULL) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " ui_gc_new failed.\n"); #endif win->create_gc = 0; } else { win->gc = gc; } } if (win->cursor_shape) { Cursor cursor; if ((cursor = ui_display_get_cursor(win->disp, win->cursor_shape))) { XDefineCursor(win->disp->display, win->my_window, cursor); } } /* Don't use win->parent here in case mlterm works as libvte. */ if (PARENT_WINDOWID_IS_TOP(win)) { /* Root window */ XSizeHints size_hints; int total; XClassHint class_hint; XWMHints wm_hints; int argc = 1; char *argv[] = { "mlterm", NULL, }; Atom protocols[2]; XID pid; win->event_mask |= StructureNotifyMask; /* * XXX * x/y/width/height are obsoleted. (see XSizeHints(3)) */ size_hints.x = win->x; size_hints.y = win->y; size_hints.width = ACTUAL_WIDTH(win); size_hints.height = ACTUAL_HEIGHT(win); size_hints.width_inc = max_width_inc(win); size_hints.height_inc = max_height_inc(win); size_hints.min_width = total_min_width(win); size_hints.min_height = total_min_height(win); total = total_width_inc(win); size_hints.base_width = (size_hints.min_width > total) ? size_hints.min_width - total : 0; total = total_height_inc(win); size_hints.base_height = (size_hints.min_height > total) ? size_hints.min_height - total : 0; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Size hints => w %d h %d wi %d hi %d mw %d mh %d bw %d bh %d\n", size_hints.width, size_hints.height, size_hints.width_inc, size_hints.height_inc, size_hints.min_width, size_hints.min_height, size_hints.base_width, size_hints.base_height); #endif if (hint & XNegative) { if (hint & YNegative) { size_hints.win_gravity = SouthEastGravity; } else { size_hints.win_gravity = NorthEastGravity; } } else { if (hint & YNegative) { size_hints.win_gravity = SouthWestGravity; } else { size_hints.win_gravity = NorthWestGravity; } } size_hints.flags = PSize | PMinSize | PResizeInc | PBaseSize | PWinGravity; if (hint & (XValue | YValue)) { size_hints.flags |= PPosition; size_hints.flags |= USPosition; } /* * XXX * If res_name = "mlterm" and res_class = "mlterm", lxde (0.99.2) doesn't * show title bar for mlterm. */ class_hint.res_name = "xterm"; /* same as xterm */ class_hint.res_class = win->app_name; wm_hints.initial_state = NormalState; /* or IconicState */ wm_hints.input = True; /* wants FocusIn/FocusOut */ wm_hints.window_group = reset_client_leader(win); wm_hints.flags = StateHint | InputHint | WindowGroupHint; #if 0 bl_debug_printf(BL_DEBUG_TAG " Group leader -> %x\n", wm_hints.window_group); #endif /* Notify to window manager. */ XmbSetWMProperties(win->disp->display, win->my_window, win->app_name, win->app_name, argv, argc, &size_hints, &wm_hints, &class_hint); protocols[0] = XA_DELETE_WINDOW(win->disp->display); protocols[1] = XA_TAKE_FOCUS(win->disp->display); XSetWMProtocols(win->disp->display, win->my_window, protocols, 2); pid = getpid(); XChangeProperty(win->disp->display, win->my_window, XA_NET_WM_PID(win->disp->display), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&pid, 1); } if (win->parent && !win->parent->is_transparent && win->parent->wall_picture_is_set) { ui_window_set_wall_picture(win, ParentRelative, 0); } /* * This should be called after Window Manager settings, because * ui_set_{window|icon}_name() can be called in win->window_realized(). */ if (win->window_realized) { (*win->window_realized)(win); } XSelectInput(win->disp->display, win->my_window, win->event_mask); #if 0 { char *locale; if ((locale = bl_get_locale())) { XChangeProperty(win->disp->display, win->my_window, XInternAtom(win->disp->display, "WM_LOCALE_NAME", False), XA_STRING, 8, PropModeReplace, locale, strlen(locale)); } } #endif /* * showing child windows. */ for (count = 0; count < win->num_children; count++) { ui_window_show(win->children[count], 0); } /* * really visualized. */ if (win->is_mapped) { XMapWindow(win->disp->display, win->my_window); if (win->inputtable > 0) { reset_input_focus(ui_get_root_window(win)); win->inputtable = 1; } #if 0 ui_window_clear_all(win); #endif } return 1; } void ui_window_map(ui_window_t *win) { if (win->is_mapped) { return; } XMapWindow(win->disp->display, win->my_window); win->is_mapped = 1; } void ui_window_unmap(ui_window_t *win) { if (!win->is_mapped) { return; } XUnmapWindow(win->disp->display, win->my_window); win->is_mapped = 0; } int ui_window_resize(ui_window_t *win, u_int width, /* excluding margin */ u_int height, /* excluding margin */ ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */ ) { if (win->width == width && win->height == height) { return 0; } /* Max width of each window is DisplayWidth(). */ if ((flag & LIMIT_RESIZE) && win->disp->width < width) { win->width = win->disp->width - win->hmargin * 2; } else { win->width = width; } /* Maui.height of each window is DisplayHeight(). */ if ((flag & LIMIT_RESIZE) && win->disp->height < height) { win->height = win->disp->height - win->vmargin * 2; } else { win->height = height; } if ((flag & NOTIFY_TO_PARENT) && win->parent && win->parent->child_window_resized) { (*win->parent->child_window_resized)(win->parent, win); } XResizeWindow(win->disp->display, win->my_window, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); if ((flag & NOTIFY_TO_MYSELF) && win->window_resized) { (*win->window_resized)(win); } #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if (win->cairo_draw) { cairo_resize(win); } #endif if (!win->configure_root && !(flag & NOTIFY_TO_PARENT) && win->parent) { notify_configure_to_children(win); } return 1; } /* * !! Notice !! * This function is not recommended. * Use ui_window_resize if at all possible. */ int ui_window_resize_with_margin(ui_window_t *win, u_int width, u_int height, ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */ ) { u_int min_width; u_int min_height; min_width = total_min_width(win); min_height = total_min_height(win); return ui_window_resize(win, width <= min_width ? min_width : width - win->hmargin * 2, height <= min_height ? min_height : height - win->vmargin * 2, flag); } void ui_window_set_maximize_flag(ui_window_t *win, ui_maximize_flag_t flag) { if (flag) { u_int w; u_int h; int x; int y; win = ui_get_root_window(win); ui_window_translate_coordinates(win, 0, 0, &x, &y); if (flag & MAXIMIZE_HORIZONTAL) { w = win->disp->width - win->hmargin * 2; x = 0; } else { w = win->width; } if (flag & MAXIMIZE_VERTICAL) { h = win->disp->height - win->vmargin * 2; y = 0; } else { h = win->height; } XMoveWindow(win->disp->display, win->my_window, x, y); ui_window_resize(win, w, h, NOTIFY_TO_MYSELF); } else { /* XXX MAXIMIZE_RESTORE is not supported for now. */ } } void ui_window_set_normal_hints(ui_window_t *win, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc) { XSizeHints size_hints; int total; ui_window_t *root; win->min_width = min_width; win->min_height = min_height; win->width_inc = width_inc; win->height_inc = height_inc; root = ui_get_root_window(win); /* * these hints must be set at the same time ! */ size_hints.width_inc = max_width_inc(root); size_hints.height_inc = max_height_inc(root); size_hints.min_width = total_min_width(root); size_hints.min_height = total_min_height(root); total = total_width_inc(win); size_hints.base_width = (size_hints.min_width > total) ? size_hints.min_width - total : 0; total = total_height_inc(win); size_hints.base_height = (size_hints.min_height > total) ? size_hints.min_height - total : 0; size_hints.flags = PMinSize | PResizeInc | PBaseSize; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Size hints => w %u h %u wi %u hi %u mw %u mh %u bw %u bh %u\n", ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), size_hints.width_inc, size_hints.height_inc, size_hints.min_width, size_hints.min_height, size_hints.base_width, size_hints.base_height); #endif XSetWMNormalHints(root->disp->display, root->my_window, &size_hints); } void ui_window_set_override_redirect(ui_window_t *win, int flag) { ui_window_t *root; XSetWindowAttributes s_attr; XWindowAttributes g_attr; root = ui_get_root_window(win); XGetWindowAttributes(root->disp->display, root->my_window, &g_attr); if (flag) { s_attr.override_redirect = True; } else { s_attr.override_redirect = False; } if (g_attr.override_redirect == s_attr.override_redirect) { return; } XChangeWindowAttributes(root->disp->display, root->my_window, CWOverrideRedirect, &s_attr); if (g_attr.map_state != IsUnmapped) { XUnmapWindow(root->disp->display, root->my_window); XMapWindow(root->disp->display, root->my_window); } reset_input_focus(root); /* XXX Always focused not to execute XSetInputFocus(). */ win->inputtable = win->is_focused = 1; } int ui_window_set_borderless_flag(ui_window_t *win, int flag) { /* * XXX * Support borderless with _MOTIF_WM_HINTS. * (See Eterm/src/windows.c) */ ui_window_t *root; Atom atom; root = ui_get_root_window(win); #ifdef __DEBUG bl_debug_printf("MOTIF_WM_HINTS: %x\nMOTIF_WM_INFO: %x\n", XInternAtom(root->disp->display, "_MOTIF_WM_HINTS", True), XInternAtom(root->disp->display, "_MOTIF_WM_INFO", True)); #endif if ((atom = XA_MWM_HINTS(root->disp->display)) != None) { if (flag) { MWMHints_t mwmhints = {MWM_HINTS_DECORATIONS, 0, 0, 0, 0}; XChangeProperty(root->disp->display, root->my_window, atom, atom, 32, PropModeReplace, (u_char *)&mwmhints, sizeof(MWMHints_t) / sizeof(u_long)); } else { XDeleteProperty(root->disp->display, root->my_window, atom); } } else { /* fall back to override redirect */ ui_window_set_override_redirect(win, flag); } return 1; } int ui_window_move(ui_window_t *win, int x, int y) { if (win->parent) { x += win->parent->hmargin; y += win->parent->vmargin; } if (win->x == x && win->y == y) { return 0; } win->x = x; win->y = y; XMoveWindow(win->disp->display, win->my_window, win->x, win->y); if (!win->configure_root && win->parent) { notify_configure_to_children(win); } return 1; } void ui_window_clear(ui_window_t *win, int x, int y, u_int width, u_int height) { #ifdef AUTO_CLEAR_MARGIN if (x + width >= win->width) { /* Clearing margin area */ width += win->hmargin; } if (x > 0) #endif { x += win->hmargin; } #ifdef AUTO_CLEAR_MARGIN else { /* Clearing margin area */ width += win->hmargin; } if (y + height >= win->height) { /* Clearing margin area */ height += win->vmargin; } if (y > 0) #endif { y += win->vmargin; } #ifdef AUTO_CLEAR_MARGIN else { /* Clearing margin area */ height += win->vmargin; } #endif XClearArea(win->disp->display, win->my_window, x, y, width, height, False); } void ui_window_clear_all(ui_window_t *win) { ui_window_clear(win, 0, 0, win->width, win->height); } void ui_window_fill(ui_window_t *win, int x, int y, u_int width, u_int height) { restore_fg_color(win); XFillRectangle(win->disp->display, win->my_window, win->gc->gc, x + win->hmargin, y + win->vmargin, width, height); } void ui_window_fill_with(ui_window_t *win, ui_color_t *color, int x, int y, u_int width, u_int height) { ui_gc_set_fg_color(win->gc, color->pixel); XFillRectangle(win->disp->display, win->my_window, win->gc->gc, x + win->hmargin, y + win->vmargin, width, height); } void ui_window_blank(ui_window_t *win) { restore_fg_color(win); XFillRectangle(win->disp->display, win->my_window, win->gc->gc, win->hmargin, win->vmargin, win->width - RIGHT_MARGIN(win), win->height - BOTTOM_MARGIN(win)); } #if 0 /* * XXX * At the present time, not used and not maintained. */ void ui_window_blank_with(ui_window_t *win, ui_color_t *color) { ui_gc_set_fg_color(win->gc, color->pixel); XFillRectangle(win->disp->display, win->my_window, win->gc->gc, win->hmargin, win->vmargin, win->width, win->height); } #endif void ui_window_update(ui_window_t *win, int flag) { if (win->update_window) { (*win->update_window)(win, flag); if (win->gc->mask) { /* * ui_window_copy_area() can set win->gc->mask. * It can cause unexpected drawing in ui_animate_inline_pictures(). */ XSetClipMask(win->disp->display, win->gc->gc, None); win->gc->mask = None; } } } void ui_window_update_all(ui_window_t *win) { u_int count; clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } for (count = 0; count < win->num_children; count++) { ui_window_update_all(win->children[count]); } } void ui_window_idling(ui_window_t *win) { u_int count; for (count = 0; count < win->num_children; count++) { ui_window_idling(win->children[count]); } #ifdef __DEBUG if (win->button_is_pressing) { bl_debug_printf(BL_DEBUG_TAG " button is pressing...\n"); } #endif if (win->button_is_pressing && win->button_press_continued) { (*win->button_press_continued)(win, &win->prev_button_press_event); } else if (win->idling) { (*win->idling)(win); } } /* * Return value: 0 => different window. * 1 => finished processing. */ int ui_window_receive_event(ui_window_t *win, XEvent *event) { u_int count; for (count = 0; count < win->num_children; count++) { if (ui_window_receive_event(win->children[count], event)) { return 1; } } if (win->my_window != event->xany.window) { /* * XXX * if some window invokes xim window open event and it doesn't have any xic * , * no xim window will be opened at XFilterEvent() in * ui_display_receive_next_event(). * but it is desired to open xim window of ui_screen when its event is * invoked * on scrollbar or title bar. * this hack enables it , but this way won't deal with the case that * multiple * xics exist. */ if (win->xic) { if (is_in_the_same_window_family(win, event->xany.window) && XFilterEvent(event, win->my_window)) { return 1; } } if (event->type == PropertyNotify && win == ui_get_root_window(win) && (event->xproperty.atom == XA_XSETROOT_ID(win->disp->display) || event->xproperty.atom == XA_XROOTPMAP_ID(win->disp->display))) { /* * Background image is changed. * (notify_property_to_children() is called here because * event->xproperty.window is not win->my_window.) * * twm => XA_XSETROOT_ID * englightment => XA_XROOTPMAP_ID */ notify_property_to_children(win); return 1; } if (event->type == MappingNotify && event->xmapping.request != MappingPointer) { if (win->disp) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " MappingNotify serial #%d\n", event->xmapping.serial); #endif XRefreshKeyboardMapping(&(event->xmapping)); ui_display_update_modifier_mapping(win->disp, event->xmapping.serial); /* have to process only once */ return 1; } if (win->mapping_notify) { (*win->mapping_notify)(win); } } return 0; } #ifndef DISABLE_XDND if (ui_dnd_filter_event(event, win)) { /* event was consumed by xdnd handlers */ return 1; } #endif if (event->type == KeyPress) { if (win->key_pressed) { (*win->key_pressed)(win, &event->xkey); } } else if (event->type == FocusIn) { #ifdef __DEBUG bl_debug_printf("FOCUS IN %p (parent %p)\n", event->xany.window, win->parent); #endif urgent_bell(win, 0); if (!win->parent && get_num_inputtables(win) > 1) { ensure_input_focus(win); } else { /* * Cygwin/X can send FocusIn/FocusOut events not to top windows * but to child ones in changing window focus, so don't encircle * notify_focus_{in|out}_to_children with if(!win->parent). */ notify_focus_in_to_children(win); } } else if (event->type == FocusOut) { #ifdef __DEBUG bl_debug_printf("FOCUS OUT %p (parent %p)\n", event->xany.window, win->parent); #endif /* * Cygwin/X can send FocusIn/FocusOut events not to top windows * but to child ones in changing window focus, so don't encircle * notify_focus_{in|out}_to_children with if(!win->parent). */ notify_focus_out_to_children(win); } else if (event->type == MotionNotify) { XEvent ahead; while (XEventsQueued(win->disp->display, QueuedAfterReading)) { XPeekEvent(win->disp->display, &ahead); if (ahead.type != MotionNotify || ahead.xmotion.window != event->xmotion.window) { break; } XNextEvent(win->disp->display, event); } /* * If ButtonReleaseMask is not set to win->event_mask, * win->button_is_pressing * is always 0. So, event->xmotion.state is also checked. */ if (win->button_is_pressing || (event->xmotion.state & ButtonMask)) { if (win->button_motion) { event->xmotion.x -= win->hmargin; event->xmotion.y -= win->vmargin; (*win->button_motion)(win, &event->xmotion); } /* following button motion ... */ win->prev_button_press_event.x = event->xmotion.x; win->prev_button_press_event.y = event->xmotion.y; win->prev_button_press_event.time = event->xmotion.time; } else if (win->pointer_motion) { event->xmotion.x -= win->hmargin; event->xmotion.y -= win->vmargin; (*win->pointer_motion)(win, &event->xmotion); } } else if (event->type == ButtonRelease) { if (win->button_released) { event->xbutton.x -= win->hmargin; event->xbutton.y -= win->vmargin; (*win->button_released)(win, &event->xbutton); } win->button_is_pressing = 0; } else if (event->type == ButtonPress) { if (win->button_pressed) { event->xbutton.x -= win->hmargin; event->xbutton.y -= win->vmargin; /* XXX If button is released outside screen, ButtonRelease event might not happen. */ if (win->button_is_pressing) { if (win->button_released) { XButtonEvent ev = event->xbutton; ev.type = ButtonRelease; (*win->button_released)(win, &ev); } win->button_is_pressing = 0; } if (win->click_num == MAX_CLICK) { win->click_num = 0; } if (win->prev_clicked_time + click_interval >= event->xbutton.time && event->xbutton.button == win->prev_clicked_button) { win->click_num++; win->prev_clicked_time = event->xbutton.time; } else { win->click_num = 1; win->prev_clicked_time = event->xbutton.time; win->prev_clicked_button = event->xbutton.button; } (*win->button_pressed)(win, &event->xbutton, win->click_num); } if (win->event_mask & ButtonReleaseMask) { /* * if ButtonReleaseMask is not set and ui_window_t doesn't receive * ButtonRelease event , button_is_pressing flag must never be set , * since once it is set , it will never unset. */ win->button_is_pressing = 1; win->prev_button_press_event = event->xbutton; } /* XXX Note that win->is_focused is always true on override redirect mode. */ if (!win->is_focused && win->inputtable && event->xbutton.button == Button1 && !event->xbutton.state) { ui_window_set_input_focus(win); } } else if (event->type == NoExpose) { win->wait_copy_area_response = 0; } else if (event->type == Expose || event->type == GraphicsExpose) { XEvent next_ev; int x; int y; u_int width; u_int height; int margin_area_exposed; #ifdef __DEBUG int nskip = 0; #endif /* Optimize redrawing. */ while (XCheckTypedWindowEvent(win->disp->display, win->my_window, event->type, &next_ev)) { XEvent ev; int diff; ev = *event; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " x %d y %d w %d h %d + x %d y %d w %d h %d ->", ev.xexpose.x, ev.xexpose.y, ev.xexpose.width, ev.xexpose.height, next_ev.xexpose.x, next_ev.xexpose.y, next_ev.xexpose.width, next_ev.xexpose.height); #endif if ((diff = ev.xexpose.x - next_ev.xexpose.x) > 0) { ev.xexpose.width += diff; ev.xexpose.x = next_ev.xexpose.x; } if ((diff = next_ev.xexpose.x + next_ev.xexpose.width - ev.xexpose.x - ev.xexpose.width) > 0) { ev.xexpose.width += diff; } if ((diff = ev.xexpose.y - next_ev.xexpose.y) > 0) { ev.xexpose.height += diff; ev.xexpose.y = next_ev.xexpose.y; } if ((diff = next_ev.xexpose.y + next_ev.xexpose.height - ev.xexpose.y - ev.xexpose.height) > 0) { ev.xexpose.height += diff; } #ifdef __DEBUG bl_msg_printf(" x %d y %d w %d h %d\n", ev.xexpose.x, ev.xexpose.y, ev.xexpose.width, ev.xexpose.height); #endif /* Minimum character size is regarded as w5 ui.h10. */ if ((ev.xexpose.width * ev.xexpose.height) / 4 >= (BL_MAX(event->xexpose.width, 5) * BL_MAX(event->xexpose.height, 10) + BL_MAX(next_ev.xexpose.width, 5) * BL_MAX(next_ev.xexpose.height, 10)) / 3) { /* Redrawing area is increased over 33.3% by this combination. */ #ifdef __DEBUG bl_msg_printf( "=> Discard combination of XExposeEvents " "because of inefficiency.\n"); #endif XPutBackEvent(win->disp->display, &next_ev); break; } else { #ifdef __DEBUG nskip++; #endif *event = ev; } } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " skipped %d expose events.\n", nskip); #endif margin_area_exposed = 0; if (event->xexpose.x < win->hmargin) { margin_area_exposed = 1; x = 0; if (x + event->xexpose.width > win->width) { width = win->width; } else if (event->xexpose.width < (win->hmargin - event->xexpose.x)) { width = 0; } else { width = event->xexpose.width - (win->hmargin - event->xexpose.x); } } else { x = event->xexpose.x - win->hmargin; if (x + event->xexpose.width > win->width) { margin_area_exposed = 1; width = win->width - x; } else { width = event->xexpose.width; } } if (event->xexpose.y < win->vmargin) { margin_area_exposed = 1; y = 0; if (y + event->xexpose.height > win->height) { height = win->height; } else if (event->xexpose.height < (win->vmargin - event->xexpose.y)) { height = 0; } else { height = event->xexpose.height - (win->vmargin - event->xexpose.y); } } else { y = event->xexpose.y - win->vmargin; if (y + event->xexpose.height > win->height) { margin_area_exposed = 1; height = win->height - y; } else { height = event->xexpose.height; } } /* * It is desirable to set win->is_scrollable = 0 before calling * window_exposed event for GraphicsExpose event, because * GraphicsExpose event itself is caused by scrolling (XCopyArea). * * XXX * But win->is_scrollable = 0 is disabled for now because there * seems no cases which cause definite inconvenience. * (ref. flush_scroll_cache() in ui_screen.c) */ if (event->type == GraphicsExpose) { win->wait_copy_area_response = 0; #if 0 win->is_scrollable = 0; #endif } if (margin_area_exposed) { clear_margin_area(win); } if (win->window_exposed) { (*win->window_exposed)(win, x, y, width, height); } #if 0 else { ui_window_clear_all(win); } #endif #if 0 if (event->type == GraphicsExpose) { win->is_scrollable = 1; } #endif } else if (event->type == ConfigureNotify) { int is_changed; XEvent next_ev; /* * Optimize transparent processing in notify_configure_to_children. */ while (XCheckTypedWindowEvent(win->disp->display, win->my_window, ConfigureNotify, &next_ev)) { *event = next_ev; } is_changed = 0; if (event->xconfigure.x != win->x || event->xconfigure.y != win->y) { /* * for fvwm2 style virtual screen. */ if (abs(event->xconfigure.x - win->x) % win->disp->width != 0 || abs(event->xconfigure.y - win->y) % win->disp->height != 0 || (event->xconfigure.x < 0 && event->xconfigure.x + (int)ACTUAL_WIDTH(win) > 0) || (event->xconfigure.x > 0 && event->xconfigure.x + (int)ACTUAL_WIDTH(win) > (int)win->disp->width) || (event->xconfigure.y < 0 && event->xconfigure.y + (int)ACTUAL_HEIGHT(win) > 0) || (event->xconfigure.y > 0 && event->xconfigure.y + (int)ACTUAL_HEIGHT(win) > (int)win->disp->height)) { is_changed = 1; } win->x = event->xconfigure.x; win->y = event->xconfigure.y; } if (event->xconfigure.width != ACTUAL_WIDTH(win) || event->xconfigure.height != ACTUAL_HEIGHT(win)) { win->width = event->xconfigure.width - win->hmargin * 2; win->height = event->xconfigure.height - win->vmargin * 2; if (win->window_resized) { win->configure_root = 1; (*win->window_resized)(win); win->configure_root = 0; } is_changed = 1; #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if (win->cairo_draw) { cairo_resize(win); } #endif } if (is_changed) { notify_configure_to_children(win); } } else if (event->type == ReparentNotify) { XEvent next_ev; /* * Optimize transparent processing in notify_reparent_to_children. */ while (XCheckTypedWindowEvent(win->disp->display, win->my_window, ReparentNotify, &next_ev)) { *event = next_ev; } win->x = event->xreparent.x; win->y = event->xreparent.y; notify_reparent_to_children(win); } #if 0 else if (event->type == MapNotify) { if (win->is_transparent && !win->wall_picture_is_set) { set_transparent(win); } } #endif else if (event->type == SelectionClear) { /* Call win->selection_cleared in ui_display_clear_selection. */ ui_display_clear_selection(win->disp, win); free(sel_bmp); sel_bmp = NULL; } else if (event->type == SelectionRequest) { Atom xa_utf8_string; Atom xa_compound_text; #ifdef DEBUG Atom xa_multiple; #endif Atom xa_targets; Atom xa_text; Atom xa_bmp; xa_compound_text = XA_COMPOUND_TEXT(win->disp->display); xa_targets = XA_TARGETS(win->disp->display); #ifdef DEBUG xa_multiple = XA_MULTIPLE(win->disp->display); #endif xa_text = XA_TEXT(win->disp->display); xa_utf8_string = XA_UTF8_STRING(win->disp->display); xa_bmp = XA_BMP(win->disp->display); if (event->xselectionrequest.target == XA_STRING) { if (win->xct_selection_requested) { (*win->xct_selection_requested)(win, &event->xselectionrequest, event->xselectionrequest.target); } } else if (event->xselectionrequest.target == xa_text || event->xselectionrequest.target == xa_compound_text) { if (win->xct_selection_requested) { /* * kterm requests selection with "TEXT" atom , but * wants it to be sent back with "COMPOUND_TEXT" atom. * why ? */ (*win->xct_selection_requested)(win, &event->xselectionrequest, xa_compound_text); } } else if (event->xselectionrequest.target == xa_utf8_string) { if (win->utf_selection_requested) { (*win->utf_selection_requested)(win, &event->xselectionrequest, xa_utf8_string); } } else if (event->xselectionrequest.target == xa_targets) { Atom targets[6]; targets[0] = xa_targets; targets[1] = XA_STRING; targets[2] = xa_text; targets[3] = xa_compound_text; targets[4] = xa_utf8_string; targets[5] = xa_bmp; send_selection(win, &event->xselectionrequest, (u_char *)targets, sizeof(targets) / sizeof targets[0], XA_ATOM, 32); } #ifdef DEBUG else if (event->xselectionrequest.target == xa_multiple) { bl_debug_printf("MULTIPLE requested(not yet implemented)\n"); } #endif else if (event->xselectionrequest.target == xa_bmp && sel_bmp) { send_selection(win, &event->xselectionrequest, (u_char *)sel_bmp, sel_bmp_size, xa_bmp, 8); } else { send_selection(win, &event->xselectionrequest, NULL, 0, 0, 0); } } else if (event->type == SelectionNotify) { Atom xa_utf8_string; Atom xa_compound_text; Atom xa_text; Atom xa_selection; xa_compound_text = XA_COMPOUND_TEXT(win->disp->display); xa_text = XA_TEXT(win->disp->display); xa_utf8_string = XA_UTF8_STRING(win->disp->display); xa_selection = XA_SELECTION(win->disp->display); if (event->xselection.property == None || event->xselection.property == XA_NONE(win->disp->display)) { /* * Selection request failed. * Retrying with xa_compound_text => xa_text => XA_STRING */ if (event->xselection.target == xa_utf8_string) { XConvertSelection(win->disp->display, XA_PRIMARY, xa_compound_text, xa_selection, win->my_window, CurrentTime); } else if (event->xselection.target == xa_compound_text) { XConvertSelection(win->disp->display, XA_PRIMARY, xa_text, xa_selection, win->my_window, CurrentTime); } else if (event->xselection.target == xa_text) { XConvertSelection(win->disp->display, XA_PRIMARY, XA_STRING, xa_selection, win->my_window, CurrentTime); } return 1; } /* SELECTION */ if (event->xselection.selection == XA_PRIMARY && (event->xselection.property == xa_selection && (event->xselection.target == XA_STRING || event->xselection.target == xa_text || event->xselection.target == xa_compound_text || event->xselection.target == xa_utf8_string))) { u_long bytes_after; XTextProperty ct; int seg; for (seg = 0;; seg += ct.nitems) { /* * XXX * long_offset and long_len is the same as rxvt-2.6.3 , * but I'm not confident if this is OK. */ if (XGetWindowProperty(win->disp->display, event->xselection.requestor, event->xselection.property, seg / 4, 4096, False, AnyPropertyType, &ct.encoding, &ct.format, &ct.nitems, &bytes_after, &ct.value) != Success) { break; } if (ct.value == NULL || ct.nitems == 0) { break; } if (ct.encoding == XA_STRING || ct.encoding == xa_text || ct.encoding == xa_compound_text) { if (win->xct_selection_notified) { (*win->xct_selection_notified)(win, ct.value, ct.nitems); } } else if (ct.encoding == xa_utf8_string) { if (win->utf_selection_notified) { (*win->utf_selection_notified)(win, ct.value, ct.nitems); } } XFree(ct.value); if (bytes_after == 0) { break; } } } XDeleteProperty(win->disp->display, event->xselection.requestor, event->xselection.property); } else if (event->type == ClientMessage) { if (event->xclient.format == 32 && event->xclient.data.l[0] == XA_DELETE_WINDOW(win->disp->display)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " DeleteWindow message is received. exiting...\n"); #endif if (win->window_destroyed) { (*win->window_destroyed)(win); } else { exit(0); } } #if 0 else if (event->xclient.format == 32 && event->xclient.data.l[0] == XA_TAKE_FOCUS(win->disp->display)) { bl_warn_printf(BL_DEBUG_TAG " TakeFocus message is received.\n"); } #endif } else if (event->type == PropertyNotify) { if (event->xproperty.atom == XA_SELECTION(win->disp->display) && event->xproperty.state == PropertyNewValue) { XTextProperty ct; u_long bytes_after; XGetWindowProperty(win->disp->display, event->xproperty.window, event->xproperty.atom, 0, 0, False, AnyPropertyType, &ct.encoding, &ct.format, &ct.nitems, &bytes_after, &ct.value); if (ct.value) { XFree(ct.value); } if (ct.encoding == XA_INCR(win->disp->display) || bytes_after == 0) { XDeleteProperty(win->disp->display, event->xproperty.window, ct.encoding); } else { XGetWindowProperty(win->disp->display, event->xproperty.window, event->xproperty.atom, 0, bytes_after, True, AnyPropertyType, &ct.encoding, &ct.format, &ct.nitems, &bytes_after, &ct.value); if (ct.encoding == XA_STRING || ct.encoding == XA_TEXT(win->disp->display) || ct.encoding == XA_COMPOUND_TEXT(win->disp->display)) { if (win->xct_selection_notified) { (*win->xct_selection_notified)(win, ct.value, ct.nitems); } } else if (ct.encoding == XA_UTF8_STRING(win->disp->display)) { if (win->utf_selection_notified) { (*win->utf_selection_notified)(win, ct.value, ct.nitems); } } if (ct.value) { XFree(ct.value); } } } } #ifdef __DEBUG else { bl_warn_printf(BL_DEBUG_TAG " event %d is received, but not processed.\n", event->type); } #endif return 1; } size_t ui_window_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { size_t len; *keysym = 0; if ((len = ui_xic_get_str(win, seq, seq_len, parser, keysym, event)) > 0) { return len; } if ((len = XLookupString(event, seq, seq_len, keysym, NULL)) > 0) { *parser = NULL; return len; } if ((len = ui_xic_get_utf8_str(win, seq, seq_len, parser, keysym, event)) > 0) { return len; } return 0; } /* * Scroll functions. * The caller side should clear the scrolled area. */ int ui_window_scroll_upward(ui_window_t *win, u_int height) { return ui_window_scroll_upward_region(win, 0, win->height, height); } int ui_window_scroll_upward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d in window((h) %d (w) %d)\n", boundary_start, boundary_end, height, win->height, win->width); #endif return 0; } scroll_region(win, 0, boundary_start + height, /* src */ win->width, boundary_end - boundary_start - height, /* size */ 0, boundary_start); /* dst */ return 1; } int ui_window_scroll_downward(ui_window_t *win, u_int height) { return ui_window_scroll_downward_region(win, 0, win->height, height); } int ui_window_scroll_downward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d\n", boundary_start, boundary_end, height); #endif return 0; } scroll_region(win, 0, boundary_start, win->width, boundary_end - boundary_start - height, 0, boundary_start + height); return 1; } int ui_window_scroll_leftward(ui_window_t *win, u_int width) { return ui_window_scroll_leftward_region(win, 0, win->width, width); } int ui_window_scroll_leftward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d in window((h) %d (w) %d)\n", boundary_start, boundary_end, width, win->height, win->width); #endif return 0; } scroll_region(win, boundary_start + width, 0, /* src */ boundary_end - boundary_start - width, win->height, /* size */ boundary_start, 0); /* dst */ return 1; } int ui_window_scroll_rightward(ui_window_t *win, u_int width) { return ui_window_scroll_rightward_region(win, 0, win->width, width); } int ui_window_scroll_rightward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d\n", boundary_start, boundary_end, width); #endif return 0; } scroll_region(win, boundary_start, 0, boundary_end - boundary_start - width, win->height, boundary_start + width, 0); return 1; } int ui_window_copy_area(ui_window_t *win, Pixmap src, PixmapMask mask, int src_x, /* >= 0 */ int src_y, /* >= 0 */ u_int width, u_int height, int dst_x, /* >= 0 */ int dst_y /* >= 0 */ ) { if (dst_x >= win->width || dst_y >= win->height) { return 0; } if (dst_x + width > win->width) { width = win->width - dst_x; } if (dst_y + height > win->height) { height = win->height - dst_y; } if (win->gc->mask != mask) { XSetClipMask(win->disp->display, win->gc->gc, mask); win->gc->mask = mask; } if (mask) { XSetClipOrigin(win->disp->display, win->gc->gc, dst_x + win->hmargin - src_x, dst_y + win->vmargin - src_y); } XCopyArea(win->disp->display, src, win->my_window, win->gc->gc, src_x, src_y, width, height, dst_x + win->hmargin, dst_y + win->vmargin); return 1; } void ui_window_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height) { #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if (win->cairo_draw) { cairo_set_clip(win, x + win->hmargin, y + win->vmargin, width, height); } else #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) if (win->xft_draw) { xft_set_clip(win, x + win->hmargin, y + win->vmargin, width, height); } else #endif { XRectangle rect; rect.x = 0; rect.y = 0; rect.width = width; rect.height = height; XSetClipRectangles(win->disp->display, win->gc->gc, x + win->hmargin, y + win->vmargin, &rect, 1, YSorted); } } void ui_window_unset_clip(ui_window_t *win) { #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if (win->cairo_draw) { cairo_unset_clip(win); } else #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) if (win->xft_draw) { xft_unset_clip(win); } else #endif { XSetClipMask(win->disp->display, win->gc->gc, None); } } void ui_window_draw_decsp_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int len) { convert_to_decsp_font_index(str, len); if (font->decsp_font) { ui_gc_set_fg_color(win->gc, fg_color->pixel); ui_decsp_font_draw_string(font->decsp_font, win->disp->display, win->my_window, win->gc->gc, x + win->hmargin, y + win->vmargin, str, len); } #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) else if (font->xfont) { ui_window_draw_string(win, font, fg_color, x, y, str, len); } #endif } void ui_window_draw_decsp_image_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, u_char *str, u_int len) { convert_to_decsp_font_index(str, len); if (font->decsp_font) { ui_gc_set_fg_color(win->gc, fg_color->pixel); ui_gc_set_bg_color(win->gc, bg_color->pixel); ui_decsp_font_draw_image_string(font->decsp_font, win->disp->display, win->my_window, win->gc->gc, x + win->hmargin, y + win->vmargin, str, len); } #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) else if (font->xfont) { ui_window_draw_image_string(win, font, fg_color, bg_color, x, y, str, len); } #endif } #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) void ui_window_draw_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int len) { /* Removing trailing spaces. */ while (1) { if (len == 0) { return; } if (*(str + len - 1) == ' ') { len--; } else { break; } } ui_gc_set_fid(win->gc, font->xfont->fid); ui_gc_set_fg_color(win->gc, fg_color->pixel); XDrawString(win->disp->display, win->my_window, win->gc->gc, x + font->x_off + win->hmargin, y + win->vmargin, (char *)str, len); if (font->double_draw_gap) { XDrawString(win->disp->display, win->my_window, win->gc->gc, x + font->x_off + win->hmargin + font->double_draw_gap, y + win->vmargin, (char *)str, len); } } void ui_window_draw_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, XChar2b *str, u_int len) { ui_gc_set_fid(win->gc, font->xfont->fid); ui_gc_set_fg_color(win->gc, fg_color->pixel); XDrawString16(win->disp->display, win->my_window, win->gc->gc, x + font->x_off + win->hmargin, y + win->vmargin, str, len); if (font->double_draw_gap) { XDrawString16(win->disp->display, win->my_window, win->gc->gc, x + font->x_off + win->hmargin + font->double_draw_gap, y + win->vmargin, str, len); } } void ui_window_draw_image_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, u_char *str, u_int len) { ui_gc_set_fid(win->gc, font->xfont->fid); ui_gc_set_fg_color(win->gc, fg_color->pixel); ui_gc_set_bg_color(win->gc, bg_color->pixel); XDrawImageString(win->disp->display, win->my_window, win->gc->gc, x + font->x_off + win->hmargin, y + win->vmargin, (char *)str, len); if (font->double_draw_gap) { XDrawString(win->disp->display, win->my_window, win->gc->gc, x + font->x_off + win->hmargin + font->double_draw_gap, y + win->vmargin, (char *)str, len); } } void ui_window_draw_image_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, XChar2b *str, u_int len) { ui_gc_set_fid(win->gc, font->xfont->fid); ui_gc_set_fg_color(win->gc, fg_color->pixel); ui_gc_set_bg_color(win->gc, bg_color->pixel); XDrawImageString16(win->disp->display, win->my_window, win->gc->gc, x + font->x_off + win->hmargin, y + win->vmargin, str, len); if (font->double_draw_gap) { XDrawString16(win->disp->display, win->my_window, win->gc->gc, x + font->x_off + win->hmargin + font->double_draw_gap, y + win->vmargin, str, len); } } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO) void ui_window_ft_draw_string8(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, size_t len) { #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if (win->cairo_draw) { ui_window_cairo_draw_string8(win, font, fg_color, x, y, str, len); return; } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) if (win->xft_draw) { ui_window_xft_draw_string8(win, font, fg_color, x, y, str, len); return; } #endif } void ui_window_ft_draw_string32(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, /* FcChar32 */ u_int32_t *str, u_int len) { #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if (win->cairo_draw) { ui_window_cairo_draw_string32(win, font, fg_color, x, y, str, len); return; } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) if (win->xft_draw) { ui_window_xft_draw_string32(win, font, fg_color, x, y, str, len); return; } #endif } #endif void ui_window_draw_rect_frame(ui_window_t *win, int x1, int y1, int x2, int y2) { XPoint points[5] = { {x1 += win->hmargin, y1 += win->vmargin}, {x1, y2 += win->vmargin}, {x2 += win->hmargin, y2}, {x2, y1}, {x1, y1}, }; restore_fg_color(win); XDrawLines(win->disp->display, win->my_window, win->gc->gc, points, 5, CoordModeOrigin); } void ui_set_use_clipboard_selection(int use_it) { if (use_clipboard == use_it) { return; } use_clipboard = use_it; /* * disp->selection_owner is reset. * If it isn't reset and value of 'use_clipboard' option is changed from false * to true dynamically, ui_window_set_selection_owner() returns before calling * XSetSelectionOwner(). */ ui_display_clear_selection(NULL, NULL); } int ui_is_using_clipboard_selection(void) { return use_clipboard; } int ui_window_set_selection_owner(ui_window_t *win, Time time) { if (ui_window_is_selection_owner(win)) { /* Already owner */ return 1; } XSetSelectionOwner(win->disp->display, XA_PRIMARY, win->my_window, time); if (use_clipboard) { XSetSelectionOwner(win->disp->display, XA_CLIPBOARD(win->disp->display), win->my_window, time); } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " XA_PRIMARY => %lu, XA_CLIPBOARD => %lu (mywin %lu)\n", XGetSelectionOwner(win->disp->display, XA_PRIMARY), XGetSelectionOwner(win->disp->display, XA_CLIPBOARD(win->disp->display)), win->my_window); #endif if (win->my_window != XGetSelectionOwner(win->disp->display, XA_PRIMARY) && (!use_clipboard || win->my_window != XGetSelectionOwner(win->disp->display, XA_CLIPBOARD(win->disp->display)))) { return 0; } else { return ui_display_own_selection(win->disp, win); } } int ui_window_xct_selection_request(ui_window_t *win, Time time) { XConvertSelection(win->disp->display, XA_PRIMARY, XA_COMPOUND_TEXT(win->disp->display), XA_SELECTION(win->disp->display), win->my_window, time); return 1; } int ui_window_utf_selection_request(ui_window_t *win, Time time) { XConvertSelection(win->disp->display, XA_PRIMARY, XA_UTF8_STRING(win->disp->display), XA_SELECTION(win->disp->display), win->my_window, time); return 1; } void ui_window_send_picture_selection(ui_window_t *win, Pixmap pixmap, u_int width, u_int height) { XImage *image; if (win->disp->visual->class == TrueColor && (image = XGetImage(win->disp->display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap))) { XVisualInfo *vinfo; if ((vinfo = ui_display_get_visual_info(win->disp))) { int shift[3]; u_long mask[3]; size_t image_size; shift[0] = right_shift((mask[0] = vinfo->blue_mask)); shift[1] = right_shift((mask[1] = vinfo->green_mask)); shift[2] = right_shift((mask[2] = vinfo->red_mask)); image_size = width * height * 4; sel_bmp_size = image_size + 54; if ((sel_bmp = calloc(1, sel_bmp_size))) { int x; int y; u_char *dst; sel_bmp->h_type[0] = 0x42; sel_bmp->h_type[1] = 0x4d; sel_bmp->h_size[0] = sel_bmp_size & 0xff; sel_bmp->h_size[1] = (sel_bmp_size >> 8) & 0xff; sel_bmp->h_size[2] = (sel_bmp_size >> 16) & 0xff; sel_bmp->h_size[3] = (sel_bmp_size >> 24) & 0xff; sel_bmp->h_offbits[0] = 54; sel_bmp->i_size[0] = 40; sel_bmp->i_width[0] = width & 0xff; sel_bmp->i_width[1] = (width >> 8) & 0xff; sel_bmp->i_width[2] = (width >> 16) & 0xff; sel_bmp->i_width[3] = (width >> 24) & 0xff; sel_bmp->i_height[0] = height & 0xff; sel_bmp->i_height[1] = (height >> 8) & 0xff; sel_bmp->i_height[2] = (height >> 16) & 0xff; sel_bmp->i_height[3] = (height >> 24) & 0xff; sel_bmp->i_planes[0] = 1; sel_bmp->i_bitcount[0] = 32; sel_bmp->i_sizeimage[0] = image_size & 0xff; sel_bmp->i_sizeimage[1] = (image_size >> 8) & 0xff; sel_bmp->i_sizeimage[2] = (image_size >> 16) & 0xff; sel_bmp->i_sizeimage[3] = (image_size >> 24) & 0xff; dst = sel_bmp->data; for (y = height - 1; y >= 0; y--) { for (x = 0; x < width; x++) { u_long pixel; int count; pixel = XGetPixel(image, x, y); for (count = 0; count < 3; count++) { if (shift[count] < 0) { *(dst++) = (pixel & mask[count]) << (-shift[count]); } else { *(dst++) = (pixel & mask[count]) >> (shift[count]); } } *(dst++) = 0x00; } } ui_window_set_selection_owner(win, CurrentTime); bl_msg_printf("Set a clicked picture to the clipboard.\n"); } XFree(vinfo); } XDestroyImage(image); } } void ui_window_send_text_selection(ui_window_t *win, XSelectionRequestEvent *req_ev, u_char *sel_data, size_t sel_len, Atom sel_type) { XEvent res_ev; res_ev.xselection.type = SelectionNotify; res_ev.xselection.display = req_ev->display; res_ev.xselection.requestor = req_ev->requestor; res_ev.xselection.selection = req_ev->selection; res_ev.xselection.target = req_ev->target; res_ev.xselection.time = req_ev->time; if (sel_data == NULL) { res_ev.xselection.property = None; } else { if (req_ev->property == None) { /* An obsolete client may fill None as a property. * Try to deal with them by using 'target' instead. */ req_ev->property = req_ev->target; } if (req_ev->property != None) { XChangeProperty(win->disp->display, req_ev->requestor, req_ev->property, sel_type, 8, PropModeReplace, sel_data, sel_len); } res_ev.xselection.property = req_ev->property; } XSendEvent(win->disp->display, res_ev.xselection.requestor, False, 0, &res_ev); } void ui_set_window_name(ui_window_t *win, u_char *name) { ui_window_t *root; XTextProperty prop; root = ui_get_root_window(win); if (name == NULL) { name = root->app_name; } if (XmbTextListToTextProperty(root->disp->display, (char **)&name, 1, XStdICCTextStyle, &prop) >= Success) { Atom atom; XSetWMName(root->disp->display, root->my_window, &prop); XFree(prop.value); if (locale_is_utf8() && (atom = XInternAtom(root->disp->display, "_NET_WM_NAME", True)) != None) { XChangeProperty(root->disp->display, root->my_window, atom, XA_UTF8_STRING(root->disp->display), 8, PropModeReplace, name, strlen(name)); } #ifdef DEBUG else { bl_debug_printf("_NET_WM_NAME is not set.\n"); } #endif } else { /* XXX which is better , doing this or return 0 without doing anything ? */ XStoreName(root->disp->display, root->my_window, name); } } void ui_set_icon_name(ui_window_t *win, u_char *name) { ui_window_t *root; XTextProperty prop; root = ui_get_root_window(win); if (name == NULL) { name = root->app_name; } if (XmbTextListToTextProperty(root->disp->display, (char **)&name, 1, XStdICCTextStyle, &prop) >= Success) { Atom atom; XSetWMIconName(root->disp->display, root->my_window, &prop); XFree(prop.value); if (locale_is_utf8() && (atom = XInternAtom(root->disp->display, "_NET_ICON_NAME", True)) != None) { XChangeProperty(root->disp->display, root->my_window, atom, XA_UTF8_STRING(root->disp->display), 8, PropModeReplace, name, strlen(name)); } #ifdef DEBUG else { bl_debug_printf("_NET_ICON_NAME is not set.\n"); } #endif } else { /* XXX which is better , doing this or return 0 without doing anything ? */ XSetIconName(root->disp->display, root->my_window, name); } } void ui_window_set_icon(ui_window_t *win, ui_icon_picture_t *icon) { ui_window_t *root; XWMHints *hints; root = ui_get_root_window(win); /* set extended window manager hint's icon */ if (icon->cardinal && icon->cardinal[0] && icon->cardinal[1]) { int num; u_long *data; /* width * height + 2 */ num = icon->cardinal[0] * icon->cardinal[1] + 2; if (sizeof(u_long) != 4) { int count; if (!(data = alloca(sizeof(u_long) * num))) { return; } for (count = 0; count < num; count++) { data[count] = icon->cardinal[count]; } } else { data = icon->cardinal; } /*it should be possible to set multiple icons...*/ XChangeProperty(root->disp->display, root->my_window, XA_NET_WM_ICON(root->disp->display), XA_CARDINAL, 32, PropModeReplace, (u_char *)data, num); } if ((hints = XGetWMHints(root->disp->display, root->my_window)) == NULL && (hints = XAllocWMHints()) == NULL) { return; } if (icon->pixmap) { hints->flags |= IconPixmapHint; hints->icon_pixmap = icon->pixmap; } if (icon->mask) { hints->flags |= IconMaskHint; hints->icon_mask = icon->mask; } XSetWMHints(root->disp->display, root->my_window, hints); XFree(hints); } void ui_window_remove_icon(ui_window_t *win) { ui_window_t *root; XWMHints *hints; root = ui_get_root_window(win); if ((hints = XGetWMHints(root->disp->display, root->my_window))) { #if 0 bl_debug_printf(" Removing icon.\n"); #endif hints->flags &= ~(IconPixmapHint | IconMaskHint); hints->icon_pixmap = None; hints->icon_mask = None; XSetWMHints(root->disp->display, root->my_window, hints); XFree(hints); } XDeleteProperty(root->disp->display, root->my_window, XA_NET_WM_ICON(root->disp->display)); } /* for xlib/ui_display.c */ void ui_window_reset_group(ui_window_t *win) { ui_window_t *root; XWMHints *hints; root = ui_get_root_window(win); if ((hints = XGetWMHints(root->disp->display, root->my_window)) == NULL && (hints = XAllocWMHints()) == NULL) { return; } hints->flags |= WindowGroupHint; hints->window_group = reset_client_leader(root); XSetWMHints(root->disp->display, root->my_window, hints); XFree(hints); } /* for xlib/ui_imagelib.c */ int ui_window_get_visible_geometry(ui_window_t *win, int *x, /* x relative to root window */ int *y, /* y relative to root window */ int *my_x, /* x relative to my window */ int *my_y, /* y relative to my window */ u_int *width, u_int *height) { Window child; XTranslateCoordinates(win->disp->display, win->my_window, win->disp->my_window, 0, 0, x, y, &child); if (*x >= (int)win->disp->width || *y >= (int)win->disp->height) { /* no visible window */ return 0; } if (*x < 0) { if (ACTUAL_WIDTH(win) <= abs(*x)) { /* no visible window */ return 0; } *my_x = abs(*x); *width = ACTUAL_WIDTH(win) - abs(*x); *x = 0; } else { *my_x = 0; *width = ACTUAL_WIDTH(win); } if (*y < 0) { if (ACTUAL_HEIGHT(win) <= abs(*y)) { /* no visible window */ return 0; } *my_y = abs(*y); *height = ACTUAL_HEIGHT(win) - abs(*y); *y = 0; } else { *my_y = 0; *height = ACTUAL_HEIGHT(win); } if (*x + (int)*width > (int)win->disp->width) { *width = win->disp->width - *x; } if (*y + (int)*height > (int)win->disp->height) { *height = win->disp->height - *y; } return 1; } void ui_set_click_interval(int interval) { click_interval = interval; } int ui_get_click_interval(void) { return click_interval; } u_int ui_window_get_mod_ignore_mask(ui_window_t *win, KeySym *keysyms) { XModifierKeymap *mod_map; int count; u_int ignore; u_int masks[] = {Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask}; KeySym default_keysyms[] = {XK_Num_Lock, XK_Scroll_Lock, XK_ISO_Level3_Lock, NoSymbol}; if (!keysyms) { keysyms = default_keysyms; } if ((mod_map = ui_window_get_modifier_mapping(win)) == NULL) { return ~0; } ignore = 0; count = 0; while (keysyms[count] != NoSymbol) { int ks_count; KeyCode kc; kc = XKeysymToKeycode(win->disp->display, keysyms[count]); for (ks_count = 0; ks_count < sizeof(masks) / sizeof(masks[0]); ks_count++) { int kc_count; KeyCode *key_codes; key_codes = &(mod_map->modifiermap[(ks_count + 3) * mod_map->max_keypermod]); for (kc_count = 0; kc_count < mod_map->max_keypermod; kc_count++) { if (key_codes[kc_count] == 0) { break; } if (key_codes[kc_count] == kc) { #ifdef DEBUG bl_debug_printf("keycode = %d, mod%d idx %d (by %s)\n", kc, ks_count + 1, kc_count + 1, XKeysymToString(keysyms[count])); #endif ignore |= masks[ks_count]; break; } } } count++; } return ~ignore; } u_int ui_window_get_mod_meta_mask(ui_window_t *win, char *mod_key) { int mask_count; int kc_count; XModifierKeymap *mod_map; KeyCode *key_codes; KeySym sym; char *mod_keys[] = {"mod1", "mod2", "mod3", "mod4", "mod5"}; u_int mod_masks[] = {Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask}; if (mod_key) { int count; for (count = 0; count < sizeof(mod_keys) / sizeof(mod_keys[0]); count++) { if (strcmp(mod_key, mod_keys[count]) == 0) { return mod_masks[count]; } } } if ((mod_map = ui_window_get_modifier_mapping(win)) == NULL) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " ui_window_get_modifier_mapping failed.\n"); #endif return 0; } key_codes = mod_map->modifiermap; for (mask_count = 0; mask_count < sizeof(mod_masks) / sizeof(mod_masks[0]); mask_count++) { int count; /* * KeyCodes order is like this. * Shift[max_keypermod] Lock[max_keypermod] Control[max_keypermod] * Mod1[max_keypermod] Mod2[max_keypermod] Mod3[max_keypermod] * Mod4[max_keypermod] Mod5[max_keypermod] */ /* * this modmap handling is tested with Xsun and XFree86-4.x * it works fine on both X servers. (2004-10-19 seiichi) */ /* skip shift/lock/control */ kc_count = (mask_count + 3) * mod_map->max_keypermod; for (count = 0; count < mod_map->max_keypermod; count++) { if (key_codes[kc_count] == 0) { break; } sym = XKeycodeToKeysym(win->disp->display, key_codes[kc_count], 0); if (((mod_key == NULL || strcmp(mod_key, "meta") == 0) && (sym == XK_Meta_L || sym == XK_Meta_R)) || ((mod_key == NULL || strcmp(mod_key, "alt") == 0) && (sym == XK_Alt_L || sym == XK_Alt_R)) || ((mod_key == NULL || strcmp(mod_key, "super") == 0) && (sym == XK_Super_L || sym == XK_Super_R)) || ((mod_key == NULL || strcmp(mod_key, "hyper") == 0) && (sym == XK_Hyper_L || sym == XK_Hyper_R))) { return mod_masks[mask_count]; } kc_count++; } } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " No meta key was found.\n"); #endif return 0; } void ui_set_use_urgent_bell(int use) { use_urgent_bell = use; } void ui_window_bell(ui_window_t *win, ui_bel_mode_t mode) { urgent_bell(win, 1); if (mode & BEL_VISUAL) { ui_window_blank(win); #if 0 XSync(win->disp->display, False); #else XFlush(win->disp->display); #endif bl_usleep(1); (*win->window_exposed)(win, 0, 0, win->width, win->height); } if (mode & BEL_SOUND) { XBell(win->disp->display, 0); } } void ui_window_translate_coordinates(ui_window_t *win, int x, int y, int *global_x, int *global_y) { Window child; XTranslateCoordinates(win->disp->display, win->my_window, DefaultRootWindow(win->disp->display), x, y, global_x, global_y, &child); } void ui_window_set_input_focus(ui_window_t *win) { reset_input_focus(ui_get_root_window(win)); win->inputtable = 1; XSetInputFocus(win->disp->display, win->my_window, RevertToParent, CurrentTime); } void ui_window_flush(ui_window_t *win) { #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) if (win->cairo_draw) { /* calls cairo_flush() */ ui_window_cairo_draw_string32(win, NULL, NULL, 0, 0, NULL, 0); } #endif } #ifdef DEBUG void ui_window_dump_children(ui_window_t *win) { int count; bl_msg_printf("%p(%li) => ", win, win->my_window); for (count = 0; count < win->num_children; count++) { bl_msg_printf("%p(%li) ", win->children[count], win->children[count]->my_window); } bl_msg_printf("\n"); for (count = 0; count < win->num_children; count++) { ui_window_dump_children(win->children[count]); } } #endif mlterm-3.8.9/uitoolkit/xlib/ui_xic.c010064400017600000144000000271431356600660700161560ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_xic.h" #include /* strlen */ #include /* X{mb|utf8}LookupString */ #include #include /* malloc */ #include /* bl_get_locale */ #include #include "ui_xim.h" /* refering mutually */ #define HAS_XIM_LISTENER(win, function) ((win)->xim_listener && (win)->xim_listener->function) /* for XIMPreeditArea, XIMStatusArea */ #if 0 #define SET_XNAREA_ATTR #endif /* --- static variables --- */ static ef_parser_t *utf8_parser; /* --- static functions --- */ #ifdef SET_XNAREA_ATTR static void get_rect(ui_window_t *win, XRectangle *rect) { rect->x = 0; rect->y = 0; rect->width = ACTUAL_WIDTH(win); rect->height = ACTUAL_HEIGHT(win); } #endif static int get_spot(ui_window_t *win, XPoint *spot) { int x; int y; if (!HAS_XIM_LISTENER(win, get_spot) || win->xim_listener->get_spot(win->xim_listener->self, &x, &y) == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " xim_listener->get_spot() failed.\n"); #endif return 0; } spot->x = x + win->hmargin; spot->y = y /* + win->vmargin */; return 1; } static XFontSet load_fontset(ui_window_t *win) { char *cur_locale; XFontSet fontset; if ((cur_locale = alloca(strlen(bl_get_locale()) + 1))) { strcpy(cur_locale, bl_get_locale()); } if (bl_locale_init(ui_get_xim_locale(win))) { if (!HAS_XIM_LISTENER(win, get_fontset)) { return NULL; } fontset = (*win->xim_listener->get_fontset)(win->xim_listener->self); /* restoring */ if (cur_locale) { bl_locale_init(cur_locale); } } else { fontset = NULL; } return fontset; } static int destroy_xic(ui_window_t *win) { if (!win->xic) { return 0; } XDestroyIC(win->xic->ic); if (win->xic->fontset) { XFreeFontSet(win->disp->display, win->xic->fontset); } free(win->xic); win->xic = NULL; return 1; } static int create_xic(ui_window_t *win) { XIMStyle selected_style; XVaNestedList preedit_attr; #ifdef SET_XNAREA_ATTR XRectangle rect; #endif XPoint spot; XFontSet fontset; XIC xic; long xim_ev_mask; if (win->xic) { /* already created */ return 0; } if ((selected_style = ui_xim_get_style(win)) == 0) { return 0; } if (selected_style & XIMPreeditPosition) { /* * over the spot style. */ #ifdef SET_XNAREA_ATTR get_rect(win, &rect); #endif if (get_spot(win, &spot) == 0) { /* forcibly set ... */ spot.x = 0; spot.y = 0; } if (!(fontset = load_fontset(win))) { return 0; } if ((preedit_attr = XVaCreateNestedList(0, /* * Some input methods use XNArea to show lookup table, * setting XNArea as follows shows lookup table at unexpected position. */ #ifdef SET_XNAREA_ATTR XNArea, &rect, #endif XNSpotLocation, &spot, XNForeground, (*win->xim_listener->get_fg_color)(win->xim_listener->self)->pixel, XNBackground, (*win->xim_listener->get_bg_color)(win->xim_listener->self)->pixel, XNFontSet, fontset, NULL)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " XVaCreateNestedList() failed.\n"); #endif XFreeFontSet(win->disp->display, fontset); return 0; } if ((xic = ui_xim_create_ic(win, selected_style, preedit_attr)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " XCreateIC() failed\n"); #endif XFree(preedit_attr); XFreeFontSet(win->disp->display, fontset); return 0; } XFree(preedit_attr); } else { /* * root style */ if ((xic = ui_xim_create_ic(win, selected_style, NULL)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " XCreateIC() failed\n"); #endif return 0; } fontset = NULL; } if ((win->xic = malloc(sizeof(ui_xic_t))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc() failed.\n"); #endif if (fontset) { XFreeFontSet(win->disp->display, fontset); } return 0; } win->xic->ic = xic; win->xic->fontset = fontset; win->xic->style = selected_style; xim_ev_mask = 0; XGetICValues(win->xic->ic, XNFilterEvents, &xim_ev_mask, NULL); ui_window_add_event_mask(win, xim_ev_mask); #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " XIC activated.\n"); #endif return 1; } /* --- global functions --- */ int ui_xic_activate(ui_window_t *win, char *xim_name, char *xim_locale) { if (win->xic) { /* already activated */ return 0; } return ui_add_xim_listener(win, xim_name, xim_locale); } int ui_xic_deactivate(ui_window_t *win) { if (win->xic == NULL) { /* already deactivated */ return 0; } #if 0 { /* * this should not be done. */ int xim_ev_mask; XGetICValues(win->xic->ic, XNFilterEvents, &xim_ev_mask, NULL); ui_window_remove_event_mask(win, xim_ev_mask); } #endif destroy_xic(win); if (!ui_remove_xim_listener(win)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ui_remove_xim_listener() failed.\n"); #endif } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " XIC deactivated.\n"); #endif return 1; } char *ui_xic_get_xim_name(ui_window_t *win) { return ui_get_xim_name(win); } char *ui_xic_get_default_xim_name(void) { return ui_get_default_xim_name(); } int ui_xic_fg_color_changed(ui_window_t *win) { XVaNestedList preedit_attr; if (win->xic == NULL || !(win->xic->style & XIMPreeditPosition)) { return 0; } if ((preedit_attr = XVaCreateNestedList( 0, XNForeground, (*win->xim_listener->get_fg_color)(win->xim_listener->self)->pixel, NULL)) == NULL) { return 0; } XSetICValues(win->xic->ic, XNPreeditAttributes, preedit_attr, NULL); XFree(preedit_attr); return 1; } int ui_xic_bg_color_changed(ui_window_t *win) { XVaNestedList preedit_attr; if (win->xic == NULL || !(win->xic->style & XIMPreeditPosition)) { return 0; } if ((preedit_attr = XVaCreateNestedList( 0, XNBackground, (*win->xim_listener->get_bg_color)(win->xim_listener->self)->pixel, NULL)) == NULL) { return 0; } XSetICValues(win->xic->ic, XNPreeditAttributes, preedit_attr, NULL); XFree(preedit_attr); return 1; } int ui_xic_font_set_changed(ui_window_t *win) { XVaNestedList preedit_attr; XFontSet fontset; if (win->xic == NULL || !(win->xic->style & XIMPreeditPosition)) { return 0; } if (!(fontset = load_fontset(win))) { return 0; } if ((preedit_attr = XVaCreateNestedList(0, XNFontSet, fontset, NULL)) == NULL) { XFreeFontSet(win->disp->display, fontset); return 0; } XSetICValues(win->xic->ic, XNPreeditAttributes, preedit_attr, NULL); XFree(preedit_attr); XFreeFontSet(win->disp->display, win->xic->fontset); win->xic->fontset = fontset; return 1; } int ui_xic_resized(ui_window_t *win) { XVaNestedList preedit_attr; #ifdef SET_XNAREA_ATTR XRectangle rect; #endif XPoint spot; if (win->xic == NULL || !(win->xic->style & XIMPreeditPosition)) { return 0; } #ifdef SET_XNAREA_ATTR get_rect(win, &rect); #endif if (get_spot(win, &spot) == 0) { /* forcibly set ...*/ spot.x = 0; spot.y = 0; } if ((preedit_attr = XVaCreateNestedList(0, #ifdef SET_XNAREA_ATTR XNArea, &rect, #endif XNSpotLocation, &spot, NULL)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " XvaCreateNestedList() failed.\n"); #endif return 0; } XSetICValues(win->xic->ic, XNPreeditAttributes, preedit_attr, NULL); XFree(preedit_attr); return 1; } int ui_xic_set_spot(ui_window_t *win) { XVaNestedList preedit_attr; XPoint spot; if (win->xic == NULL || !(win->xic->style & XIMPreeditPosition)) { return 0; } if (get_spot(win, &spot) == 0) { /* XNSpotLocation not changed */ return 0; } if ((preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " XvaCreateNestedList failed.\n"); #endif return 0; } XSetICValues(win->xic->ic, XNPreeditAttributes, preedit_attr, NULL); XFree(preedit_attr); return 1; } size_t ui_xic_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { Status stat; size_t len; if (win->xic == NULL) { return 0; } if ((len = XmbLookupString(win->xic->ic, event, seq, seq_len, keysym, &stat)) == 0) { return 0; } else if (stat == XBufferOverflow /* len > seq_len */) { /* * Input string is too large for seq. seq and keysym are not modified. * len is required size for input string. */ return len; } if (IS_ENCODING_BASED_ON_ISO2022(win->xim->encoding) && *seq < 0x20) { /* * XXX hack * control char(except delete char[0x7f]) is received. * in afraid of it being parsed as part of iso2022 sequence , * *parser is set NULL. */ *parser = NULL; } else { *parser = win->xim->parser; } return len; } size_t ui_xic_get_utf8_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { #ifdef HAVE_XUTF8_LOOKUP_STRING Status stat; size_t len; if (win->xic == NULL) { return 0; } if ((len = Xutf8LookupString(win->xic->ic, event, seq, seq_len, keysym, &stat)) == 0) { return 0; } else if (stat == XBufferOverflow /* len > seq_len */) { /* * Input string is too large for seq. seq and keysym are not modified. * len is required size for input string. */ return len; } if (!utf8_parser) { utf8_parser = ef_utf8_parser_new(); } *parser = utf8_parser; return len; #else return 0; #endif } int ui_xic_set_focus(ui_window_t *win) { if (!win->xic) { return 0; } XSetICFocus(win->xic->ic); return 1; } int ui_xic_unset_focus(ui_window_t *win) { if (!win->xic) { return 0; } XUnsetICFocus(win->xic->ic); return 1; } int ui_xic_is_active(ui_window_t *win) { #ifdef XNPreeditState XIMPreeditState preedit_state; XVaNestedList preedit_attr; int res; if (!win->xic) { return 0; } preedit_attr = XVaCreateNestedList(0, XNPreeditState, &preedit_state, NULL); if (XGetICValues(win->xic->ic, XNPreeditAttributes, preedit_attr, NULL) != NULL) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " XIM doesn't support XNPreeditState.\n"); #endif res = 0; } else { res = (preedit_state == XIMPreeditEnable); #ifdef DEBUG if (res) { bl_debug_printf(BL_DEBUG_TAG " XIM is enabled.\n"); } else { bl_debug_printf(BL_DEBUG_TAG " XIM is disabled.\n"); } #endif } XFree(preedit_attr); return res; #else return 0; #endif } int ui_xic_switch_mode(ui_window_t *win) { #ifdef XNPreeditState XVaNestedList preedit_attr; if (!win->xic) { return 0; } preedit_attr = XVaCreateNestedList( 0, XNPreeditState, ui_xic_is_active(win) ? XIMPreeditDisable : XIMPreeditEnable, NULL); if (XSetICValues(win->xic->ic, XNPreeditAttributes, preedit_attr, NULL) != NULL) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " XIM doesn't support XNPreeditState.\n"); #endif } XFree(preedit_attr); return 1; #else return 0; #endif } /* * ui_xim.c <-> ui_xic.c communication functions */ int ui_xim_activated(ui_window_t *win) { return create_xic(win); } int ui_xim_destroyed(ui_window_t *win) { return destroy_xic(win); } mlterm-3.8.9/uitoolkit/xlib/ui_xim.c010064400017600000144000000255241356600660700161710ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_xim.h" #include /* sprintf */ #include /* strcmp/memset */ #include /* dup/close */ #include /* bl_set_file_cloexec */ #include #include /* strdup */ #include /* bl_locale_init/bl_get_locale/bl_get_codeset */ #include /* alloca/realloc */ #include "../ui_xic.h" /* refering mutually */ #if 0 #define __DEBUG #endif #define MAX_XIMS_SAME_TIME 5 /* --- static variables --- */ static int use_xim; static char *default_xim_name; /* this can be NULL */ static ui_xim_t xims[MAX_XIMS_SAME_TIME]; static u_int num_xims; /* --- static functions --- */ /* refered in xim_server_destroyed */ static void xim_server_instantiated(Display *display, XPointer client_data, XPointer call_data); static int close_xim(ui_xim_t *xim) { if (xim->im) { XCloseIM(xim->im); } if (xim->parser) { (*xim->parser->destroy)(xim->parser); } free(xim->name); free(xim->locale); free(xim->xic_wins); return 1; } static int invoke_xim_destroyed(ui_xim_t *xim) { int count; for (count = 0; count < xim->num_xic_wins; count++) { ui_xim_destroyed(xims->xic_wins[count]); } return 1; } static void xim_server_destroyed(XIM im, XPointer data1, XPointer data2) { int count; for (count = 0; count < num_xims; count++) { if (xims[count].im == im) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " %s xim(with %d xic) server destroyed.\n", xims[count].name, xims[count].num_xic_wins); #endif invoke_xim_destroyed(&xims[count]); xims[count].im = NULL; break; } } /* * XXX * XRegisterIMInstantiateCallback of sunos/openwin seems buggy. */ #if !defined(sun) && !defined(__sun__) && !defined(__sun) /* it is necessary to reset callback */ XRegisterIMInstantiateCallback(XDisplayOfIM(im), NULL, NULL, NULL, xim_server_instantiated, NULL); #endif } static int open_xim(ui_xim_t *xim, Display *display) { char *xmod; char *cur_locale; int result; int next_fd; /* to deal with brain-dead XIM implemantations */ /* 4 is the length of "@im=" */ if ((xmod = alloca(4 + strlen(xim->name) + 1)) == NULL) { return 0; } sprintf(xmod, "@im=%s", xim->name); cur_locale = bl_get_locale(); if (strcmp(xim->locale, cur_locale) == 0) { /* the same locale as current */ cur_locale = NULL; } else { cur_locale = strdup(cur_locale); if (!bl_locale_init(xim->locale)) { /* setlocale() failed. restoring */ bl_locale_init(cur_locale); free(cur_locale); return 0; } } result = 0; next_fd = dup(0); if (next_fd != -1) { /* remember the lowest unused fd */ close(next_fd); } if (XSetLocaleModifiers(xmod) && (xim->im = XOpenIM(display, NULL, NULL, NULL))) { if ((xim->encoding = vt_get_char_encoding(bl_get_codeset())) == VT_UNKNOWN_ENCODING || (xim->parser = vt_char_encoding_parser_new(xim->encoding)) == NULL) { XCloseIM(xim->im); xim->im = NULL; } else { XIMCallback callback = {NULL, xim_server_destroyed}; XSetIMValues(xim->im, XNDestroyCallback, &callback, NULL); #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " XIM %s is successfully opened.\n", xmod); #endif /* succeeded */ result = 1; } } if (next_fd > 0) { /* if XOpenIM() internally opens a fd, * we should close it on exec() */ bl_file_set_cloexec(next_fd); } if (cur_locale) { /* restoring */ bl_locale_init(cur_locale); free(cur_locale); } return result; } static int activate_xim(ui_xim_t *xim, Display *display) { u_int count; if (!xim->im && !open_xim(xim, display)) { return 0; } for (count = 0; count < xim->num_xic_wins; count++) { ui_xim_activated(xim->xic_wins[count]); } return 1; } static void xim_server_instantiated(Display *display, XPointer client_data, XPointer call_data) { int count; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " new xim server is instantiated.\n"); #endif for (count = 0; count < num_xims; count++) { activate_xim(&xims[count], display); } } static ui_xim_t *search_xim(Display *display, char *xim_name) { int count; for (count = 0; count < num_xims; count++) { if (strcmp(xims[count].name, xim_name) == 0) { if (!xims[count].im) { return &xims[count]; } else if (XDisplayOfIM(xims[count].im) == display) { return &xims[count]; } } } return NULL; } static ui_xim_t *get_xim(Display *display, char *xim_name, char *xim_locale) { ui_xim_t *xim; if ((xim = search_xim(display, xim_name)) == NULL) { if (num_xims == MAX_XIMS_SAME_TIME) { int count; count = 0; while (1) { if (count == num_xims) { return NULL; } else if (xims[count].num_xic_wins == 0) { close_xim(&xims[count]); xims[count] = xims[--num_xims]; break; } else { count++; } } } xim = &xims[num_xims++]; memset(xim, 0, sizeof(ui_xim_t)); xim->name = strdup(xim_name); xim->locale = strdup(xim_locale); } return xim; } static XIMStyle search_xim_style(XIMStyles *xim_styles, XIMStyle *supported_styles, u_int size) { int count; for (count = 0; count < xim_styles->count_styles; count++) { int _count; for (_count = 0; _count < size; _count++) { if (supported_styles[_count] == xim_styles->supported_styles[count]) { return supported_styles[_count]; } } } return 0; } /* --- global functions --- */ int ui_xim_init(int _use_xim) { char *xmod; char *p; if (!(use_xim = _use_xim)) { return 0; } xmod = XSetLocaleModifiers(""); /* 4 is the length of "@im=" */ if (xmod && strlen(xmod) >= 4 && (p = strstr(xmod, "@im=")) && (default_xim_name = strdup(p + 4))) { if ((p = strstr(default_xim_name, "@"))) { /* only the first entry is used , others are ignored. */ *p = '\0'; } } return 1; } int ui_xim_final(void) { int count; if (!use_xim) { return 0; } for (count = 0; count < num_xims; count++) { close_xim(&xims[count]); } free(default_xim_name); return 1; } int ui_xim_display_opened(Display *display) { if (!use_xim) { return 0; } /* * XXX * XRegisterIMInstantiateCallback of sunos/openwin seems buggy. */ #if !defined(sun) && !defined(__sun__) && !defined(__sun) XRegisterIMInstantiateCallback(display, NULL, NULL, NULL, xim_server_instantiated, NULL); #endif return 1; } int ui_xim_display_closed(Display *display) { int count; if (!use_xim) { return 0; } count = 0; while (count < num_xims) { if (xims[count].im && XDisplayOfIM(xims[count].im) == display) { close_xim(&xims[count]); xims[count] = xims[--num_xims]; } else { count++; } } /* * XXX * XRegisterIMInstantiateCallback of sunos/openwin seems buggy. */ #if !defined(sun) && !defined(__sun__) && !defined(__sun) XUnregisterIMInstantiateCallback(display, NULL, NULL, NULL, xim_server_instantiated, NULL); #endif return 1; } int ui_add_xim_listener(ui_window_t *win, char *xim_name, char *xim_locale) { void *p; if (!use_xim) { return 0; } /* * If xim_name is "none", call XSetLocaleModifiers("@im=none"). * If xim_name is "unused", do nothing. */ if (strcmp(xim_locale, "C") == 0 || strcmp(xim_name, "unused") == 0) { return 0; } if (*xim_name == '\0' && win->xim) { /* * reactivating current xim. */ return activate_xim(win->xim, win->disp->display); } if (win->xim) { ui_remove_xim_listener(win); } if (*xim_name == '\0') { if (default_xim_name) { xim_name = default_xim_name; } else { xim_name = "none"; } } if ((win->xim = get_xim(win->disp->display, xim_name, xim_locale)) == NULL) { return 0; } if ((p = realloc(win->xim->xic_wins, sizeof(ui_window_t*) * (win->xim->num_xic_wins + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } win->xim->xic_wins = p; win->xim->xic_wins[win->xim->num_xic_wins++] = win; return activate_xim(win->xim, win->disp->display); } int ui_remove_xim_listener(ui_window_t *win) { int count; if (win->xim == NULL) { return 0; } if (win->xim->num_xic_wins == 0) { return 0; } for (count = 0; count < win->xim->num_xic_wins; count++) { if (win->xim->xic_wins[count] == win) { win->xim->xic_wins[count] = win->xim->xic_wins[--win->xim->num_xic_wins]; win->xim = NULL; /* * memory area of win->xim->xic_wins is not shrunk. */ return 1; } } return 0; } XIC ui_xim_create_ic(ui_window_t *win, XIMStyle selected_style, XVaNestedList preedit_attr) { if (win->xim == NULL) { return NULL; } if (preedit_attr) { return XCreateIC(win->xim->im, XNClientWindow, win->my_window, XNFocusWindow, win->my_window, XNInputStyle, selected_style, XNPreeditAttributes, preedit_attr, NULL); } else { return XCreateIC(win->xim->im, XNClientWindow, win->my_window, XNFocusWindow, win->my_window, XNInputStyle, selected_style, NULL); } } XIMStyle ui_xim_get_style(ui_window_t *win) { XIMStyle over_the_spot_styles[] = { XIMPreeditPosition | XIMStatusNothing, XIMPreeditPosition | XIMStatusNone, }; XIMStyle root_styles[] = { XIMPreeditNothing | XIMStatusNothing, #if 0 /* * These styles doesn't support character * composing(XK_dead_xxx,XK_Multi_key...). */ XIMPreeditNothing | XIMStatusNone, XIMPreeditNone | XIMStatusNothing, XIMPreeditNone | XIMStatusNone, #endif }; XIMStyle selected_style; XIMStyles *xim_styles; if (win->xim == NULL) { return 0; } if (XGetIMValues(win->xim->im, XNQueryInputStyle, &xim_styles, NULL) || !xim_styles) { return 0; } if (!(selected_style = search_xim_style(xim_styles, over_the_spot_styles, sizeof(over_the_spot_styles) / sizeof(over_the_spot_styles[0])))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " over the spot style not found.\n"); #endif if (!(selected_style = search_xim_style(xim_styles, root_styles, sizeof(root_styles) / sizeof(root_styles[0])))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " root style not found.\n"); #endif XFree(xim_styles); return 0; } } XFree(xim_styles); return selected_style; } char *ui_get_xim_name(ui_window_t *win) { if (win->xim == NULL) { return "unused"; } return win->xim->name; } char *ui_get_xim_locale(ui_window_t *win) { if (win->xim == NULL) { return ""; } return win->xim->locale; } char *ui_get_default_xim_name(void) { if (!use_xim) { return "disable"; } return default_xim_name ? default_xim_name : "none"; } mlterm-3.8.9/uitoolkit/xlib/ui.h010064400017600000144000000026371356600660700153210ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_H__ #define ___UI_H__ /* This must be included ahead of Xft.h on XFree86-4.0.x or before. */ #include #include /* XK_xxx */ #include /* XA_xxx */ #include /* IsKeypadKey */ #include /* for cursor shape */ typedef Pixmap PixmapMask; #ifdef XK_F21 #define XK_FMAX XK_F35 #else #define XK_FMAX XK_F20 #endif /* === Platform dependent options === */ #define UI_COLOR_HAS_RGB #define SUPPORT_TRUE_TRANSPARENT_BG #undef TYPE_XCORE_SCALABLE #undef MANAGE_ROOT_WINDOWS_BY_MYSELF #undef MANAGE_SUB_WINDOWS_BY_MYSELF #undef INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS #define SUPPORT_POINT_SIZE_FONT #undef XIM_SPOT_IS_LINE_TOP #define USE_GC #define CHANGEABLE_CURSOR #undef PLUGIN_MODULE_SUFFIX #undef KEY_REPEAT_BY_MYSELF #undef ROTATABLE_DISPLAY #undef PSEUDO_COLOR_DISPLAY #undef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE #define SUPPORT_URGENT_BELL #undef FORCE_UNICODE #define NEED_DISPLAY_SYNC_EVERY_TIME #undef DRAW_SCREEN_IN_PIXELS #undef NO_DRAW_IMAGE_STRING /* * for ui_picture.c * Xlib doesn't work on threading without XInitThreads(). * (libpthread is not linked to mlterm explicitly for now.) */ #undef HAVE_PTHREAD #define COMPOSE_DECSP_FONT #undef USE_REAL_VERTICAL_FONT #undef NO_DISPLAY_FD #undef FLICK_SCROLL #undef UIWINDOW_SUPPORTS_PREEDITING #endif mlterm-3.8.9/uitoolkit/wayland004075500017600000144000000000001356600660700151505ustar kenusersmlterm-3.8.9/uitoolkit/wayland/gtk-primary-selection.h010064400017600000144000000527221356600660700216360ustar kenusers/* Generated by wayland-scanner 1.17.0 */ #ifndef GTK_PRIMARY_SELECTION_CLIENT_PROTOCOL_H #define GTK_PRIMARY_SELECTION_CLIENT_PROTOCOL_H #include #include #include "wayland-client.h" #ifdef __cplusplus extern "C" { #endif /** * @page page_gtk_primary_selection The gtk_primary_selection protocol * Primary selection protocol * * @section page_desc_gtk_primary_selection Description * * This protocol provides the ability to have a primary selection device to * match that of the X server. This primary selection is a shortcut to the * common clipboard selection, where text just needs to be selected in order * to allow copying it elsewhere. The de facto way to perform this action * is the middle mouse button, although it is not limited to this one. * * Clients wishing to honor primary selection should create a primary * selection source and set it as the selection through * wp_primary_selection_device.set_selection whenever the text selection * changes. In order to minimize calls in pointer-driven text selection, * it should happen only once after the operation finished. Similarly, * a NULL source should be set when text is unselected. * * wp_primary_selection_offer objects are first announced through the * wp_primary_selection_device.data_offer event. Immediately after this event, * the primary data offer will emit wp_primary_selection_offer.offer events * to let know of the mime types being offered. * * When the primary selection changes, the client with the keyboard focus * will receive wp_primary_selection_device.selection events. Only the client * with the keyboard focus will receive such events with a non-NULL * wp_primary_selection_offer. Across keyboard focus changes, previously * focused clients will receive wp_primary_selection_device.events with a * NULL wp_primary_selection_offer. * * In order to request the primary selection data, the client must pass * a recent serial pertaining to the press event that is triggering the * operation, if the compositor deems the serial valid and recent, the * wp_primary_selection_source.send event will happen in the other end * to let the transfer begin. The client owning the primary selection * should write the requested data, and close the file descriptor * immediately. * * If the primary selection owner client disappeared during the transfer, * the client reading the data will receive a * wp_primary_selection_device.selection event with a NULL * wp_primary_selection_offer, the client should take this as a hint * to finish the reads related to the no longer existing offer. * * The primary selection owner should be checking for errors during * writes, merely cancelling the ongoing transfer if any happened. * * @section page_ifaces_gtk_primary_selection Interfaces * - @subpage page_iface_gtk_primary_selection_device_manager - X primary selection emulation * - @subpage page_iface_gtk_primary_selection_device - * - @subpage page_iface_gtk_primary_selection_offer - offer to transfer primary selection contents * - @subpage page_iface_gtk_primary_selection_source - offer to replace the contents of the primary selection * @section page_copyright_gtk_primary_selection Copyright *
 *
 * Copyright © 2015, 2016 Red Hat
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 * 
*/ struct gtk_primary_selection_device; struct gtk_primary_selection_device_manager; struct gtk_primary_selection_offer; struct gtk_primary_selection_source; struct wl_seat; /** * @page page_iface_gtk_primary_selection_device_manager gtk_primary_selection_device_manager * @section page_iface_gtk_primary_selection_device_manager_desc Description * * The primary selection device manager is a singleton global object that * provides access to the primary selection. It allows to create * wp_primary_selection_source objects, as well as retrieving the per-seat * wp_primary_selection_device objects. * @section page_iface_gtk_primary_selection_device_manager_api API * See @ref iface_gtk_primary_selection_device_manager. */ /** * @defgroup iface_gtk_primary_selection_device_manager The gtk_primary_selection_device_manager interface * * The primary selection device manager is a singleton global object that * provides access to the primary selection. It allows to create * wp_primary_selection_source objects, as well as retrieving the per-seat * wp_primary_selection_device objects. */ extern const struct wl_interface gtk_primary_selection_device_manager_interface; /** * @page page_iface_gtk_primary_selection_device gtk_primary_selection_device * @section page_iface_gtk_primary_selection_device_api API * See @ref iface_gtk_primary_selection_device. */ /** * @defgroup iface_gtk_primary_selection_device The gtk_primary_selection_device interface */ extern const struct wl_interface gtk_primary_selection_device_interface; /** * @page page_iface_gtk_primary_selection_offer gtk_primary_selection_offer * @section page_iface_gtk_primary_selection_offer_desc Description * * A wp_primary_selection_offer represents an offer to transfer the contents * of the primary selection clipboard to the client. Similar to * wl_data_offer, the offer also describes the mime types that the source * will transferthat the * data can be converted to and provides the mechanisms for transferring the * data directly to the client. * @section page_iface_gtk_primary_selection_offer_api API * See @ref iface_gtk_primary_selection_offer. */ /** * @defgroup iface_gtk_primary_selection_offer The gtk_primary_selection_offer interface * * A wp_primary_selection_offer represents an offer to transfer the contents * of the primary selection clipboard to the client. Similar to * wl_data_offer, the offer also describes the mime types that the source * will transferthat the * data can be converted to and provides the mechanisms for transferring the * data directly to the client. */ extern const struct wl_interface gtk_primary_selection_offer_interface; /** * @page page_iface_gtk_primary_selection_source gtk_primary_selection_source * @section page_iface_gtk_primary_selection_source_desc Description * * The source side of a wp_primary_selection_offer, it provides a way to * describe the offered data and respond to requests to transfer the * requested contents of the primary selection clipboard. * @section page_iface_gtk_primary_selection_source_api API * See @ref iface_gtk_primary_selection_source. */ /** * @defgroup iface_gtk_primary_selection_source The gtk_primary_selection_source interface * * The source side of a wp_primary_selection_offer, it provides a way to * describe the offered data and respond to requests to transfer the * requested contents of the primary selection clipboard. */ extern const struct wl_interface gtk_primary_selection_source_interface; #define GTK_PRIMARY_SELECTION_DEVICE_MANAGER_CREATE_SOURCE 0 #define GTK_PRIMARY_SELECTION_DEVICE_MANAGER_GET_DEVICE 1 #define GTK_PRIMARY_SELECTION_DEVICE_MANAGER_DESTROY 2 /** * @ingroup iface_gtk_primary_selection_device_manager */ #define GTK_PRIMARY_SELECTION_DEVICE_MANAGER_CREATE_SOURCE_SINCE_VERSION 1 /** * @ingroup iface_gtk_primary_selection_device_manager */ #define GTK_PRIMARY_SELECTION_DEVICE_MANAGER_GET_DEVICE_SINCE_VERSION 1 /** * @ingroup iface_gtk_primary_selection_device_manager */ #define GTK_PRIMARY_SELECTION_DEVICE_MANAGER_DESTROY_SINCE_VERSION 1 /** @ingroup iface_gtk_primary_selection_device_manager */ static inline void gtk_primary_selection_device_manager_set_user_data(struct gtk_primary_selection_device_manager *gtk_primary_selection_device_manager, void *user_data) { wl_proxy_set_user_data((struct wl_proxy *) gtk_primary_selection_device_manager, user_data); } /** @ingroup iface_gtk_primary_selection_device_manager */ static inline void * gtk_primary_selection_device_manager_get_user_data(struct gtk_primary_selection_device_manager *gtk_primary_selection_device_manager) { return wl_proxy_get_user_data((struct wl_proxy *) gtk_primary_selection_device_manager); } static inline uint32_t gtk_primary_selection_device_manager_get_version(struct gtk_primary_selection_device_manager *gtk_primary_selection_device_manager) { return wl_proxy_get_version((struct wl_proxy *) gtk_primary_selection_device_manager); } /** * @ingroup iface_gtk_primary_selection_device_manager * * Create a new primary selection source. */ static inline struct gtk_primary_selection_source * gtk_primary_selection_device_manager_create_source(struct gtk_primary_selection_device_manager *gtk_primary_selection_device_manager) { struct wl_proxy *id; id = wl_proxy_marshal_constructor((struct wl_proxy *) gtk_primary_selection_device_manager, GTK_PRIMARY_SELECTION_DEVICE_MANAGER_CREATE_SOURCE, >k_primary_selection_source_interface, NULL); return (struct gtk_primary_selection_source *) id; } /** * @ingroup iface_gtk_primary_selection_device_manager * * Create a new data device for a given seat. */ static inline struct gtk_primary_selection_device * gtk_primary_selection_device_manager_get_device(struct gtk_primary_selection_device_manager *gtk_primary_selection_device_manager, struct wl_seat *seat) { struct wl_proxy *id; id = wl_proxy_marshal_constructor((struct wl_proxy *) gtk_primary_selection_device_manager, GTK_PRIMARY_SELECTION_DEVICE_MANAGER_GET_DEVICE, >k_primary_selection_device_interface, NULL, seat); return (struct gtk_primary_selection_device *) id; } /** * @ingroup iface_gtk_primary_selection_device_manager * * Destroy the primary selection device manager. */ static inline void gtk_primary_selection_device_manager_destroy(struct gtk_primary_selection_device_manager *gtk_primary_selection_device_manager) { wl_proxy_marshal((struct wl_proxy *) gtk_primary_selection_device_manager, GTK_PRIMARY_SELECTION_DEVICE_MANAGER_DESTROY); wl_proxy_destroy((struct wl_proxy *) gtk_primary_selection_device_manager); } /** * @ingroup iface_gtk_primary_selection_device * @struct gtk_primary_selection_device_listener */ struct gtk_primary_selection_device_listener { /** * introduce a new wp_primary_selection_offer * * Introduces a new wp_primary_selection_offer object that may be * used to receive the current primary selection. Immediately * following this event, the new wp_primary_selection_offer object * will send wp_primary_selection_offer.offer events to describe * the offered mime types. */ void (*data_offer)(void *data, struct gtk_primary_selection_device *gtk_primary_selection_device, struct gtk_primary_selection_offer *offer); /** * advertise a new primary selection * * The wp_primary_selection_device.selection event is sent to * notify the client of a new primary selection. This event is sent * after the wp_primary_selection.data_offer event introducing this * object, and after the offer has announced its mimetypes through * wp_primary_selection_offer.offer. * * The data_offer is valid until a new offer or NULL is received or * until the client loses keyboard focus. The client must destroy * the previous selection data_offer, if any, upon receiving this * event. */ void (*selection)(void *data, struct gtk_primary_selection_device *gtk_primary_selection_device, struct gtk_primary_selection_offer *id); }; /** * @ingroup iface_gtk_primary_selection_device */ static inline int gtk_primary_selection_device_add_listener(struct gtk_primary_selection_device *gtk_primary_selection_device, const struct gtk_primary_selection_device_listener *listener, void *data) { return wl_proxy_add_listener((struct wl_proxy *) gtk_primary_selection_device, (void (**)(void)) listener, data); } #define GTK_PRIMARY_SELECTION_DEVICE_SET_SELECTION 0 #define GTK_PRIMARY_SELECTION_DEVICE_DESTROY 1 /** * @ingroup iface_gtk_primary_selection_device */ #define GTK_PRIMARY_SELECTION_DEVICE_DATA_OFFER_SINCE_VERSION 1 /** * @ingroup iface_gtk_primary_selection_device */ #define GTK_PRIMARY_SELECTION_DEVICE_SELECTION_SINCE_VERSION 1 /** * @ingroup iface_gtk_primary_selection_device */ #define GTK_PRIMARY_SELECTION_DEVICE_SET_SELECTION_SINCE_VERSION 1 /** * @ingroup iface_gtk_primary_selection_device */ #define GTK_PRIMARY_SELECTION_DEVICE_DESTROY_SINCE_VERSION 1 /** @ingroup iface_gtk_primary_selection_device */ static inline void gtk_primary_selection_device_set_user_data(struct gtk_primary_selection_device *gtk_primary_selection_device, void *user_data) { wl_proxy_set_user_data((struct wl_proxy *) gtk_primary_selection_device, user_data); } /** @ingroup iface_gtk_primary_selection_device */ static inline void * gtk_primary_selection_device_get_user_data(struct gtk_primary_selection_device *gtk_primary_selection_device) { return wl_proxy_get_user_data((struct wl_proxy *) gtk_primary_selection_device); } static inline uint32_t gtk_primary_selection_device_get_version(struct gtk_primary_selection_device *gtk_primary_selection_device) { return wl_proxy_get_version((struct wl_proxy *) gtk_primary_selection_device); } /** * @ingroup iface_gtk_primary_selection_device * * Replaces the current selection. The previous owner of the primary selection * will receive a wp_primary_selection_source.cancelled event. * * To unset the selection, set the source to NULL. */ static inline void gtk_primary_selection_device_set_selection(struct gtk_primary_selection_device *gtk_primary_selection_device, struct gtk_primary_selection_source *source, uint32_t serial) { wl_proxy_marshal((struct wl_proxy *) gtk_primary_selection_device, GTK_PRIMARY_SELECTION_DEVICE_SET_SELECTION, source, serial); } /** * @ingroup iface_gtk_primary_selection_device * * Destroy the primary selection device. */ static inline void gtk_primary_selection_device_destroy(struct gtk_primary_selection_device *gtk_primary_selection_device) { wl_proxy_marshal((struct wl_proxy *) gtk_primary_selection_device, GTK_PRIMARY_SELECTION_DEVICE_DESTROY); wl_proxy_destroy((struct wl_proxy *) gtk_primary_selection_device); } /** * @ingroup iface_gtk_primary_selection_offer * @struct gtk_primary_selection_offer_listener */ struct gtk_primary_selection_offer_listener { /** * advertise offered mime type * * Sent immediately after creating announcing the * wp_primary_selection_offer through * wp_primary_selection_device.data_offer. One event is sent per * offered mime type. */ void (*offer)(void *data, struct gtk_primary_selection_offer *gtk_primary_selection_offer, const char *mime_type); }; /** * @ingroup iface_gtk_primary_selection_offer */ static inline int gtk_primary_selection_offer_add_listener(struct gtk_primary_selection_offer *gtk_primary_selection_offer, const struct gtk_primary_selection_offer_listener *listener, void *data) { return wl_proxy_add_listener((struct wl_proxy *) gtk_primary_selection_offer, (void (**)(void)) listener, data); } #define GTK_PRIMARY_SELECTION_OFFER_RECEIVE 0 #define GTK_PRIMARY_SELECTION_OFFER_DESTROY 1 /** * @ingroup iface_gtk_primary_selection_offer */ #define GTK_PRIMARY_SELECTION_OFFER_OFFER_SINCE_VERSION 1 /** * @ingroup iface_gtk_primary_selection_offer */ #define GTK_PRIMARY_SELECTION_OFFER_RECEIVE_SINCE_VERSION 1 /** * @ingroup iface_gtk_primary_selection_offer */ #define GTK_PRIMARY_SELECTION_OFFER_DESTROY_SINCE_VERSION 1 /** @ingroup iface_gtk_primary_selection_offer */ static inline void gtk_primary_selection_offer_set_user_data(struct gtk_primary_selection_offer *gtk_primary_selection_offer, void *user_data) { wl_proxy_set_user_data((struct wl_proxy *) gtk_primary_selection_offer, user_data); } /** @ingroup iface_gtk_primary_selection_offer */ static inline void * gtk_primary_selection_offer_get_user_data(struct gtk_primary_selection_offer *gtk_primary_selection_offer) { return wl_proxy_get_user_data((struct wl_proxy *) gtk_primary_selection_offer); } static inline uint32_t gtk_primary_selection_offer_get_version(struct gtk_primary_selection_offer *gtk_primary_selection_offer) { return wl_proxy_get_version((struct wl_proxy *) gtk_primary_selection_offer); } /** * @ingroup iface_gtk_primary_selection_offer * * To transfer the contents of the primary selection clipboard, the client * issues this request and indicates the mime type that it wants to * receive. The transfer happens through the passed file descriptor * (typically created with the pipe system call). The source client writes * the data in the mime type representation requested and then closes the * file descriptor. * * The receiving client reads from the read end of the pipe until EOF and * closes its end, at which point the transfer is complete. */ static inline void gtk_primary_selection_offer_receive(struct gtk_primary_selection_offer *gtk_primary_selection_offer, const char *mime_type, int32_t fd) { wl_proxy_marshal((struct wl_proxy *) gtk_primary_selection_offer, GTK_PRIMARY_SELECTION_OFFER_RECEIVE, mime_type, fd); } /** * @ingroup iface_gtk_primary_selection_offer * * Destroy the primary selection offer. */ static inline void gtk_primary_selection_offer_destroy(struct gtk_primary_selection_offer *gtk_primary_selection_offer) { wl_proxy_marshal((struct wl_proxy *) gtk_primary_selection_offer, GTK_PRIMARY_SELECTION_OFFER_DESTROY); wl_proxy_destroy((struct wl_proxy *) gtk_primary_selection_offer); } /** * @ingroup iface_gtk_primary_selection_source * @struct gtk_primary_selection_source_listener */ struct gtk_primary_selection_source_listener { /** * send the primary selection contents * * Request for the current primary selection contents from the * client. Send the specified mime type over the passed file * descriptor, then close it. */ void (*send)(void *data, struct gtk_primary_selection_source *gtk_primary_selection_source, const char *mime_type, int32_t fd); /** * request for primary selection contents was canceled * * This primary selection source is no longer valid. The client * should clean up and destroy this primary selection source. */ void (*cancelled)(void *data, struct gtk_primary_selection_source *gtk_primary_selection_source); }; /** * @ingroup iface_gtk_primary_selection_source */ static inline int gtk_primary_selection_source_add_listener(struct gtk_primary_selection_source *gtk_primary_selection_source, const struct gtk_primary_selection_source_listener *listener, void *data) { return wl_proxy_add_listener((struct wl_proxy *) gtk_primary_selection_source, (void (**)(void)) listener, data); } #define GTK_PRIMARY_SELECTION_SOURCE_OFFER 0 #define GTK_PRIMARY_SELECTION_SOURCE_DESTROY 1 /** * @ingroup iface_gtk_primary_selection_source */ #define GTK_PRIMARY_SELECTION_SOURCE_SEND_SINCE_VERSION 1 /** * @ingroup iface_gtk_primary_selection_source */ #define GTK_PRIMARY_SELECTION_SOURCE_CANCELLED_SINCE_VERSION 1 /** * @ingroup iface_gtk_primary_selection_source */ #define GTK_PRIMARY_SELECTION_SOURCE_OFFER_SINCE_VERSION 1 /** * @ingroup iface_gtk_primary_selection_source */ #define GTK_PRIMARY_SELECTION_SOURCE_DESTROY_SINCE_VERSION 1 /** @ingroup iface_gtk_primary_selection_source */ static inline void gtk_primary_selection_source_set_user_data(struct gtk_primary_selection_source *gtk_primary_selection_source, void *user_data) { wl_proxy_set_user_data((struct wl_proxy *) gtk_primary_selection_source, user_data); } /** @ingroup iface_gtk_primary_selection_source */ static inline void * gtk_primary_selection_source_get_user_data(struct gtk_primary_selection_source *gtk_primary_selection_source) { return wl_proxy_get_user_data((struct wl_proxy *) gtk_primary_selection_source); } static inline uint32_t gtk_primary_selection_source_get_version(struct gtk_primary_selection_source *gtk_primary_selection_source) { return wl_proxy_get_version((struct wl_proxy *) gtk_primary_selection_source); } /** * @ingroup iface_gtk_primary_selection_source * * This request adds a mime type to the set of mime types advertised to * targets. Can be called several times to offer multiple types. */ static inline void gtk_primary_selection_source_offer(struct gtk_primary_selection_source *gtk_primary_selection_source, const char *mime_type) { wl_proxy_marshal((struct wl_proxy *) gtk_primary_selection_source, GTK_PRIMARY_SELECTION_SOURCE_OFFER, mime_type); } /** * @ingroup iface_gtk_primary_selection_source * * Destroy the primary selection source. */ static inline void gtk_primary_selection_source_destroy(struct gtk_primary_selection_source *gtk_primary_selection_source) { wl_proxy_marshal((struct wl_proxy *) gtk_primary_selection_source, GTK_PRIMARY_SELECTION_SOURCE_DESTROY); wl_proxy_destroy((struct wl_proxy *) gtk_primary_selection_source); } #ifdef __cplusplus } #endif #endif mlterm-3.8.9/uitoolkit/wayland/ui.h010064400017600000144000000312561356600660700160210ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_H__ #define ___UI_H__ #ifndef COMPAT_LIBVTE #define XDG_SHELL_V6 #endif #include #include #include #include #include #include "gtk-primary-selection.h" #ifdef XDG_SHELL_V6 #include "xdg-shell-unstable-v6-client-protocol.h" #endif #ifdef USE_FREETYPE #include /* u_int32_t etc */ #endif typedef int KeyCode; /* Same as type of wparam */ typedef int KeySym; /* Same as type of wparam */ typedef unsigned long Atom; /* Same as definition in X11/X.h */ typedef uint32_t Time; typedef struct { int type; Time time; unsigned int state; KeySym ksym; unsigned int keycode; } XKeyEvent; typedef struct { int type; Time time; int x; int y; unsigned int state; unsigned int button; } XButtonEvent; typedef struct { int type; Time time; int x; int y; unsigned int state; } XMotionEvent; typedef struct { int type; struct ui_window *target; } XSelectionRequestEvent; typedef union { int type; XKeyEvent xkey; XButtonEvent xbutton; XMotionEvent xmotion; XSelectionRequestEvent xselectionrequest; } XEvent; typedef struct { struct wl_display *display; struct wl_output *output; struct wl_registry *registry; struct wl_compositor *compositor; struct wl_shm *shm; struct wl_cursor_theme *cursor_theme; struct wl_cursor *cursor[10]; struct wl_surface *cursor_surface; struct wl_seat *seat; struct wl_keyboard *keyboard; struct wl_pointer *pointer; struct ui_xkb { struct xkb_context *ctx; struct xkb_keymap *keymap; struct xkb_state *state; xkb_mod_index_t ctrl; xkb_mod_index_t alt; xkb_mod_index_t shift; xkb_mod_index_t logo; unsigned int mods; } * xkb; struct wl_surface *current_kbd_surface; struct wl_surface *current_pointer_surface; int pointer_x; int pointer_y; int pointer_button; int current_cursor; int kbd_repeat_wait; XKeyEvent prev_kev; u_int kbd_repeat_count; struct wl_data_device_manager *data_device_manager; struct wl_data_device *data_device; struct wl_data_offer *dnd_offer; struct wl_surface *data_surface; uint32_t dnd_action; struct wl_data_offer *sel_offer; char *sel_offer_mime; struct wl_data_source *sel_source; struct gtk_primary_selection_device_manager *xsel_device_manager; struct gtk_primary_selection_device *xsel_device; struct gtk_primary_selection_offer *xsel_offer; char *xsel_offer_mime; struct gtk_primary_selection_source *xsel_source; int32_t sel_fd; uint32_t serial; int ref_count; /* * These members should be placed at the end of this structure because * ui_*.c except ui_display.c refers this structure correctly * if COMPAT_LIBVTE is defined or not. */ #ifdef COMPAT_LIBVTE struct wl_subcompositor *subcompositor; int is_xdg_shell; /* for sway 1.0 */ #else struct wl_shell *shell; #ifdef XDG_SHELL_V6 struct zxdg_shell_v6 *xdg_shell; #endif #endif } ui_wlserv_t; typedef struct { ui_wlserv_t *wlserv; unsigned char *fb; struct wl_buffer *buffer; struct wl_surface *surface; unsigned int bytes_per_pixel; unsigned int line_length; int lock_state; struct rgb_info { unsigned int r_limit; unsigned int g_limit; unsigned int b_limit; unsigned int r_offset; unsigned int g_offset; unsigned int b_offset; } rgbinfo; unsigned int width; unsigned int height; int damage_x; int damage_y; unsigned int damage_width; unsigned int damage_height; int is_resizing; struct ui_display *parent; /* * These members should be placed at the end of this structure because * ui_*.c except ui_display.c refers this structure correctly * if COMPAT_LIBVTE is defined or not. */ #ifdef COMPAT_LIBVTE struct wl_surface *parent_surface; struct wl_subsurface *subsurface; int x; int y; #else struct wl_shell_surface *shell_surface; #ifdef XDG_SHELL_V6 struct zxdg_surface_v6 *xdg_surface; struct zxdg_toplevel_v6 *xdg_toplevel; int xdg_surface_configured; #endif #endif } Display; #define PIXEL_RED(pixel, rgbinfo) (((pixel) >> (rgbinfo).r_offset) << (rgbinfo).r_limit) #define PIXEL_BLUE(pixel, rgbinfo) (((pixel) >> (rgbinfo).b_offset) << (rgbinfo).b_limit) #define PIXEL_GREEN(pixel, rgbinfo) (((pixel) >> (rgbinfo).g_offset) << (rgbinfo).g_limit) #define RGB_TO_PIXEL(r, g, b, rgbinfo) \ ((((r) >> (rgbinfo).r_limit) << (rgbinfo).r_offset) | \ (((g) >> (rgbinfo).g_limit) << (rgbinfo).g_offset) | \ (((b) >> (rgbinfo).b_limit) << (rgbinfo).b_offset)) typedef int XIC; /* dummy */ typedef void *XID; /* dummy */ typedef void *Window; /* dummy */ typedef void *Drawable; /* dummy */ typedef struct { unsigned char *image; unsigned int width; unsigned int height; } * Pixmap; typedef unsigned char *PixmapMask; typedef int GC; typedef int Font; typedef int Cursor; typedef struct /* Same as definition in X11/X.h */ { int max_keypermod; KeyCode *modifiermap; } XModifierKeymap; typedef struct /* Same as definition in X11/X.h */ { unsigned char byte1; unsigned char byte2; } XChar2b; typedef struct _XFontStruct { char *file; #ifdef USE_FREETYPE int32_t format; /* XXX (fontsize|FONT_BOLD|FONT_ITALIC) on freetype. */ #endif int32_t num_glyphs; unsigned char *glyphs; int32_t glyph_width_bytes; unsigned char width; /* Width of full width characters or max width of half width characters. */ unsigned char width_full; unsigned char height; unsigned char ascent; #if 0 u_int16_t *glyph_indeces; #else unsigned short *glyph_indeces; #endif /* for pcf */ int16_t min_char_or_byte2; int16_t max_char_or_byte2; int16_t min_byte1; int16_t max_byte1; int32_t *glyph_offsets; #ifdef USE_FREETYPE /* for freetype */ void *face; u_int32_t num_indeces; u_int32_t glyph_size; int is_aa; #ifdef USE_FONTCONFIG struct _XFontStruct **compl_xfonts; #endif #endif unsigned int ref_count; } XFontStruct; typedef int XFontSet; /* dummy */ #define None 0L /* Same as definition in X11/X.h */ #define NoSymbol 0L /* Same as definition in X11/X.h */ #define CurrentTime 0L /* Same as definition in X11/X.h */ /* Same as definition in X11/X.h */ #define NoEventMask 0L #define KeyPressMask (1L << 0) #define KeyReleaseMask (1L << 1) #define ButtonPressMask (1L << 2) #define ButtonReleaseMask (1L << 3) #define EnterWindowMask (1L << 4) #define LeaveWindowMask (1L << 5) #define PointerMotionMask (1L << 6) #define PointerMotionHintMask (1L << 7) #define Button1MotionMask (1L << 8) #define Button2MotionMask (1L << 9) #define Button3MotionMask (1L << 10) #define Button4MotionMask (1L << 11) #define Button5MotionMask (1L << 12) #define ButtonMotionMask (1L << 13) #define KeymapStateMask (1L << 14) #define ExposureMask (1L << 15) #define VisibilityChangeMask (1L << 16) #define StructureNotifyMask (1L << 17) #define ResizeRedirectMask (1L << 18) #define SubstructureNotifyMask (1L << 19) #define SubstructureRedirectMask (1L << 20) #define FocusChangeMask (1L << 21) #define PropertyChangeMask (1L << 22) #define ColormapChangeMask (1L << 23) #define OwnerGrabButtonMask (1L << 24) #define ShiftMask (1 << 0) #define LockMask (1 << 1) #define ControlMask (1 << 2) #define Mod1Mask (1 << 3) #define Mod2Mask (1 << 4) #define Mod3Mask (1 << 5) #define Mod4Mask (1 << 6) #define Mod5Mask (1 << 7) #define Button1Mask (1 << 8) #define Button2Mask (1 << 9) #define Button3Mask (1 << 10) #define Button4Mask (1 << 11) #define Button5Mask (1 << 12) #define Button1 1 #define Button2 2 #define Button3 3 #define Button4 4 #define Button5 5 #define XK_Super_L XKB_KEY_Super_L #define XK_Super_R XKB_KEY_Super_R #define XK_Hyper_L XKB_KEY_Hyper_L #define XK_Hyper_R XKB_KEY_Hyper_R #define XK_BackSpace XKB_KEY_BackSpace #define XK_Tab XKB_KEY_Tab #define XK_Clear XKB_KEY_Clear #define XK_Linefeed XKB_KEY_Linefeed #define XK_Return XKB_KEY_Return #define XK_Shift_L XKB_KEY_Shift_L #define XK_Control_L XKB_KEY_Control_L #define XK_Alt_L XKB_KEY_Alt_L #define XK_Shift_R XKB_KEY_Shift_R #define XK_Control_R XKB_KEY_Control_R #define XK_Alt_R XKB_KEY_Alt_R #define XK_Meta_L XKB_KEY_Meta_L #define XK_Meta_R XKB_KEY_Meta_R #define XK_Pause XKB_KEY_Pause #define XK_Shift_Lock XKB_KEY_Shift_Lock #define XK_Caps_Lock XKB_KEY_Caps_Lock #define XK_Escape XKB_KEY_Escape #define XK_Prior XKB_KEY_Prior #define XK_Next XKB_KEY_Next #define XK_End XKB_KEY_End #define XK_Home XKB_KEY_Home #define XK_Left XKB_KEY_Left #define XK_Up XKB_KEY_Up #define XK_Right XKB_KEY_Right #define XK_Down XKB_KEY_Down #define XK_Select XKB_KEY_Select #define XK_Print XKB_KEY_Print #define XK_Execute XKB_KEY_Execute #define XK_Insert XKB_KEY_Insert #define XK_Delete XKB_KEY_Delete #define XK_Help XKB_KEY_Help #define XK_F1 XKB_KEY_F1 #define XK_F2 XKB_KEY_F2 #define XK_F3 XKB_KEY_F3 #define XK_F4 XKB_KEY_F4 #define XK_F5 XKB_KEY_F5 #define XK_F6 XKB_KEY_F6 #define XK_F7 XKB_KEY_F7 #define XK_F8 XKB_KEY_F8 #define XK_F9 XKB_KEY_F9 #define XK_F10 XKB_KEY_F10 #define XK_F11 XKB_KEY_F11 #define XK_F12 XKB_KEY_F12 #define XK_F13 XKB_KEY_F13 #define XK_F14 XKB_KEY_F14 #define XK_F15 XKB_KEY_F15 #define XK_F16 XKB_KEY_F16 #define XK_F17 XKB_KEY_F17 #define XK_F18 XKB_KEY_F18 #define XK_F19 XKB_KEY_F19 #define XK_F20 XKB_KEY_F20 #define XK_F21 XKB_KEY_F21 #define XK_F22 XKB_KEY_F22 #define XK_F23 XKB_KEY_F23 #define XK_F24 XKB_KEY_F24 #define XK_FMAX XKB_KEY_F24 #define XK_Num_Lock XKB_KEY_Num_Lock #define XK_Scroll_Lock XKB_KEY_Scroll_Lock #define XK_Find XKB_KEY_Find #define XK_Menu XKB_KEY_Menu #define XK_Begin XKB_KEY_Begin #define XK_Muhenkan XKB_KEY_Muhenkan #define XK_Henkan_Mode XKB_KEY_Henkan_Mode #define XK_Zenkaku_Hankaku XKB_KEY_Zenkaku_Hankaku #define XK_Hiragana_Katakana 0xfffe /* dummy */ #define XK_KP_Prior XKB_KEY_KP_Prior #define XK_KP_Next XKB_KEY_KP_Next #define XK_KP_End XKB_KEY_KP_End #define XK_KP_Home XKB_KEY_KP_Home #define XK_KP_Left XKB_KEY_KP_Left #define XK_KP_Up XKB_KEY_KP_Up #define XK_KP_Right XKB_KEY_KP_Right #define XK_KP_Down XKB_KEY_KP_Down #define XK_KP_Insert XKB_KEY_KP_Insert #define XK_KP_Delete XKB_KEY_KP_Delete #define XK_KP_F1 XKB_KEY_KP_F1 #define XK_KP_F2 XKB_KEY_KP_F2 #define XK_KP_F3 XKB_KEY_KP_F3 #define XK_KP_F4 XKB_KEY_KP_F4 #define XK_KP_Begin XKB_KEY_KP_Begin #define XK_KP_Multiply XKB_KEY_KP_Multiply #define XK_KP_Add XKB_KEY_KP_Add #define XK_KP_Separator XKB_KEY_KP_Separator #define XK_KP_Subtract XKB_KEY_KP_Subtract #define XK_KP_Decimal XKB_KEY_KP_Decimal #define XK_KP_Divide XKB_KEY_KP_Divide #define XK_KP_0 XKB_KEY_KP_0 #define XK_KP_1 XKB_KEY_KP_1 #define XK_KP_2 XKB_KEY_KP_2 #define XK_KP_3 XKB_KEY_KP_3 #define XK_KP_4 XKB_KEY_KP_4 #define XK_KP_5 XKB_KEY_KP_5 #define XK_KP_6 XKB_KEY_KP_6 #define XK_KP_7 XKB_KEY_KP_7 #define XK_KP_8 XKB_KEY_KP_8 #define XK_KP_9 XKB_KEY_KP_9 #define IsKeypadKey(ksym) (XKB_KEY_KP_Space <= (ksym) && (ksym) < XKB_KEY_F1) #define IsModifierKey(ksym) (0) #define XK_ISO_Left_Tab XKB_KEY_ISO_Left_Tab typedef struct { short x; short y; } XPoint; /* XXX dummy */ #define XKeysymToKeycode(disp, ks) (ks) #define XKeycodeToKeysym(disp, kc, i) (kc) #define XKeysymToString(ks) "" #define DefaultScreen(disp) (0) #define BlackPixel(disp, screen) (0xff000000 | RGB(0, 0, 0)) #define WhitePixel(disp, screen) (0xff000000 | RGB(0xff, 0xff, 0xff)) /* Same as definition in X11/cursorfont.h */ #define XC_xterm 152 #define XC_left_ptr 68 /* Same as definition in X11/Xutil.h */ #define NoValue 0x0000 #define XValue 0x0001 #define YValue 0x0002 #define WidthValue 0x0004 #define HeightValue 0x0008 #define AllValues 0x000F #define XNegative 0x0010 #define YNegative 0x0020 int XParseGeometry(char *str, int *x, int *y, unsigned int *width, unsigned int *height); KeySym XStringToKeysym(char *str); /* === Platform dependent options === */ #define UI_COLOR_HAS_RGB #define SUPPORT_TRUE_TRANSPARENT_BG #ifdef USE_FREETYPE #define TYPE_XCORE_SCALABLE #else #undef TYPE_XCORE_SCALABLE #endif #define MANAGE_SUB_WINDOWS_BY_MYSELF /* ui_im_{candidate|status}_screen.c, ui_window.c */ #undef MANAGE_ROOT_WINDOWS_BY_MYSELF #define INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS #undef SUPPORT_POINT_SIZE_FONT #undef XIM_SPOT_IS_LINE_TOP #undef USE_GC #undef CHANGEABLE_CURSOR #define PLUGIN_MODULE_SUFFIX "wl" #define KEY_REPEAT_BY_MYSELF #define ROTATABLE_DISPLAY #undef PSEUDO_COLOR_DISPLAY #undef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE #undef SUPPORT_URGENT_BELL #undef FORCE_UNICODE #define NEED_DISPLAY_SYNC_EVERY_TIME #define DRAW_SCREEN_IN_PIXELS #undef NO_DRAW_IMAGE_STRING /* libpthread is not linked to mlterm explicitly for now. */ #undef HAVE_PTHREAD #define COMPOSE_DECSP_FONT #ifdef USE_FREETYPE #define USE_REAL_VERTICAL_FONT #else #undef USE_REAL_VERTICAL_FONT #endif #undef NO_DISPLAY_FD #undef FLICK_SCROLL #undef UIWINDOW_SUPPORTS_PREEDITING #endif mlterm-3.8.9/uitoolkit/wayland/ui_color.c012075500017600000144000000000001356600660700217572../fb/ui_color.custar kenusersmlterm-3.8.9/uitoolkit/wayland/ui_connect_dialog.c012075500017600000144000000000001356600660700254432../fb/ui_connect_dialog.custar kenusersmlterm-3.8.9/uitoolkit/wayland/ui_decsp_font.c012075500017600000144000000000001356600660700237732../fb/ui_decsp_font.custar kenusersmlterm-3.8.9/uitoolkit/wayland/ui_decsp_font.h012075500017600000144000000000001356600660700240052../fb/ui_decsp_font.hustar kenusersmlterm-3.8.9/uitoolkit/wayland/ui_display.c010064400017600000144000002353521356600660700175440ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_display.h" #include /* memset/memcpy */ #include #include #include #include #include #include #include /* strdup */ #include /* bl_file_set_cloexec */ #include /* BL_SWAP */ #include "../ui_window.h" #include "../ui_picture.h" #include "../ui_imagelib.h" #if 0 #define __DEBUG #endif #ifndef BTN_LEFT #define BTN_LEFT 0x110 #endif #ifndef BTN_RIGHT #define BTN_RIGHT 0x111 #endif #ifndef BTN_MIDDLE #define BTN_MIDDLE 0x112 #endif #define DECORATION_MARGIN 0 /* for decorataion */ #define RESIZE_MARGIN 4 /* for resizing area */ #define KEY_REPEAT_UNIT 25 /* msec (see ui_event_source.c) */ #define DEFAULT_KEY_REPEAT_1 400 /* msec */ #define DEFAULT_KEY_REPEAT_N 50 /* msec */ /* --- static variables --- */ static u_int num_wlservs; static ui_wlserv_t **wlservs; static u_int num_displays; static ui_display_t **displays; static int rotate_display; int kbd_repeat_1 = DEFAULT_KEY_REPEAT_1; int kbd_repeat_N = DEFAULT_KEY_REPEAT_N; /* --- static functions --- */ static int create_tmpfile_cloexec(char *tmpname) { int fd; #ifdef HAVE_MKOSTEMP if ((fd = mkostemp(tmpname, O_CLOEXEC)) >= 0) { unlink(tmpname); } #else if ((fd = mkstemp(tmpname)) >= 0) { bl_file_set_cloexec(fd); unlink(tmpname); } #endif return fd; } static int create_anonymous_file(off_t size) { static const char template[] = "/weston-shared-XXXXXX"; const char *path; char *name; int fd; int ret; if (!(path = getenv("XDG_RUNTIME_DIR"))) { return -1; } if (!(name = malloc(strlen(path) + sizeof(template)))) { return -1; } strcpy(name, path); strcat(name, template); fd = create_tmpfile_cloexec(name); free(name); if (fd < 0) { return -1; } if ((ret = posix_fallocate(fd, 0, size)) != 0) { close(fd); return -1; } return fd; } static ui_window_t *search_focused_window(ui_window_t *win) { u_int count; ui_window_t *focused; /* * *parent* - *child* * ^^^^^^^ => Hit this window instead of the parent window. * - child * - child * (**: is_focused == 1) */ for (count = 0; count < win->num_children; count++) { if ((focused = search_focused_window(win->children[count]))) { return focused; } } if (win->is_focused) { return win; } return NULL; } static ui_window_t *search_inputtable_window(ui_window_t *candidate, ui_window_t *win) { u_int count; if (win->inputtable) { if (candidate == NULL || win->inputtable > candidate->inputtable) { candidate = win; } } for (count = 0; count < win->num_children; count++) { candidate = search_inputtable_window(candidate, win->children[count]); } return candidate; } /* * x and y are rotated values. */ static inline ui_window_t *get_window(ui_window_t *win, int x, int y) { u_int count; for (count = 0; count < win->num_children; count++) { ui_window_t *child; if ((child = win->children[count])->is_mapped) { if (child->x <= x && x < child->x + ACTUAL_WIDTH(child) && child->y <= y && y < child->y + ACTUAL_HEIGHT(child)) { return get_window(child, x - child->x, y - child->y); } } } return win; } static inline u_char *get_fb(Display *display, int x, int y) { return ((u_char*)display->fb) + (y + DECORATION_MARGIN) * display->line_length + x * display->bytes_per_pixel; } static ui_display_t *surface_to_display(struct wl_surface *surface) { u_int count; for (count = 0; count < num_displays; count++) { if (surface == displays[count]->display->surface) { return displays[count]; } } return NULL; } #ifdef COMPAT_LIBVTE static ui_display_t *parent_surface_to_display(struct wl_surface *surface) { u_int count; for (count = 0; count < num_displays; count++) { if (surface == displays[count]->display->parent_surface) { return displays[count]; } } return NULL; } static ui_display_t *add_root_to_display(ui_display_t *disp, ui_window_t *root, struct wl_surface *parent_surface) { ui_wlserv_t *wlserv = disp->display->wlserv; ui_display_t *new; void *p; u_int count; if (!(p = realloc(displays, sizeof(ui_display_t*) * (num_displays + 1)))) { return NULL; } displays = p; if (wlservs == NULL) { if (!(wlservs = malloc(sizeof(ui_wlserv_t*)))) { return NULL; } wlservs[0] = wlserv; num_wlservs = 1; } if (!(new = calloc(1, sizeof(ui_display_t) + sizeof(Display)))) { return NULL; } memcpy(new, disp, sizeof(ui_display_t)); new->display = new + 1; new->name = strdup(disp->name); new->roots = NULL; new->num_roots = 0; memcpy(new->display, disp->display, sizeof(Display)); new->display->parent_surface = parent_surface; for (count = 0; count < num_displays; count++) { if (strcmp(displays[count]->name, new->name) == 0) { new->selection_owner = displays[count]->selection_owner; break; } } displays[num_displays++] = new; if ((p = realloc(disp->roots, sizeof(ui_window_t*) * (disp->num_roots + 1)))) { disp->roots = p; disp->roots[disp->num_roots++] = root; } wlserv->ref_count++; return new; } static ui_display_t *remove_root_from_display(ui_display_t *disp, ui_window_t *root) { u_int count; for (count = 0; count < disp->num_roots; count++) { if (disp->roots[count] == root) { disp->roots[count] = disp->roots[--disp->num_roots]; break; } } for (count = 0; count < num_displays; count++) { if (displays[count]->roots[0] == root) { return displays[count]; } } return NULL; } #endif static void seat_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability caps); static void seat_name(void *data, struct wl_seat *seat, const char *name) { #ifdef __DEBUG bl_debug_printf("seat_name %s\n", name); #endif } static const struct wl_seat_listener seat_listener = { seat_capabilities, seat_name, }; #ifdef XDG_SHELL_V6 static void xdg_shell_ping(void *data, struct zxdg_shell_v6 *xdg_shell, uint32_t serial) { zxdg_shell_v6_pong(xdg_shell, serial); } static const struct zxdg_shell_v6_listener xdg_shell_listener = { xdg_shell_ping }; #endif static void registry_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { ui_wlserv_t *wlserv = data; if(strcmp(interface, "wl_compositor") == 0) { wlserv->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1); } #ifdef COMPAT_LIBVTE else if (strcmp(interface, "wl_subcompositor") == 0) { wlserv->subcompositor = wl_registry_bind(registry, name, &wl_subcompositor_interface, 1); } /* For sway 1.0 which doesn't support wl_surface. (supports only xdg-shell) */ else if (strcmp(interface, "wl_shell") == 0) { wlserv->is_xdg_shell = -1; /* not xdg_shell */ } else if (strcmp(interface, "zxdg_shell_v6") == 0) { if (wlserv->is_xdg_shell == 0) { wlserv->is_xdg_shell = 1; } } #else else if (strcmp(interface, "wl_shell") == 0) { wlserv->shell = wl_registry_bind(registry, name, &wl_shell_interface, 1); #ifdef XDG_SHELL_V6 if (wlserv->xdg_shell) { zxdg_shell_v6_destroy(wlserv->xdg_shell); wlserv->xdg_shell = NULL; } #endif } #ifdef XDG_SHELL_V6 else if (strcmp(interface, "zxdg_shell_v6") == 0) { if (wlserv->shell == NULL) { wlserv->xdg_shell = wl_registry_bind(registry, name, &zxdg_shell_v6_interface, 1); zxdg_shell_v6_add_listener(wlserv->xdg_shell, &xdg_shell_listener, NULL); } } #endif #endif else if (strcmp(interface, "wl_shm") == 0) { wlserv->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); } else if (strcmp(interface, "wl_seat") == 0) { wlserv->seat = wl_registry_bind(registry, name, &wl_seat_interface, 4); /* 4 is for keyboard_repeat_info */ wl_seat_add_listener(wlserv->seat, &seat_listener, wlserv); } else if (strcmp(interface, "wl_output") == 0) { wlserv->output = wl_registry_bind(registry, name, &wl_output_interface, 1); } else if (strcmp(interface, "wl_data_device_manager") == 0) { wlserv->data_device_manager = wl_registry_bind(registry, name, &wl_data_device_manager_interface, 3); } else if (strcmp(interface, "gtk_primary_selection_device_manager") == 0) { wlserv->xsel_device_manager = wl_registry_bind(registry, name, >k_primary_selection_device_manager_interface, 1); } #ifdef __DEBUG else { bl_debug_printf("Unknown interface: %s\n", interface); } #endif } static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t name) { } static const struct wl_registry_listener registry_listener = { registry_global, registry_global_remove }; static void receive_key_event(ui_wlserv_t *wlserv, XKeyEvent *ev) { if (wlserv->current_kbd_surface) { ui_display_t *disp = surface_to_display(wlserv->current_kbd_surface); ui_window_t *win; #ifdef COMPAT_LIBVTE if (!disp) { disp = parent_surface_to_display(wlserv->current_kbd_surface); } #endif /* Key event for dead surface may be received. */ if (disp && (win = search_focused_window(disp->roots[0]))) { ui_window_receive_event(win, ev); } } } static void keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size){ ui_wlserv_t *wlserv = data; char *string; if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { close(fd); return; } if ((string = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { close(fd); return; } wlserv->xkb->keymap = xkb_keymap_new_from_string(wlserv->xkb->ctx, string, XKB_KEYMAP_FORMAT_TEXT_V1, 0); munmap(string, size); close(fd); wlserv->xkb->state = xkb_state_new(wlserv->xkb->keymap); wlserv->xkb->ctrl = xkb_keymap_mod_get_index(wlserv->xkb->keymap, XKB_MOD_NAME_CTRL); wlserv->xkb->alt = xkb_keymap_mod_get_index(wlserv->xkb->keymap, XKB_MOD_NAME_ALT); wlserv->xkb->shift = xkb_keymap_mod_get_index(wlserv->xkb->keymap, XKB_MOD_NAME_SHIFT); wlserv->xkb->logo = xkb_keymap_mod_get_index(wlserv->xkb->keymap, XKB_MOD_NAME_LOGO); } static void auto_repeat(void) { u_int count; for (count = 0; count < num_wlservs; count++) { /* If prev_kev.type > 0, kbd_repeat_wait is always greater than 0. */ if (wlservs[count]->prev_kev.type && /* wlservs[count]->kbd_repeat_wait > 0 && */ --wlservs[count]->kbd_repeat_wait == 0) { if (wlservs[count]->kbd_repeat_count++ == 2) { /* * Selecting next candidate of ibus lookup table by repeating space key * freezes without this. */ wl_display_roundtrip(wlservs[count]->display); wlservs[count]->kbd_repeat_count = 0; } wlservs[count]->prev_kev.time += kbd_repeat_N; receive_key_event(wlservs[count], &wlservs[count]->prev_kev); if (kbd_repeat_N < KEY_REPEAT_UNIT / 2) { wlservs[count]->kbd_repeat_wait = 1; } else { wlservs[count]->kbd_repeat_wait = (kbd_repeat_N + KEY_REPEAT_UNIT / 2) / KEY_REPEAT_UNIT; } } } } static void keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { ui_display_t *disp = surface_to_display(surface); ui_wlserv_t *wlserv = data; ui_window_t *win; #ifdef COMPAT_LIBVTE if (!disp || disp->num_roots == 0) { wlserv->current_kbd_surface = surface; return; } #endif if (disp->display->parent) { /* XXX input method */ disp = disp->display->parent; surface = disp->display->surface; } wlserv->current_kbd_surface = surface; #ifdef __DEBUG bl_debug_printf("keyboard_enter %p\n", surface); #endif if ((win = search_inputtable_window(NULL, disp->roots[0]))) { #ifdef __DEBUG bl_debug_printf("FOCUSED %p\n", win); #endif ui_window_set_input_focus(win); } /* During resizing keyboard leaves. keyboard_enter() means that resizing has finished. */ disp->display->is_resizing = 0; } static void keyboard_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) { ui_wlserv_t *wlserv = data; ui_display_t *disp = surface_to_display(surface); ui_window_t *win; #ifdef __DEBUG bl_debug_printf("keyboard_leave %p\n", surface); #endif #if 0 wlserv->prev_kev.type = 0; #endif #ifdef COMPAT_LIBVTE if (!disp || disp->num_roots == 0) { return; } #endif if (wlserv->current_kbd_surface == surface) { u_int count; for (count = 0; count < num_displays; count++) { if (displays[count]->display->parent == disp) { /* * Don't send FocusOut event to the surface which has an input method surface * as transient one, because the surface might receive this event by creating * and showing the input method surface. * As a secondary effect, the surface can't receive FocusOut event as long as * the input method surface is active. */ return; } } wlserv->current_kbd_surface = NULL; } /* surface may have been already destroyed. So null check of disp is necessary. */ if (disp && !disp->display->parent /* not input method window */ && (win = search_focused_window(disp->roots[0]))) { XEvent ev; #ifdef __DEBUG bl_debug_printf("UNFOCUSED %p\n", win); #endif ev.type = FocusOut; ui_window_receive_event(ui_get_root_window(win), &ev); } } static void keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state_w) { ui_wlserv_t *wlserv = data; XKeyEvent ev; if (state_w == WL_KEYBOARD_KEY_STATE_PRESSED) { ev.ksym = xkb_state_key_get_one_sym(wlserv->xkb->state, key + 8); ev.type = KeyPress; ev.keycode = 0; ev.state = wlserv->xkb->mods; ev.time = time; if (kbd_repeat_N == 0) { /* disable key repeating */ wlserv->kbd_repeat_wait = 0; wlserv->prev_kev.type = 0; } else { if (kbd_repeat_1 == 0) { wlserv->kbd_repeat_wait = 1; } else { wlserv->kbd_repeat_wait = (kbd_repeat_1 + KEY_REPEAT_UNIT - 1) / KEY_REPEAT_UNIT; } wlserv->prev_kev = ev; } #ifdef __DEBUG bl_debug_printf("key pressed %x %x at %d\n", ev.ksym, wlserv->xkb->mods, time); #endif } else if (state_w == WL_KEYBOARD_KEY_STATE_RELEASED) { #if 0 ev.type = KeyRelease; ev.time = time; ev.ksym = ev.keycode = ev.state = 0; #endif wlserv->prev_kev.type = 0; #ifdef __DEBUG bl_debug_printf("key released\n"); #endif return; } else { return; } wlserv->serial = serial; receive_key_event(wlserv, &ev); } static void keyboard_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { ui_wlserv_t *wlserv = data; xkb_mod_mask_t mod_mask; xkb_state_update_mask(wlserv->xkb->state, mods_depressed, mods_latched, mods_locked, group, 0, 0); mod_mask = xkb_state_serialize_mods(wlserv->xkb->state, XKB_STATE_MODS_EFFECTIVE); wlserv->xkb->mods = 0; if (mod_mask & (1 << wlserv->xkb->ctrl)) wlserv->xkb->mods |= ControlMask; if (mod_mask & (1 << wlserv->xkb->alt)) wlserv->xkb->mods |= Mod1Mask; /* XXX ModMask disables yourei by Ctrl+Alt+H on fcitx */ if (mod_mask & (1 << wlserv->xkb->shift)) wlserv->xkb->mods |= ShiftMask; #if 0 if (mod_mask & (1 << wlserv->xkb->logo)) wlserv->xkb->mods |= MOD_MASK_LOGO; #endif #ifdef __DEBUG bl_debug_printf("MODIFIER MASK %x\n", wlserv->xkb->mods); #endif } static void keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay) { #ifdef __DEBUG bl_debug_printf("Repeat info rate %d delay %d.\n", rate, delay); #endif kbd_repeat_1 = delay; /* The rate of repeating keys in characters per second. 0 disables any repeating. */ if (rate == 0) { kbd_repeat_N = 0; } else { kbd_repeat_N = 1000 / rate; } } static const struct wl_keyboard_listener keyboard_listener = { keyboard_keymap, keyboard_enter, keyboard_leave, keyboard_key, keyboard_modifiers, keyboard_repeat_info, }; static void change_cursor(struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, struct wl_cursor *cursor) { struct wl_buffer *buffer; struct wl_cursor_image *image; image = cursor->images[0]; if (!(buffer = wl_cursor_image_get_buffer(image))) { return; } wl_pointer_set_cursor(pointer, serial, surface, image->hotspot_x, image->hotspot_y); wl_surface_attach(surface, buffer, 0, 0); wl_surface_damage(surface, 0, 0, image->width, image->height); wl_surface_commit(surface); } static void pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t sx_w, wl_fixed_t sy_w) { ui_wlserv_t *wlserv = data; #ifdef __DEBUG bl_debug_printf("pointer_enter %p\n", surface); #endif wlserv->current_pointer_surface = surface; #ifdef COMPAT_LIBVTE if (parent_surface_to_display(surface)) { return; } #endif if (wlserv->cursor[0]) { change_cursor(pointer, serial, wlserv->cursor_surface, wlserv->cursor[0]); wlserv->current_cursor = 0; } } static void pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface) { ui_wlserv_t *wlserv = data; if (wlserv->current_pointer_surface == surface) { wlserv->current_pointer_surface = NULL; } #ifdef __DEBUG bl_debug_printf("pointer_leave %p\n", surface); #endif } static int get_edge_state(u_int width, u_int height, int x, int y) { if (x < RESIZE_MARGIN) { if (y < height / 8) { return WL_SHELL_SURFACE_RESIZE_TOP_LEFT; } else if (y > height - height / 8) { return WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT; } return WL_SHELL_SURFACE_RESIZE_LEFT; } else if (x > width - RESIZE_MARGIN * 2) { if (y < height / 8) { return WL_SHELL_SURFACE_RESIZE_TOP_RIGHT; } else if (y > height - height / 8) { return WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT; } return WL_SHELL_SURFACE_RESIZE_RIGHT; } else if (y < RESIZE_MARGIN) { if (x < width / 8) { return WL_SHELL_SURFACE_RESIZE_TOP_LEFT; } else if (x > width - width / 8) { return WL_SHELL_SURFACE_RESIZE_TOP_RIGHT; } else if (width * 2 / 5 < x && x < width - width * 2 / 5) { return 11; } return WL_SHELL_SURFACE_RESIZE_TOP; } else if (y > height - RESIZE_MARGIN * 2) { if (x < width / 8){ return WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT; } else if (x > width - width / 8){ return WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT; } else if (width * 2 / 5 < x && x < width - width * 2 / 5) { return 11; } return WL_SHELL_SURFACE_RESIZE_BOTTOM; } return WL_SHELL_SURFACE_RESIZE_NONE; } static void pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time /* milisec */, wl_fixed_t sx_w, wl_fixed_t sy_w) { ui_wlserv_t *wlserv = data; ui_display_t *disp; #ifdef ____DEBUG bl_debug_printf("pointer_motion (time: %d)\n", time); #endif disp = surface_to_display(wlserv->current_pointer_surface); if (disp) { XMotionEvent ev; ui_window_t *win; int resize_state; ev.type = MotionNotify; ev.time = time; ev.state = wlserv->xkb->mods; if (wlserv->pointer_button) { ev.state |= (Button1Mask << (wlserv->pointer_button - 1)); } wlserv->pointer_x = ev.x = wl_fixed_to_int(sx_w); wlserv->pointer_y = ev.y = wl_fixed_to_int(sy_w); if ((resize_state = get_edge_state(disp->display->width, disp->display->height, ev.x, ev.y))) { if (resize_state > 3) { /* 3 and 7 are missing numbers in wl_shell_surface_resize */ if (resize_state > 7) { resize_state -= 2; } else { resize_state --; } } if (!wlserv->cursor[resize_state]) { resize_state = 0; } } if (resize_state != wlserv->current_cursor) { change_cursor(pointer, 0, wlserv->cursor_surface, wlserv->cursor[resize_state]); wlserv->current_cursor = resize_state; } if (rotate_display) { int tmp = ev.x; if (rotate_display > 0) { ev.x = ev.y; ev.y = disp->display->width - tmp - 1; } else { ev.x = disp->display->height - ev.y - 1; ev.y = tmp; } } win = get_window(disp->roots[0], ev.x, ev.y); ev.x -= win->x; ev.y -= win->y; #ifdef ____DEBUG bl_debug_printf("Motion event state %x x %d y %d in %p window.\n", ev.state, ev.x, ev.y, win); #endif ui_window_receive_event(win, &ev); } } #ifdef COMPAT_LIBVTE void focus_gtk_window(ui_window_t *win, uint32_t time); #endif static void pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state_w) { ui_wlserv_t *wlserv = data; ui_display_t *disp; #ifdef __DEBUG bl_debug_printf("pointer_button (time: %d)\n", time); #endif disp = surface_to_display(wlserv->current_pointer_surface); if (disp) { XButtonEvent ev; ui_window_t *win; ev.x = wlserv->pointer_x; ev.y = wlserv->pointer_y; if (state_w == WL_POINTER_BUTTON_STATE_PRESSED) { ev.type = ButtonPress; if (button == BTN_LEFT) { #ifndef COMPAT_LIBVTE int state = get_edge_state(disp->display->width, disp->display->height, ev.x, ev.y); if (state > 0) { if (state == 11) { #ifdef XDG_SHELL_V6 if (disp->display->xdg_toplevel) { zxdg_toplevel_v6_move(disp->display->xdg_toplevel, wlserv->seat, serial); } else #endif { wl_shell_surface_move(disp->display->shell_surface, wlserv->seat, serial); } } else { disp->display->is_resizing = 1; #ifdef XDG_SHELL_V6 if (disp->display->xdg_toplevel) { zxdg_toplevel_v6_resize(disp->display->xdg_toplevel, wlserv->seat, serial, state); } else #endif { wl_shell_surface_resize(disp->display->shell_surface, wlserv->seat, serial, state); } } return; } #endif ev.button = 1; } else if (button == BTN_MIDDLE) { ev.button = 2; } else if (button == BTN_RIGHT) { ev.button = 3; } else { return; } wlserv->pointer_button = ev.button; } else { ev.type = ButtonRelease; ev.button = wlserv->pointer_button; wlserv->pointer_button = 0; } ev.time = time; ev.state = wlserv->xkb->mods; if (rotate_display) { int tmp = ev.x; if (rotate_display > 0) { ev.x = ev.y; ev.y = disp->display->width - tmp - 1; } else { ev.x = disp->display->height - ev.y - 1; ev.y = tmp; } } win = get_window(disp->roots[0], ev.x, ev.y); ev.x -= win->x; ev.y -= win->y; #ifdef __DEBUG bl_debug_printf("Button event type %d button %d state %x x %d y %d in %p window.\n", ev.type, ev.button, ev.state, ev.x, ev.y, win); #endif wlserv->serial = serial; ui_window_receive_event(win, &ev); #ifdef COMPAT_LIBVTE if (ev.type == ButtonPress && disp->display->parent == NULL /* Not input method */) { focus_gtk_window(win, time); } #endif } } static void pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { ui_wlserv_t *wlserv = data; ui_display_t *disp; #ifdef __DEBUG bl_debug_printf("pointer_axis (time: %d)\n", time); #endif disp = surface_to_display(wlserv->current_pointer_surface); if (disp) { XButtonEvent ev; ui_window_t *win; if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { /* Vertical scroll */ if (value < 0) { ev.button = 4; } else { ev.button = 5; } } else /* if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) */ { /* Horizontal scroll */ return; } ev.time = time; ev.state = wlserv->xkb->mods; ev.x = wlserv->pointer_x; ev.y = wlserv->pointer_y; if (rotate_display) { int tmp = ev.x; if (rotate_display > 0) { ev.x = ev.y; ev.y = disp->display->width - tmp - 1; } else { ev.x = disp->display->height - ev.y - 1; ev.y = tmp; } } win = get_window(disp->roots[0], ev.x, ev.y); ev.x -= win->x; ev.y -= win->y; #ifdef __DEBUG bl_debug_printf("Wheel event button %d state %x x %d y %d in %p window.\n", ev.button, ev.state, ev.x, ev.y, win); #endif ev.type = ButtonPress; ui_window_receive_event(win, &ev); ev.type = ButtonRelease; ui_window_receive_event(win, &ev); } } static const struct wl_pointer_listener pointer_listener = { pointer_enter, pointer_leave, pointer_motion, pointer_button, pointer_axis, }; static void seat_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability caps) { ui_wlserv_t *wlserv = data; #ifdef DEBUG bl_debug_printf("KBD: %s, MOUSE %s\n", (caps & WL_SEAT_CAPABILITY_KEYBOARD) ? "attach" : "detach", (caps & WL_SEAT_CAPABILITY_POINTER) ? "attach" : "detach"); #endif if (caps & WL_SEAT_CAPABILITY_KEYBOARD) { if (!wlserv->keyboard) { wlserv->keyboard = wl_seat_get_keyboard(wlserv->seat); wl_keyboard_add_listener(wlserv->keyboard, &keyboard_listener, wlserv); } } else { if (wlserv->keyboard) { wl_keyboard_destroy(wlserv->keyboard); wlserv->keyboard = NULL; } } if (caps & WL_SEAT_CAPABILITY_POINTER) { if (!wlserv->pointer) { wlserv->pointer = wl_seat_get_pointer(wlserv->seat); wl_pointer_add_listener(wlserv->pointer, &pointer_listener, wlserv); } } else { if (wlserv->pointer) { wl_pointer_destroy(wlserv->pointer); wlserv->pointer = NULL; } } wl_display_flush(wlserv->display); } static void surface_enter(void *data, struct wl_surface *surface, struct wl_output *output) { ui_wlserv_t *wlserv = data; #ifdef __DEBUG bl_debug_printf("surface_enter %p\n", surface); #endif wlserv->current_kbd_surface = surface; } static void surface_leave(void *data, struct wl_surface *surface, struct wl_output *output) { ui_wlserv_t *wlserv = data; #ifdef __DEBUG bl_debug_printf("surface_leave %p\n", surface); #endif if (wlserv->current_kbd_surface == surface) { wlserv->current_kbd_surface = NULL; } } static const struct wl_surface_listener surface_listener = { surface_enter, surface_leave }; /* Call this after display->surface was created. */ static int create_shm_buffer(Display *display) { struct wl_shm_pool *pool; int fd; int size; #ifdef __DEBUG bl_debug_printf("Buffer w %d h %d bpp %d\n", display->width, display->height, display->bytes_per_pixel * 8); #endif display->line_length = display->width * display->bytes_per_pixel; size = display->line_length * (display->height + DECORATION_MARGIN); if ((fd = create_anonymous_file(size)) < 0) { return 0; } if ((display->fb = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { return 0; } pool = wl_shm_create_pool(display->wlserv->shm, fd, size); display->buffer = wl_shm_pool_create_buffer(pool, 0, display->width, display->height, display->line_length, WL_SHM_FORMAT_ARGB8888); wl_shm_pool_destroy(pool); close(fd); #if defined(COMPAT_LIBVTE) if (display->wlserv->is_xdg_shell != 1) #elif defined(XDG_SHELL_V6) /* wl_surface_attach() must be called after xdg_surface_configure() on xdg-shell. */ if (display->xdg_surface == NULL) #endif { wl_surface_attach(display->surface, display->buffer, 0, 0); } return 1; } static void destroy_shm_buffer(Display *display) { #if 0 display->damage_x = display->damage_y = display->damage_width = display->damage_height = 0; #endif wl_surface_attach(display->surface, NULL, 0, 0); wl_buffer_destroy(display->buffer); munmap(display->fb, display->line_length * (display->height + DECORATION_MARGIN)); } static u_int total_min_width(ui_window_t *win) { u_int count; u_int min_width; min_width = win->min_width + win->hmargin * 2; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped) { /* XXX */ min_width += total_min_width(win->children[count]); } } return min_width; } static u_int total_min_height(ui_window_t *win) { u_int count; u_int min_height; min_height = win->min_height + win->vmargin * 2; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped) { /* XXX */ min_height += total_min_height(win->children[count]); } } return min_height; } static u_int max_width_inc(ui_window_t *win) { u_int count; u_int width_inc; width_inc = win->width_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped) { u_int sub_inc; /* * XXX * we should calculate least common multiple of width_inc and sub_inc. */ if ((sub_inc = max_width_inc(win->children[count])) > width_inc) { width_inc = sub_inc; } } } return width_inc; } static u_int max_height_inc(ui_window_t *win) { u_int count; u_int height_inc; height_inc = win->height_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped) { u_int sub_inc; /* * XXX * we should calculate least common multiple of width_inc and sub_inc. */ if ((sub_inc = max_height_inc(win->children[count])) > height_inc) { height_inc = sub_inc; } } } return height_inc; } static int resize_display(ui_display_t *disp, u_int width, u_int height, int roundtrip) { int do_create; if (disp->width == width && disp->height == height) { return 0; } if (roundtrip) { /* Process pending shell_surface_configure events in advance. */ wl_display_roundtrip(disp->display->wlserv->display); } #ifdef __DEBUG bl_debug_printf("Resizing display from w %d h %d to w %d h %d.\n", disp->width, disp->height, width, height); #endif #ifdef COMPAT_LIBVTE /* For the case of resizing a window which contains multiple tabs. */ if (disp->display->buffer) { destroy_shm_buffer(disp->display); do_create = 1; } else { do_create = 0; } #else destroy_shm_buffer(disp->display); do_create = 1; #endif disp->width = width; disp->height = height; if (rotate_display) { disp->display->width = height; disp->display->height = width; } else { disp->display->width = width; disp->display->height = height; } if (do_create) { create_shm_buffer(disp->display); } return 1; } #ifndef COMPAT_LIBVTE static void shell_surface_ping(void *data, struct wl_shell_surface *shell_surface, uint32_t serial) { wl_shell_surface_pong(shell_surface, serial); } static int check_resize(u_int old_width, u_int old_height, int32_t *new_width, int32_t *new_height, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc, int check_inc) { u_int diff; if (rotate_display) { BL_SWAP(unsigned int, min_width, min_height); BL_SWAP(unsigned int, width_inc, height_inc); } if (old_width < *new_width) { diff = ((*new_width - old_width) / width_inc) * width_inc; if (check_inc || diff < width_inc) { *new_width = old_width + diff; } } else if (*new_width < old_width) { diff = ((old_width - *new_width) / width_inc) * width_inc; if (!check_inc && diff >= width_inc) { diff = old_width - *new_width; } if (old_width < min_width + diff) { *new_width = min_width; } else { *new_width = old_width - diff; } } if (old_height < *new_height) { diff = ((*new_height - old_height) / height_inc) * height_inc; if (check_inc || diff < height_inc) { *new_height = old_height + diff; } } else if (*new_height < old_height) { diff = ((old_height - *new_height) / height_inc) * height_inc; if (!check_inc && diff >= height_inc) { diff = old_height - *new_height; } if (old_height < min_height + diff) { *new_height = min_height; } else { *new_height = old_height - diff; } } if (old_width == *new_width && old_height == *new_height) { return 0; } else { return 1; } } /* XXX I don't know why, but edges is always 0 even if resizing by dragging an edge. */ static void shell_surface_configure(void *data, struct wl_shell_surface *shell_surface, uint32_t edges, int32_t width, int32_t height) { ui_display_t *disp = data; #ifdef __DEBUG bl_debug_printf("shell_surface_configure\nConfiguring size from w %d h %d to w %d h %d.\n", disp->display->width, disp->display->height, width, height); #endif if (check_resize(disp->display->width, disp->display->height, &width, &height, total_min_width(disp->roots[0]), total_min_height(disp->roots[0]), max_width_inc(disp->roots[0]), max_height_inc(disp->roots[0]), disp->display->is_resizing)) { #ifdef __DEBUG bl_msg_printf("-> modified size w %d h %d\n", width, height); #endif if (rotate_display) { resize_display(disp, height, width, 0); } else { resize_display(disp, width, height, 0); } ui_window_resize_with_margin(disp->roots[0], disp->width, disp->height, NOTIFY_TO_MYSELF); } } static void shell_surface_popup_done(void *data, struct wl_shell_surface *shell_surface) { } static const struct wl_shell_surface_listener shell_surface_listener = { shell_surface_ping, shell_surface_configure, shell_surface_popup_done }; #ifdef XDG_SHELL_V6 static void xdg_surface_configure(void *data, struct zxdg_surface_v6 *xdg_surface, uint32_t serial) { ui_display_t *disp = data; #ifdef __DEBUG bl_debug_printf("xdg_surface_configure\n"); #endif zxdg_surface_v6_ack_configure(xdg_surface, serial); disp->display->xdg_surface_configured = 1; /* See flush_damage() */ #if 0 wl_surface_attach(disp->display->surface, disp->display->buffer, 0, 0); wl_surface_damage(disp->display->surface, 0, 0, disp->display->width, disp->display->height); wl_surface_commit(disp->display->surface); #endif } static const struct zxdg_surface_v6_listener xdg_surface_listener = { xdg_surface_configure }; static void xdg_toplevel_configure(void *data, struct zxdg_toplevel_v6 *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states) { ui_display_t *disp = data; #ifdef __DEBUG uint32_t *ps; bl_debug_printf("xdg_toplevel_configure: w %d, h %d / states: ", width, height); wl_array_for_each(ps, states) { switch(*ps) { case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED: bl_msg_printf("MAXIMIZED "); break; case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN: bl_msg_printf("FULLSCREEN "); break; case ZXDG_TOPLEVEL_V6_STATE_RESIZING: bl_msg_printf("RESIZING "); break; case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED: bl_msg_printf("ACTIVATED "); break; } } bl_msg_printf("\n"); #endif #ifdef __DEBUG bl_debug_printf("Configuring size from w %d h %d to w %d h %d.\n", disp->display->width, disp->display->height, width, height); #endif if (width == 0) { width = disp->display->width; } if (height == 0) { height = disp->display->height; } if (check_resize(disp->display->width, disp->display->height, &width, &height, total_min_width(disp->roots[0]), total_min_height(disp->roots[0]), max_width_inc(disp->roots[0]), max_height_inc(disp->roots[0]), disp->display->is_resizing)) { #ifdef __DEBUG bl_msg_printf("-> modified size w %d h %d\n", width, height); #endif if (rotate_display) { resize_display(disp, height, width, 0); } else { resize_display(disp, width, height, 0); } ui_window_resize_with_margin(disp->roots[0], disp->width, disp->height, NOTIFY_TO_MYSELF); } } static void xdg_toplevel_close(void *data, struct zxdg_toplevel_v6 *toplevel) { ui_display_t *disp = data; if (disp->roots[0]->window_destroyed) { (*disp->roots[0]->window_destroyed)(disp->roots[0]); } } const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = { xdg_toplevel_configure, xdg_toplevel_close }; #endif #endif static void update_mime(char **mime, char *new_mime) { if (strcmp(new_mime, "text/plain;charset=utf-8") == 0) { *mime = "text/plain;charset=utf-8"; } else if (*mime == NULL && strcmp(new_mime, "UTF8_STRING") == 0) { *mime = "UTF8_STRING"; } } static void data_offer_offer(void *data, struct wl_data_offer *offer, const char *type) { ui_wlserv_t *wlserv = data; #ifdef __DEBUG bl_debug_printf("data_offer_offer %s\n", type); #endif update_mime(&wlserv->sel_offer_mime, type); } static void data_offer_source_action(void *data, struct wl_data_offer *data_offer, uint32_t source_actions) { #ifdef __DEBUG bl_debug_printf("DND: source_action %d\n", source_actions); #endif } static void data_offer_action(void *data, struct wl_data_offer *data_offer, uint32_t dnd_action) { ui_wlserv_t *wlserv = data; #ifdef __DEBUG bl_debug_printf("DND: action %d\n", dnd_action); #endif wlserv->dnd_action = dnd_action; } static const struct wl_data_offer_listener data_offer_listener = { data_offer_offer, data_offer_source_action, data_offer_action }; static void data_device_data_offer(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer) { ui_wlserv_t *wlserv = data; #ifdef __DEBUG bl_debug_printf("data_device_data_offer %p\n", offer); #endif wl_data_offer_add_listener(offer, &data_offer_listener, wlserv); wlserv->dnd_offer = offer; wlserv->sel_offer_mime = NULL; } static void data_device_enter(void *data, struct wl_data_device *data_device, uint32_t serial, struct wl_surface *surface, wl_fixed_t x_w, wl_fixed_t y_w, struct wl_data_offer *offer) { ui_wlserv_t *wlserv = data; #ifdef __DEBUG bl_debug_printf("DND: enter %p\n", offer); #endif wl_data_offer_accept(offer, serial, "text/uri-list"); /* wl_data_device_manager_get_version() >= 3 */ wl_data_offer_set_actions(offer, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY| WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE, WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY); wlserv->data_surface = surface; } static void data_device_leave(void *data, struct wl_data_device *data_device) { ui_wlserv_t *wlserv = data; #ifdef __DEBUG bl_debug_printf("DND: leave\n"); #endif if (wlserv->dnd_offer) { wl_data_offer_destroy(wlserv->dnd_offer); wlserv->dnd_offer = NULL; } if (wlserv->sel_offer) { wl_data_offer_destroy(wlserv->sel_offer); wlserv->sel_offer = NULL; } wlserv->data_surface = NULL; } static void data_device_motion(void *data, struct wl_data_device *data_device, uint32_t time, wl_fixed_t x_w, wl_fixed_t y_w) { } static int unescape(char *src) { char *dst; int c; dst = src; while (*src) { if (*src == '%' && sscanf(src, "%%%2x", &c) == 1) { *(dst++) = c; src += 3; } else { *(dst++) = *(src++); } } *dst = '\0'; return (src != dst); } static void receive_data(ui_display_t *disp, void *offer, const char *mime, int clipboard) { int fds[2]; if (pipe(fds) == 0) { char buf[512]; ssize_t len; if (clipboard) { wl_data_offer_receive(offer, mime, fds[1]); } else { gtk_primary_selection_offer_receive(offer, mime, fds[1]); } wl_display_flush(disp->display->wlserv->display); close(fds[1]); while ((len = read(fds[0], buf, sizeof(buf) - 1)) > 0) { if (strcmp(mime, "text/uri-list") == 0) { char *p; while (buf[len - 1] == '\n' || buf[len - 1] == '\r') { len--; } buf[len] = '\0'; for (p = buf; *p; p++) { if (*p == 'f') { if (strncmp(p + 1, "ile://", 6) == 0) { memmove(p, p + 7, len - 7 + 1); p += 6; len -= 7; } } else if (*p == '\r' || *p == '\n') { *p = ' '; } } if (unescape(buf)) { len = strlen(buf); } } #ifdef __DEBUG else { buf[len] = '\0'; } bl_debug_printf("Receive data (len %d, mime %s): %s\n", len, mime, buf); #endif if (disp->display->wlserv->dnd_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE /* Shift+Drop */ && disp->roots[0]->set_xdnd_config) { (*disp->roots[0]->set_xdnd_config)(disp->roots[0], NULL, "scp", buf); break; } else if (disp->roots[0]->utf_selection_notified) { (*disp->roots[0]->utf_selection_notified)(disp->roots[0], buf, len); } } close(fds[0]); } } static void data_device_drop(void *data, struct wl_data_device *data_device) { ui_wlserv_t *wlserv = data; ui_display_t *disp; #ifdef __DEBUG bl_debug_printf("DND: drop\n"); #endif if ((disp = surface_to_display(wlserv->data_surface))) { receive_data(disp, wlserv->dnd_offer, "text/uri-list", 1); } } static void data_device_selection(void *data, struct wl_data_device *data_device, struct wl_data_offer *offer) { ui_wlserv_t *wlserv = data; #ifdef __DEBUG bl_debug_printf("data_device_selection %p -> %p\n", wlserv->sel_offer, offer); #endif if (wlserv->sel_source) { return; } if (wlserv->sel_offer) { wl_data_offer_destroy(wlserv->sel_offer); } wlserv->sel_offer = offer; } static const struct wl_data_device_listener data_device_listener = { data_device_data_offer, data_device_enter, data_device_leave, data_device_motion, data_device_drop, data_device_selection }; static void data_source_target(void *data, struct wl_data_source *source, const char *mime) { } static void data_source_send(void *data, struct wl_data_source *source, const char *mime, int32_t fd) { ui_display_t *disp = data; disp->display->wlserv->sel_fd = fd; #ifdef __DEBUG bl_debug_printf("data_source_send %s\n", mime); #endif if (disp->selection_owner->utf_selection_requested) { /* utf_selection_requested() calls ui_display_send_text_selection() */ (*disp->selection_owner->utf_selection_requested)(disp->selection_owner, NULL, 0); } } #ifdef COMPAT_LIBVTE #include gint64 deadline_ignoring_source_cancelled_event; #endif static void data_source_cancelled(void *data, struct wl_data_source *source) { ui_display_t *disp = data; ui_wlserv_t *wlserv = disp->display->wlserv; #ifdef __DEBUG bl_debug_printf("data_source_cancelled %p %p\n", source, wlserv->sel_source); #endif #ifdef COMPAT_LIBVTE if (deadline_ignoring_source_cancelled_event != 0 && deadline_ignoring_source_cancelled_event > g_get_monotonic_time()) { } else { deadline_ignoring_source_cancelled_event = 0; #endif if (source == wlserv->sel_source) { ui_display_clear_selection(disp, disp->selection_owner); } #ifdef COMPAT_LIBVTE } #endif } void data_source_dnd_drop_performed(void *data, struct wl_data_source *wl_data_source) { } void data_source_dnd_finished(void *data, struct wl_data_source *wl_data_source) { } void data_source_action(void *data, struct wl_data_source *wl_data_source, uint32_t dnd_action) { } static const struct wl_data_source_listener data_source_listener = { data_source_target, data_source_send, data_source_cancelled, data_source_dnd_drop_performed, data_source_dnd_finished, data_source_action, }; static void xsel_offer_offer(void *data, struct gtk_primary_selection_offer *offer, const char *type) { ui_wlserv_t *wlserv = data; #ifdef __DEBUG bl_debug_printf("xsel_offer_offer %s\n", type); #endif update_mime(&wlserv->xsel_offer_mime, type); } static const struct gtk_primary_selection_offer_listener xsel_offer_listener = { xsel_offer_offer, }; static void xsel_device_data_offer(void *data, struct gtk_primary_selection_device *device, struct gtk_primary_selection_offer *offer) { ui_wlserv_t *wlserv = data; #ifdef __DEBUG bl_debug_printf("gtk_device_data_offer %p\n", offer); #endif gtk_primary_selection_offer_add_listener(offer, &xsel_offer_listener, wlserv); wlserv->xsel_offer_mime = NULL; } static void xsel_device_selection(void *data, struct gtk_primary_selection_device *device, struct gtk_primary_selection_offer *offer) { ui_wlserv_t *wlserv = data; #ifdef __DEBUG bl_debug_printf("gtk_device_selection %p -> %p\n", wlserv->xsel_offer, offer); #endif if (wlserv->xsel_source) { return; } if (wlserv->xsel_offer) { gtk_primary_selection_offer_destroy(wlserv->xsel_offer); } wlserv->xsel_offer = offer; } static const struct gtk_primary_selection_device_listener xsel_device_listener = { xsel_device_data_offer, xsel_device_selection }; static void xsel_source_send(void *data, struct gtk_primary_selection_source *source, const char *mime, int32_t fd) { ui_display_t *disp = data; disp->display->wlserv->sel_fd = fd; #ifdef __DEBUG bl_debug_printf("xsel_source_send %s\n", mime); #endif if (disp->selection_owner->utf_selection_requested) { /* utf_selection_requested() calls ui_display_send_text_selection() */ (*disp->selection_owner->utf_selection_requested)(disp->selection_owner, NULL, 0); } } static void xsel_source_cancelled(void *data, struct gtk_primary_selection_source *source) { ui_display_t *disp = data; ui_wlserv_t *wlserv = disp->display->wlserv; #ifdef __DEBUG bl_debug_printf("xsel_source_cancelled %p %p\n", source, wlserv->xsel_source); #endif #ifdef COMPAT_LIBVTE if (deadline_ignoring_source_cancelled_event != 0 && deadline_ignoring_source_cancelled_event > g_get_monotonic_time()) { } else { deadline_ignoring_source_cancelled_event = 0; #endif if (source == wlserv->xsel_source) { ui_display_clear_selection(disp, disp->selection_owner); } #ifdef COMPAT_LIBVTE } #endif } static const struct gtk_primary_selection_source_listener xsel_source_listener = { xsel_source_send, xsel_source_cancelled, }; static ui_wlserv_t *open_wl_display(char *name) { ui_wlserv_t *wlserv; if (!(wlserv = calloc(1, sizeof(ui_wlserv_t) + sizeof(*wlserv->xkb)))) { return NULL; } wlserv->xkb = wlserv + 1; if ((wlserv->display = wl_display_connect(name)) == NULL) { bl_error_printf("Couldn't open display %s.\n", name); free(wlserv); return NULL; } /* set close-on-exec flag on the socket connected to X. */ bl_file_set_cloexec(wl_display_get_fd(wlserv->display)); wlserv->registry = wl_display_get_registry(wlserv->display); wl_registry_add_listener(wlserv->registry, ®istry_listener, wlserv); wl_display_roundtrip(wlserv->display); wlserv->xkb->ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); /* See seat_capabilities() */ #if 0 wlserv->keyboard = wl_seat_get_keyboard(wlserv->seat); wl_keyboard_add_listener(wlserv->keyboard, &keyboard_listener, wlserv); wlserv->pointer = wl_seat_get_pointer(wlserv->seat); wl_pointer_add_listener(wlserv->pointer, &pointer_listener, wlserv); #endif if ((wlserv->cursor_theme = wl_cursor_theme_load(NULL, 32, wlserv->shm))) { /* The order should be the one of wl_shell_surface_resize. */ char *names[] = { "xterm", "n-resize", "s-resize", "w-resize", "nw-resize", "sw-resize", "e-resize", "ne-resize", "se-resize", "move" }; int count; int has_cursor = 0; for (count = 0; count < sizeof(names) / sizeof(names[0]); count++) { if ((wlserv->cursor[count] = wl_cursor_theme_get_cursor(wlserv->cursor_theme, names[count]))) { has_cursor = 1; } } if (has_cursor) { wlserv->cursor_surface = wl_compositor_create_surface(wlserv->compositor); } else { wl_cursor_theme_destroy(wlserv->cursor_theme); wlserv->cursor_theme = NULL; } } if (wlserv->data_device_manager) { wlserv->data_device = wl_data_device_manager_get_data_device(wlserv->data_device_manager, wlserv->seat); wl_data_device_add_listener(wlserv->data_device, &data_device_listener, wlserv); } if (wlserv->xsel_device_manager) { wlserv->xsel_device = gtk_primary_selection_device_manager_get_device(wlserv->xsel_device_manager, wlserv->seat); gtk_primary_selection_device_add_listener(wlserv->xsel_device, &xsel_device_listener, wlserv); } wlserv->sel_fd = -1; return wlserv; } static void close_wl_display(ui_wlserv_t *wlserv) { #ifdef __DEBUG bl_debug_printf("Closing wldisplay.\n"); #endif #if 0 if (wlserv->dnd_offer) { wl_data_offer_destroy(wlserv->dnd_offer); wlserv->dnd_offer = NULL; } if (wlserv->sel_offer) { wl_data_offer_destroy(wlserv->sel_offer); wlserv->sel_offer = NULL; } #endif if (wlserv->sel_source) { wl_data_source_destroy(wlserv->sel_source); wlserv->sel_source = NULL; } if (wlserv->xsel_source) { gtk_primary_selection_source_destroy(wlserv->xsel_source); wlserv->xsel_source = NULL; } #ifdef COMPAT_LIBVTE wl_subcompositor_destroy(wlserv->subcompositor); #else #ifdef XDG_SHELL_V6 if (wlserv->xdg_shell) { zxdg_shell_v6_destroy(wlserv->xdg_shell); wlserv->xdg_shell = NULL; } else if (wlserv->shell) #endif { wl_shell_destroy(wlserv->shell); wlserv->shell = NULL; } #endif wl_output_destroy(wlserv->output); wl_compositor_destroy(wlserv->compositor); #ifndef COMPAT_LIBVTE wl_registry_destroy(wlserv->registry); #endif if (wlserv->cursor_surface) { wl_surface_destroy(wlserv->cursor_surface); } if (wlserv->cursor_theme) { wl_cursor_theme_destroy(wlserv->cursor_theme); } if (wlserv->keyboard) { wl_keyboard_destroy(wlserv->keyboard); wlserv->keyboard = NULL; } xkb_state_unref(wlserv->xkb->state); xkb_keymap_unref(wlserv->xkb->keymap); xkb_context_unref(wlserv->xkb->ctx); if (wlserv->pointer) { wl_pointer_destroy(wlserv->pointer); wlserv->pointer = NULL; } wl_seat_destroy(wlserv->seat); wl_data_device_destroy(wlserv->data_device); wl_data_device_manager_destroy(wlserv->data_device_manager); #ifndef COMPAT_LIBVTE wl_display_disconnect(wlserv->display); free(wlserv); #endif } static void close_display(ui_display_t *disp) { u_int count; #ifdef __DEBUG bl_debug_printf("Closing ui_display_t\n"); #endif free(disp->name); for (count = 0; count < disp->num_roots; count++) { ui_window_unmap(disp->roots[count]); ui_window_final(disp->roots[count]); } free(disp->roots); ui_picture_display_closed(disp->display); #ifdef COMPAT_LIBVTE if (disp->display->subsurface) { /* disp->display->buffer may have been destroyed in ui_display_unmap(). */ if (disp->display->buffer) { destroy_shm_buffer(disp->display); disp->display->buffer = NULL; } wl_subsurface_destroy(disp->display->subsurface); wl_surface_destroy(disp->display->surface); } #else #ifdef XDG_SHELL_V6 if (disp->display->xdg_surface) { destroy_shm_buffer(disp->display); disp->display->buffer = NULL; zxdg_toplevel_v6_destroy(disp->display->xdg_toplevel); zxdg_surface_v6_destroy(disp->display->xdg_surface); wl_surface_destroy(disp->display->surface); } else #endif if (disp->display->shell_surface) { destroy_shm_buffer(disp->display); disp->display->buffer = NULL; wl_shell_surface_destroy(disp->display->shell_surface); wl_surface_destroy(disp->display->surface); } #endif if (disp->display->wlserv->ref_count == 1) { u_int count; close_wl_display(disp->display->wlserv); for (count = 0; count < num_wlservs; count++) { if (disp->display->wlserv == wlservs[count]) { if (--num_wlservs == 0) { free(wlservs); wlservs = NULL; } else { wlservs[count] = wlservs[--num_wlservs]; } } } } else { disp->display->wlserv->ref_count--; } free(disp); } static int flush_damage(Display *display) { if (display->damage_height > 0) { /* * xdg_shell seems to require calling wl_surface_attach() every time * differently from wl_shell. */ #if defined(COMPAT_LIBVTE) if (display->wlserv->is_xdg_shell == 1) { wl_surface_attach(display->surface, display->buffer, 0, 0); } else #elif defined(XDG_SHELL_V6) if (display->xdg_surface) { if (display->xdg_surface_configured) { wl_surface_attach(display->surface, display->buffer, 0, 0); } else { return 0; } } #endif wl_surface_damage(display->surface, display->damage_x, display->damage_y, display->damage_width, display->damage_height); display->damage_x = display->damage_y = display->damage_width = display->damage_height = 0; return 1; } else { return 0; } } static int cache_damage_h(Display *display, int x, int y, u_int width, u_int height) { if (x == display->damage_x && width == display->damage_width) { if (y == display->damage_y + display->damage_height) { display->damage_height += height; return 1; } else if (y + height == display->damage_y) { display->damage_y = y; display->damage_height += height; return 1; } } return 0; } static int cache_damage_v(Display *display, int x, int y, u_int width, u_int height) { if (y == display->damage_y && height == display->damage_height) { if (x == display->damage_x + display->damage_width) { display->damage_width += width; return 1; } else if (x + width == display->damage_x) { display->damage_x = x; display->damage_width += width; return 1; } } return 0; } static void damage_buffer(Display *display, int x, int y, u_int width, u_int height) { if (!cache_damage_v(display, x, y, width, height) && !cache_damage_h(display, x, y, width, height)) { if (display->damage_height > 0) { wl_surface_damage(display->surface, display->damage_x, display->damage_y, display->damage_width, display->damage_height); } display->damage_x = x; display->damage_y = y; display->damage_width = width; display->damage_height = height; } } static int flush_display(Display *display) { if (flush_damage(display)) { wl_surface_commit(display->surface); #ifdef COMPAT_LIBVTE if (display->parent) { /* * Input method window. * refrect wl_surface_damage() immediately. */ wl_surface_commit(display->parent_surface); } #endif return 1; } else { return 0; } } static void create_surface(ui_display_t *disp, u_int width, u_int height, char *app_name) { Display *display = disp->display; ui_wlserv_t *wlserv = display->wlserv; display->surface = wl_compositor_create_surface(wlserv->compositor); #ifdef COMPAT_LIBVTE display->subsurface = wl_subcompositor_get_subsurface(wlserv->subcompositor, display->surface, display->parent_surface); #else #ifdef XDG_SHELL_V6 if (wlserv->xdg_shell) { display->xdg_surface = zxdg_shell_v6_get_xdg_surface(wlserv->xdg_shell, display->surface); zxdg_surface_v6_add_listener(display->xdg_surface, &xdg_surface_listener, disp); display->xdg_toplevel = zxdg_surface_v6_get_toplevel(display->xdg_surface); zxdg_toplevel_v6_set_app_id(display->xdg_toplevel, app_name); zxdg_toplevel_v6_add_listener(display->xdg_toplevel, &xdg_toplevel_listener, disp); wl_surface_commit(display->surface); } else #endif { display->shell_surface = wl_shell_get_shell_surface(wlserv->shell, display->surface); wl_shell_surface_set_class(display->shell_surface, app_name); if (!display->parent) { /* Not input method */ wl_surface_add_listener(display->surface, &surface_listener, wlserv); wl_shell_surface_add_listener(display->shell_surface, &shell_surface_listener, disp); wl_shell_surface_set_toplevel(display->shell_surface); wl_shell_surface_set_title(display->shell_surface, app_name); } } #endif disp->width = width; disp->height = height; if (rotate_display) { display->width = height; display->height = width; } else { display->width = width; display->height = height; } } /* --- global functions --- */ ui_display_t *ui_display_open(char *disp_name, u_int depth) { u_int count; ui_display_t *disp; ui_wlserv_t *wlserv = NULL; void *p; struct rgb_info rgbinfo = {0, 0, 0, 16, 8, 0}; static int added_auto_repeat; if (!(disp = calloc(1, sizeof(ui_display_t) + sizeof(Display)))) { return NULL; } disp->display = disp + 1; if ((p = realloc(displays, sizeof(ui_display_t*) * (num_displays + 1))) == NULL) { free(disp); return NULL; } displays = p; displays[num_displays] = disp; for (count = 0; count < num_displays; count++) { if (strcmp(displays[count]->name, disp_name) == 0) { disp->selection_owner = displays[count]->selection_owner; wlserv = displays[count]->display->wlserv; break; } } if (wlserv == NULL) { if ((wlserv = open_wl_display(disp_name)) == NULL) { free(disp); return NULL; } if ((p = realloc(wlservs, sizeof(ui_wlserv_t*) * (num_wlservs + 1))) == NULL) { close_wl_display(wlserv); free(disp); return NULL; } wlservs = p; wlservs[num_wlservs++] = wlserv; } disp->display->wlserv = wlserv; disp->name = strdup(disp_name); disp->display->rgbinfo = rgbinfo; disp->display->bytes_per_pixel = 4; disp->depth = 32; wlserv->ref_count++; num_displays++; ui_picture_display_opened(disp->display); if (!added_auto_repeat) { ui_event_source_add_fd(-10, auto_repeat); added_auto_repeat = 1; } return disp; } void ui_display_close(ui_display_t *disp) { u_int count; for (count = 0; count < num_displays; count++) { if (displays[count] == disp) { close_display(disp); if (--num_displays == 0) { free(displays); displays = NULL; } else { displays[count] = displays[num_displays]; } #ifdef __DEBUG bl_debug_printf("wayland display connection closed.\n"); #endif return; } } } void ui_display_close_all(void) { while (num_displays > 0) { close_display(displays[0]); } } ui_display_t **ui_get_opened_displays(u_int *num) { *num = num_displays; return displays; } int ui_display_fd(ui_display_t *disp) { return wl_display_get_fd(disp->display->wlserv->display); } int ui_display_show_root(ui_display_t *disp, ui_window_t *root, int x, int y, int hint, char *app_name, Window parent_window) { void *p; if (parent_window) { #ifdef COMPAT_LIBVTE disp = add_root_to_display(disp, root, parent_window); #endif } else { if (disp->num_roots > 0) { /* XXX Input Method */ ui_display_t *parent = disp; disp = ui_display_open(disp->name, disp->depth); disp->display->parent = parent; #ifdef COMPAT_LIBVTE parent_window = disp->display->parent_surface = parent->display->parent_surface; #endif } } root->parent_window = parent_window; if ((p = realloc(disp->roots, sizeof(ui_window_t *) * (disp->num_roots + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } disp->roots = p; root->disp = disp; root->parent = NULL; root->gc = disp->gc; root->x = 0; root->y = 0; if (app_name) { root->app_name = app_name; } /* * root is added to disp->roots before ui_window_show() because * ui_display_get_group_leader() is called in ui_window_show(). */ disp->roots[disp->num_roots++] = root; create_surface(disp, ACTUAL_WIDTH(root), ACTUAL_HEIGHT(root), root->app_name); #ifdef COMPAT_LIBVTE if (!disp->display->parent) { /* do nothing until ui_display_map() except input method */ } else #endif { #if 0 /* def XDG_SHELL_V6 */ if (disp->display->xdg_surface && disp->display->parent == NULL && (hint & (XValue | YValue))) { zxdg_surface_v6_set_window_geometry(disp->display->xdg_surface, x, y, ACTUAL_WIDTH(root), ACTUAL_HEIGHT(root)); } #endif create_shm_buffer(disp->display); #ifndef COMPAT_LIBVTE if (disp->display->parent) #endif { /* XXX Input Method */ /* XXX * x and y of wl_shell_surface_set_transient() aren't applied without calling * wl_surface_commit() here before calling wl_shell_surface_set_transient(). */ wl_surface_commit(disp->display->surface); /* * XXX wl_shell_surface_set_transient() doesn't move surface to the specified position * if it is called before create_shm_buffer(). */ ui_display_move(disp, x, y); } ui_window_show(root, hint); } /* XXX mlterm -sbmod=none on sway 1.0 stops without calling wl_display_dispatch() here. */ wl_display_dispatch(disp->display->wlserv->display); return 1; } int ui_display_remove_root(ui_display_t *disp, ui_window_t *root) { u_int count; for (count = 0; count < disp->num_roots; count++) { if (disp->roots[count] == root) { #ifdef COMPAT_LIBVTE if (disp->display->parent) { /* XXX input method (do nothing) */ } else { disp = remove_root_from_display(disp, root); } count = 0; #endif /* Don't switching on or off screen in exiting. */ ui_window_unmap(root); ui_window_final(root); disp->num_roots--; if (count == disp->num_roots) { disp->roots[count] = NULL; if (disp->num_roots == 0 #ifndef COMPAT_LIBVTE && disp->display->parent /* XXX input method alone */ #endif ) { ui_display_close(disp); } } else { disp->roots[count] = disp->roots[disp->num_roots]; } return 1; } } return 0; } void ui_display_idling(ui_display_t *disp) { u_int count; #ifdef COMPAT_LIBVTE static int display_idling_wait = 4; if (--display_idling_wait > 0) { goto skip; } display_idling_wait = 4; #endif for (count = 0; count < disp->num_roots; count++) { #ifdef COMPAT_LIBVTE if (disp->roots[count]->disp->display->buffer) #endif { ui_window_idling(disp->roots[count]); } } ui_display_sync(disp); skip: auto_repeat(); } #ifndef COMPAT_LIBVTE int ui_display_receive_next_event(ui_display_t *disp) { u_int count; ui_display_sync(disp); for (count = 0; count < num_displays; count++) { if (displays[count]->display->wlserv == disp->display->wlserv) { if (displays[count] == disp) { return (wl_display_dispatch(disp->display->wlserv->display) != -1); } else { break; } } } return 0; } int ui_display_receive_next_event_singly(ui_display_t *disp) { u_int count; ui_display_sync(disp); for (count = 0; count < num_displays; count++) { if (displays[count]->display->wlserv == disp->display->wlserv) { return (wl_display_dispatch(disp->display->wlserv->display) != -1); } else { break; } } return 0; } #endif void ui_display_sync(ui_display_t *disp) { #ifdef COMPAT_LIBVTE u_int count; int flushed = 0; /* * ui_display_sync() is called from ui_display_idling() alone on libvte compat library. * ui_display_idling() is called with disp in vte.c, not displays in ui_display.c, so * call flush_display() with all displays here. */ for (count = 0; count < num_displays; count++) { if (displays[count]->display->buffer) { flushed |= flush_display(displays[count]->display); } } if (flushed) { wl_display_flush(wlservs[0]->display); } #else if (flush_display(disp->display)) { wl_display_flush(disp->display->wlserv->display); } #endif } /* * Folloing functions called from ui_window.c */ int ui_display_own_selection(ui_display_t *disp, ui_window_t *win) { ui_wlserv_t *wlserv = disp->display->wlserv; u_int count; if (disp->selection_owner) { ui_display_clear_selection(NULL, disp->selection_owner); } for (count = 0; count < num_displays; count++) { if (displays[count]->display->wlserv == wlserv) { displays[count]->selection_owner = win; } } if (wlserv->xsel_device_manager) { wlserv->xsel_source = gtk_primary_selection_device_manager_create_source(wlserv->xsel_device_manager); gtk_primary_selection_source_offer(wlserv->xsel_source, "UTF8_STRING"); /* gtk_primary_selection_source_offer(wlserv->xsel_source, "COMPOUND_TEXT"); */ gtk_primary_selection_source_offer(wlserv->xsel_source, "TEXT"); gtk_primary_selection_source_offer(wlserv->xsel_source, "STRING"); gtk_primary_selection_source_offer(wlserv->xsel_source, "text/plain;charset=utf-8"); gtk_primary_selection_source_offer(wlserv->xsel_source, "text/plain"); gtk_primary_selection_source_add_listener(wlserv->xsel_source, &xsel_source_listener, disp); gtk_primary_selection_device_set_selection(wlserv->xsel_device, wlserv->xsel_source, wlserv->serial); } if (wlserv->data_device_manager) { wlserv->sel_source = wl_data_device_manager_create_data_source(wlserv->data_device_manager); wl_data_source_offer(wlserv->sel_source, "UTF8_STRING"); /* wl_data_source_offer(wlserv->sel_source, "COMPOUND_TEXT"); */ wl_data_source_offer(wlserv->sel_source, "TEXT"); wl_data_source_offer(wlserv->sel_source, "STRING"); wl_data_source_offer(wlserv->sel_source, "text/plain;charset=utf-8"); wl_data_source_offer(wlserv->sel_source, "text/plain"); wl_data_source_add_listener(wlserv->sel_source, &data_source_listener, disp); wl_data_device_set_selection(wlserv->data_device, wlserv->sel_source, wlserv->serial); } #ifdef __DEBUG bl_debug_printf("set_selection\n"); #endif return 1; } int ui_display_clear_selection(ui_display_t *disp, /* NULL means all selection owner windows. */ ui_window_t *win) { u_int count; for (count = 0; count < num_displays; count++) { if ((disp == NULL || disp->display->wlserv == displays[count]->display->wlserv) && (displays[count]->selection_owner == win)) { displays[count]->selection_owner = NULL; if (displays[count]->display->wlserv->sel_source) { wl_data_source_destroy(displays[count]->display->wlserv->sel_source); displays[count]->display->wlserv->sel_source = NULL; } if (displays[count]->display->wlserv->xsel_source) { gtk_primary_selection_source_destroy(displays[count]->display->wlserv->xsel_source); displays[count]->display->wlserv->xsel_source = NULL; } } } if (win->selection_cleared) { (*win->selection_cleared)(win); } return 1; } XModifierKeymap *ui_display_get_modifier_mapping(ui_display_t *disp) { return disp->modmap.map; } void ui_display_update_modifier_mapping(ui_display_t *disp, u_int serial) {} XID ui_display_get_group_leader(ui_display_t *disp) { if (disp->num_roots > 0) { return disp->roots[0]->my_window; } else { return None; } } void ui_display_rotate(int rotate) { if (num_displays > 0) { bl_msg_printf("rotate_display option is not changeable.\n"); return; } rotate_display = rotate; } /* Don't call this internally from ui_display.c. Call resize_display(..., 0) instead. */ int ui_display_resize(ui_display_t *disp, u_int width, u_int height) { return resize_display(disp, width, height, 1); } int ui_display_move(ui_display_t *disp, int x, int y) { Display *display = disp->display; #ifdef COMPAT_LIBVTE if (!display->buffer || (display->x == x && display->y == y)) { return 0; } display->x = x; display->y = y; if (display->subsurface) { #ifdef __DEBUG bl_debug_printf("Move display (on libvte) at %d %d\n", x, y); #endif wl_subsurface_set_position(display->subsurface, x, y); if (display->parent) { /* * Input method window. * refrect wl_subsurface_set_position() immediately. */ wl_surface_commit(display->parent_surface); } } #else #ifdef XDG_SHELL_V6 if (display->xdg_surface) { /* XXX */ bl_warn_printf("It is impossible to move windows on xdg_shell for now.\n"); } else #endif if (display->parent) { /* input method window */ #ifdef __DEBUG bl_debug_printf("Move display (set transient) at %d %d\n", x, y); #endif wl_shell_surface_set_transient(display->shell_surface, display->parent->display->surface, x, y, WL_SHELL_SURFACE_TRANSIENT_INACTIVE); } #endif return 1; } u_long ui_display_get_pixel(ui_display_t *disp, int x, int y) { u_char *fb; u_long pixel; #ifdef COMPAT_LIBVTE if (!disp->display->buffer) { return 0; } #endif if (rotate_display) { int tmp; if (rotate_display > 0) { tmp = x; x = disp->height - y - 1; y = tmp; } else { tmp = x; x = y; y = disp->width - tmp - 1; } } fb = get_fb(disp->display, x, y); pixel = TOINT32(fb); return pixel; } void ui_display_put_image(ui_display_t *disp, int x, int y, u_char *image, size_t size, int need_fb_pixel) { Display *display = disp->display; #ifdef COMPAT_LIBVTE if (!display->buffer) { return; } #endif if (rotate_display) { /* Display is rotated. */ u_char *fb; int tmp; int line_length; size_t count; tmp = x; if (rotate_display > 0) { x = disp->height - y - 1; y = tmp; line_length = display->line_length; } else { x = y; y = disp->width - tmp - 1; line_length = -display->line_length; } fb = get_fb(display, x, y); if (display->bytes_per_pixel == 2) { size /= 2; for (count = 0; count < size; count++) { *((u_int16_t*)fb) = ((u_int16_t*)image)[count]; fb += line_length; } } else /* if (display->bytes_per_pixel == 4) */ { size /= 4; for (count = 0; count < size; count++) { *((u_int32_t*)fb) = ((u_int32_t*)image)[count]; fb += line_length; } } damage_buffer(display, x, rotate_display > 0 ? y : y - size + 1, 1, size); } else { memcpy(get_fb(display, x, y), image, size); damage_buffer(display, x, y, size, 1); } } void ui_display_copy_lines(ui_display_t *disp, int src_x, int src_y, int dst_x, int dst_y, u_int width, u_int height) { Display *display = disp->display; u_char *src; u_char *dst; u_int copy_len; u_int count; size_t line_length; #ifdef COMPAT_LIBVTE if (!display->buffer) { return; } #endif if (rotate_display) { int tmp; if (rotate_display > 0) { tmp = src_x; src_x = disp->height - src_y - height; src_y = tmp; tmp = dst_x; dst_x = disp->height - dst_y - height; dst_y = tmp; } else { tmp = src_x; src_x = src_y; src_y = disp->width - tmp - width; tmp = dst_x; dst_x = dst_y; dst_y = disp->width - tmp - width; } tmp = height; height = width; width = tmp; } copy_len = width * display->bytes_per_pixel; line_length = display->line_length; if (src_y <= dst_y) { src = get_fb(display, src_x, src_y + height - 1); dst = get_fb(display, dst_x, dst_y + height - 1); if (src_y == dst_y) { for (count = 0; count < height; count++) { memmove(dst, src, copy_len); dst -= line_length; src -= line_length; } } else { for (count = 0; count < height; count++) { memcpy(dst, src, copy_len); dst -= line_length; src -= line_length; } } } else { src = get_fb(display, src_x, src_y); dst = get_fb(display, dst_x, dst_y); for (count = 0; count < height; count++) { memcpy(dst, src, copy_len); dst += line_length; src += line_length; } } damage_buffer(display, dst_x, dst_y, width, height); } void ui_display_request_text_selection(ui_display_t *disp) { if (disp->selection_owner) { XSelectionRequestEvent ev; ev.type = 0; ev.target = disp->roots[0]; if (disp->selection_owner->utf_selection_requested) { /* utf_selection_requested() calls ui_display_send_text_selection() */ (*disp->selection_owner->utf_selection_requested)(disp->selection_owner, &ev, 0); } } else { ui_wlserv_t *wlserv = disp->display->wlserv; if (wlserv->xsel_offer && wlserv->xsel_offer_mime) { receive_data(disp, wlserv->xsel_offer, wlserv->xsel_offer_mime, 0); } else if (wlserv->sel_offer && wlserv->sel_offer_mime) { receive_data(disp, wlserv->sel_offer, wlserv->sel_offer_mime, 1); } } } void ui_display_send_text_selection(ui_display_t *disp, XSelectionRequestEvent *ev, u_char *sel_data, size_t sel_len) { if (disp->display->wlserv->sel_fd != -1) { write(disp->display->wlserv->sel_fd, sel_data, sel_len); close(disp->display->wlserv->sel_fd); disp->display->wlserv->sel_fd = -1; } else if (ev && ev->target->utf_selection_notified) { (*ev->target->utf_selection_notified)(ev->target, sel_data, sel_len); } } size_t ui_display_get_utf8(char *utf8 /* 7 bytes (UTF_MAX_SIZE + 1) */, KeySym ksym) { /* xkb_keysym_to_utf8() appends '\0' to utf8 bytes. */ return xkb_keysym_to_utf8(ksym, utf8, 7); } void ui_display_logical_to_physical_coordinates(ui_display_t *disp, int *x, int *y) { if (rotate_display) { int tmp = *y; if (rotate_display > 0) { *y = *x; *x = disp->display->width - tmp - 1; } else { *y = disp->display->height - *x - 1; *x = tmp; } } #ifdef COMPAT_LIBVTE *x += disp->display->x; *y += disp->display->y; #endif } void ui_display_set_maximized(ui_display_t *disp, int flag) { #ifndef COMPAT_LIBVTE if (flag) { #ifdef XDG_SHELL_V6 if (disp->display->xdg_toplevel) { zxdg_toplevel_v6_set_maximized(disp->display->xdg_toplevel); } else #endif { wl_shell_surface_set_maximized(disp->display->shell_surface, disp->display->wlserv->output); } } #endif } void ui_display_set_title(ui_display_t *disp, const u_char *name) { #ifndef COMPAT_LIBVTE #ifdef XDG_SHELL_V6 if (disp->display->xdg_toplevel) { zxdg_toplevel_v6_set_title(disp->display->xdg_toplevel, name); } else #endif { wl_shell_surface_set_title(disp->display->shell_surface, name); } #endif } #ifdef COMPAT_LIBVTE /* * Only one ui_wlserv_t exists on libvte compat library. * disp in vte.c shares one ui_wlserv_t but doesn't have shm buffer and surface. * displays in ui_display.c share one ui_wlserv_t and have each shm buffer and surface. */ void ui_display_init_wlserv(ui_wlserv_t *wlserv) { wl_registry_add_listener(wlserv->registry, ®istry_listener, wlserv); wl_display_roundtrip(wlserv->display); wlserv->xkb->ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); /* See seat_capabilities() */ #if 0 wlserv->keyboard = wl_seat_get_keyboard(wlserv->seat); wl_keyboard_add_listener(wlserv->keyboard, &keyboard_listener, wlserv); wlserv->pointer = wl_seat_get_pointer(wlserv->seat); wl_pointer_add_listener(wlserv->pointer, &pointer_listener, wlserv); #endif if (wlserv->data_device_manager) { wlserv->data_device = wl_data_device_manager_get_data_device(wlserv->data_device_manager, wlserv->seat); wl_data_device_add_listener(wlserv->data_device, &data_device_listener, wlserv); } if (wlserv->xsel_device_manager) { wlserv->xsel_device = gtk_primary_selection_device_manager_get_device(wlserv->xsel_device_manager, wlserv->seat); gtk_primary_selection_device_add_listener(wlserv->xsel_device, &xsel_device_listener, wlserv); } if ((wlserv->cursor_theme = wl_cursor_theme_load(NULL, 32, wlserv->shm))) { wlserv->cursor[0] = wl_cursor_theme_get_cursor(wlserv->cursor_theme, "xterm"); wlserv->cursor_surface = wl_compositor_create_surface(wlserv->compositor); } wlserv->sel_fd = -1; } void ui_display_map(ui_display_t *disp) { if (!disp->display->buffer) { ui_window_t *win; #ifdef __DEBUG bl_debug_printf("Creating new shm buffer.\n"); #endif /* * wl_subsurface should be desynchronized between create_shm_buffer() and * destroy_shm_buffer() to draw screen correctly. */ wl_subsurface_set_desync(disp->display->subsurface); create_shm_buffer(disp->display); /* * gnome-terminal doesn't invoke FocusIn event in switching tabs, so * it is necessary to set current_kbd_surface and is_focused manually. */ disp->display->wlserv->current_kbd_surface = disp->display->surface; if ((win = search_inputtable_window(NULL, disp->roots[0]))) { /* * ui_window_set_input_focus() is not called here, because it is not necessary to * call win->window_focused() which is called in ui_window_set_input_focus(). */ win->inputtable = win->is_focused = 1; } /* * shell_surface_configure() might have been already received and * the size of ui_display_t and ui_window_t might mismatch. * So, ui_window_show() doesn't show anything. */ disp->roots[0]->is_mapped = 0; ui_window_show(disp->roots[0], 0); disp->roots[0]->is_mapped = 1; if (!ui_window_resize_with_margin(disp->roots[0], disp->width, disp->height, NOTIFY_TO_MYSELF)) { ui_window_update_all(disp->roots[0]); } } } void ui_display_unmap(ui_display_t *disp) { if (disp->display->buffer) { #ifdef __DEBUG bl_debug_printf("Destroying shm buffer.\n"); #endif destroy_shm_buffer(disp->display); /* * Without calling wl_subsurface_set_sync() before wl_surface_commit(), * is_surface_effectively_shnchronized(surface->sub.parent) in meta-wayland-surface.c * (mutter-3.22.3) causes segfault because surface->sub.parent can be NULL before * ui_display_unmap() is called. */ wl_subsurface_set_sync(disp->display->subsurface); wl_surface_commit(disp->display->surface); disp->display->buffer = NULL; disp->display->x = disp->display->y = 0; } } #endif /* COMPAT_LIBVTE */ mlterm-3.8.9/uitoolkit/wayland/ui_display.h010064400017600000144000000033161356600660700175420ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_DISPLAY_H__ #define ___UI_DISPLAY_H__ #include "../ui_display.h" #define CLKED 1 #define NLKED 2 #define SLKED 4 #define ALKED 8 #define KeyPress 2 /* Private in wayland/ */ #define ButtonPress 4 /* Private in wayland/ */ #define ButtonRelease 5 /* Private in wayland/ */ #define MotionNotify 6 /* Private in wayland/ */ #define FocusOut 10 /* Private in wayland/ */ /* common functions for ui_window.c */ u_long ui_display_get_pixel(ui_display_t *disp, int x, int y); void ui_display_put_image(ui_display_t *disp, int x, int y, u_char *image, size_t size, int need_fb_pixel); void ui_display_copy_lines(ui_display_t *disp, int src_x, int src_y, int dst_x, int dst_y, u_int width, u_int height); /* common functions for ui_window.c (pseudo color) */ #define ui_display_fill_with(x, y, width, height, pixel) (0) #define ui_cmap_get_closest_color(closest, red, green, blue) (0) #define ui_cmap_get_pixel_rgb(red, green, blue, pixel) (0) /* platform specific functions for ui_window.c */ int ui_display_receive_next_event_singly(ui_display_t *disp); int ui_display_resize(ui_display_t *disp, u_int width, u_int height); int ui_display_move(ui_display_t *disp, int x, int y); void ui_display_request_text_selection(ui_display_t *disp); void ui_display_send_text_selection(ui_display_t *disp, XSelectionRequestEvent *ev, u_char *sel_data, size_t sel_len); size_t ui_display_get_utf8(char *utf8, KeySym ksym); void ui_display_set_title(ui_display_t *disp, const u_char *name); void ui_display_set_maximized(ui_display_t *disp, int flag); #endif mlterm-3.8.9/uitoolkit/wayland/ui_dnd.c012075500017600000144000000000001356600660700210352../fb/ui_dnd.custar kenusersmlterm-3.8.9/uitoolkit/wayland/ui_font.c012075500017600000144000000000001356600660700214372../fb/ui_font.custar kenusersmlterm-3.8.9/uitoolkit/wayland/ui_font.h012075500017600000144000000000001356600660700214512../fb/ui_font.hustar kenusersmlterm-3.8.9/uitoolkit/wayland/ui_gc.c012075500017600000144000000000001356600660700205052../fb/ui_gc.custar kenusersmlterm-3.8.9/uitoolkit/wayland/ui_imagelib.c012075500017600000144000000000001356600660700230452../fb/ui_imagelib.custar kenusersmlterm-3.8.9/uitoolkit/wayland/ui_selection_encoding.c012075500017600000144000000000001356600660700275602../xlib/ui_selection_encoding.custar kenusersmlterm-3.8.9/uitoolkit/wayland/ui_window.c012075500017600000144000000000001356600660700223412../fb/ui_window.custar kenusersmlterm-3.8.9/uitoolkit/wayland/ui_xic.c012075500017600000144000000000001356600660700210712../fb/ui_xic.custar kenusersmlterm-3.8.9/uitoolkit/wayland/xdg-shell-unstable-v6-client-protocol.c010064400017600000144000000115511356600660700245410ustar kenusers/* Generated by wayland-scanner 1.17.0 */ /* * Copyright © 2008-2013 Kristian Høgsberg * Copyright © 2013 Rafael Antognolli * Copyright © 2013 Jasper St. Pierre * Copyright © 2010-2013 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include "wayland-util.h" extern const struct wl_interface wl_output_interface; extern const struct wl_interface wl_seat_interface; extern const struct wl_interface wl_surface_interface; extern const struct wl_interface zxdg_popup_v6_interface; extern const struct wl_interface zxdg_positioner_v6_interface; extern const struct wl_interface zxdg_surface_v6_interface; extern const struct wl_interface zxdg_toplevel_v6_interface; static const struct wl_interface *types[] = { NULL, NULL, NULL, NULL, &zxdg_positioner_v6_interface, &zxdg_surface_v6_interface, &wl_surface_interface, &zxdg_toplevel_v6_interface, &zxdg_popup_v6_interface, &zxdg_surface_v6_interface, &zxdg_positioner_v6_interface, &zxdg_toplevel_v6_interface, &wl_seat_interface, NULL, NULL, NULL, &wl_seat_interface, NULL, &wl_seat_interface, NULL, NULL, &wl_output_interface, &wl_seat_interface, NULL, }; static const struct wl_message zxdg_shell_v6_requests[] = { { "destroy", "", types + 0 }, { "create_positioner", "n", types + 4 }, { "get_xdg_surface", "no", types + 5 }, { "pong", "u", types + 0 }, }; static const struct wl_message zxdg_shell_v6_events[] = { { "ping", "u", types + 0 }, }; WL_EXPORT const struct wl_interface zxdg_shell_v6_interface = { "zxdg_shell_v6", 1, 4, zxdg_shell_v6_requests, 1, zxdg_shell_v6_events, }; static const struct wl_message zxdg_positioner_v6_requests[] = { { "destroy", "", types + 0 }, { "set_size", "ii", types + 0 }, { "set_anchor_rect", "iiii", types + 0 }, { "set_anchor", "u", types + 0 }, { "set_gravity", "u", types + 0 }, { "set_constraint_adjustment", "u", types + 0 }, { "set_offset", "ii", types + 0 }, }; WL_EXPORT const struct wl_interface zxdg_positioner_v6_interface = { "zxdg_positioner_v6", 1, 7, zxdg_positioner_v6_requests, 0, NULL, }; static const struct wl_message zxdg_surface_v6_requests[] = { { "destroy", "", types + 0 }, { "get_toplevel", "n", types + 7 }, { "get_popup", "noo", types + 8 }, { "set_window_geometry", "iiii", types + 0 }, { "ack_configure", "u", types + 0 }, }; static const struct wl_message zxdg_surface_v6_events[] = { { "configure", "u", types + 0 }, }; WL_EXPORT const struct wl_interface zxdg_surface_v6_interface = { "zxdg_surface_v6", 1, 5, zxdg_surface_v6_requests, 1, zxdg_surface_v6_events, }; static const struct wl_message zxdg_toplevel_v6_requests[] = { { "destroy", "", types + 0 }, { "set_parent", "?o", types + 11 }, { "set_title", "s", types + 0 }, { "set_app_id", "s", types + 0 }, { "show_window_menu", "ouii", types + 12 }, { "move", "ou", types + 16 }, { "resize", "ouu", types + 18 }, { "set_max_size", "ii", types + 0 }, { "set_min_size", "ii", types + 0 }, { "set_maximized", "", types + 0 }, { "unset_maximized", "", types + 0 }, { "set_fullscreen", "?o", types + 21 }, { "unset_fullscreen", "", types + 0 }, { "set_minimized", "", types + 0 }, }; static const struct wl_message zxdg_toplevel_v6_events[] = { { "configure", "iia", types + 0 }, { "close", "", types + 0 }, }; WL_EXPORT const struct wl_interface zxdg_toplevel_v6_interface = { "zxdg_toplevel_v6", 1, 14, zxdg_toplevel_v6_requests, 2, zxdg_toplevel_v6_events, }; static const struct wl_message zxdg_popup_v6_requests[] = { { "destroy", "", types + 0 }, { "grab", "ou", types + 22 }, }; static const struct wl_message zxdg_popup_v6_events[] = { { "configure", "iiii", types + 0 }, { "popup_done", "", types + 0 }, }; WL_EXPORT const struct wl_interface zxdg_popup_v6_interface = { "zxdg_popup_v6", 1, 2, zxdg_popup_v6_requests, 2, zxdg_popup_v6_events, }; mlterm-3.8.9/uitoolkit/wayland/xdg-shell-unstable-v6-client-protocol.h010064400017600000144000001664001356600660700245520ustar kenusers/* Generated by wayland-scanner 1.17.0 */ #ifndef XDG_SHELL_UNSTABLE_V6_CLIENT_PROTOCOL_H #define XDG_SHELL_UNSTABLE_V6_CLIENT_PROTOCOL_H #include #include #include "wayland-client.h" #ifdef __cplusplus extern "C" { #endif /** * @page page_xdg_shell_unstable_v6 The xdg_shell_unstable_v6 protocol * @section page_ifaces_xdg_shell_unstable_v6 Interfaces * - @subpage page_iface_zxdg_shell_v6 - create desktop-style surfaces * - @subpage page_iface_zxdg_positioner_v6 - child surface positioner * - @subpage page_iface_zxdg_surface_v6 - desktop user interface surface base interface * - @subpage page_iface_zxdg_toplevel_v6 - toplevel surface * - @subpage page_iface_zxdg_popup_v6 - short-lived, popup surfaces for menus * @section page_copyright_xdg_shell_unstable_v6 Copyright *
 *
 * Copyright © 2008-2013 Kristian Høgsberg
 * Copyright © 2013      Rafael Antognolli
 * Copyright © 2013      Jasper St. Pierre
 * Copyright © 2010-2013 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 * 
*/ struct wl_output; struct wl_seat; struct wl_surface; struct zxdg_popup_v6; struct zxdg_positioner_v6; struct zxdg_shell_v6; struct zxdg_surface_v6; struct zxdg_toplevel_v6; /** * @page page_iface_zxdg_shell_v6 zxdg_shell_v6 * @section page_iface_zxdg_shell_v6_desc Description * * xdg_shell allows clients to turn a wl_surface into a "real window" * which can be dragged, resized, stacked, and moved around by the * user. Everything about this interface is suited towards traditional * desktop environments. * @section page_iface_zxdg_shell_v6_api API * See @ref iface_zxdg_shell_v6. */ /** * @defgroup iface_zxdg_shell_v6 The zxdg_shell_v6 interface * * xdg_shell allows clients to turn a wl_surface into a "real window" * which can be dragged, resized, stacked, and moved around by the * user. Everything about this interface is suited towards traditional * desktop environments. */ extern const struct wl_interface zxdg_shell_v6_interface; /** * @page page_iface_zxdg_positioner_v6 zxdg_positioner_v6 * @section page_iface_zxdg_positioner_v6_desc Description * * The xdg_positioner provides a collection of rules for the placement of a * child surface relative to a parent surface. Rules can be defined to ensure * the child surface remains within the visible area's borders, and to * specify how the child surface changes its position, such as sliding along * an axis, or flipping around a rectangle. These positioner-created rules are * constrained by the requirement that a child surface must intersect with or * be at least partially adjacent to its parent surface. * * See the various requests for details about possible rules. * * At the time of the request, the compositor makes a copy of the rules * specified by the xdg_positioner. Thus, after the request is complete the * xdg_positioner object can be destroyed or reused; further changes to the * object will have no effect on previous usages. * * For an xdg_positioner object to be considered complete, it must have a * non-zero size set by set_size, and a non-zero anchor rectangle set by * set_anchor_rect. Passing an incomplete xdg_positioner object when * positioning a surface raises an error. * @section page_iface_zxdg_positioner_v6_api API * See @ref iface_zxdg_positioner_v6. */ /** * @defgroup iface_zxdg_positioner_v6 The zxdg_positioner_v6 interface * * The xdg_positioner provides a collection of rules for the placement of a * child surface relative to a parent surface. Rules can be defined to ensure * the child surface remains within the visible area's borders, and to * specify how the child surface changes its position, such as sliding along * an axis, or flipping around a rectangle. These positioner-created rules are * constrained by the requirement that a child surface must intersect with or * be at least partially adjacent to its parent surface. * * See the various requests for details about possible rules. * * At the time of the request, the compositor makes a copy of the rules * specified by the xdg_positioner. Thus, after the request is complete the * xdg_positioner object can be destroyed or reused; further changes to the * object will have no effect on previous usages. * * For an xdg_positioner object to be considered complete, it must have a * non-zero size set by set_size, and a non-zero anchor rectangle set by * set_anchor_rect. Passing an incomplete xdg_positioner object when * positioning a surface raises an error. */ extern const struct wl_interface zxdg_positioner_v6_interface; /** * @page page_iface_zxdg_surface_v6 zxdg_surface_v6 * @section page_iface_zxdg_surface_v6_desc Description * * An interface that may be implemented by a wl_surface, for * implementations that provide a desktop-style user interface. * * It provides a base set of functionality required to construct user * interface elements requiring management by the compositor, such as * toplevel windows, menus, etc. The types of functionality are split into * xdg_surface roles. * * Creating an xdg_surface does not set the role for a wl_surface. In order * to map an xdg_surface, the client must create a role-specific object * using, e.g., get_toplevel, get_popup. The wl_surface for any given * xdg_surface can have at most one role, and may not be assigned any role * not based on xdg_surface. * * A role must be assigned before any other requests are made to the * xdg_surface object. * * The client must call wl_surface.commit on the corresponding wl_surface * for the xdg_surface state to take effect. * * Creating an xdg_surface from a wl_surface which has a buffer attached or * committed is a client error, and any attempts by a client to attach or * manipulate a buffer prior to the first xdg_surface.configure call must * also be treated as errors. * * For a surface to be mapped by the compositor, the following conditions * must be met: (1) the client has assigned a xdg_surface based role to the * surface, (2) the client has set and committed the xdg_surface state and * the role dependent state to the surface and (3) the client has committed a * buffer to the surface. * @section page_iface_zxdg_surface_v6_api API * See @ref iface_zxdg_surface_v6. */ /** * @defgroup iface_zxdg_surface_v6 The zxdg_surface_v6 interface * * An interface that may be implemented by a wl_surface, for * implementations that provide a desktop-style user interface. * * It provides a base set of functionality required to construct user * interface elements requiring management by the compositor, such as * toplevel windows, menus, etc. The types of functionality are split into * xdg_surface roles. * * Creating an xdg_surface does not set the role for a wl_surface. In order * to map an xdg_surface, the client must create a role-specific object * using, e.g., get_toplevel, get_popup. The wl_surface for any given * xdg_surface can have at most one role, and may not be assigned any role * not based on xdg_surface. * * A role must be assigned before any other requests are made to the * xdg_surface object. * * The client must call wl_surface.commit on the corresponding wl_surface * for the xdg_surface state to take effect. * * Creating an xdg_surface from a wl_surface which has a buffer attached or * committed is a client error, and any attempts by a client to attach or * manipulate a buffer prior to the first xdg_surface.configure call must * also be treated as errors. * * For a surface to be mapped by the compositor, the following conditions * must be met: (1) the client has assigned a xdg_surface based role to the * surface, (2) the client has set and committed the xdg_surface state and * the role dependent state to the surface and (3) the client has committed a * buffer to the surface. */ extern const struct wl_interface zxdg_surface_v6_interface; /** * @page page_iface_zxdg_toplevel_v6 zxdg_toplevel_v6 * @section page_iface_zxdg_toplevel_v6_desc Description * * This interface defines an xdg_surface role which allows a surface to, * among other things, set window-like properties such as maximize, * fullscreen, and minimize, set application-specific metadata like title and * id, and well as trigger user interactive operations such as interactive * resize and move. * @section page_iface_zxdg_toplevel_v6_api API * See @ref iface_zxdg_toplevel_v6. */ /** * @defgroup iface_zxdg_toplevel_v6 The zxdg_toplevel_v6 interface * * This interface defines an xdg_surface role which allows a surface to, * among other things, set window-like properties such as maximize, * fullscreen, and minimize, set application-specific metadata like title and * id, and well as trigger user interactive operations such as interactive * resize and move. */ extern const struct wl_interface zxdg_toplevel_v6_interface; /** * @page page_iface_zxdg_popup_v6 zxdg_popup_v6 * @section page_iface_zxdg_popup_v6_desc Description * * A popup surface is a short-lived, temporary surface. It can be used to * implement for example menus, popovers, tooltips and other similar user * interface concepts. * * A popup can be made to take an explicit grab. See xdg_popup.grab for * details. * * When the popup is dismissed, a popup_done event will be sent out, and at * the same time the surface will be unmapped. See the xdg_popup.popup_done * event for details. * * Explicitly destroying the xdg_popup object will also dismiss the popup and * unmap the surface. Clients that want to dismiss the popup when another * surface of their own is clicked should dismiss the popup using the destroy * request. * * The parent surface must have either the xdg_toplevel or xdg_popup surface * role. * * A newly created xdg_popup will be stacked on top of all previously created * xdg_popup surfaces associated with the same xdg_toplevel. * * The parent of an xdg_popup must be mapped (see the xdg_surface * description) before the xdg_popup itself. * * The x and y arguments passed when creating the popup object specify * where the top left of the popup should be placed, relative to the * local surface coordinates of the parent surface. See * xdg_surface.get_popup. An xdg_popup must intersect with or be at least * partially adjacent to its parent surface. * * The client must call wl_surface.commit on the corresponding wl_surface * for the xdg_popup state to take effect. * @section page_iface_zxdg_popup_v6_api API * See @ref iface_zxdg_popup_v6. */ /** * @defgroup iface_zxdg_popup_v6 The zxdg_popup_v6 interface * * A popup surface is a short-lived, temporary surface. It can be used to * implement for example menus, popovers, tooltips and other similar user * interface concepts. * * A popup can be made to take an explicit grab. See xdg_popup.grab for * details. * * When the popup is dismissed, a popup_done event will be sent out, and at * the same time the surface will be unmapped. See the xdg_popup.popup_done * event for details. * * Explicitly destroying the xdg_popup object will also dismiss the popup and * unmap the surface. Clients that want to dismiss the popup when another * surface of their own is clicked should dismiss the popup using the destroy * request. * * The parent surface must have either the xdg_toplevel or xdg_popup surface * role. * * A newly created xdg_popup will be stacked on top of all previously created * xdg_popup surfaces associated with the same xdg_toplevel. * * The parent of an xdg_popup must be mapped (see the xdg_surface * description) before the xdg_popup itself. * * The x and y arguments passed when creating the popup object specify * where the top left of the popup should be placed, relative to the * local surface coordinates of the parent surface. See * xdg_surface.get_popup. An xdg_popup must intersect with or be at least * partially adjacent to its parent surface. * * The client must call wl_surface.commit on the corresponding wl_surface * for the xdg_popup state to take effect. */ extern const struct wl_interface zxdg_popup_v6_interface; #ifndef ZXDG_SHELL_V6_ERROR_ENUM #define ZXDG_SHELL_V6_ERROR_ENUM enum zxdg_shell_v6_error { /** * given wl_surface has another role */ ZXDG_SHELL_V6_ERROR_ROLE = 0, /** * xdg_shell was destroyed before children */ ZXDG_SHELL_V6_ERROR_DEFUNCT_SURFACES = 1, /** * the client tried to map or destroy a non-topmost popup */ ZXDG_SHELL_V6_ERROR_NOT_THE_TOPMOST_POPUP = 2, /** * the client specified an invalid popup parent surface */ ZXDG_SHELL_V6_ERROR_INVALID_POPUP_PARENT = 3, /** * the client provided an invalid surface state */ ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE = 4, /** * the client provided an invalid positioner */ ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER = 5, }; #endif /* ZXDG_SHELL_V6_ERROR_ENUM */ /** * @ingroup iface_zxdg_shell_v6 * @struct zxdg_shell_v6_listener */ struct zxdg_shell_v6_listener { /** * check if the client is alive * * The ping event asks the client if it's still alive. Pass the * serial specified in the event back to the compositor by sending * a "pong" request back with the specified serial. See * xdg_shell.ping. * * Compositors can use this to determine if the client is still * alive. It's unspecified what will happen if the client doesn't * respond to the ping request, or in what timeframe. Clients * should try to respond in a reasonable amount of time. * * A compositor is free to ping in any way it wants, but a client * must always respond to any xdg_shell object it created. * @param serial pass this to the pong request */ void (*ping)(void *data, struct zxdg_shell_v6 *zxdg_shell_v6, uint32_t serial); }; /** * @ingroup iface_zxdg_shell_v6 */ static inline int zxdg_shell_v6_add_listener(struct zxdg_shell_v6 *zxdg_shell_v6, const struct zxdg_shell_v6_listener *listener, void *data) { return wl_proxy_add_listener((struct wl_proxy *) zxdg_shell_v6, (void (**)(void)) listener, data); } #define ZXDG_SHELL_V6_DESTROY 0 #define ZXDG_SHELL_V6_CREATE_POSITIONER 1 #define ZXDG_SHELL_V6_GET_XDG_SURFACE 2 #define ZXDG_SHELL_V6_PONG 3 /** * @ingroup iface_zxdg_shell_v6 */ #define ZXDG_SHELL_V6_PING_SINCE_VERSION 1 /** * @ingroup iface_zxdg_shell_v6 */ #define ZXDG_SHELL_V6_DESTROY_SINCE_VERSION 1 /** * @ingroup iface_zxdg_shell_v6 */ #define ZXDG_SHELL_V6_CREATE_POSITIONER_SINCE_VERSION 1 /** * @ingroup iface_zxdg_shell_v6 */ #define ZXDG_SHELL_V6_GET_XDG_SURFACE_SINCE_VERSION 1 /** * @ingroup iface_zxdg_shell_v6 */ #define ZXDG_SHELL_V6_PONG_SINCE_VERSION 1 /** @ingroup iface_zxdg_shell_v6 */ static inline void zxdg_shell_v6_set_user_data(struct zxdg_shell_v6 *zxdg_shell_v6, void *user_data) { wl_proxy_set_user_data((struct wl_proxy *) zxdg_shell_v6, user_data); } /** @ingroup iface_zxdg_shell_v6 */ static inline void * zxdg_shell_v6_get_user_data(struct zxdg_shell_v6 *zxdg_shell_v6) { return wl_proxy_get_user_data((struct wl_proxy *) zxdg_shell_v6); } static inline uint32_t zxdg_shell_v6_get_version(struct zxdg_shell_v6 *zxdg_shell_v6) { return wl_proxy_get_version((struct wl_proxy *) zxdg_shell_v6); } /** * @ingroup iface_zxdg_shell_v6 * * Destroy this xdg_shell object. * * Destroying a bound xdg_shell object while there are surfaces * still alive created by this xdg_shell object instance is illegal * and will result in a protocol error. */ static inline void zxdg_shell_v6_destroy(struct zxdg_shell_v6 *zxdg_shell_v6) { wl_proxy_marshal((struct wl_proxy *) zxdg_shell_v6, ZXDG_SHELL_V6_DESTROY); wl_proxy_destroy((struct wl_proxy *) zxdg_shell_v6); } /** * @ingroup iface_zxdg_shell_v6 * * Create a positioner object. A positioner object is used to position * surfaces relative to some parent surface. See the interface description * and xdg_surface.get_popup for details. */ static inline struct zxdg_positioner_v6 * zxdg_shell_v6_create_positioner(struct zxdg_shell_v6 *zxdg_shell_v6) { struct wl_proxy *id; id = wl_proxy_marshal_constructor((struct wl_proxy *) zxdg_shell_v6, ZXDG_SHELL_V6_CREATE_POSITIONER, &zxdg_positioner_v6_interface, NULL); return (struct zxdg_positioner_v6 *) id; } /** * @ingroup iface_zxdg_shell_v6 * * This creates an xdg_surface for the given surface. While xdg_surface * itself is not a role, the corresponding surface may only be assigned * a role extending xdg_surface, such as xdg_toplevel or xdg_popup. * * This creates an xdg_surface for the given surface. An xdg_surface is * used as basis to define a role to a given surface, such as xdg_toplevel * or xdg_popup. It also manages functionality shared between xdg_surface * based surface roles. * * See the documentation of xdg_surface for more details about what an * xdg_surface is and how it is used. */ static inline struct zxdg_surface_v6 * zxdg_shell_v6_get_xdg_surface(struct zxdg_shell_v6 *zxdg_shell_v6, struct wl_surface *surface) { struct wl_proxy *id; id = wl_proxy_marshal_constructor((struct wl_proxy *) zxdg_shell_v6, ZXDG_SHELL_V6_GET_XDG_SURFACE, &zxdg_surface_v6_interface, NULL, surface); return (struct zxdg_surface_v6 *) id; } /** * @ingroup iface_zxdg_shell_v6 * * A client must respond to a ping event with a pong request or * the client may be deemed unresponsive. See xdg_shell.ping. */ static inline void zxdg_shell_v6_pong(struct zxdg_shell_v6 *zxdg_shell_v6, uint32_t serial) { wl_proxy_marshal((struct wl_proxy *) zxdg_shell_v6, ZXDG_SHELL_V6_PONG, serial); } #ifndef ZXDG_POSITIONER_V6_ERROR_ENUM #define ZXDG_POSITIONER_V6_ERROR_ENUM enum zxdg_positioner_v6_error { /** * invalid input provided */ ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT = 0, }; #endif /* ZXDG_POSITIONER_V6_ERROR_ENUM */ #ifndef ZXDG_POSITIONER_V6_ANCHOR_ENUM #define ZXDG_POSITIONER_V6_ANCHOR_ENUM enum zxdg_positioner_v6_anchor { /** * the center of the anchor rectangle */ ZXDG_POSITIONER_V6_ANCHOR_NONE = 0, /** * the top edge of the anchor rectangle */ ZXDG_POSITIONER_V6_ANCHOR_TOP = 1, /** * the bottom edge of the anchor rectangle */ ZXDG_POSITIONER_V6_ANCHOR_BOTTOM = 2, /** * the left edge of the anchor rectangle */ ZXDG_POSITIONER_V6_ANCHOR_LEFT = 4, /** * the right edge of the anchor rectangle */ ZXDG_POSITIONER_V6_ANCHOR_RIGHT = 8, }; #endif /* ZXDG_POSITIONER_V6_ANCHOR_ENUM */ #ifndef ZXDG_POSITIONER_V6_GRAVITY_ENUM #define ZXDG_POSITIONER_V6_GRAVITY_ENUM enum zxdg_positioner_v6_gravity { /** * center over the anchor edge */ ZXDG_POSITIONER_V6_GRAVITY_NONE = 0, /** * position above the anchor edge */ ZXDG_POSITIONER_V6_GRAVITY_TOP = 1, /** * position below the anchor edge */ ZXDG_POSITIONER_V6_GRAVITY_BOTTOM = 2, /** * position to the left of the anchor edge */ ZXDG_POSITIONER_V6_GRAVITY_LEFT = 4, /** * position to the right of the anchor edge */ ZXDG_POSITIONER_V6_GRAVITY_RIGHT = 8, }; #endif /* ZXDG_POSITIONER_V6_GRAVITY_ENUM */ #ifndef ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_ENUM #define ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_ENUM /** * @ingroup iface_zxdg_positioner_v6 * vertically resize the surface * * Resize the surface vertically so that it is completely unconstrained. */ enum zxdg_positioner_v6_constraint_adjustment { ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE = 0, ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1, ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 2, ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X = 4, ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y = 8, ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X = 16, ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 32, }; #endif /* ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_ENUM */ #define ZXDG_POSITIONER_V6_DESTROY 0 #define ZXDG_POSITIONER_V6_SET_SIZE 1 #define ZXDG_POSITIONER_V6_SET_ANCHOR_RECT 2 #define ZXDG_POSITIONER_V6_SET_ANCHOR 3 #define ZXDG_POSITIONER_V6_SET_GRAVITY 4 #define ZXDG_POSITIONER_V6_SET_CONSTRAINT_ADJUSTMENT 5 #define ZXDG_POSITIONER_V6_SET_OFFSET 6 /** * @ingroup iface_zxdg_positioner_v6 */ #define ZXDG_POSITIONER_V6_DESTROY_SINCE_VERSION 1 /** * @ingroup iface_zxdg_positioner_v6 */ #define ZXDG_POSITIONER_V6_SET_SIZE_SINCE_VERSION 1 /** * @ingroup iface_zxdg_positioner_v6 */ #define ZXDG_POSITIONER_V6_SET_ANCHOR_RECT_SINCE_VERSION 1 /** * @ingroup iface_zxdg_positioner_v6 */ #define ZXDG_POSITIONER_V6_SET_ANCHOR_SINCE_VERSION 1 /** * @ingroup iface_zxdg_positioner_v6 */ #define ZXDG_POSITIONER_V6_SET_GRAVITY_SINCE_VERSION 1 /** * @ingroup iface_zxdg_positioner_v6 */ #define ZXDG_POSITIONER_V6_SET_CONSTRAINT_ADJUSTMENT_SINCE_VERSION 1 /** * @ingroup iface_zxdg_positioner_v6 */ #define ZXDG_POSITIONER_V6_SET_OFFSET_SINCE_VERSION 1 /** @ingroup iface_zxdg_positioner_v6 */ static inline void zxdg_positioner_v6_set_user_data(struct zxdg_positioner_v6 *zxdg_positioner_v6, void *user_data) { wl_proxy_set_user_data((struct wl_proxy *) zxdg_positioner_v6, user_data); } /** @ingroup iface_zxdg_positioner_v6 */ static inline void * zxdg_positioner_v6_get_user_data(struct zxdg_positioner_v6 *zxdg_positioner_v6) { return wl_proxy_get_user_data((struct wl_proxy *) zxdg_positioner_v6); } static inline uint32_t zxdg_positioner_v6_get_version(struct zxdg_positioner_v6 *zxdg_positioner_v6) { return wl_proxy_get_version((struct wl_proxy *) zxdg_positioner_v6); } /** * @ingroup iface_zxdg_positioner_v6 * * Notify the compositor that the xdg_positioner will no longer be used. */ static inline void zxdg_positioner_v6_destroy(struct zxdg_positioner_v6 *zxdg_positioner_v6) { wl_proxy_marshal((struct wl_proxy *) zxdg_positioner_v6, ZXDG_POSITIONER_V6_DESTROY); wl_proxy_destroy((struct wl_proxy *) zxdg_positioner_v6); } /** * @ingroup iface_zxdg_positioner_v6 * * Set the size of the surface that is to be positioned with the positioner * object. The size is in surface-local coordinates and corresponds to the * window geometry. See xdg_surface.set_window_geometry. * * If a zero or negative size is set the invalid_input error is raised. */ static inline void zxdg_positioner_v6_set_size(struct zxdg_positioner_v6 *zxdg_positioner_v6, int32_t width, int32_t height) { wl_proxy_marshal((struct wl_proxy *) zxdg_positioner_v6, ZXDG_POSITIONER_V6_SET_SIZE, width, height); } /** * @ingroup iface_zxdg_positioner_v6 * * Specify the anchor rectangle within the parent surface that the child * surface will be placed relative to. The rectangle is relative to the * window geometry as defined by xdg_surface.set_window_geometry of the * parent surface. The rectangle must be at least 1x1 large. * * When the xdg_positioner object is used to position a child surface, the * anchor rectangle may not extend outside the window geometry of the * positioned child's parent surface. * * If a zero or negative size is set the invalid_input error is raised. */ static inline void zxdg_positioner_v6_set_anchor_rect(struct zxdg_positioner_v6 *zxdg_positioner_v6, int32_t x, int32_t y, int32_t width, int32_t height) { wl_proxy_marshal((struct wl_proxy *) zxdg_positioner_v6, ZXDG_POSITIONER_V6_SET_ANCHOR_RECT, x, y, width, height); } /** * @ingroup iface_zxdg_positioner_v6 * * Defines a set of edges for the anchor rectangle. These are used to * derive an anchor point that the child surface will be positioned * relative to. If two orthogonal edges are specified (e.g. 'top' and * 'left'), then the anchor point will be the intersection of the edges * (e.g. the top left position of the rectangle); otherwise, the derived * anchor point will be centered on the specified edge, or in the center of * the anchor rectangle if no edge is specified. * * If two parallel anchor edges are specified (e.g. 'left' and 'right'), * the invalid_input error is raised. */ static inline void zxdg_positioner_v6_set_anchor(struct zxdg_positioner_v6 *zxdg_positioner_v6, uint32_t anchor) { wl_proxy_marshal((struct wl_proxy *) zxdg_positioner_v6, ZXDG_POSITIONER_V6_SET_ANCHOR, anchor); } /** * @ingroup iface_zxdg_positioner_v6 * * Defines in what direction a surface should be positioned, relative to * the anchor point of the parent surface. If two orthogonal gravities are * specified (e.g. 'bottom' and 'right'), then the child surface will be * placed in the specified direction; otherwise, the child surface will be * centered over the anchor point on any axis that had no gravity * specified. * * If two parallel gravities are specified (e.g. 'left' and 'right'), the * invalid_input error is raised. */ static inline void zxdg_positioner_v6_set_gravity(struct zxdg_positioner_v6 *zxdg_positioner_v6, uint32_t gravity) { wl_proxy_marshal((struct wl_proxy *) zxdg_positioner_v6, ZXDG_POSITIONER_V6_SET_GRAVITY, gravity); } /** * @ingroup iface_zxdg_positioner_v6 * * Specify how the window should be positioned if the originally intended * position caused the surface to be constrained, meaning at least * partially outside positioning boundaries set by the compositor. The * adjustment is set by constructing a bitmask describing the adjustment to * be made when the surface is constrained on that axis. * * If no bit for one axis is set, the compositor will assume that the child * surface should not change its position on that axis when constrained. * * If more than one bit for one axis is set, the order of how adjustments * are applied is specified in the corresponding adjustment descriptions. * * The default adjustment is none. */ static inline void zxdg_positioner_v6_set_constraint_adjustment(struct zxdg_positioner_v6 *zxdg_positioner_v6, uint32_t constraint_adjustment) { wl_proxy_marshal((struct wl_proxy *) zxdg_positioner_v6, ZXDG_POSITIONER_V6_SET_CONSTRAINT_ADJUSTMENT, constraint_adjustment); } /** * @ingroup iface_zxdg_positioner_v6 * * Specify the surface position offset relative to the position of the * anchor on the anchor rectangle and the anchor on the surface. For * example if the anchor of the anchor rectangle is at (x, y), the surface * has the gravity bottom|right, and the offset is (ox, oy), the calculated * surface position will be (x + ox, y + oy). The offset position of the * surface is the one used for constraint testing. See * set_constraint_adjustment. * * An example use case is placing a popup menu on top of a user interface * element, while aligning the user interface element of the parent surface * with some user interface element placed somewhere in the popup surface. */ static inline void zxdg_positioner_v6_set_offset(struct zxdg_positioner_v6 *zxdg_positioner_v6, int32_t x, int32_t y) { wl_proxy_marshal((struct wl_proxy *) zxdg_positioner_v6, ZXDG_POSITIONER_V6_SET_OFFSET, x, y); } #ifndef ZXDG_SURFACE_V6_ERROR_ENUM #define ZXDG_SURFACE_V6_ERROR_ENUM enum zxdg_surface_v6_error { ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED = 1, ZXDG_SURFACE_V6_ERROR_ALREADY_CONSTRUCTED = 2, ZXDG_SURFACE_V6_ERROR_UNCONFIGURED_BUFFER = 3, }; #endif /* ZXDG_SURFACE_V6_ERROR_ENUM */ /** * @ingroup iface_zxdg_surface_v6 * @struct zxdg_surface_v6_listener */ struct zxdg_surface_v6_listener { /** * suggest a surface change * * The configure event marks the end of a configure sequence. A * configure sequence is a set of one or more events configuring * the state of the xdg_surface, including the final * xdg_surface.configure event. * * Where applicable, xdg_surface surface roles will during a * configure sequence extend this event as a latched state sent as * events before the xdg_surface.configure event. Such events * should be considered to make up a set of atomically applied * configuration states, where the xdg_surface.configure commits * the accumulated state. * * Clients should arrange their surface for the new states, and * then send an ack_configure request with the serial sent in this * configure event at some point before committing the new surface. * * If the client receives multiple configure events before it can * respond to one, it is free to discard all but the last event it * received. * @param serial serial of the configure event */ void (*configure)(void *data, struct zxdg_surface_v6 *zxdg_surface_v6, uint32_t serial); }; /** * @ingroup iface_zxdg_surface_v6 */ static inline int zxdg_surface_v6_add_listener(struct zxdg_surface_v6 *zxdg_surface_v6, const struct zxdg_surface_v6_listener *listener, void *data) { return wl_proxy_add_listener((struct wl_proxy *) zxdg_surface_v6, (void (**)(void)) listener, data); } #define ZXDG_SURFACE_V6_DESTROY 0 #define ZXDG_SURFACE_V6_GET_TOPLEVEL 1 #define ZXDG_SURFACE_V6_GET_POPUP 2 #define ZXDG_SURFACE_V6_SET_WINDOW_GEOMETRY 3 #define ZXDG_SURFACE_V6_ACK_CONFIGURE 4 /** * @ingroup iface_zxdg_surface_v6 */ #define ZXDG_SURFACE_V6_CONFIGURE_SINCE_VERSION 1 /** * @ingroup iface_zxdg_surface_v6 */ #define ZXDG_SURFACE_V6_DESTROY_SINCE_VERSION 1 /** * @ingroup iface_zxdg_surface_v6 */ #define ZXDG_SURFACE_V6_GET_TOPLEVEL_SINCE_VERSION 1 /** * @ingroup iface_zxdg_surface_v6 */ #define ZXDG_SURFACE_V6_GET_POPUP_SINCE_VERSION 1 /** * @ingroup iface_zxdg_surface_v6 */ #define ZXDG_SURFACE_V6_SET_WINDOW_GEOMETRY_SINCE_VERSION 1 /** * @ingroup iface_zxdg_surface_v6 */ #define ZXDG_SURFACE_V6_ACK_CONFIGURE_SINCE_VERSION 1 /** @ingroup iface_zxdg_surface_v6 */ static inline void zxdg_surface_v6_set_user_data(struct zxdg_surface_v6 *zxdg_surface_v6, void *user_data) { wl_proxy_set_user_data((struct wl_proxy *) zxdg_surface_v6, user_data); } /** @ingroup iface_zxdg_surface_v6 */ static inline void * zxdg_surface_v6_get_user_data(struct zxdg_surface_v6 *zxdg_surface_v6) { return wl_proxy_get_user_data((struct wl_proxy *) zxdg_surface_v6); } static inline uint32_t zxdg_surface_v6_get_version(struct zxdg_surface_v6 *zxdg_surface_v6) { return wl_proxy_get_version((struct wl_proxy *) zxdg_surface_v6); } /** * @ingroup iface_zxdg_surface_v6 * * Destroy the xdg_surface object. An xdg_surface must only be destroyed * after its role object has been destroyed. */ static inline void zxdg_surface_v6_destroy(struct zxdg_surface_v6 *zxdg_surface_v6) { wl_proxy_marshal((struct wl_proxy *) zxdg_surface_v6, ZXDG_SURFACE_V6_DESTROY); wl_proxy_destroy((struct wl_proxy *) zxdg_surface_v6); } /** * @ingroup iface_zxdg_surface_v6 * * This creates an xdg_toplevel object for the given xdg_surface and gives * the associated wl_surface the xdg_toplevel role. * * See the documentation of xdg_toplevel for more details about what an * xdg_toplevel is and how it is used. */ static inline struct zxdg_toplevel_v6 * zxdg_surface_v6_get_toplevel(struct zxdg_surface_v6 *zxdg_surface_v6) { struct wl_proxy *id; id = wl_proxy_marshal_constructor((struct wl_proxy *) zxdg_surface_v6, ZXDG_SURFACE_V6_GET_TOPLEVEL, &zxdg_toplevel_v6_interface, NULL); return (struct zxdg_toplevel_v6 *) id; } /** * @ingroup iface_zxdg_surface_v6 * * This creates an xdg_popup object for the given xdg_surface and gives the * associated wl_surface the xdg_popup role. * * See the documentation of xdg_popup for more details about what an * xdg_popup is and how it is used. */ static inline struct zxdg_popup_v6 * zxdg_surface_v6_get_popup(struct zxdg_surface_v6 *zxdg_surface_v6, struct zxdg_surface_v6 *parent, struct zxdg_positioner_v6 *positioner) { struct wl_proxy *id; id = wl_proxy_marshal_constructor((struct wl_proxy *) zxdg_surface_v6, ZXDG_SURFACE_V6_GET_POPUP, &zxdg_popup_v6_interface, NULL, parent, positioner); return (struct zxdg_popup_v6 *) id; } /** * @ingroup iface_zxdg_surface_v6 * * The window geometry of a surface is its "visible bounds" from the * user's perspective. Client-side decorations often have invisible * portions like drop-shadows which should be ignored for the * purposes of aligning, placing and constraining windows. * * The window geometry is double buffered, and will be applied at the * time wl_surface.commit of the corresponding wl_surface is called. * * Once the window geometry of the surface is set, it is not possible to * unset it, and it will remain the same until set_window_geometry is * called again, even if a new subsurface or buffer is attached. * * If never set, the value is the full bounds of the surface, * including any subsurfaces. This updates dynamically on every * commit. This unset is meant for extremely simple clients. * * The arguments are given in the surface-local coordinate space of * the wl_surface associated with this xdg_surface. * * The width and height must be greater than zero. Setting an invalid size * will raise an error. When applied, the effective window geometry will be * the set window geometry clamped to the bounding rectangle of the * combined geometry of the surface of the xdg_surface and the associated * subsurfaces. */ static inline void zxdg_surface_v6_set_window_geometry(struct zxdg_surface_v6 *zxdg_surface_v6, int32_t x, int32_t y, int32_t width, int32_t height) { wl_proxy_marshal((struct wl_proxy *) zxdg_surface_v6, ZXDG_SURFACE_V6_SET_WINDOW_GEOMETRY, x, y, width, height); } /** * @ingroup iface_zxdg_surface_v6 * * When a configure event is received, if a client commits the * surface in response to the configure event, then the client * must make an ack_configure request sometime before the commit * request, passing along the serial of the configure event. * * For instance, for toplevel surfaces the compositor might use this * information to move a surface to the top left only when the client has * drawn itself for the maximized or fullscreen state. * * If the client receives multiple configure events before it * can respond to one, it only has to ack the last configure event. * * A client is not required to commit immediately after sending * an ack_configure request - it may even ack_configure several times * before its next surface commit. * * A client may send multiple ack_configure requests before committing, but * only the last request sent before a commit indicates which configure * event the client really is responding to. */ static inline void zxdg_surface_v6_ack_configure(struct zxdg_surface_v6 *zxdg_surface_v6, uint32_t serial) { wl_proxy_marshal((struct wl_proxy *) zxdg_surface_v6, ZXDG_SURFACE_V6_ACK_CONFIGURE, serial); } #ifndef ZXDG_TOPLEVEL_V6_RESIZE_EDGE_ENUM #define ZXDG_TOPLEVEL_V6_RESIZE_EDGE_ENUM /** * @ingroup iface_zxdg_toplevel_v6 * edge values for resizing * * These values are used to indicate which edge of a surface * is being dragged in a resize operation. */ enum zxdg_toplevel_v6_resize_edge { ZXDG_TOPLEVEL_V6_RESIZE_EDGE_NONE = 0, ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP = 1, ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM = 2, ZXDG_TOPLEVEL_V6_RESIZE_EDGE_LEFT = 4, ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_LEFT = 5, ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_LEFT = 6, ZXDG_TOPLEVEL_V6_RESIZE_EDGE_RIGHT = 8, ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_RIGHT = 9, ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_RIGHT = 10, }; #endif /* ZXDG_TOPLEVEL_V6_RESIZE_EDGE_ENUM */ #ifndef ZXDG_TOPLEVEL_V6_STATE_ENUM #define ZXDG_TOPLEVEL_V6_STATE_ENUM /** * @ingroup iface_zxdg_toplevel_v6 * the surface is now activated * * Client window decorations should be painted as if the window is * active. Do not assume this means that the window actually has * keyboard or pointer focus. */ enum zxdg_toplevel_v6_state { /** * the surface is maximized */ ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED = 1, /** * the surface is fullscreen */ ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN = 2, /** * the surface is being resized */ ZXDG_TOPLEVEL_V6_STATE_RESIZING = 3, /** * the surface is now activated */ ZXDG_TOPLEVEL_V6_STATE_ACTIVATED = 4, }; #endif /* ZXDG_TOPLEVEL_V6_STATE_ENUM */ /** * @ingroup iface_zxdg_toplevel_v6 * @struct zxdg_toplevel_v6_listener */ struct zxdg_toplevel_v6_listener { /** * suggest a surface change * * This configure event asks the client to resize its toplevel * surface or to change its state. The configured state should not * be applied immediately. See xdg_surface.configure for details. * * The width and height arguments specify a hint to the window * about how its surface should be resized in window geometry * coordinates. See set_window_geometry. * * If the width or height arguments are zero, it means the client * should decide its own window dimension. This may happen when the * compositor needs to configure the state of the surface but * doesn't have any information about any previous or expected * dimension. * * The states listed in the event specify how the width/height * arguments should be interpreted, and possibly how it should be * drawn. * * Clients must send an ack_configure in response to this event. * See xdg_surface.configure and xdg_surface.ack_configure for * details. */ void (*configure)(void *data, struct zxdg_toplevel_v6 *zxdg_toplevel_v6, int32_t width, int32_t height, struct wl_array *states); /** * surface wants to be closed * * The close event is sent by the compositor when the user wants * the surface to be closed. This should be equivalent to the user * clicking the close button in client-side decorations, if your * application has any. * * This is only a request that the user intends to close the * window. The client may choose to ignore this request, or show a * dialog to ask the user to save their data, etc. */ void (*close)(void *data, struct zxdg_toplevel_v6 *zxdg_toplevel_v6); }; /** * @ingroup iface_zxdg_toplevel_v6 */ static inline int zxdg_toplevel_v6_add_listener(struct zxdg_toplevel_v6 *zxdg_toplevel_v6, const struct zxdg_toplevel_v6_listener *listener, void *data) { return wl_proxy_add_listener((struct wl_proxy *) zxdg_toplevel_v6, (void (**)(void)) listener, data); } #define ZXDG_TOPLEVEL_V6_DESTROY 0 #define ZXDG_TOPLEVEL_V6_SET_PARENT 1 #define ZXDG_TOPLEVEL_V6_SET_TITLE 2 #define ZXDG_TOPLEVEL_V6_SET_APP_ID 3 #define ZXDG_TOPLEVEL_V6_SHOW_WINDOW_MENU 4 #define ZXDG_TOPLEVEL_V6_MOVE 5 #define ZXDG_TOPLEVEL_V6_RESIZE 6 #define ZXDG_TOPLEVEL_V6_SET_MAX_SIZE 7 #define ZXDG_TOPLEVEL_V6_SET_MIN_SIZE 8 #define ZXDG_TOPLEVEL_V6_SET_MAXIMIZED 9 #define ZXDG_TOPLEVEL_V6_UNSET_MAXIMIZED 10 #define ZXDG_TOPLEVEL_V6_SET_FULLSCREEN 11 #define ZXDG_TOPLEVEL_V6_UNSET_FULLSCREEN 12 #define ZXDG_TOPLEVEL_V6_SET_MINIMIZED 13 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_CONFIGURE_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_CLOSE_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_DESTROY_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_SET_PARENT_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_SET_TITLE_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_SET_APP_ID_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_SHOW_WINDOW_MENU_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_MOVE_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_RESIZE_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_SET_MAX_SIZE_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_SET_MIN_SIZE_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_SET_MAXIMIZED_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_UNSET_MAXIMIZED_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_SET_FULLSCREEN_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_UNSET_FULLSCREEN_SINCE_VERSION 1 /** * @ingroup iface_zxdg_toplevel_v6 */ #define ZXDG_TOPLEVEL_V6_SET_MINIMIZED_SINCE_VERSION 1 /** @ingroup iface_zxdg_toplevel_v6 */ static inline void zxdg_toplevel_v6_set_user_data(struct zxdg_toplevel_v6 *zxdg_toplevel_v6, void *user_data) { wl_proxy_set_user_data((struct wl_proxy *) zxdg_toplevel_v6, user_data); } /** @ingroup iface_zxdg_toplevel_v6 */ static inline void * zxdg_toplevel_v6_get_user_data(struct zxdg_toplevel_v6 *zxdg_toplevel_v6) { return wl_proxy_get_user_data((struct wl_proxy *) zxdg_toplevel_v6); } static inline uint32_t zxdg_toplevel_v6_get_version(struct zxdg_toplevel_v6 *zxdg_toplevel_v6) { return wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_v6); } /** * @ingroup iface_zxdg_toplevel_v6 * * Unmap and destroy the window. The window will be effectively * hidden from the user's point of view, and all state like * maximization, fullscreen, and so on, will be lost. */ static inline void zxdg_toplevel_v6_destroy(struct zxdg_toplevel_v6 *zxdg_toplevel_v6) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_DESTROY); wl_proxy_destroy((struct wl_proxy *) zxdg_toplevel_v6); } /** * @ingroup iface_zxdg_toplevel_v6 * * Set the "parent" of this surface. This window should be stacked * above a parent. The parent surface must be mapped as long as this * surface is mapped. * * Parent windows should be set on dialogs, toolboxes, or other * "auxiliary" surfaces, so that the parent is raised when the dialog * is raised. */ static inline void zxdg_toplevel_v6_set_parent(struct zxdg_toplevel_v6 *zxdg_toplevel_v6, struct zxdg_toplevel_v6 *parent) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_SET_PARENT, parent); } /** * @ingroup iface_zxdg_toplevel_v6 * * Set a short title for the surface. * * This string may be used to identify the surface in a task bar, * window list, or other user interface elements provided by the * compositor. * * The string must be encoded in UTF-8. */ static inline void zxdg_toplevel_v6_set_title(struct zxdg_toplevel_v6 *zxdg_toplevel_v6, const char *title) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_SET_TITLE, title); } /** * @ingroup iface_zxdg_toplevel_v6 * * Set an application identifier for the surface. * * The app ID identifies the general class of applications to which * the surface belongs. The compositor can use this to group multiple * surfaces together, or to determine how to launch a new application. * * For D-Bus activatable applications, the app ID is used as the D-Bus * service name. * * The compositor shell will try to group application surfaces together * by their app ID. As a best practice, it is suggested to select app * ID's that match the basename of the application's .desktop file. * For example, "org.freedesktop.FooViewer" where the .desktop file is * "org.freedesktop.FooViewer.desktop". * * See the desktop-entry specification [0] for more details on * application identifiers and how they relate to well-known D-Bus * names and .desktop files. * * [0] http://standards.freedesktop.org/desktop-entry-spec/ */ static inline void zxdg_toplevel_v6_set_app_id(struct zxdg_toplevel_v6 *zxdg_toplevel_v6, const char *app_id) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_SET_APP_ID, app_id); } /** * @ingroup iface_zxdg_toplevel_v6 * * Clients implementing client-side decorations might want to show * a context menu when right-clicking on the decorations, giving the * user a menu that they can use to maximize or minimize the window. * * This request asks the compositor to pop up such a window menu at * the given position, relative to the local surface coordinates of * the parent surface. There are no guarantees as to what menu items * the window menu contains. * * This request must be used in response to some sort of user action * like a button press, key press, or touch down event. */ static inline void zxdg_toplevel_v6_show_window_menu(struct zxdg_toplevel_v6 *zxdg_toplevel_v6, struct wl_seat *seat, uint32_t serial, int32_t x, int32_t y) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_SHOW_WINDOW_MENU, seat, serial, x, y); } /** * @ingroup iface_zxdg_toplevel_v6 * * Start an interactive, user-driven move of the surface. * * This request must be used in response to some sort of user action * like a button press, key press, or touch down event. The passed * serial is used to determine the type of interactive move (touch, * pointer, etc). * * The server may ignore move requests depending on the state of * the surface (e.g. fullscreen or maximized), or if the passed serial * is no longer valid. * * If triggered, the surface will lose the focus of the device * (wl_pointer, wl_touch, etc) used for the move. It is up to the * compositor to visually indicate that the move is taking place, such as * updating a pointer cursor, during the move. There is no guarantee * that the device focus will return when the move is completed. */ static inline void zxdg_toplevel_v6_move(struct zxdg_toplevel_v6 *zxdg_toplevel_v6, struct wl_seat *seat, uint32_t serial) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_MOVE, seat, serial); } /** * @ingroup iface_zxdg_toplevel_v6 * * Start a user-driven, interactive resize of the surface. * * This request must be used in response to some sort of user action * like a button press, key press, or touch down event. The passed * serial is used to determine the type of interactive resize (touch, * pointer, etc). * * The server may ignore resize requests depending on the state of * the surface (e.g. fullscreen or maximized). * * If triggered, the client will receive configure events with the * "resize" state enum value and the expected sizes. See the "resize" * enum value for more details about what is required. The client * must also acknowledge configure events using "ack_configure". After * the resize is completed, the client will receive another "configure" * event without the resize state. * * If triggered, the surface also will lose the focus of the device * (wl_pointer, wl_touch, etc) used for the resize. It is up to the * compositor to visually indicate that the resize is taking place, * such as updating a pointer cursor, during the resize. There is no * guarantee that the device focus will return when the resize is * completed. * * The edges parameter specifies how the surface should be resized, * and is one of the values of the resize_edge enum. The compositor * may use this information to update the surface position for * example when dragging the top left corner. The compositor may also * use this information to adapt its behavior, e.g. choose an * appropriate cursor image. */ static inline void zxdg_toplevel_v6_resize(struct zxdg_toplevel_v6 *zxdg_toplevel_v6, struct wl_seat *seat, uint32_t serial, uint32_t edges) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_RESIZE, seat, serial, edges); } /** * @ingroup iface_zxdg_toplevel_v6 * * Set a maximum size for the window. * * The client can specify a maximum size so that the compositor does * not try to configure the window beyond this size. * * The width and height arguments are in window geometry coordinates. * See xdg_surface.set_window_geometry. * * Values set in this way are double-buffered. They will get applied * on the next commit. * * The compositor can use this information to allow or disallow * different states like maximize or fullscreen and draw accurate * animations. * * Similarly, a tiling window manager may use this information to * place and resize client windows in a more effective way. * * The client should not rely on the compositor to obey the maximum * size. The compositor may decide to ignore the values set by the * client and request a larger size. * * If never set, or a value of zero in the request, means that the * client has no expected maximum size in the given dimension. * As a result, a client wishing to reset the maximum size * to an unspecified state can use zero for width and height in the * request. * * Requesting a maximum size to be smaller than the minimum size of * a surface is illegal and will result in a protocol error. * * The width and height must be greater than or equal to zero. Using * strictly negative values for width and height will result in a * protocol error. */ static inline void zxdg_toplevel_v6_set_max_size(struct zxdg_toplevel_v6 *zxdg_toplevel_v6, int32_t width, int32_t height) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_SET_MAX_SIZE, width, height); } /** * @ingroup iface_zxdg_toplevel_v6 * * Set a minimum size for the window. * * The client can specify a minimum size so that the compositor does * not try to configure the window below this size. * * The width and height arguments are in window geometry coordinates. * See xdg_surface.set_window_geometry. * * Values set in this way are double-buffered. They will get applied * on the next commit. * * The compositor can use this information to allow or disallow * different states like maximize or fullscreen and draw accurate * animations. * * Similarly, a tiling window manager may use this information to * place and resize client windows in a more effective way. * * The client should not rely on the compositor to obey the minimum * size. The compositor may decide to ignore the values set by the * client and request a smaller size. * * If never set, or a value of zero in the request, means that the * client has no expected minimum size in the given dimension. * As a result, a client wishing to reset the minimum size * to an unspecified state can use zero for width and height in the * request. * * Requesting a minimum size to be larger than the maximum size of * a surface is illegal and will result in a protocol error. * * The width and height must be greater than or equal to zero. Using * strictly negative values for width and height will result in a * protocol error. */ static inline void zxdg_toplevel_v6_set_min_size(struct zxdg_toplevel_v6 *zxdg_toplevel_v6, int32_t width, int32_t height) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_SET_MIN_SIZE, width, height); } /** * @ingroup iface_zxdg_toplevel_v6 * * Maximize the surface. * * After requesting that the surface should be maximized, the compositor * will respond by emitting a configure event with the "maximized" state * and the required window geometry. The client should then update its * content, drawing it in a maximized state, i.e. without shadow or other * decoration outside of the window geometry. The client must also * acknowledge the configure when committing the new content (see * ack_configure). * * It is up to the compositor to decide how and where to maximize the * surface, for example which output and what region of the screen should * be used. * * If the surface was already maximized, the compositor will still emit * a configure event with the "maximized" state. */ static inline void zxdg_toplevel_v6_set_maximized(struct zxdg_toplevel_v6 *zxdg_toplevel_v6) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_SET_MAXIMIZED); } /** * @ingroup iface_zxdg_toplevel_v6 * * Unmaximize the surface. * * After requesting that the surface should be unmaximized, the compositor * will respond by emitting a configure event without the "maximized" * state. If available, the compositor will include the window geometry * dimensions the window had prior to being maximized in the configure * request. The client must then update its content, drawing it in a * regular state, i.e. potentially with shadow, etc. The client must also * acknowledge the configure when committing the new content (see * ack_configure). * * It is up to the compositor to position the surface after it was * unmaximized; usually the position the surface had before maximizing, if * applicable. * * If the surface was already not maximized, the compositor will still * emit a configure event without the "maximized" state. */ static inline void zxdg_toplevel_v6_unset_maximized(struct zxdg_toplevel_v6 *zxdg_toplevel_v6) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_UNSET_MAXIMIZED); } /** * @ingroup iface_zxdg_toplevel_v6 * * Make the surface fullscreen. * * You can specify an output that you would prefer to be fullscreen. * If this value is NULL, it's up to the compositor to choose which * display will be used to map this surface. * * If the surface doesn't cover the whole output, the compositor will * position the surface in the center of the output and compensate with * black borders filling the rest of the output. */ static inline void zxdg_toplevel_v6_set_fullscreen(struct zxdg_toplevel_v6 *zxdg_toplevel_v6, struct wl_output *output) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_SET_FULLSCREEN, output); } /** * @ingroup iface_zxdg_toplevel_v6 */ static inline void zxdg_toplevel_v6_unset_fullscreen(struct zxdg_toplevel_v6 *zxdg_toplevel_v6) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_UNSET_FULLSCREEN); } /** * @ingroup iface_zxdg_toplevel_v6 * * Request that the compositor minimize your surface. There is no * way to know if the surface is currently minimized, nor is there * any way to unset minimization on this surface. * * If you are looking to throttle redrawing when minimized, please * instead use the wl_surface.frame event for this, as this will * also work with live previews on windows in Alt-Tab, Expose or * similar compositor features. */ static inline void zxdg_toplevel_v6_set_minimized(struct zxdg_toplevel_v6 *zxdg_toplevel_v6) { wl_proxy_marshal((struct wl_proxy *) zxdg_toplevel_v6, ZXDG_TOPLEVEL_V6_SET_MINIMIZED); } #ifndef ZXDG_POPUP_V6_ERROR_ENUM #define ZXDG_POPUP_V6_ERROR_ENUM enum zxdg_popup_v6_error { /** * tried to grab after being mapped */ ZXDG_POPUP_V6_ERROR_INVALID_GRAB = 0, }; #endif /* ZXDG_POPUP_V6_ERROR_ENUM */ /** * @ingroup iface_zxdg_popup_v6 * @struct zxdg_popup_v6_listener */ struct zxdg_popup_v6_listener { /** * configure the popup surface * * This event asks the popup surface to configure itself given * the configuration. The configured state should not be applied * immediately. See xdg_surface.configure for details. * * The x and y arguments represent the position the popup was * placed at given the xdg_positioner rule, relative to the upper * left corner of the window geometry of the parent surface. * @param x x position relative to parent surface window geometry * @param y y position relative to parent surface window geometry * @param width window geometry width * @param height window geometry height */ void (*configure)(void *data, struct zxdg_popup_v6 *zxdg_popup_v6, int32_t x, int32_t y, int32_t width, int32_t height); /** * popup interaction is done * * The popup_done event is sent out when a popup is dismissed by * the compositor. The client should destroy the xdg_popup object * at this point. */ void (*popup_done)(void *data, struct zxdg_popup_v6 *zxdg_popup_v6); }; /** * @ingroup iface_zxdg_popup_v6 */ static inline int zxdg_popup_v6_add_listener(struct zxdg_popup_v6 *zxdg_popup_v6, const struct zxdg_popup_v6_listener *listener, void *data) { return wl_proxy_add_listener((struct wl_proxy *) zxdg_popup_v6, (void (**)(void)) listener, data); } #define ZXDG_POPUP_V6_DESTROY 0 #define ZXDG_POPUP_V6_GRAB 1 /** * @ingroup iface_zxdg_popup_v6 */ #define ZXDG_POPUP_V6_CONFIGURE_SINCE_VERSION 1 /** * @ingroup iface_zxdg_popup_v6 */ #define ZXDG_POPUP_V6_POPUP_DONE_SINCE_VERSION 1 /** * @ingroup iface_zxdg_popup_v6 */ #define ZXDG_POPUP_V6_DESTROY_SINCE_VERSION 1 /** * @ingroup iface_zxdg_popup_v6 */ #define ZXDG_POPUP_V6_GRAB_SINCE_VERSION 1 /** @ingroup iface_zxdg_popup_v6 */ static inline void zxdg_popup_v6_set_user_data(struct zxdg_popup_v6 *zxdg_popup_v6, void *user_data) { wl_proxy_set_user_data((struct wl_proxy *) zxdg_popup_v6, user_data); } /** @ingroup iface_zxdg_popup_v6 */ static inline void * zxdg_popup_v6_get_user_data(struct zxdg_popup_v6 *zxdg_popup_v6) { return wl_proxy_get_user_data((struct wl_proxy *) zxdg_popup_v6); } static inline uint32_t zxdg_popup_v6_get_version(struct zxdg_popup_v6 *zxdg_popup_v6) { return wl_proxy_get_version((struct wl_proxy *) zxdg_popup_v6); } /** * @ingroup iface_zxdg_popup_v6 * * This destroys the popup. Explicitly destroying the xdg_popup * object will also dismiss the popup, and unmap the surface. * * If this xdg_popup is not the "topmost" popup, a protocol error * will be sent. */ static inline void zxdg_popup_v6_destroy(struct zxdg_popup_v6 *zxdg_popup_v6) { wl_proxy_marshal((struct wl_proxy *) zxdg_popup_v6, ZXDG_POPUP_V6_DESTROY); wl_proxy_destroy((struct wl_proxy *) zxdg_popup_v6); } /** * @ingroup iface_zxdg_popup_v6 * * This request makes the created popup take an explicit grab. An explicit * grab will be dismissed when the user dismisses the popup, or when the * client destroys the xdg_popup. This can be done by the user clicking * outside the surface, using the keyboard, or even locking the screen * through closing the lid or a timeout. * * If the compositor denies the grab, the popup will be immediately * dismissed. * * This request must be used in response to some sort of user action like a * button press, key press, or touch down event. The serial number of the * event should be passed as 'serial'. * * The parent of a grabbing popup must either be an xdg_toplevel surface or * another xdg_popup with an explicit grab. If the parent is another * xdg_popup it means that the popups are nested, with this popup now being * the topmost popup. * * Nested popups must be destroyed in the reverse order they were created * in, e.g. the only popup you are allowed to destroy at all times is the * topmost one. * * When compositors choose to dismiss a popup, they may dismiss every * nested grabbing popup as well. When a compositor dismisses popups, it * will follow the same dismissing order as required from the client. * * The parent of a grabbing popup must either be another xdg_popup with an * active explicit grab, or an xdg_popup or xdg_toplevel, if there are no * explicit grabs already taken. * * If the topmost grabbing popup is destroyed, the grab will be returned to * the parent of the popup, if that parent previously had an explicit grab. * * If the parent is a grabbing popup which has already been dismissed, this * popup will be immediately dismissed. If the parent is a popup that did * not take an explicit grab, an error will be raised. * * During a popup grab, the client owning the grab will receive pointer * and touch events for all their surfaces as normal (similar to an * "owner-events" grab in X11 parlance), while the top most grabbing popup * will always have keyboard focus. */ static inline void zxdg_popup_v6_grab(struct zxdg_popup_v6 *zxdg_popup_v6, struct wl_seat *seat, uint32_t serial) { wl_proxy_marshal((struct wl_proxy *) zxdg_popup_v6, ZXDG_POPUP_V6_GRAB, seat, serial); } #ifdef __cplusplus } #endif #endif mlterm-3.8.9/uitoolkit/wayland/ui.c012075500017600000144000000000001356600660700173632../fb/ui.custar kenusersmlterm-3.8.9/uitoolkit/wayland/gtk-primary-selection.c010064400017600000144000000071041356600660700216230ustar kenusers/* Generated by wayland-scanner 1.17.0 */ /* * Copyright © 2015, 2016 Red Hat * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include "wayland-util.h" extern const struct wl_interface gtk_primary_selection_device_interface; extern const struct wl_interface gtk_primary_selection_offer_interface; extern const struct wl_interface gtk_primary_selection_source_interface; extern const struct wl_interface wl_seat_interface; static const struct wl_interface *types[] = { NULL, NULL, >k_primary_selection_source_interface, >k_primary_selection_device_interface, &wl_seat_interface, >k_primary_selection_source_interface, NULL, >k_primary_selection_offer_interface, >k_primary_selection_offer_interface, }; static const struct wl_message gtk_primary_selection_device_manager_requests[] = { { "create_source", "n", types + 2 }, { "get_device", "no", types + 3 }, { "destroy", "", types + 0 }, }; WL_EXPORT const struct wl_interface gtk_primary_selection_device_manager_interface = { "gtk_primary_selection_device_manager", 1, 3, gtk_primary_selection_device_manager_requests, 0, NULL, }; static const struct wl_message gtk_primary_selection_device_requests[] = { { "set_selection", "?ou", types + 5 }, { "destroy", "", types + 0 }, }; static const struct wl_message gtk_primary_selection_device_events[] = { { "data_offer", "n", types + 7 }, { "selection", "?o", types + 8 }, }; WL_EXPORT const struct wl_interface gtk_primary_selection_device_interface = { "gtk_primary_selection_device", 1, 2, gtk_primary_selection_device_requests, 2, gtk_primary_selection_device_events, }; static const struct wl_message gtk_primary_selection_offer_requests[] = { { "receive", "sh", types + 0 }, { "destroy", "", types + 0 }, }; static const struct wl_message gtk_primary_selection_offer_events[] = { { "offer", "s", types + 0 }, }; WL_EXPORT const struct wl_interface gtk_primary_selection_offer_interface = { "gtk_primary_selection_offer", 1, 2, gtk_primary_selection_offer_requests, 1, gtk_primary_selection_offer_events, }; static const struct wl_message gtk_primary_selection_source_requests[] = { { "offer", "s", types + 0 }, { "destroy", "", types + 0 }, }; static const struct wl_message gtk_primary_selection_source_events[] = { { "send", "sh", types + 0 }, { "cancelled", "", types + 0 }, }; WL_EXPORT const struct wl_interface gtk_primary_selection_source_interface = { "gtk_primary_selection_source", 1, 2, gtk_primary_selection_source_requests, 2, gtk_primary_selection_source_events, }; mlterm-3.8.9/uitoolkit/libtype004075500017600000144000000000001356600660700151615ustar kenusersmlterm-3.8.9/uitoolkit/libtype/ui_window_xft.c010064400017600000144000000110101356600660700202570ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_window.h" #include #include /* alloca */ #define ui_color_to_xft(xcolor) _ui_color_to_xft(alloca(sizeof(XftColor)), (xcolor)) /* --- static functions --- */ static XftColor* _ui_color_to_xft(XftColor *xftcolor, ui_color_t *xcolor) { xftcolor->pixel = xcolor->pixel; xftcolor->color.red = (xcolor->red << 8) + xcolor->red; xftcolor->color.green = (xcolor->green << 8) + xcolor->green; xftcolor->color.blue = (xcolor->blue << 8) + xcolor->blue; xftcolor->color.alpha = (xcolor->alpha << 8) + xcolor->alpha; return xftcolor; } /* --- global functions --- */ int ui_window_set_use_xft(ui_window_t *win, int use_xft) { if (use_xft) { if ((win->xft_draw = XftDrawCreate(win->disp->display, win->my_window, win->disp->visual, win->disp->colormap))) { return 1; } } else { XftDrawDestroy(win->xft_draw); win->xft_draw = NULL; return 1; } return 0; } void ui_window_xft_draw_string8(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, size_t len) { XftColor *xftcolor = ui_color_to_xft(fg_color); ef_charset_t cs = FONT_CS(font->id); if (IS_ISCII(cs)) { /* * Font name: "BN-TTDurga" * FT_ENCODING: _APPLE_ROMAN _UNICODE * 0x86 => 0x2020 * 0x99 => 0x2122 * * It seems impossible to make XftDrawString8() use FT_ENCODING_APPLE_ROMAN, * so both FT_Select_Charmap() and FT_Get_Char_Index() are used to show ISCII. */ FT_Face face = XftLockFace(font->xft_font); FT_UInt *glyphs = alloca(sizeof(*glyphs) * len); if (glyphs) { size_t count; /* Call FT_Select_Charmap() every time to keep FT_ENCODING_APPLE_ROMAN. */ FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN); for (count = 0; count < len; count++) { glyphs[count] = FT_Get_Char_Index(face, str[count]); } XftDrawGlyphs(win->xft_draw, xftcolor, font->xft_font, x + font->x_off + win->hmargin, y + win->vmargin, glyphs, len); if (font->double_draw_gap) { XftDrawGlyphs(win->xft_draw, xftcolor, font->xft_font, x + font->x_off + win->hmargin + font->double_draw_gap, y + win->vmargin, glyphs, len); } } XftUnlockFace(font->xft_font); } else { /* Removing trailing spaces. */ while (1) { if (len == 0) { return; } if (*(str + len - 1) == ' ') { len--; } else { break; } } XftDrawString8(win->xft_draw, xftcolor, font->xft_font, x + font->x_off + win->hmargin, y + win->vmargin, str, len); if (font->double_draw_gap) { XftDrawString8(win->xft_draw, xftcolor, font->xft_font, x + font->x_off + win->hmargin + font->double_draw_gap, y + win->vmargin, str, len); } } } void ui_window_xft_draw_string32(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, FcChar32* str, u_int len) { XftColor *xftcolor; xftcolor = ui_color_to_xft(fg_color); #ifdef USE_OT_LAYOUT if (font->use_ot_layout /* && font->ot_font */) { XftDrawGlyphs(win->xft_draw, xftcolor, font->xft_font, x + font->x_off + win->hmargin, y + win->vmargin, str, len); } else #endif { XftDrawString32(win->xft_draw, xftcolor, font->xft_font, x + font->x_off + win->hmargin, y + win->vmargin, str, len); } if (font->double_draw_gap) { #ifdef USE_OT_LAYOUT if (font->use_ot_layout /* && font->ot_font */) { XftDrawGlyphs(win->xft_draw, xftcolor, font->xft_font, x + font->x_off + win->hmargin, y + win->vmargin, str, len); } else #endif { XftDrawString32(win->xft_draw, xftcolor, font->xft_font, x + font->x_off + win->hmargin + font->double_draw_gap, y + win->vmargin, str, len); } } } void xft_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height) { XRectangle rect; rect.x = 0; rect.y = 0; rect.width = width; rect.height = height; XftDrawSetClipRectangles(win->xft_draw, x, y, &rect, 1); } void xft_unset_clip(ui_window_t *win) { XRectangle rect; rect.x = 0; rect.y = 0; rect.width = ACTUAL_WIDTH(win); rect.height = ACTUAL_HEIGHT(win); XftDrawSetClipRectangles(win->xft_draw, 0, 0, &rect, 1); } mlterm-3.8.9/uitoolkit/libtype/dexport-sun.map012075500017600000144000000000001356600660700224032dexport.mapustar kenusersmlterm-3.8.9/uitoolkit/libtype/dexport.map010064400017600000144000000001301356600660700174130ustar kenusersmlterm { global: ui_type_xft_func_table ; ui_type_cairo_func_table ; local: * ; } ; mlterm-3.8.9/uitoolkit/libtype/fc_wrapper.c010064400017600000144000000005071356600660700175330ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include #include FT_UInt FcFreeTypeCharIndex(FT_Face face, FcChar32 ucs4) { return FT_Get_Char_Index(face, ucs4); } FcBool FcCharSetHasChar(const FcCharSet *fcs, FcChar32 ucs4) { return FcTrue; } mlterm-3.8.9/uitoolkit/libtype/ui_font_cairo.c010064400017600000144000000003001356600660700202120ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef USE_TYPE_CAIRO #define USE_TYPE_CAIRO #endif #ifdef USE_TYPE_XFT #undef USE_TYPE_XFT #endif #include "ui_font_ft.c" mlterm-3.8.9/uitoolkit/libtype/ui_font_ft.c010064400017600000144000001133111356600660700175350ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_font.h" #include /* strtod */ #ifdef USE_TYPE_XFT #include #endif #ifdef USE_TYPE_CAIRO #include #include /* FcChar32 */ #include #endif #include #include /* realloc */ #include /* bl_str_to_int/memset/strncasecmp */ #include /* UTF_MAX_SIZE */ #ifdef USE_OT_LAYOUT #include #endif #define DIVIDE_ROUNDING(a, b) (((int)((a)*10 + (b)*5)) / ((int)((b)*10))) #define DIVIDE_ROUNDINGUP(a, b) (((int)((a)*10 + (b)*10 - 1)) / ((int)((b)*10))) /* Be careful not to round down 5.99999... to 5 */ #define DOUBLE_ROUNDUP_TO_INT(a) ((int)((a) + 0.9)) /* * XXX * cairo always uses double drawing fow now, because width of normal font is not * always the same as that of bold font in cairo. */ #if 1 #define CAIRO_FORCE_DOUBLE_DRAWING #endif #if 0 #define __DEBUG #endif /* --- static variables --- */ static const char *fc_size_type = FC_PIXEL_SIZE; static double dpi_for_fc; /* --- static functions --- */ /* Same processing as win32/ui_font.c (partially) and libtype/ui_font_ft.c */ static int parse_fc_font_name( char **font_family, int *font_weight, /* if weight is not specified in font_name , not changed. */ int *font_slant, /* if slant is not specified in font_name , not changed. */ double *font_size, /* if size is not specified in font_name , not changed. */ char **font_encoding, /* if encoding is not specified in font_name , not changed. */ u_int *percent, /* if percent is not specified in font_name , not changed. */ char *font_name /* modified by this function. */ ) { char *p; size_t len; #if 1 /* * Compat with mlterm 3.6.3 or before: ... [SIZE]-[Encoding]:[Percentage] * ^^^^^^^^^^^ */ if ((p = strstr(font_name, "-iso10646-1"))) { memmove(p, p + 11, strlen(p + 11) + 1); } #endif /* * [Family]( [WEIGHT] [SLANT] [SIZE]:[Percentage]) */ *font_family = font_name; p = font_name + strlen(font_name) - 1; if ('0' <= *p && *p <= '9') { do { p--; } while ('0' <= *p && *p <= '9'); if (*p == ':' && bl_str_to_uint(percent, p + 1)) { /* Parsing ":[Percentage]" */ *p = '\0'; } } p = font_name; while (1) { if (*p == '\\' && *(p + 1)) { /* Compat with 3.6.3 or before. (e.g. Foo\-Bold-iso10646-1) */ /* skip backslash */ p++; } else if (*p == '\0') { /* encoding and percentage is not specified. */ *font_name = '\0'; break; } *(font_name++) = *(p++); } /* * Parsing "[Family] [WEIGHT] [SLANT] [SIZE]". * Following is the same as ui_font_win32.c:parse_font_name() * except FC_*. */ #if 0 bl_debug_printf("Parsing %s for [Family] [Weight] [Slant]\n", *font_family); #endif p = bl_str_chop_spaces(*font_family); len = strlen(p); while (len > 0) { size_t step = 0; if (*p == ' ') { char *orig_p; orig_p = p; do { p++; len--; } while (*p == ' '); if (len == 0) { *orig_p = '\0'; break; } else { int count; struct { char *style; int weight; int slant; } styles[] = { /* * Portable styles. */ /* slant */ { "italic", 0, FC_SLANT_ITALIC, }, /* weight */ { "bold", FC_WEIGHT_BOLD, 0, }, /* * Hack for styles which can be returned by * gtk_font_selection_dialog_get_font_name(). */ /* slant */ { "oblique", 0, FC_SLANT_OBLIQUE, }, /* weight */ { "light", /* e.g. "Bookman Old Style Light" */ FC_WEIGHT_LIGHT, 0, }, { "semi-bold", FC_WEIGHT_DEMIBOLD, 0, }, { "heavy", /* e.g. "Arial Black Heavy" */ FC_WEIGHT_BLACK, 0, }, /* other */ { "semi-condensed", /* XXX This style is ignored. */ 0, 0, }, }; for (count = 0; count < sizeof(styles) / sizeof(styles[0]); count++) { size_t len_v; len_v = strlen(styles[count].style); /* XXX strncasecmp is not portable? */ if (len >= len_v && strncasecmp(p, styles[count].style, len_v) == 0) { *orig_p = '\0'; step = len_v; if (styles[count].weight) { *font_weight = styles[count].weight; } else if (styles[count].slant) { *font_slant = styles[count].slant; } goto next_char; } } if (*p != '0' || /* In case of "DevLys 010" font family. */ *(p + 1) == '\0') /* "MS Gothic 0" => "MS Gothic" + "0" */ { char *end; double size; size = strtod(p, &end); if (*end == '\0') { /* p has no more parameters. */ *orig_p = '\0'; if (size > 0) { *font_size = size; } break; } } step = 1; } } else { step = 1; } next_char: p += step; len -= step; } return 1; } static u_int get_fc_col_width(ui_font_t *font, double fontsize_d, u_int percent, u_int cols, u_int letter_space) { if (percent == 0) { if (letter_space == 0 || font->is_var_col_width) { #ifdef USE_TYPE_XFT if (!font->is_vertical) #endif return 0; } percent = 100; } if (strcmp(fc_size_type, FC_SIZE) == 0) { double dpi; if (dpi_for_fc) { dpi = dpi_for_fc; } else { double widthpix; double widthmm; widthpix = DisplayWidth(font->display, DefaultScreen(font->display)); widthmm = DisplayWidthMM(font->display, DefaultScreen(font->display)); dpi = (widthpix * 254) / (widthmm * 10); } return DIVIDE_ROUNDINGUP(dpi * fontsize_d * cols * percent, 72 * 100 * 2) + letter_space; } else { return DIVIDE_ROUNDINGUP(fontsize_d * cols * percent, 100 * 2) + letter_space; } } static FcPattern *fc_pattern_create(char *family, /* can be NULL */ double size, char *encoding, /* can be NULL */ int weight, int slant, int ch_width, /* can be 0 */ int aa_opt) { FcPattern *pattern; if (family) { /* * XXX * FcNameParse() unexpectedly separates "BN-TTDurga" to "BN" and "TTDurga". * '-' must be escaped by '\' before calling FcNameParse(). */ if (strchr(family, '-')) { if (strchr(family, ':')) { /* BN-TTDurga:style=... */ bl_msg_printf("Failed to parse %s.\n", family); } } else if ((pattern = FcNameParse(family))) { goto created; } } if ((pattern = FcPatternCreate())) { if (family) { FcPatternAddString(pattern, FC_FAMILY, family); } } else { return NULL; } created: FcPatternAddDouble(pattern, fc_size_type, size); if (weight >= 0) { FcPatternAddInteger(pattern, FC_WEIGHT, weight); } if (slant >= 0) { FcPatternAddInteger(pattern, FC_SLANT, slant); } #ifdef USE_TYPE_XFT if (ch_width > 0) { FcPatternAddInteger(pattern, FC_SPACING, FC_CHARCELL); /* XXX FC_CHAR_WIDTH doesn't make effect in cairo ... */ FcPatternAddInteger(pattern, FC_CHAR_WIDTH, ch_width); } #endif if (aa_opt) { FcPatternAddBool(pattern, FC_ANTIALIAS, aa_opt == 1 ? True : False); } if (dpi_for_fc) { FcPatternAddDouble(pattern, FC_DPI, dpi_for_fc); } #ifdef USE_TYPE_XFT if (encoding) { /* no meaning on xft2 */ FcPatternAddString(pattern, XFT_ENCODING, encoding); } #endif #if 0 FcPatternAddBool(pattern, "embeddedbitmap", True); #endif FcConfigSubstitute(NULL, pattern, FcMatchPattern); return pattern; } /* XXX Lazy check */ static int check_iscii_font(FcPattern *pattern) { FcValue val; if (FcPatternGet(pattern, FC_FAMILY, 0, &val) == FcResultMatch && strstr(val.u.s, "-TT")) { return 1; } else { return 0; } } #ifdef USE_TYPE_XFT static XftFont *xft_font_open(ui_font_t *font, char *family, /* can be NULL */ double size, char *encoding, /* can be NULL */ int weight, int slant, int ch_width, int aa_opt) { FcPattern *pattern; FcPattern *match; FcResult result; XftFont *xfont; int is_iscii; if (!(pattern = fc_pattern_create(family, size, encoding, weight, slant, ch_width, aa_opt))) { return NULL; } if ((is_iscii = IS_ISCII(FONT_CS(font->id)))) { /* no meaning on xft2 */ FcPatternAddString(pattern, XFT_ENCODING, "apple-roman"); } match = XftFontMatch(font->display, DefaultScreen(font->display), pattern, &result); FcPatternDestroy(pattern); if (!match) { return NULL; } if (is_iscii && !check_iscii_font(match)) { FcPatternDestroy(match); return NULL; } #if 0 FcPatternPrint(match); #endif /* If XftFontOpenPattern() succeeds, don't call FcPatternDestroy(match) */ if (!(xfont = XftFontOpenPattern(font->display, match))) { FcPatternDestroy(match); return NULL; } /* ui_window_xft_draw_string8() calls FT_Select_Charmap(FT_ENCODING_APPLE_ROMAN) */ #if 0 if (is_iscii) { FT_Face face; int count; face = XftLockFace(xfont); for (count = 0; count < face->num_charmaps; count++) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " ISCII font encoding %c%c%c%c\n", ((face->charmaps[count]->encoding) >> 24) & 0xff, ((face->charmaps[count]->encoding) >> 16) & 0xff, ((face->charmaps[count]->encoding) >> 8) & 0xff, (face->charmaps[count]->encoding & 0xff)); #endif if (face->charmaps[count]->encoding == FT_ENCODING_APPLE_ROMAN) { FT_Set_Charmap(face, face->charmaps[count]); break; } } XftUnlockFace(xfont); } #endif return xfont; } #endif #ifdef USE_TYPE_CAIRO static int is_same_family(FcPattern *pattern, const char *family) { int count; FcValue val; for (count = 0; FcPatternGet(pattern, FC_FAMILY, count, &val) == FcResultMatch; count++) { if (strcmp(family, val.u.s) == 0) { return 1; } } return 0; } static cairo_scaled_font_t *cairo_font_open_intern(cairo_t *cairo, FcPattern *match, cairo_font_options_t *options) { cairo_font_face_t *font_face; double pixel_size; int pixel_size2; cairo_matrix_t font_matrix; cairo_matrix_t ctm; cairo_scaled_font_t *scaled_font; font_face = cairo_ft_font_face_create_for_pattern(match); FcPatternGetDouble(match, FC_PIXEL_SIZE, 0, &pixel_size); /* * 10.5 / 2.0 = 5.25 ->(roundup) 6 -> 6 * 2 = 12 * 11.5 / 2.0 = 5.75 ->(roundup) 6 -> 6 * 2 = 12 * * If half width is 5.25 -> 6 and full width is 5.25 * 2 = 10.5 -> 11, * half width char -> ui_bearing = 1 / width 5 * full width char -> ui_bearing = 1 / width 10. * This results in gap between chars. */ pixel_size2 = DIVIDE_ROUNDINGUP(pixel_size, 2.0) * 2; cairo_matrix_init_scale(&font_matrix, pixel_size2, pixel_size2); cairo_get_matrix(cairo, &ctm); scaled_font = cairo_scaled_font_create(font_face, &font_matrix, &ctm, options); cairo_destroy(cairo); cairo_font_options_destroy(options); cairo_font_face_destroy(font_face); return scaled_font; } static cairo_scaled_font_t *cairo_font_open(ui_font_t *font, char *family, /* can be NULL */ double size, char *encoding, /* can be NULL */ int weight, int slant, int ch_width, int aa_opt) { cairo_font_options_t *options; cairo_t *cairo; FcPattern *pattern; FcPattern *match; FcResult result; cairo_scaled_font_t *xfont; FcCharSet *charset; ef_charset_t cs; if (!(pattern = fc_pattern_create(family, size, encoding, weight, slant, ch_width, aa_opt))) { return NULL; } if (!(cairo = cairo_create(cairo_xlib_surface_create( font->display, DefaultRootWindow(font->display), DefaultVisual(font->display, DefaultScreen(font->display)), DisplayWidth(font->display, DefaultScreen(font->display)), DisplayHeight(font->display, DefaultScreen(font->display)))))) { goto error1; } options = cairo_font_options_create(); cairo_get_font_options(cairo, options); #ifndef CAIRO_FORCE_DOUBLE_DRAWING /* * XXX * CAIRO_HINT_METRICS_OFF has bad effect, but CAIRO_HINT_METRICS_ON * disarranges * column width by boldening etc. */ cairo_font_options_set_hint_metrics(options, CAIRO_HINT_METRICS_OFF); #else /* For performance */ cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE); #endif #if 0 cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL); cairo_font_options_set_subpixel_order(options, CAIRO_SUBPIXEL_ORDER_RGB); #endif cairo_ft_font_options_substitute(options, pattern); /* Supply default values for underspecified options */ FcDefaultSubstitute(pattern); if (!(match = FcFontMatch(NULL, pattern, &result))) { cairo_destroy(cairo); cairo_font_options_destroy(options); goto error1; } cs = FONT_CS(font->id); if (IS_ISCII(cs) && !check_iscii_font(match)) { goto error2; } #if 0 FcPatternPrint(match); #endif if (!(xfont = cairo_font_open_intern(cairo, match, options))) { goto error2; } if (cairo_scaled_font_status(xfont)) { cairo_scaled_font_destroy(xfont); goto error2; } /* ui_window_cairo_draw_string8() calls FT_Select_Charmap(FT_ENCODING_APPLE_ROMAN) */ #if 0 if (IS_ISCII(cs)) { FT_Face face; int count; FcPatternDestroy(pattern); face = cairo_ft_scaled_font_lock_face(xfont); for (count = 0; count < face->num_charmaps; count++) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " ISCII font encoding %c%c%c%c\n", ((face->charmaps[count]->encoding) >> 24) & 0xff, ((face->charmaps[count]->encoding) >> 16) & 0xff, ((face->charmaps[count]->encoding) >> 8) & 0xff, (face->charmaps[count]->encoding & 0xff)); #endif if (face->charmaps[count]->encoding == FT_ENCODING_APPLE_ROMAN) { FT_Set_Charmap(face, face->charmaps[count]); } } cairo_ft_scaled_font_unlock_face(xfont); } else #endif if (cs != US_ASCII && cs != ISO8859_1_R && FcPatternGetCharSet(match, FC_CHARSET, 0, &charset) == FcResultMatch && (font->compl_fonts = malloc(sizeof(*font->compl_fonts)))) { FcValue val; int count; font->compl_fonts[0].charset = FcCharSetCopy(charset); font->compl_fonts[0].next = NULL; count = 0; while (FcPatternGet(pattern, FC_FAMILY, count, &val) == FcResultMatch) { if (is_same_family(match, val.u.s)) { /* Remove not only matched name but also alias names */ FcPatternRemove(pattern, FC_FAMILY, count); } else { int count2 = ++count; FcValue val2; while (FcPatternGet(pattern, FC_FAMILY, count2, &val2) == FcResultMatch) { if (strcmp(val.u.s, val2.u.s) == 0) { FcPatternRemove(pattern, FC_FAMILY, count2); } else { count2++; } } } } FcPatternRemove(pattern, FC_FAMILYLANG, 0); FcPatternRemove(pattern, FC_STYLELANG, 0); FcPatternRemove(pattern, FC_FULLNAMELANG, 0); #ifdef FC_NAMELANG FcPatternRemove(pattern, FC_NAMELANG, 0); #endif FcPatternRemove(pattern, FC_LANG, 0); font->pattern = pattern; } else { FcPatternDestroy(pattern); } FcPatternDestroy(match); return xfont; error2: FcPatternDestroy(match); error1: FcPatternDestroy(pattern); return NULL; } #if 0 static void print_family(FcPattern *pattern) { int count; FcValue val; for (count = 0; FcPatternGet(pattern, FC_FAMILY, count, &val) == FcResultMatch; count++) { bl_debug_printf("Match(%d): %s\n", count, val.u.s); } } #endif static struct { char *family; FcCharSet *charset; } *charset_cache; static u_int charset_cache_size; static u_int max_charset_cache_size; static int search_nearest_pos_in_cache(const char *family, int beg, int end) { int count = 0; while (1) { if (beg + 1 == end) { return beg; } else { int pos = (beg + end) / 2; int ret = strcmp(family, charset_cache[pos].family); if (ret == 0) { return pos; } else if (ret > 0) { beg = pos; } else { end = pos; } } count++; } } static FcCharSet *add_charset_to_cache(const char *family, FcCharSet *charset) { int pos; if (charset_cache_size >= max_charset_cache_size) { void *p; if (!(p = realloc(charset_cache, (max_charset_cache_size + 50) * sizeof(*charset_cache)))) { return NULL; } charset_cache = p; max_charset_cache_size += 50; } if (charset_cache_size == 0) { pos = 0; } else { pos = search_nearest_pos_in_cache(family, 0, charset_cache_size); if (strcmp(family, charset_cache[pos].family) > 0) { pos++; } } memmove(charset_cache + pos + 1, charset_cache + pos, (charset_cache_size - pos) * sizeof(*charset_cache)); charset_cache_size++; charset_cache[pos].family = strdup(family); return (charset_cache[pos].charset = FcCharSetCopy(charset)); } static FcCharSet *get_cached_charset(const char *family) { if (charset_cache_size > 0) { int pos = search_nearest_pos_in_cache(family, 0, charset_cache_size); if (strcmp(family, charset_cache[pos].family) == 0) { return charset_cache[pos].charset; } } return NULL; } #if 0 static void destroy_charset_chache(void) { u_int count; for (count = 0; count < charset_cache_size; count++) { free(charset_cache[count].family); FcCharSetDestroy(charset_cache[count].charset); charset_cache_size = 0; } free(charset_cache); charset_cache = NULL; max_charset_cache_size = 0; } #endif static int cairo_compl_font_open(ui_font_t *font, int num_compl_fonts, FcPattern *orig_pattern, int ch) { FcValue val; cairo_t *cairo; cairo_font_options_t *options; FcPattern *pattern; FcPattern *match = NULL; FcResult result; cairo_scaled_font_t *xfont; FcCharSet *charset; int count; int ret = 0; if (!(pattern = FcPatternDuplicate(orig_pattern))) { return 0; } #if 0 FcPatternPrint(orig_pattern); #endif for (count = 0; FcPatternGet(pattern, FC_FAMILY, 0, &val) == FcResultMatch; count++) { void *p; if ((charset = get_cached_charset(val.u.s))) { if (!FcCharSetHasChar(charset, ch)) { FcPatternRemove(pattern, FC_FAMILY, 0); continue; } if (!(match = FcFontMatch(NULL, pattern, &result))) { break; } FcPatternRemove(pattern, FC_FAMILY, 0); } else { FcResult ret; if (!(match = FcFontMatch(NULL, pattern, &result))) { break; } ret = FcPatternGetCharSet(match, FC_CHARSET, 0, &charset); if (!(charset = add_charset_to_cache(val.u.s, charset))) { break; } FcPatternRemove(pattern, FC_FAMILY, 0); if (ret != FcResultMatch || !FcCharSetHasChar(charset, ch)) { FcPatternDestroy(match); match = NULL; continue; } } #if 0 print_family(match); #endif FcPatternRemove(orig_pattern, FC_FAMILY, count++); while (FcPatternGet(orig_pattern, FC_FAMILY, count, &val) == FcResultMatch) { if (is_same_family(match, val.u.s)) { FcPatternRemove(orig_pattern, FC_FAMILY, count); } else { count++; } } if ((p = realloc(font->compl_fonts, sizeof(*font->compl_fonts) * (num_compl_fonts + 1)))) { font->compl_fonts = p; } else { break; } #if 0 FcPatternPrint(match); #endif if (!(cairo = cairo_create(cairo_xlib_surface_create( font->display, DefaultRootWindow(font->display), DefaultVisual(font->display, DefaultScreen(font->display)), DisplayWidth(font->display, DefaultScreen(font->display)), DisplayHeight(font->display, DefaultScreen(font->display)))))) { break; } options = cairo_font_options_create(); cairo_get_font_options(cairo, options); /* For performance */ cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE); if (!(xfont = cairo_font_open_intern(cairo, match, options))) { break; } if (cairo_scaled_font_status(xfont)) { cairo_scaled_font_destroy(xfont); break; } font->compl_fonts[num_compl_fonts - 1].next = xfont; font->compl_fonts[num_compl_fonts].charset = charset; font->compl_fonts[num_compl_fonts].next = NULL; ret = 1; break; } #if 0 { int i; for (i = 0; i < charset_cache_size; i++) { bl_debug_printf("%d %s\n", i, charset_cache[i].family); } } #endif FcPatternDestroy(pattern); if (match) { FcPatternDestroy(match); } return ret; } #endif static void *ft_font_open(ui_font_t *font, char *family, double size, char *encoding, int weight, int slant, int ch_width, int aa_opt, int use_xft) { if (use_xft) { #ifdef USE_TYPE_XFT return xft_font_open(font, family, size, encoding, weight, slant, ch_width, aa_opt); #else return NULL; #endif } else { #ifdef USE_TYPE_CAIRO return cairo_font_open(font, family, size, encoding, weight, slant, ch_width, aa_opt); #else return NULL; #endif } } u_int xft_calculate_char_width(ui_font_t *font, u_int32_t ch); u_int cairo_calculate_char_width(ui_font_t *font, u_int32_t ch); void xft_unset_font(ui_font_t *font); static int fc_set_font(ui_font_t *font, const char *fontname, u_int fontsize, u_int col_width, /* if usascii font wants to be set , 0 will be set. */ u_int letter_space, int aa_opt, /* 0 = default , 1 = enable , -1 = disable */ int use_xft) { char *font_encoding; int weight; int slant; u_int ch_width; void *xfont; u_int cols; /* * encoding, weight and slant can be modified in parse_fc_font_name(). */ font_encoding = NULL; if ( #ifdef CAIRO_FORCE_DOUBLE_DRAWING use_xft && #endif (font->id & FONT_BOLD)) { weight = FC_WEIGHT_BOLD; } else { weight = -1; /* use default value */ } if (font->id & FONT_ITALIC) { #ifdef USE_TYPE_XFT /* * XXX * FC_CHAR_WIDTH=ch_width and FC_SPACING=FC_MONO make * the width of italic kochi font double of ch_width * on xft if slant >= 0. (They works fine for Dejavu * Sans Mono Italic, though.) */ font->is_var_col_width = 1; #endif slant = FC_SLANT_ITALIC; } else { slant = -1; /* use default value */ } if (font->id & FONT_FULLWIDTH) { cols = 2; } else { cols = 1; } /* * x_off related to percent is set before ft_font_open while * x_off related to is_vertical and letter_space is set after. */ if (fontname) { char *p; char *font_family; double fontsize_d; u_int percent; if ((p = alloca(strlen(fontname) + 1)) == NULL) { return 0; } strcpy(p, fontname); fontsize_d = (double)fontsize; percent = 0; if (parse_fc_font_name(&font_family, &weight, &slant, &fontsize_d, &font_encoding, &percent, p)) { #ifdef USE_TYPE_XFT /* * XXX * FC_CHAR_WIDTH=ch_width and FC_SPACING=FC_MONO make * the width of italic kochi font double of ch_width * on xft if slant >= 0. (They works fine for Dejavu * Sans Mono Italic, though.) */ if (slant >= 0) { font->is_var_col_width = 1; } #endif if (col_width == 0) { /* basic font (e.g. usascii) width */ /* if font->is_var_col_width is true, 0 is returned. */ ch_width = get_fc_col_width(font, fontsize_d, percent, cols, letter_space); if (percent > 100) { /* * Centering * (fontsize * percent / 100 + letter_space = ch_width * -> fontsize = (ch_width - letter_space) * 100 / percent * -> fontsize * (percent - 100) / 100 * = (ch_width - letter_space) * (percent - 100) * / percent) */ font->x_off = (ch_width - letter_space) * (percent - 100) / percent / 2; } if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ ch_width *= 2; } } else { if (font->is_var_col_width) { ch_width = 0; } else if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ ch_width = col_width; } else { ch_width = col_width * cols; } } #ifdef DEBUG bl_debug_printf( "Loading font %s%s%s %f %d%s\n", font_family, weight == FC_WEIGHT_BOLD ? ":Bold" : weight == FC_WEIGHT_LIGHT ? " Light" : "", slant == FC_SLANT_ITALIC ? ":Italic" : "", fontsize_d, ch_width, font->is_var_col_width ? "(varcolwidth)" : ""); #endif if ((xfont = ft_font_open(font, font_family, fontsize_d, font_encoding, weight, slant, ch_width, aa_opt, use_xft))) { goto font_found; } font->x_off = 0; } bl_msg_printf("Font %s (for size %f) couldn't be loaded.\n", fontname, fontsize_d); } if (col_width == 0) { /* basic font (e.g. usascii) width */ ch_width = get_fc_col_width(font, (double)fontsize, 0, cols, letter_space); if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ ch_width *= 2; } } else { if (font->is_var_col_width) { ch_width = 0; } else if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ ch_width = col_width; } else { ch_width = col_width * cols; } } if ((xfont = ft_font_open(font, NULL, (double)fontsize, font_encoding, weight, slant, ch_width, aa_opt, use_xft))) { goto font_found; } #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ft_font_open(%s) failed.\n", fontname); #endif return 0; font_found: if (use_xft) { #ifdef USE_TYPE_XFT #ifndef FC_EMBOLDEN /* Synthetic emboldening (fontconfig >= 2.3.0) */ if (weight == FC_WEIGHT_BOLD && XftPatternGetInteger(xfont->pattern, FC_WEIGHT, 0, &weight) == XftResultMatch && weight != FC_WEIGHT_BOLD) { font->double_draw_gap = 1; } #endif /* FC_EMBOLDEN */ font->xft_font = xfont; font->height = font->xft_font->height; font->ascent = font->xft_font->ascent; if (ch_width == 0) { /* * (US_ASCII) * font->is_var_col_width is true or letter_space == 0. * (see get_fc_col_width()) * (Other CS) * font->is_var_col_width is true. */ font->width = xft_calculate_char_width(font, 'W'); if (font->width != xft_calculate_char_width(font, 'l') || (col_width > 0 && font->width != col_width * cols) || /* * 'W' and 'l' are the same width, but tamil glyphs are proportional in * "Noto Sans Tamil" font. */ IS_ISCII(FONT_CS(font->id)) || FONT_CS(font->id) == ISO10646_UCS4_1_V) { /* Regard it as proportional. */ if (font->is_var_col_width) { font->is_proportional = 1; } else { u_int new_width; new_width = xft_calculate_char_width(font, 'M'); if (font->is_vertical) { new_width *= 2; } xft_unset_font(font); /* reloading it as mono spacing. */ return fc_set_font(font, fontname, fontsize, new_width, letter_space, aa_opt, use_xft); } } } else { /* Always mono space */ font->width = ch_width; } font->x_off += (letter_space * cols / 2); if (font->is_vertical && cols == 1) { font->x_off += (font->width / 4); /* Centering */ } #endif /* USE_TYPE_XFT */ } else { #ifdef USE_TYPE_CAIRO cairo_font_extents_t extents; #ifdef CAIRO_FORCE_DOUBLE_DRAWING if (font->id & FONT_BOLD) { font->double_draw_gap = 1; } #endif font->cairo_font = xfont; cairo_scaled_font_extents(font->cairo_font, &extents); font->height = DOUBLE_ROUNDUP_TO_INT(extents.height); font->ascent = DOUBLE_ROUNDUP_TO_INT(extents.ascent); if (cols == 2) { font->width = DOUBLE_ROUNDUP_TO_INT(extents.max_x_advance); } else { font->width = cairo_calculate_char_width(font, 'W'); if (font->is_vertical) { font->is_proportional = 1; font->width *= 2; font->x_off = font->width / 4; /* Centering */ } else if (font->width != cairo_calculate_char_width(font, 'l')) { if (!font->is_var_col_width) { #if CAIRO_VERSION_ENCODE(1, 8, 0) <= CAIRO_VERSION font->width = cairo_calculate_char_width(font, 'N'); #else font->width = cairo_calculate_char_width(font, 'M'); #endif } /* Regard it as proportional. */ font->is_proportional = 1; } } if (!font->is_var_col_width) { /* * Set letter_space here because cairo_font_open() ignores it. * (FC_CHAR_WIDTH doesn't make effect in cairo.) * Note that letter_space is ignored in variable column width mode. */ if (letter_space > 0) { font->is_proportional = 1; if (font->is_vertical) { letter_space *= 2; } else { letter_space *= cols; } font->width += letter_space; font->x_off += (letter_space / 2); /* Centering */ } if (ch_width > 0 && ch_width != font->width) { bl_msg_printf( "Font(id %x) width(%d) is not matched with " "standard width(%d).\n", font->id, font->width, ch_width); /* * XXX * Note that ch_width = 12 and extents.max_x_advance = 12.28 * (dealt as 13 though should be dealt as 12) may happen. */ font->is_proportional = 1; if (font->width < ch_width) { font->x_off += (ch_width - font->width) / 2; } font->width = ch_width; } #if CAIRO_VERSION_ENCODE(1, 8, 0) <= CAIRO_VERSION if (font->is_proportional && !font->is_var_col_width) { font->is_proportional = 0; } #endif } else if (!font->is_proportional) { /* is_var_col_width is true and is_proportional is false */ if ((col_width > 0 && font->width != col_width * cols) || /* * 'W' and 'l' are the same width, but tamil glyphs are proportional in * "Noto Sans Tamil" font. */ IS_ISCII(FONT_CS(font->id)) || FONT_CS(font->id) == ISO10646_UCS4_1_V) { font->is_proportional = 1; } } #endif /* USE_TYPE_CAIRO */ } /* * checking if font height/ascent member is sane. * font width must be always sane. */ if (font->height == 0) { /* XXX this may be inaccurate. */ font->height = fontsize; } if (font->ascent == 0) { /* XXX this may be inaccurate. */ font->ascent = fontsize; } return 1; } /* --- global functions --- */ #ifdef USE_TYPE_XFT int xft_set_font(ui_font_t *font, const char *fontname, u_int fontsize, u_int col_width, /* if usascii font wants to be set , 0 will be set. */ u_int letter_space, int aa_opt, /* 0 = default , 1 = enable , -1 = disable */ int use_point_size, double dpi) { if (use_point_size) { fc_size_type = FC_SIZE; } else { fc_size_type = FC_PIXEL_SIZE; } dpi_for_fc = dpi; return fc_set_font(font, fontname, fontsize, col_width, letter_space, aa_opt, 1); } void xft_unset_font(ui_font_t *font) { #ifdef USE_OT_LAYOUT if (font->ot_font) { otl_close(font->ot_font); } #endif XftFontClose(font->display, font->xft_font); font->xft_font = NULL; } int xft_set_ot_font(ui_font_t *font) { #ifdef USE_OT_LAYOUT font->ot_font = otl_open(XftLockFace(font->xft_font), 0); XftUnlockFace(font->xft_font); return (font->ot_font != NULL); #else return 0; #endif } u_int xft_calculate_char_width(ui_font_t *font, u_int32_t ch /* US-ASCII or Unicode */ ) { XGlyphInfo extents; #ifdef USE_OT_LAYOUT if (font->use_ot_layout /* && font->ot_font */) { if (sizeof(FT_UInt) != sizeof(u_int32_t)) { FT_UInt idx; idx = ch; XftGlyphExtents(font->display, font->xft_font, &idx, 1, &extents); } else { XftGlyphExtents(font->display, font->xft_font, &ch, 1, &extents); } } else #endif if (ch < 0x100) { u_char c; c = ch; XftTextExtents8(font->display, font->xft_font, &c, 1, &extents); } else { XftTextExtents32(font->display, font->xft_font, &ch, 1, &extents); } if (extents.xOff < 0) { /* Some (indic) fonts could return minus value as text width. */ return 0; } else { return extents.xOff; } } #endif #ifdef USE_TYPE_CAIRO int ui_search_next_cairo_font(ui_font_t *font, int ch) { int count; if (!font->compl_fonts) { return -1; } for (count = 0; font->compl_fonts[count].next; count++) { if (FcCharSetHasChar(font->compl_fonts[count + 1].charset, ch)) { return count; } } if (cairo_compl_font_open(font, count + 1, font->pattern, ch)) { return count; } else { /* To avoid to search it again. */ FcCharSetAddChar(font->compl_fonts[0].charset, ch); return -1; } } int cairo_set_font(ui_font_t *font, const char *fontname, u_int fontsize, u_int col_width, /* if usascii font wants to be set , 0 will be set. */ u_int letter_space, int aa_opt, /* 0 = default , 1 = enable , -1 = disable */ int use_point_size, double dpi) { if (use_point_size) { fc_size_type = FC_SIZE; } else { fc_size_type = FC_PIXEL_SIZE; } dpi_for_fc = dpi; return fc_set_font(font, fontname, fontsize, col_width, letter_space, aa_opt, 0); } void cairo_unset_font(ui_font_t *font) { #ifdef USE_OT_LAYOUT if (font->ot_font) { otl_close(font->ot_font); } #endif cairo_scaled_font_destroy(font->cairo_font); font->cairo_font = NULL; if (font->compl_fonts) { int count; cairo_scaled_font_t *xfont; for (count = 0;; count++) { if (!(xfont = font->compl_fonts[count].next)) { break; } cairo_scaled_font_destroy(xfont); } free(font->compl_fonts); } if (font->pattern) { FcPatternDestroy(font->pattern); } #if 0 destroy_charset_cache(); #endif } int cairo_set_ot_font(ui_font_t *font) { #ifdef USE_OT_LAYOUT font->ot_font = otl_open(cairo_ft_scaled_font_lock_face(font->cairo_font), 0); cairo_ft_scaled_font_unlock_face(font->cairo_font); return (font->ot_font != NULL); #else return 0; #endif } size_t ui_convert_ucs4_to_utf8(u_char *utf8, /* size of utf8 should be greater than 5. */ u_int32_t ucs) { /* ucs is unsigned */ if (/* 0x00 <= ucs && */ ucs <= 0x7f) { *utf8 = ucs; return 1; } else if (ucs <= 0x07ff) { *(utf8++) = ((ucs >> 6) & 0xff) | 0xc0; *utf8 = (ucs & 0x3f) | 0x80; return 2; } else if (ucs <= 0xffff) { *(utf8++) = ((ucs >> 12) & 0x0f) | 0xe0; *(utf8++) = ((ucs >> 6) & 0x3f) | 0x80; *utf8 = (ucs & 0x3f) | 0x80; return 3; } else if (ucs <= 0x1fffff) { *(utf8++) = ((ucs >> 18) & 0x07) | 0xf0; *(utf8++) = ((ucs >> 12) & 0x3f) | 0x80; *(utf8++) = ((ucs >> 6) & 0x3f) | 0x80; *utf8 = (ucs & 0x3f) | 0x80; return 4; } else if (ucs <= 0x03ffffff) { *(utf8++) = ((ucs >> 24) & 0x03) | 0xf8; *(utf8++) = ((ucs >> 18) & 0x3f) | 0x80; *(utf8++) = ((ucs >> 12) & 0x3f) | 0x80; *(utf8++) = ((ucs >> 6) & 0x3f) | 0x80; *utf8 = (ucs & 0x3f) | 0x80; return 5; } else if (ucs <= 0x7fffffff) { *(utf8++) = ((ucs >> 30) & 0x01) | 0xfc; *(utf8++) = ((ucs >> 24) & 0x3f) | 0x80; *(utf8++) = ((ucs >> 18) & 0x3f) | 0x80; *(utf8++) = ((ucs >> 12) & 0x3f) | 0x80; *(utf8++) = ((ucs >> 6) & 0x3f) | 0x80; *utf8 = (ucs & 0x3f) | 0x80; return 6; } else { return 0; } } u_int cairo_calculate_char_width(ui_font_t *font, u_int32_t ch) { u_char utf8[UTF_MAX_SIZE + 1]; cairo_text_extents_t extents; int width; #ifdef USE_OT_LAYOUT if (font->use_ot_layout /* && font->ot_font */) { cairo_glyph_t glyph; glyph.index = ch; glyph.x = glyph.y = 0; cairo_scaled_font_glyph_extents(font->cairo_font, &glyph, 1, &extents); } else #endif { int idx; utf8[ui_convert_ucs4_to_utf8(utf8, ch)] = '\0'; if (font->compl_fonts && !FcCharSetHasChar(font->compl_fonts[0].charset, ch) && (idx = ui_search_next_cairo_font(font, ch)) >= 0) { cairo_scaled_font_text_extents(font->compl_fonts[idx].next, utf8, &extents); } else { cairo_scaled_font_text_extents(font->cairo_font, utf8, &extents); } } #if 0 bl_debug_printf(BL_DEBUG_TAG " CHAR(%x) ui_bearing %f width %f x_advance %f\n", ch, extents.ui_bearing, extents.width, extents.x_advance); #endif if ((width = DOUBLE_ROUNDUP_TO_INT(extents.x_advance)) < 0) { return 0; } else { /* Some (indic) fonts could return minus value as text width. */ return width; } } #endif u_int ft_convert_text_to_glyphs(ui_font_t *font, u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features) { #ifdef USE_OT_LAYOUT return otl_convert_text_to_glyphs(font->ot_font, shaped, shaped_len, offsets, widths, cmapped, src, src_len, script, features, 0); #else return 0; #endif } mlterm-3.8.9/uitoolkit/libtype/ui_font_xft.c010064400017600000144000000003001356600660700177160ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef USE_TYPE_XFT #define USE_TYPE_XFT #endif #ifdef USE_TYPE_CAIRO #undef USE_TYPE_CAIRO #endif #include "ui_font_ft.c" mlterm-3.8.9/uitoolkit/libtype/ui_functbl_cairo.c010064400017600000144000000015511356600660700207120ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../xlib/ui_type_loader.h" /* Dummy declaration */ void ui_window_set_use_cairo(void); void ui_window_cairo_draw_string8(void); void ui_window_cairo_draw_string32(void); void cairo_resize(void); void cairo_set_font(void); void cairo_unset_font(void); void cairo_calculate_char_width(void); void cairo_set_clip(void); void cairo_unset_clip(void); void cairo_set_ot_font(void); void ft_convert_text_to_glyphs(void); /* --- global variables --- */ void *ui_type_cairo_func_table[MAX_TYPE_FUNCS] = { (void*)TYPE_API_COMPAT_CHECK_MAGIC, ui_window_set_use_cairo, ui_window_cairo_draw_string8, ui_window_cairo_draw_string32, cairo_resize, cairo_set_font, cairo_unset_font, cairo_calculate_char_width, cairo_set_clip, cairo_unset_clip, cairo_set_ot_font, ft_convert_text_to_glyphs, }; mlterm-3.8.9/uitoolkit/libtype/ui_functbl_xft.c010064400017600000144000000014751356600660700204230ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../xlib/ui_type_loader.h" #include /* NULL */ /* Dummy declaration */ void ui_window_set_use_xft(void); void ui_window_xft_draw_string8(void); void ui_window_xft_draw_string32(void); void xft_set_font(void); void xft_unset_font(void); void xft_calculate_char_width(void); void xft_set_clip(void); void xft_unset_clip(void); void xft_set_ot_font(void); void ft_convert_text_to_glyphs(void); /* --- global variables --- */ void *ui_type_xft_func_table[MAX_TYPE_FUNCS] = { (void*)TYPE_API_COMPAT_CHECK_MAGIC, ui_window_set_use_xft, ui_window_xft_draw_string8, ui_window_xft_draw_string32, NULL, xft_set_font, xft_unset_font, xft_calculate_char_width, xft_set_clip, xft_unset_clip, xft_set_ot_font, ft_convert_text_to_glyphs, }; mlterm-3.8.9/uitoolkit/libtype/ui_window_cairo.c010064400017600000144000000313311356600660700205630ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_window.h" #include #include /* FcChar32 */ #include #include /* alloca */ #include /* UTF_MAX_SIZE */ #define DIVIDE_ROUNDINGUP(a, b) (((int)((a)*10 + (b)*10 - 1)) / ((int)((b)*10))) #if CAIRO_VERSION_ENCODE(1, 8, 0) <= CAIRO_VERSION static cairo_glyph_t *glyph_buf; static int num_glyph_buf; #endif /* Implemented in ui_font_ft.c */ size_t ui_convert_ucs4_to_utf8(u_char *utf8, u_int32_t ucs); int ui_search_next_cairo_font(ui_font_t *font, int ch); /* --- static functions --- */ #if CAIRO_VERSION_ENCODE(1, 8, 0) <= CAIRO_VERSION static void adjust_glyphs(ui_font_t *font, cairo_glyph_t *glyphs, int num_glyphs) { if (!font->is_var_col_width) { int count; double prev_x; int adjust; int std_width; adjust = 0; prev_x = glyphs[0].x; for (count = 1; count < num_glyphs; count++) { int w; w = glyphs[count].x - prev_x; prev_x = glyphs[count].x; if (!adjust) { if (w == font->width) { continue; } adjust = 1; std_width = font->width - font->x_off * 2; } glyphs[count].x = glyphs[count - 1].x + font->width; glyphs[count - 1].x += ((std_width - w) / 2); } } } static void flush_glyphs(cairo_t *cr) { if (num_glyph_buf > 0) { u_long pixel = cairo_get_user_data(cr, 2); cairo_set_scaled_font(cr, cairo_get_user_data(cr, 1)); cairo_set_source_rgba(cr, (double)((pixel >> 16) & 0xff) / 255.0, (double)((pixel >> 8) & 0xff) / 255.0, (double)(pixel & 0xff) / 255.0, (double)((pixel >> 24) & 0xff) / 255.0); cairo_show_glyphs(cr, glyph_buf, num_glyph_buf); num_glyph_buf = 0; } } static void add_glyphs(cairo_glyph_t *glyphs, int num) { static int buf_size; if (num_glyph_buf + num > buf_size) { void *p; buf_size = num_glyph_buf + num + 100; if (!(p = realloc(glyph_buf, sizeof(cairo_glyph_t) * buf_size))) { return; } glyph_buf = p; } memcpy(glyph_buf + num_glyph_buf, glyphs, sizeof(cairo_glyph_t) * num); num_glyph_buf += num; } static int show_iscii(cairo_t *cr, cairo_scaled_font_t *xfont, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int str_len) { cairo_glyph_t *glyphs; u_int count; cairo_text_extents_t extents; FT_Face face; int drawn_x; if (cairo_get_user_data(cr, 1) != xfont) { flush_glyphs(cr); cairo_set_user_data(cr, 1, xfont, NULL); } /* * If cairo_get_user_data() returns NULL, it means that source rgb value is * default one (black == 0). */ if ((u_long)cairo_get_user_data(cr, 2) != (u_long)((fg_color->red << 16) | (fg_color->green << 8) | (fg_color->blue) | (fg_color->alpha << 24))) { flush_glyphs(cr); cairo_set_user_data(cr, 2, (u_long)((fg_color->red << 16) | (fg_color->green << 8) | (fg_color->blue) | (fg_color->alpha << 24)), NULL); } if (font->size_attr == DOUBLE_WIDTH) { flush_glyphs(cr); x /= 2; font->width /= 2; cairo_scale(cr, 2.0, 1.0); } if (!(glyphs = alloca(sizeof(*glyphs) * (str_len + 1)))) { return 0; } face = cairo_ft_scaled_font_lock_face(xfont); FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN); glyphs[0].x = x; glyphs[0].y = y; for (count = 0; count < str_len; count++) { glyphs[count].index = FT_Get_Char_Index(face, str[count]); cairo_scaled_font_glyph_extents(xfont, glyphs + count, 1, &extents); glyphs[count + 1].x = glyphs[count].x + extents.x_advance; glyphs[count + 1].y = y; } cairo_ft_scaled_font_unlock_face(xfont); add_glyphs(glyphs, str_len); if (font->double_draw_gap) { for (count = 0; count < str_len; count++) { glyphs[count].x += font->double_draw_gap; } add_glyphs(glyphs, str_len); } drawn_x = glyphs[str_len].x; if (font->size_attr == DOUBLE_WIDTH) { flush_glyphs(cr); font->width *= 2; cairo_scale(cr, 0.5, 1.0); } return drawn_x; } #endif static int show_text(cairo_t *cr, cairo_scaled_font_t *xfont, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str /* NULL-terminated UTF8 or FcChar32* */, u_int str_len) { #if CAIRO_VERSION_ENCODE(1, 8, 0) <= CAIRO_VERSION int drawn_x; #endif #if CAIRO_VERSION_ENCODE(1, 4, 0) <= CAIRO_VERSION if (cairo_get_user_data(cr, 1) != xfont) #endif { #if CAIRO_VERSION_ENCODE(1, 8, 0) > CAIRO_VERSION cairo_set_scaled_font(cr, xfont); #else flush_glyphs(cr); #endif #if CAIRO_VERSION_ENCODE(1, 4, 0) <= CAIRO_VERSION cairo_set_user_data(cr, 1, xfont, NULL); #endif } #if CAIRO_VERSION_ENCODE(1, 4, 0) <= CAIRO_VERSION /* * If cairo_get_user_data() returns NULL, it means that source rgb value is * default one (black == 0). */ if ((u_long)cairo_get_user_data(cr, 2) != (u_long)((fg_color->red << 16) | (fg_color->green << 8) | (fg_color->blue) | (fg_color->alpha << 24))) #endif { #if CAIRO_VERSION_ENCODE(1, 8, 0) > CAIRO_VERSION cairo_set_source_rgba(cr, (double)fg_color->red / 255.0, (double)fg_color->green / 255.0, (double)fg_color->blue / 255.0, (double)fg_color->alpha / 255.0); #else flush_glyphs(cr); #endif #if CAIRO_VERSION_ENCODE(1, 4, 0) <= CAIRO_VERSION cairo_set_user_data(cr, 2, (u_long)((fg_color->red << 16) | (fg_color->green << 8) | (fg_color->blue) | (fg_color->alpha << 24)), NULL); #endif } if (font->size_attr == DOUBLE_WIDTH) { flush_glyphs(cr); x /= 2; font->width /= 2; cairo_scale(cr, 2.0, 1.0); } #if CAIRO_VERSION_ENCODE(1, 8, 0) > CAIRO_VERSION cairo_move_to(cr, x, y); cairo_show_text(cr, str); if (font->double_draw_gap) { cairo_move_to(cr, x + font->double_draw_gap, y); cairo_show_text(cr, str); } if (font->size_attr == DOUBLE_WIDTH) { font->width *= 2; cairo_scale(cr, 0.5, 1.0); } return 1; #else #ifdef USE_OT_LAYOUT if (font->use_ot_layout /* && font->ot_font */) { cairo_glyph_t *glyphs; u_int count; cairo_text_extents_t extent; if (!(glyphs = alloca(sizeof(*glyphs) * (str_len + 1)))) { return 0; } glyphs[0].x = x; for (count = 0; count < str_len;) { glyphs[count].index = ((FcChar32*)str)[count]; glyphs[count].y = y; cairo_scaled_font_glyph_extents(xfont, glyphs + count, 1, &extent); count++; glyphs[count].x = glyphs[count - 1].x + extent.x_advance; } adjust_glyphs(font, glyphs, str_len + 1); add_glyphs(glyphs, str_len); if (font->double_draw_gap) { for (count = 0; count < str_len; count++) { glyphs[count].x += font->double_draw_gap; } add_glyphs(glyphs, str_len); } drawn_x = glyphs[str_len].x; } else #endif { static cairo_glyph_t *glyphs; static int num_glyphs; cairo_glyph_t *orig_glyphs; u_char *str2; orig_glyphs = glyphs; if (!(str2 = alloca(str_len + 2))) { return 0; } memcpy(str2, str, str_len); str2[str_len] = ' '; /* dummy */ str2[str_len + 1] = '\0'; if (cairo_scaled_font_text_to_glyphs(xfont, x, y, str2, str_len + 1, &glyphs, &num_glyphs, NULL, NULL, NULL) == CAIRO_STATUS_SUCCESS) { adjust_glyphs(font, glyphs, num_glyphs); num_glyphs--; /* remove dummy */ add_glyphs(glyphs, num_glyphs); if (font->double_draw_gap) { int count; for (count = 0; count < num_glyphs; count++) { glyphs[count].x += font->double_draw_gap; } add_glyphs(glyphs, num_glyphs); } } if (orig_glyphs != glyphs) { cairo_glyph_free(orig_glyphs); } drawn_x = glyphs[num_glyphs].x; } if (font->size_attr == DOUBLE_WIDTH) { flush_glyphs(cr); font->width *= 2; cairo_scale(cr, 0.5, 1.0); } return drawn_x; #endif } static int draw_string32(ui_window_t *win, cairo_scaled_font_t *xfont, ui_font_t *font, ui_color_t *fg_color, int x, int y, FcChar32* str, u_int len) { u_char *buf; u_int count; char *p; #ifdef USE_OT_LAYOUT if (font->use_ot_layout /* && font->ot_font */) { buf = str; } else #endif { if (!(p = buf = alloca(UTF_MAX_SIZE * len + 1))) { return 0; } for (count = 0; count < len; count++) { p += ui_convert_ucs4_to_utf8(p, str[count]); } *p = '\0'; len = strlen(buf); } return show_text(win->cairo_draw, xfont, font, fg_color, x + win->hmargin, y + win->vmargin, buf, len); } /* --- global functions --- */ int ui_window_set_use_cairo(ui_window_t *win, int use_cairo) { if (use_cairo) { cairo_surface_t *surface = cairo_xlib_surface_create(win->disp->display, win->my_window, win->disp->visual, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); if (surface) { win->cairo_draw = cairo_create(surface); cairo_surface_destroy(surface); #if 0 cairo_set_operator(win->cairo_draw, CAIRO_OPERATOR_CLEAR /*CAIRO_OPERATOR_ATOP*/); cairo_set_antialias(win->cairo_draw, CAIRO_ANTIALIAS_NONE); #endif if (win->cairo_draw) { return 1; } } } else { cairo_destroy(win->cairo_draw); win->cairo_draw = NULL; return 1; } return 0; } void ui_window_cairo_draw_string8(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, size_t len) { u_char *buf; size_t count; u_char *p; #if CAIRO_VERSION_ENCODE(1, 8, 0) <= CAIRO_VERSION ef_charset_t cs = FONT_CS(font->id); if (IS_ISCII(cs)) { show_iscii(win->cairo_draw, font->cairo_font, font, fg_color, x + font->x_off + win->hmargin, y + win->vmargin, str, len); return; } #endif /* Removing trailing spaces. */ while (1) { if (len == 0) { return; } if (*(str + len - 1) == ' ') { len--; } else { break; } } /* Max utf8 size of 0x80 - 0xff is 2 */ if (!(p = buf = alloca(2 * len + 1))) { return; } for (count = 0; count < len; count++) { p += ui_convert_ucs4_to_utf8(p, (u_int32_t)(str[count])); } *p = '\0'; show_text(win->cairo_draw, font->cairo_font, font, fg_color, x + font->x_off + win->hmargin, y + win->vmargin, buf, strlen(buf)); } void ui_window_cairo_draw_string32(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, FcChar32* str, u_int len) { cairo_scaled_font_t *xfont; if (str == NULL) { #if CAIRO_VERSION_ENCODE(1, 8, 0) <= CAIRO_VERSION flush_glyphs(win->cairo_draw); #endif return; } xfont = font->cairo_font; /* draw_string32() before 1.8.0 doesn't return x position. */ #if CAIRO_VERSION_ENCODE(1, 8, 0) <= CAIRO_VERSION if ( #ifdef USE_OT_LAYOUT (!font->use_ot_layout /* || ! font->ot_font */) && #endif font->compl_fonts) { u_int count; for (count = 0; count < len;) { if (!FcCharSetHasChar(font->compl_fonts[0].charset, str[count])) { int compl_idx; if ((compl_idx = ui_search_next_cairo_font(font, str[count])) >= 0) { FcChar32* substr; int x_off; if (count > 0) { x = draw_string32(win, xfont, font, fg_color, x + font->x_off, y, str, count); } substr = str + count; for (count++; count < len && !FcCharSetHasChar(font->compl_fonts[0].charset, str[count]) && FcCharSetHasChar(font->compl_fonts[compl_idx + 1].charset, str[count]); count++); x_off = font->x_off; font->x_off = 0; x = draw_string32(win, font->compl_fonts[compl_idx].next, font, fg_color, x + font->x_off, y, substr, substr - str + count); font->x_off = x_off; str += count; len -= count; count = 0; continue; } } count ++; } } #endif draw_string32(win, xfont, font, fg_color, x + font->x_off, y, str, len); } void cairo_resize(ui_window_t *win) { cairo_xlib_surface_set_size(cairo_get_target(win->cairo_draw), ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); } void cairo_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height) { cairo_rectangle(win->cairo_draw, x, y, width, height); cairo_clip(win->cairo_draw); } void cairo_unset_clip(ui_window_t *win) { cairo_reset_clip(win->cairo_draw); } mlterm-3.8.9/uitoolkit/libtype/Makefile.in010064400017600000144000000045531356600660700173110ustar kenuserstop_builddir = ../.. top_srcdir = @top_srcdir@ prefix = @prefix@ sysconfdir = @sysconfdir@ exec_prefix = @exec_prefix@ datadir = @datadir@ bindir = @bindir@ libdir = @libdir@ libexecdir = @libexecdir@ CC = @CC@ LIBTOOL = @LIBTOOL@ INSTALL = @INSTALL@ LIBDIR = $(DESTDIR)$(libdir)/mlterm VPATH = $(top_srcdir)/uitoolkit/libtype XFT_OBJ = ui_window_xft.o ui_font_xft.o ui_functbl_xft.o CAIRO_OBJ = ui_window_cairo.o ui_font_cairo.o ui_functbl_cairo.o NODL_OBJ = @NODL_OBJ@ ui_font_ft.o LPOBL = @LPOBL@ LPOBL_DEB = -lpobl_deb # XDATADIR is to avoid conflicting with DATADIR structure in w32api/objidl.h. CFLAGS = $(CFLAGS_LOCAL) @POBL_CFLAGS@ @MEF_CFLAGS@ @DEB_CFLAGS@ @X_CFLAGS@ @XFT_CFLAGS@ \ @CAIRO_CFLAGS@ @TYPE_CFLAGS@ @OT_LAYOUT_CFLAGS@ @CFLAGS@ @CPPFLAGS@ \ -DLIBDIR=\"$(libdir)\" \ -I/usr/local/include -I${top_srcdir}/vtemu -I${top_srcdir}/uitoolkit/libotl XFT_LIBS = @XFT_LIBS@ CAIRO_LIBS = @CAIRO_LIBS@ LIBS = $(LIBS_LOCAL) $(LPOBL) -L/usr/local/lib -R/usr/local/lib LIBTOOL_CC = $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) TYPE_LIBS = @TYPE_LIBS@ all: $(TYPE_LIBS) libtype_xft.la: $(XFT_OBJ) $(LIBTOOL_LINK) -o libtype_xft.la $(XFT_OBJ:.o=.lo) \ -rpath $(libdir)/mlterm \ -module -avoid-version @NO_UNDEFINED_FLAG@ @DEXPORT@ \ $(LIBS) $(XFT_LIBS) libtype_cairo.la: $(CAIRO_OBJ) $(LIBTOOL_LINK) -o libtype_cairo.la $(CAIRO_OBJ:.o=.lo) \ -rpath $(libdir)/mlterm \ -module -avoid-version @NO_UNDEFINED_FLAG@ @DEXPORT@ \ $(LIBS) $(CAIRO_LIBS) libtype.a: $(NODL_OBJ) $(LIBTOOL_LINK) -o libtype.a $(NODL_OBJ:.o=.lo) ui_font_ft.o: ui_font_ft.c $(LIBTOOL_CC) @TYPE_CFLAGS@ -c $< .SUFFIXES: .c .o .c.o: $(LIBTOOL_CC) -c $< install : $(LIBDIR) if test "$(TYPE_LIBS)" != "" ; then \ $(LIBTOOL_INSTALL) $(TYPE_LIBS) $(LIBDIR) ; \ fi uninstall : rm -f $(LIBDIR)/*type_* $(LIBDIR) : mkdir -p $(LIBDIR) wc : find . -name "*.[ch]" -a \! -name "test_*" | xargs wc -l clean: rm -rf $(TYPE_LIBS) $(XFT_OBJ) $(XFT_OBJ:.o=.lo) \ $(CAIRO_OBJ) $(CAIRO_OBJ:.o=.lo) ui_font_ft.o ui_font_ft.lo .libs distclean: clean rm -f Makefile libfc_wrapper.la: fc_wrapper.o $(LIBTOOL_LINK) -o libfc_wrapper.la fc_wrapper.lo -rpath $(libdir)/mlterm \ -module -avoid-version `pkg-config freetype2 --libs` install_fc_wrapper : $(LIBDIR) $(LIBTOOL_INSTALL) libfc_wrapper.la $(LIBDIR) mlterm-3.8.9/uitoolkit/quartz004075500017600000144000000000001356600660700150375ustar kenusersmlterm-3.8.9/uitoolkit/quartz/ui_event_source-cocoa.m010064400017600000144000000074441356600660700215620ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_event_source.h" #ifdef COCOA_TOUCH #import #else #import #endif #include #include #include #include #include #include #include "../ui_display.h" /* --- static variables --- */ static struct { int fd; void (*handler)(void); } * additional_fds; static u_int num_additional_fds; /* --- global functions --- */ void ui_event_source_init(void) {} void ui_event_source_final(void) {} int ui_event_source_process(void) { static int ret = -1; static fd_set read_fds; static int maxfd; static int is_cont_read; static struct timeval tval; for (;;) { tval.tv_usec = 100000; /* 0.1 sec */ tval.tv_sec = 0; dispatch_sync(dispatch_get_main_queue(), ^{ vt_close_dead_terms(); vt_term_t **terms; u_int num_terms = vt_get_all_terms(&terms); int count; int ptyfd; if (ret > 0) { for (count = 0; count < num_additional_fds; count++) { if (additional_fds[count].fd < 0) { (*additional_fds[count].handler)(); } } for (count = 0; count < num_terms; count++) { if ((ptyfd = vt_term_get_master_fd(terms[count])) >= 0 && FD_ISSET(ptyfd, &read_fds)) { vt_term_parse_vt100_sequence(terms[count]); } } if (++is_cont_read >= 2) { [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; } } else if (ret == 0) { ui_display_idling(NULL); is_cont_read = 0; } FD_ZERO(&read_fds); maxfd = -1; for (count = 0; count < num_terms; count++) { if ((ptyfd = vt_term_get_master_fd(terms[count])) >= 0) { FD_SET(ptyfd, &read_fds); if (ptyfd > maxfd) { maxfd = ptyfd; } if (vt_term_is_sending_data(terms[count])) { tval.tv_usec = 0; vt_term_parse_vt100_sequence(terms[count]); } } } for (count = 0; count < num_additional_fds; count++) { if (additional_fds[count].fd >= 0) { FD_SET(additional_fds[count].fd, &read_fds); if (additional_fds[count].fd > maxfd) { maxfd = additional_fds[count].fd; } } } }); if (maxfd == -1 || ((ret = select(maxfd + 1, &read_fds, NULL, NULL, &tval)) < 0 && errno != EAGAIN && errno != EINTR && errno != EBADF /* vt_pty_{ssh|mosh}_set_use_loopback() can cause EBADF */)) { break; } } return 1; } /* * fd >= 0 -> Normal file descriptor. handler is invoked if fd is ready. * fd < 0 -> Special ID. handler is invoked at interval of 0.1 sec. */ int ui_event_source_add_fd(int fd, void (*handler)(void)) { void *p; if (!handler) { return 0; } if ((p = realloc(additional_fds, sizeof(*additional_fds) * (num_additional_fds + 1))) == NULL) { return 0; } additional_fds = p; additional_fds[num_additional_fds].fd = fd; additional_fds[num_additional_fds++].handler = handler; if (fd >= 0) { bl_file_set_cloexec(fd); } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " %d is added to additional fds.\n", fd); #endif return 1; } void ui_event_source_remove_fd(int fd) { u_int count; for (count = 0; count < num_additional_fds; count++) { if (additional_fds[count].fd == fd) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Additional fd %d is removed.\n", fd); #endif additional_fds[count] = additional_fds[--num_additional_fds]; return; } } } mlterm-3.8.9/uitoolkit/quartz/cocoa.m010064400017600000144000001277531356600660700163740ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #import #include "ui_window.h" #include "ui_scrollbar.h" #include #include /* bl_getuid/bl_getgid */ #include #include /* bl_compare_str */ #include "../ui_screen_manager.h" /* ui_mlclient */ #include "../ui_event_source.h" #include "../ui_selection_encoding.h" /* XXX USE_CGLAYER is defined if 10.14 Mojave or later for now. */ #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101400 #define USE_CGLAYER #endif @interface MLTermView : NSView { ui_window_t *uiwindow; CGContextRef ctx; #ifdef USE_CGLAYER CGLayerRef layer; #endif int forceExpose; /* 2 = visual bell */ BOOL ignoreKeyDown; NSString *markedText; int currentShiftMask; NSRange markedRange; NSRange selectedRange; int cand_x; int cand_y; } - (void)drawString:(ui_font_t *)font :(ui_color_t *)fg_color :(int)x :(int)y :(u_char *)str :(size_t)len; - (void)drawString16:(ui_font_t *)font :(ui_color_t *)fg_color :(int)x :(int)y :(XChar2b *)str :(size_t)len; - (void)fillWith:(ui_color_t *)color:(int)x:(int)y:(u_int)width:(u_int)height; - (void)drawRectFrame:(ui_color_t *)color:(int)x1:(int)y1:(int)x2:(int)y2; - (void)copyArea:(Pixmap)src :(int)src_x :(int)src_y :(u_int)width :(u_int)height :(int)dst_x :(int)dst_y; #if 0 - (void)scroll:(int)src_x:(int)src_y:(u_int)width:(u_int)height:(int)dst_x:(int)dst_y; #endif - (void)setClip:(int)x:(int)y:(u_int)width:(u_int)height; - (void)unsetClip; - (void)update:(int)flag; - (void)bgColorChanged; @end @interface MLSecureTextField : NSSecureTextField @end /* --- static variables --- */ static ui_window_t *uiwindow_for_mlterm_view; static NSMenuItem *configMenuItem; static NSMenuItem *pasteMenuItem; char *global_args; /* --- static functions --- */ #define set_fill_color(color) \ CGContextSetRGBFillColor(ctx, (((color)->pixel >> 16) & 0xff) / 255.0, \ (((color)->pixel >> 8) & 0xff) / 255.0, \ ((color)->pixel & 0xff) / 255.0, 1.0); #define IS_OPAQUE \ ((uiwindow->bg_color.pixel & 0xff000000) == 0xff000000 || \ ui_window_has_wall_picture(uiwindow)) static void exit_program(void) { /* This function is called twice from willClose() and monitor_pty() */ static int exited; if (!exited) { exited = 1; #ifdef DEBUG main_loop_final(); bl_alloca_garbage_collect(); bl_mem_free_all(); bl_dl_close_all(); #endif [[NSApplication sharedApplication] terminate:nil]; } } static void monitor_pty(void) { #if 0 /* normal user (Don't call before NSApplicationMain()) */ bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); #endif dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ ui_event_source_process(); /* See ui_event_source-cocoa.m */ dispatch_sync(dispatch_get_main_queue(), ^{ exit_program(); }); }); } /* Undocumented */ bool CGFontGetGlyphsForUnichars(CGFontRef, unichar[], CGGlyph[], size_t); static void drawUnistr(CGContextRef ctx, ui_font_t *font, unichar *str, u_int len, int x, int y) { CGGlyph glyphs_buf[len]; CGGlyph *glyphs; #ifdef USE_OT_LAYOUT if (font->use_ot_layout /* && font->otf */) { glyphs = str; } else #endif { glyphs = memset(glyphs_buf, 0, sizeof(CGGlyph) * len); CGFontGetGlyphsForUnichars(font->xfont->cg_font, str, glyphs_buf, len); for (; len > 0 && glyphs[len - 1] == 0; len--) ; } CGContextSetFont(ctx, font->xfont->cg_font); CGAffineTransform t; if (font->xfont->is_italic) { CGFloat f = -tanf(-12.0 * acosf(0) / 90); t = CGAffineTransformMake(1.0, 0.0, f, 1.0, -y * f, 0.0); } else { t = CGAffineTransformIdentity; } u_int width = font->width; u_int fontsize = font->xfont->size; switch (font->size_attr) { case DOUBLE_WIDTH: width /= 2; x = (x + 1) / 2; t = CGAffineTransformScale(t, 2.0, 1.0); break; case DOUBLE_HEIGHT_TOP: case DOUBLE_HEIGHT_BOTTOM: fontsize *= 2; break; } CGContextSetTextMatrix(ctx, t); CGPoint points[len]; if (font->is_proportional) { int advances[len]; if (!CGFontGetGlyphAdvances(font->xfont->cg_font, glyphs, len, advances)) { return; } int units = CGFontGetUnitsPerEm(font->xfont->cg_font); int cur_x = x; u_int count; for (count = 0; count < len; count++) { points[count] = CGPointMake(cur_x, y); if (advances[count] > 0) { cur_x += (advances[count] * fontsize / units); } } } else { u_int count; x += font->x_off; for (count = 0; count < len; count++) { points[count] = CGPointMake((x + width * count), y); } } CGContextSetFontSize(ctx, fontsize); CGContextShowGlyphsAtPositions(ctx, glyphs, points, len); if (font->double_draw_gap) { int gap = font->double_draw_gap; font->double_draw_gap = 0; drawUnistr(ctx, font, str, len, x + font->double_draw_gap, y); font->double_draw_gap = gap; } } static void update_ime_text(ui_window_t *uiwindow, const char *preedit_text, const char *cur_preedit_text) { (*uiwindow->preedit)(uiwindow, preedit_text, cur_preedit_text); } static void remove_all_observers(ui_window_t *uiwindow) { u_int count; for (count = 0; count < uiwindow->num_children; count++) { [[NSNotificationCenter defaultCenter] removeObserver:uiwindow->children[count]->my_window]; remove_all_observers(uiwindow->children[count]); } } static NSAlert *create_dialog(const char *msg, int has_cancel) { if (![NSThread isMainThread]) { return nil; } NSAlert *alert = [[NSAlert alloc] init]; [alert autorelease]; NSString *ns_msg = [NSString stringWithCString:msg encoding:NSUTF8StringEncoding]; [alert setMessageText:ns_msg]; [alert addButtonWithTitle:@"OK"]; /* First */ if (has_cancel) { [alert addButtonWithTitle:@"Cancel"]; /* Second */ } return alert; } /* --- class --- */ int cocoa_dialog_alert(const char *msg); @implementation MLTermView - (id)initWithFrame:(NSRect)frame { if (uiwindow_for_mlterm_view) { uiwindow = uiwindow_for_mlterm_view; } else { if (global_args) { char *args; if ((args = alloca(strlen(global_args) + 1))) { ui_mlclient(strcpy(args, global_args), NULL); } } else { char args[] = "mlclient"; ui_mlclient(args, NULL); } ui_screen_t **screens; u_int num = ui_get_all_screens(&screens); if (num == 0) { cocoa_dialog_alert("Failed to open screen"); exit(1); } uiwindow = &screens[num - 1]->window; } uiwindow->my_window = (NSView *)self; forceExpose = 1; [super initWithFrame:frame]; [self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]]; ignoreKeyDown = FALSE; markedText = nil; markedRange = NSMakeRange(NSNotFound, 0); selectedRange = NSMakeRange(NSNotFound, 0); if (uiwindow_for_mlterm_view) { uiwindow_for_mlterm_view = NULL; } if (!configMenuItem) { monitor_pty(); #if 1 [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent *event) { switch (event.keyCode) { case 0x66: /* Eisu */ case 0x68: /* Kana */ ignoreKeyDown = TRUE; } [event.window.firstResponder keyDown:event]; return (NSEvent *)nil; }]; #endif /* for mlconfig */ setenv("PANGO_LIBDIR", [[[NSBundle mainBundle] bundlePath] UTF8String], 1); NSMenu *appmenu = [[NSMenu alloc] initWithTitle:@""]; configMenuItem = [appmenu addItemWithTitle:@"Config" action:@selector(configMenu:) keyEquivalent:@"C"]; pasteMenuItem = [appmenu addItemWithTitle:@"Paste" action:@selector(pasteMenu:) keyEquivalent:@"P"]; [configMenuItem setTarget:self]; [pasteMenuItem setTarget:self]; NSMenu *menu = [[NSMenu alloc] initWithTitle:@""]; [[menu addItemWithTitle:@"" action:nil keyEquivalent:@""] setSubmenu:appmenu]; [[NSApplication sharedApplication] setMainMenu:menu]; } return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; #ifdef USE_CGLAYER if (layer) { CGLayerRelease(layer); layer = nil; } #endif [super dealloc]; } - (void)configMenu:(id)sender { /* if by any change */ if (((ui_screen_t *)uiwindow)->term) { ui_screen_exec_cmd((ui_screen_t *)uiwindow, "mlconfig"); } } - (void)pasteMenu:(id)sender { /* if by any change */ if (((ui_screen_t *)uiwindow)->term) { ui_screen_exec_cmd((ui_screen_t *)uiwindow, "paste"); } } #ifdef USE_CGLAYER - (void)setFrameSize:(NSSize)s { if (layer) { CGLayerRelease(layer); layer = nil; } [super setFrameSize:s]; } #endif static void reset_position(ui_window_t *uiwindow) { u_int count; for (count = 0; count < uiwindow->num_children; count++) { ui_window_t *child = uiwindow->children[count]; [((NSView *)child->my_window) setFrame:NSMakeRect(child->x, ((int)ACTUAL_HEIGHT(uiwindow)) - ((int)ACTUAL_HEIGHT(child)) - child->y, ACTUAL_WIDTH(child), ACTUAL_HEIGHT(child))]; reset_position(child); } } - (void)resized:(NSNotification *)note { if (!uiwindow->parent || !((ui_screen_t *)uiwindow)->term) { /* It has been already removed from ui_layout or term has been detached. */ return; } uiwindow->parent->width = ((NSView *)[self window].contentView).frame.size.width - uiwindow->parent->hmargin * 2; uiwindow->parent->height = ((NSView *)[self window].contentView).frame.size.height - uiwindow->parent->vmargin * 2; (*uiwindow->parent->window_resized)(uiwindow->parent); reset_position(uiwindow->parent); } - (void)viewDidMoveToWindow { if ([self window] == nil) { /* just before being deallocated */ return; } struct terminal *term = ((ui_screen_t *)uiwindow)->screen_scroll_listener->self; if (!uiwindow->parent->my_window) { [[self window] orderOut:self]; if (uiwindow->event_mask & PointerMotionMask) { [self window].acceptsMouseMovedEvents = YES; } } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resized:) name:NSViewFrameDidChangeNotification object:[self window].contentView]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(focused:) name:NSWindowDidBecomeMainNotification object:[self window]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(unfocused:) name:NSWindowDidResignMainNotification object:[self window]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willClose:) name:NSWindowWillCloseNotification object:[self window]]; int diff_x = [self window].frame.size.width - self.frame.size.width; int diff_y = [self window].frame.size.height - self.frame.size.height; u_int sb_width = [NSScroller scrollerWidth]; int y = ACTUAL_HEIGHT(uiwindow->parent) - ACTUAL_HEIGHT(uiwindow) - uiwindow->y; /* Change view size */ self.frame = CGRectMake(uiwindow->x, y, ACTUAL_WIDTH(uiwindow), ACTUAL_HEIGHT(uiwindow)); /* Creating scrollbar */ CGRect r = CGRectMake(term->scrollbar.window.x, y, sb_width, ACTUAL_HEIGHT(uiwindow)); NSScroller *scroller = [[NSScroller alloc] initWithFrame:r]; [scroller setEnabled:YES]; [scroller setTarget:self]; [scroller setAction:@selector(scrollerAction:)]; #if 1 [scroller setFloatValue:0.0 knobProportion:1.0]; /* Deprecated since 10.6 */ #else scroller.knobProportion = 1.0; scroller.doubleValue = 0.0; #endif #if 0 [scroller setArrowsPosition:NSScrollerArrowsMaxEnd]; #endif [[self window].contentView addSubview:scroller]; term->scrollbar.window.my_window = (NSView *)scroller; if (term->sb_mode != SBM_NONE) { uiwindow->parent->width = uiwindow->parent->width + sb_width - term->scrollbar.window.width; } else { [scroller setHidden:YES]; } term->scrollbar.window.width = sb_width; /* Change window size */ if (!uiwindow->parent->my_window) { [[self window] useOptimizedDrawing:YES]; #if 0 [[self window] allowsConcurrentViewDrawing:YES]; #endif uiwindow->parent->my_window = [self window]; r = [self window].frame; r.size.width = ACTUAL_WIDTH(uiwindow->parent) + diff_x; float new_height = ACTUAL_HEIGHT(uiwindow->parent) + diff_y; r.origin.y += (r.size.height - new_height); r.size.height = new_height; [[self window] setResizeIncrements:NSMakeSize(uiwindow->width_inc, uiwindow->height_inc)]; [[self window] setFrame:r display:NO]; if (!IS_OPAQUE) { [self bgColorChanged]; } [[self window] makeKeyAndOrderFront:self]; /* * Adjust by uiwindow->parent->{x,y} after [window setFrame:r] above adjusted * window position. */ if (uiwindow->parent->x > 0 || uiwindow->parent->y > 0) { r = [self window].frame; r.origin.x += uiwindow->parent->x; r.origin.y -= uiwindow->parent->y; [[self window] setFrame:r display:NO]; } } NSRect sr = [[[self window] screen] visibleFrame]; uiwindow->disp->width = sr.size.width; uiwindow->disp->height = sr.size.height; /* Adjust scroller position */ [scroller setFrameOrigin:NSMakePoint(term->scrollbar.window.x, y)]; } - (void)scrollerAction:(id)sender { struct terminal *term = ((ui_screen_t *)uiwindow)->screen_scroll_listener->self; ui_scrollbar_t *sb = &term->scrollbar; float pos = [sender floatValue]; switch ([sender hitPart]) { case NSScrollerKnob: case NSScrollerKnobSlot: ui_scrollbar_is_moved(sb, pos); break; case NSScrollerDecrementLine: ui_scrollbar_move_upward(sb, 1); (sb->sb_listener->screen_scroll_downward)(sb->sb_listener->self, 1); break; case NSScrollerDecrementPage: ui_scrollbar_move_upward(sb, 10); (sb->sb_listener->screen_scroll_downward)(sb->sb_listener->self, 10); break; case NSScrollerIncrementLine: ui_scrollbar_move_downward(sb, 1); (sb->sb_listener->screen_scroll_upward)(sb->sb_listener->self, 1); break; case NSScrollerIncrementPage: ui_scrollbar_move_downward(sb, 10); (sb->sb_listener->screen_scroll_upward)(sb->sb_listener->self, 10); break; case NSScrollerNoPart: break; } } - (void)drawRect:(NSRect)rect { if (!uiwindow->parent || !((ui_screen_t *)uiwindow)->term) { /* It has been already removed from ui_layout or term has been detached. */ return; } XExposeEvent ev; #ifdef USE_CGLAYER CGContextRef screen_ctx = [[NSGraphicsContext currentContext] graphicsPort]; CGContextSetBlendMode(screen_ctx, kCGBlendModeCopy); #else ctx = [[NSGraphicsContext currentContext] graphicsPort]; #endif #if 0 CGAffineTransform t = CGContextGetCTM(ctx); bl_debug_printf("%f %f %f %f %f %f\n", t.a, t.b, t.c, t.d, t.tx, t.ty); #endif #ifdef USE_CGLAYER if (!layer) { layer = CGLayerCreateWithContext(screen_ctx, self.bounds.size, NULL); ctx = CGLayerGetContext(layer); if (uiwindow->update_window_flag == 0) { uiwindow->update_window_flag = 3; /* UPDATE_SCREEN|UPDATE_CURSOR (ui_screen.c) */ } forceExpose = 1; } CGPoint p = CGPointMake(0, 0); #endif CGContextSetBlendMode(ctx, kCGBlendModeCopy); if (forceExpose & 2) { /* Visual bell */ [self fillWith:&uiwindow->fg_color :uiwindow->hmargin :uiwindow->vmargin :uiwindow->width :uiwindow->height]; CGContextFlush(ctx); #ifdef USE_CGLAYER CGContextDrawLayerAtPoint(screen_ctx, p, layer); #endif [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; forceExpose &= ~2; uiwindow->update_window_flag = 0; } ev.type = UI_EXPOSE; ev.x = rect.origin.x; ev.width = rect.size.width; ev.height = rect.size.height; ev.y = ACTUAL_HEIGHT(uiwindow) - rect.origin.y - ev.height; ev.force_expose = forceExpose; ui_window_receive_event(uiwindow, (XEvent *)&ev); forceExpose = 0; uiwindow->update_window_flag = 0; #ifdef USE_CGLAYER CGContextDrawLayerAtPoint(screen_ctx, p, layer); #endif } - (BOOL)isOpaque { return IS_OPAQUE ? YES : NO; } - (BOOL)wantsDefaultClipping { return IS_OPAQUE ? YES : NO; } static ui_window_t *get_current_window(ui_window_t *win) { u_int count; if (win->inputtable > 0) { return win; } for (count = 0; count < win->num_children; count++) { ui_window_t *hit; if ((hit = get_current_window(win->children[count]))) { return hit; } } return NULL; } - (void)focused:(NSNotification *)note { if (!uiwindow->parent || !((ui_screen_t *)uiwindow)->term) { /* It has been already removed from ui_layout or term has been detached. */ return; } XEvent ev; ev.type = UI_FOCUS_IN; ui_window_receive_event(ui_get_root_window(uiwindow), &ev); ui_window_t *focused; if ((focused = get_current_window(ui_get_root_window(uiwindow)))) { [configMenuItem setTarget:focused->my_window]; [pasteMenuItem setTarget:focused->my_window]; } } - (void)unfocused:(NSNotification *)note { if (!uiwindow->parent || !((ui_screen_t *)uiwindow)->term) { /* It has been already removed from ui_layout or term has been detached. */ return; } XEvent ev; ev.type = UI_FOCUS_OUT; ui_window_receive_event(ui_get_root_window(uiwindow), &ev); } - (BOOL)acceptsFirstResponder { return YES; } - (BOOL)becomeFirstResponder { if ([super becomeFirstResponder] != YES) { return NO; } XEvent ev; ev.type = UI_KEY_FOCUS_IN; ui_window_receive_event(uiwindow, &ev); [configMenuItem setTarget:uiwindow->my_window]; [pasteMenuItem setTarget:uiwindow->my_window]; return YES; } - (void)willClose:(NSNotification *)note { if (ui_get_all_screens(NULL) == 0) { [[NSNotificationCenter defaultCenter] removeObserver:self]; return; } ui_window_t *root = ui_get_root_window(uiwindow); if (root->num_children == 0) { /* * This function can be called if root->num_children == 0 * by window_dealloc() in ui_window.c. */ return; } remove_all_observers(root); XEvent ev; ev.type = UI_CLOSE_WINDOW; ui_window_receive_event(root, &ev); ui_close_dead_screens(); if (ui_get_all_screens(NULL) == 0) { exit_program(); } } - (void)mouseDown:(NSEvent *)event { NSPoint loc = [event locationInWindow]; XButtonEvent bev; bev.type = UI_BUTTON_PRESS; bev.time = event.timestamp * 1000; bev.x = loc.x - self.frame.origin.x; bev.y = ACTUAL_HEIGHT(uiwindow->parent) - loc.y - /* self.frame.origin.y - */ 1; bev.state = event.modifierFlags & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask); if (event.type == NSLeftMouseDown) { bev.button = 1; } else { bev.button = 3; } bev.click_count = event.clickCount; ui_window_receive_event(uiwindow, (XEvent *)&bev); } - (void)mouseUp:(NSEvent *)event { NSPoint loc = [event locationInWindow]; XButtonEvent bev; bev.type = UI_BUTTON_RELEASE; bev.time = event.timestamp * 1000; bev.x = loc.x - self.frame.origin.x; bev.y = ACTUAL_HEIGHT(uiwindow->parent) - loc.y - /* self.frame.origin.y - */ 1; bev.state = event.modifierFlags & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask); if (event.type == NSLeftMouseUp) { bev.button = 1; } else { bev.button = 3; } ui_window_receive_event(uiwindow, (XEvent *)&bev); } - (void)rightMouseUp:(NSEvent *)event { NSPoint loc = [event locationInWindow]; XButtonEvent bev; bev.type = UI_BUTTON_RELEASE; bev.time = event.timestamp * 1000; bev.x = loc.x - self.frame.origin.x; bev.y = ACTUAL_HEIGHT(uiwindow->parent) - loc.y - /* self.frame.origin.y - */ 1; bev.state = event.modifierFlags & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask); bev.button = 3; ui_window_receive_event(uiwindow, (XEvent *)&bev); } - (NSMenu *)menuForEvent:(NSEvent *)event { NSPoint loc = [event locationInWindow]; XButtonEvent bev; bev.type = UI_BUTTON_PRESS; bev.time = event.timestamp * 1000; bev.x = loc.x - self.frame.origin.x; bev.y = ACTUAL_HEIGHT(uiwindow->parent) - loc.y - /* self.frame.origin.y - */ 1; bev.state = event.modifierFlags & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask); bev.button = 3; bev.click_count = event.clickCount; ui_window_receive_event(uiwindow, (XEvent *)&bev); return (NSMenu *)nil; } - (void)mouseDragged:(NSEvent *)event { NSPoint loc = [event locationInWindow]; XMotionEvent mev; mev.type = UI_BUTTON_MOTION; mev.time = event.timestamp * 1000; mev.x = loc.x - self.frame.origin.x; mev.y = ACTUAL_HEIGHT(uiwindow->parent) - loc.y - /* self.frame.origin.y */ -1; if (event.type == NSLeftMouseDragged) { mev.state = Button1Mask; } else { mev.state = Button3Mask; } ui_window_receive_event(uiwindow, (XEvent *)&mev); } - (void)rightMouseDragged:(NSEvent *)event { NSPoint loc = [event locationInWindow]; XMotionEvent mev; mev.type = UI_BUTTON_MOTION; mev.time = event.timestamp * 1000; mev.x = loc.x - self.frame.origin.x; mev.y = ACTUAL_HEIGHT(uiwindow->parent) - loc.y - /* self.frame.origin.y */ -1; mev.state = Button3Mask; ui_window_receive_event(uiwindow, (XEvent *)&mev); } - (void)mouseMoved:(NSEvent *)event { NSPoint loc = [event locationInWindow]; XMotionEvent mev; mev.type = UI_POINTER_MOTION; mev.time = event.timestamp * 1000; mev.x = loc.x - self.frame.origin.x; mev.y = ACTUAL_HEIGHT(uiwindow->parent) - loc.y - /* self.frame.origin.y */ -1; mev.state = 0; ui_window_receive_event(uiwindow, (XEvent *)&mev); } - (void)scrollWheel:(NSEvent *)event { NSPoint loc = [event locationInWindow]; XButtonEvent bevPress; XButtonEvent bevRelease; bevPress.type = UI_BUTTON_PRESS; bevRelease.type = UI_BUTTON_RELEASE; bevPress.time = event.timestamp * 1000; bevRelease.time = (event.timestamp * 1000) + 1; bevPress.x = loc.x - self.frame.origin.x; bevRelease.x = loc.x - self.frame.origin.x; bevPress.y = ACTUAL_HEIGHT(uiwindow->parent) - loc.y - /* self.frame.origin.y - */ 1; bevRelease.y = ACTUAL_HEIGHT(uiwindow->parent) - loc.y - /* self.frame.origin.y - */ 1; bevPress.state = event.modifierFlags & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask); bevRelease.state = event.modifierFlags & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask); bevPress.click_count = 1; if (event.deltaY > 1) { bevPress.button = 4; bevRelease.button = 4; } if (event.deltaY < -1) { bevPress.button = 5; bevRelease.button = 5; } if (event.deltaY < -1 || event.deltaY > 1) { ui_window_receive_event(uiwindow, (XEvent *)&bevPress); ui_window_receive_event(uiwindow, (XEvent *)&bevRelease); } } - (void)keyDown:(NSEvent *)event { if ([event type] == NSFlagsChanged) { return; } u_int flags = event.modifierFlags; /* ShiftMask is not set without this. (see insertText()) */ currentShiftMask = flags & NSShiftKeyMask; NSString *oldMarkedText = markedText; /* Alt+x isn't interpreted unless preediting. */ if (markedText || !(flags & NSAlternateKeyMask) || (flags & NSControlKeyMask)) { [self interpretKeyEvents:[NSArray arrayWithObject:event]]; } if (ignoreKeyDown) { ignoreKeyDown = FALSE; } else if (!oldMarkedText && !markedText) { XKeyEvent kev; kev.type = UI_KEY_PRESS; kev.state = flags & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask); if (kev.state & NSControlKeyMask) { kev.keysym = [[event charactersIgnoringModifiers] characterAtIndex:0]; kev.utf8 = [event characters].UTF8String; } else if (kev.state & NSAlternateKeyMask) { kev.keysym = [[event charactersIgnoringModifiers] characterAtIndex:0]; kev.utf8 = NULL; } else { kev.keysym = [[event characters] characterAtIndex:0]; kev.utf8 = [event characters].UTF8String; } if ((kev.state & NSShiftKeyMask) && 'A' <= kev.keysym && kev.keysym <= 'Z') { kev.keysym += 0x20; } ui_window_receive_event(uiwindow, (XEvent *)&kev); } } #if 0 - (BOOL)_wantsKeyDownForEvent:(id)event { return YES; } #endif - (void)pasteboard:(NSPasteboard *)sender provideDataForType:(NSString *)type { /* * If this view exits with owning pasteboard, this method is called * after ui_screen_t::term is deleted. */ if (((ui_screen_t *)uiwindow)->term) { XSelectionRequestEvent ev; ev.type = UI_SELECTION_REQUESTED; ev.sender = sender; ui_window_receive_event(uiwindow, (XEvent *)&ev); } } - (NSDragOperation)draggingEntered:(id)sender { NSPasteboard *pboard = [sender draggingPasteboard]; if ([[pboard types] containsObject:NSFilenamesPboardType]) { #ifdef __DEBUG NSDragOperation sourceMask = [sender draggingSourceOperationMask]; bl_debug_printf("draggingEntered SourceMask %d\n", sourceMask); #endif return NSDragOperationGeneric; } return NSDragOperationNone; } - (BOOL)performDragOperation:(id)sender { NSPasteboard *pboard = [sender draggingPasteboard]; if ([[pboard types] containsObject:NSFilenamesPboardType]) { NSDragOperation sourceMask = [sender draggingSourceOperationMask]; NSArray *files = [pboard propertyListForType:NSFilenamesPboardType]; int count; #ifdef __DEBUG bl_debug_printf("performDragOperation SourceMask %d\n", sourceMask); #endif if (sourceMask == NSDragOperationGeneric /* Command */ && uiwindow->set_xdnd_config) { for (count = 0; count < [files count]; count++) { (*uiwindow->set_xdnd_config)(uiwindow, NULL, "scp", [[files objectAtIndex:count] UTF8String]); } } else { XSelectionNotifyEvent ev; ev.type = UI_SELECTION_NOTIFIED; for (count = 0; count < [files count]; count++) { ev.data = [[files objectAtIndex:count] UTF8String]; ev.len = strlen(ev.data); ui_window_receive_event(uiwindow, (XEvent *)&ev); } } } return YES; } - (NSUInteger)characterIndexForPoint:(NSPoint)point { return 0; } - (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange { int x = cand_x + uiwindow->x + uiwindow->hmargin; int y = ACTUAL_HEIGHT(uiwindow->parent) - (cand_y + uiwindow->y + uiwindow->vmargin); if (vt_term_get_vertical_mode(((ui_screen_t*)uiwindow)->term)) { /* * XXX Adjust candidate window position. * * +-+-+------ * | |1|ABCDE * * <-->^ * 25 x */ x += 25; } NSRect r = NSMakeRect(x, y, ui_col_width((ui_screen_t *)uiwindow), ui_line_height((ui_screen_t *)uiwindow)); r.origin = [[self window] convertBaseToScreen:r.origin]; return r; } - (NSArray *)validAttributesForMarkedText { return nil; } - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)range actualRange:(NSRangePointer) actualRange { return nil; } - (BOOL)hasMarkedText { if (markedText) { return YES; } else { return NO; } } - (NSRange)markedRange { return markedRange; } - (NSRange)selectedRange { return selectedRange; } - (void)unmarkText { [markedText release]; markedText = nil; update_ime_text(uiwindow, "", NULL); } - (void)setMarkedText:(id)string selectedRange:(NSRange)selected replacementRange:(NSRange)replacement { if ([string isKindOfClass:[NSAttributedString class]]) { string = [string string]; } selectedRange = selected; if ([string length] > 0) { char *p; if (!(p = alloca(strlen([string UTF8String]) + 10))) { return; } *p = '\0'; if (selectedRange.location > 0) { strcpy(p, [[string substringWithRange: NSMakeRange(0, selectedRange.location)] UTF8String]); } if (selectedRange.length > 0) { sprintf(p + strlen(p), "\x1b[7m%s\x1b[27m", [[string substringWithRange:selectedRange] UTF8String]); } if (selectedRange.location + selectedRange.length < [string length]) { strcat(p, [[string substringWithRange: NSMakeRange( selectedRange.location + selectedRange.length, [string length] - selectedRange.location - selectedRange.length)] UTF8String]); } if (!markedText) { if (!uiwindow->xim_listener || !(*uiwindow->xim_listener->get_spot)(uiwindow->xim_listener->self, &cand_x, &cand_y)) { cand_x = cand_y = 0; } } update_ime_text(uiwindow, p, markedText ? markedText.UTF8String : NULL); } else if (markedText) { update_ime_text(uiwindow, "", markedText.UTF8String); } if (markedText) { [markedText release]; markedText = nil; } if ([string length] > 0) { markedText = [string copy]; markedRange = NSMakeRange(0, [string length]); } else { markedRange = NSMakeRange(NSNotFound, 0); } } - (void)doCommandBySelector:(SEL)selector { } - (void)insertText:(id)string replacementRange:(NSRange)replacementRange { [self unmarkText]; if ([string length] > 0) { XKeyEvent kev; kev.type = UI_KEY_PRESS; kev.state = currentShiftMask; kev.keysym = 0; kev.utf8 = [string UTF8String]; ui_window_receive_event(uiwindow, (XEvent *)&kev); ignoreKeyDown = TRUE; } } - (void)drawString:(ui_font_t *)font :(ui_color_t *)fg_color :(int)x :(int)y :(u_char *)str :(size_t)len { set_fill_color(fg_color); #if 0 u_char *p = alloca(len + 1); memcpy(p, str, len); p[len] = '\0'; bl_debug_printf("%d %d %s %x\n", x, y, p, p[len - 1]); #endif #if 0 CGContextSelectFont(ctx, "Menlo", 16, kCGEncodingMacRoman); CGContextShowTextAtPoint(ctx, x, ACTUAL_HEIGHT(uiwindow) - y - 1, str, len); #else unichar ustr[len]; int count; for (count = 0; count < len; count++) { ustr[count] = str[count]; } drawUnistr(ctx, font, ustr, len, x, ACTUAL_HEIGHT(uiwindow) - y - 1); #endif } - (void)drawString16:(ui_font_t *)font :(ui_color_t *)fg_color :(int)x :(int)y :(XChar2b *)str :(size_t)len { set_fill_color(fg_color); drawUnistr(ctx, font, (unichar *)str, len, x, ACTUAL_HEIGHT(uiwindow) - y - 1); } - (void)fillWith:(ui_color_t *)color:(int)x:(int)y:(u_int)width:(u_int)height { #if 0 static int count = 0; color->pixel += (0x10 * (count++)); #endif CGFloat alpha; if (IS_OPAQUE) { alpha = 1.0; } else { alpha = (((color)->pixel >> 24) & 0xff) / 255.0; } CGContextSetRGBFillColor(ctx, (((color)->pixel >> 16) & 0xff) / 255.0, (((color)->pixel >> 8) & 0xff) / 255.0, ((color)->pixel & 0xff) / 255.0, alpha); CGRect rect = CGRectMake(x, ACTUAL_HEIGHT(uiwindow) - y - height, width, height); CGContextAddRect(ctx, rect); CGContextFillPath(ctx); } - (void)drawRectFrame:(ui_color_t *)color:(int)x1:(int)y1:(int)x2:(int)y2 { set_fill_color(color); CGRect rect = CGRectMake(x1, ACTUAL_HEIGHT(uiwindow) - y2 - 1, 1, y2 - y1); CGContextAddRect(ctx, rect); rect = CGRectMake(x1, ACTUAL_HEIGHT(uiwindow) - y2 - 1, x2 - x1, 1); CGContextAddRect(ctx, rect); rect = CGRectMake(x2, ACTUAL_HEIGHT(uiwindow) - y2 - 1, 1, y2 - y1); CGContextAddRect(ctx, rect); rect = CGRectMake(x1, ACTUAL_HEIGHT(uiwindow) - y1 - 1, x2 - x1 + 1, 1); CGContextAddRect(ctx, rect); CGContextFillPath(ctx); } - (void)copyArea:(Pixmap)src :(int)src_x :(int)src_y :(u_int)width :(u_int)height :(int)dst_x :(int)dst_y { CGImageRef clipped = CGImageCreateWithImageInRect( src, CGRectMake(src_x, src_y, width, height)); CGContextDrawImage( ctx, CGRectMake(dst_x, ACTUAL_HEIGHT(uiwindow) - dst_y - height, width, height), clipped); CGImageRelease(clipped); } #if 0 - (void)scroll:(int)src_x:(int)src_y:(u_int)width:(u_int)height:(int)dst_x:(int)dst_y { CGContextFlush(ctx); /* Don't release this CGImage */ NSRect src_r = NSMakeRect(src_x, ACTUAL_HEIGHT(uiwindow) - src_y - height, width, height); NSBitmapImageRep *bir = [self bitmapImageRepForCachingDisplayInRect:src_r]; [self cacheDisplayInRect:src_r toBitmapImageRep:bir]; CGImageRef image = bir.CGImage; CGRect dst_r = CGRectMake(dst_x, ACTUAL_HEIGHT(uiwindow) - dst_y - height, width, height); CGContextDrawImage(ctx, dst_r, image); static int i; if (i == 0) { CFURLRef url = [NSURL fileURLWithPath:@"/Users/ken/kallist/log.png"]; CGImageDestinationRef dest = CGImageDestinationCreateWithURL( url, kUTTypePNG, 1, NULL); CGImageDestinationAddImage(dest, image, nil); CGImageDestinationFinalize(dest); CFRelease( dest); i++; } else if (i == 1) { NSImage * nsimage = [[[NSImage alloc]initWithSize:src_r.size] autorelease]; [nsimage addRepresentation:bir]; [[nsimage TIFFRepresentation] writeToFile:@"/Users/ken/kallist/log.tiff" atomically:YES]; i++; } } #endif - (void)update:(int)flag { forceExpose |= flag; if (IS_OPAQUE || forceExpose) { /* * setNeedsDisplay:YES calls drawRect with full screen 'rect'. * But if forceExpose is 0, expose() in ui_window.c ignores it. */ [self setNeedsDisplay:YES]; } else { int x; int y; if (!uiwindow->xim_listener || !(*uiwindow->xim_listener->get_spot)(uiwindow->xim_listener->self, &x, &y)) { x = y = 0; } x += (uiwindow->hmargin); y += (uiwindow->vmargin); [self setNeedsDisplayInRect:NSMakeRect(x, ACTUAL_HEIGHT(uiwindow) - y, 1, 1)]; } } - (void)setClip:(int)x:(int)y:(u_int)width:(u_int)height { CGContextSaveGState(ctx); y = ACTUAL_HEIGHT(uiwindow) - y; CGContextBeginPath(ctx); CGContextMoveToPoint(ctx, x, y); CGContextAddLineToPoint(ctx, x + width, y); CGContextAddLineToPoint(ctx, x + width, y - height); CGContextAddLineToPoint(ctx, x, y - height); CGContextClosePath(ctx); CGContextClip(ctx); } - (void)unsetClip { CGContextRestoreGState(ctx); } - (void)bgColorChanged { if (IS_OPAQUE) { [[self window] setBackgroundColor:[NSColor whiteColor]]; [[self window] setOpaque:YES]; } else { [[self window] setBackgroundColor:[NSColor clearColor]]; [[self window] setOpaque:NO]; } } @end @implementation MLSecureTextField - (void)viewDidMoveToWindow { [super viewDidMoveToWindow]; [self becomeFirstResponder]; } @end /* --- global functions --- */ void view_alloc(ui_window_t *uiwindow) { uiwindow_for_mlterm_view = uiwindow; MLTermView *view = [[MLTermView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]; [((NSWindow *)uiwindow->parent->my_window).contentView addSubview:view]; [view release]; } void view_dealloc(NSView *view) { /* view is also released by this. */ [view removeFromSuperviewWithoutNeedingDisplay]; } void view_update(MLTermView *view, int flag) { [view update:flag]; } void view_set_clip(MLTermView *view, int x, int y, u_int width, u_int height) { [view setClip:x:y:width:height]; } void view_unset_clip(MLTermView *view) { [view unsetClip]; } void view_draw_string(MLTermView *view, ui_font_t *font, ui_color_t *fg_color, int x, int y, char *str, size_t len) { [view drawString:font:fg_color:x:y:str:len]; } void view_draw_string16(MLTermView *view, ui_font_t *font, ui_color_t *fg_color, int x, int y, XChar2b *str, size_t len) { [view drawString16:font:fg_color:x:y:str:len]; } void view_fill_with(MLTermView *view, ui_color_t *color, int x, int y, u_int width, u_int height) { [view fillWith:color:x:y:width:height]; } void view_draw_rect_frame(MLTermView *view, ui_color_t *color, int x1, int y1, int x2, int y2) { [view drawRectFrame:color:x1:y1:x2:y2]; } void view_copy_area(MLTermView *view, Pixmap src, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y) { [view copyArea:src:src_x:src_y:width:height:dst_x:dst_y]; } void view_scroll(MLTermView *view, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y) { #if 0 [view scroll:src_x:src_y:width:height:dst_x:dst_y]; #endif } void view_bg_color_changed(MLTermView *view) { [view bgColorChanged]; } void view_visual_bell(MLTermView *view) { [view update:2]; } void view_set_input_focus(NSView *view) { [[view window] makeFirstResponder:view]; } void view_set_rect(NSView *view, int x, int y, /* The origin is left-botom. */ u_int width, u_int height) { #if 0 /* Scrollbar position is corrupt in spliting screen vertically. */ [view setFrame:NSMakeRect(x,y,width,height)]; #else [view setFrameSize:NSMakeSize(width, height)]; [view setFrameOrigin:NSMakePoint(x, y)]; #endif } void view_set_hidden(NSView *view, int flag) { [view setHidden:flag]; } void window_alloc(ui_window_t *root) { uiwindow_for_mlterm_view = root->children[1]; NSNib *nib = [[NSNib alloc] initWithNibNamed:@"Main" bundle:nil]; [nib instantiateNibWithOwner:nil topLevelObjects:nil]; [nib release]; } void window_dealloc(NSWindow *window) { [window release]; } void window_resize(NSWindow *window, int width, int height) { CGRect wr = window.frame; CGSize vs = ((NSView *)window.contentView).frame.size; int diff_x = wr.size.width - vs.width; int diff_y = wr.size.height - vs.height; wr.origin.y += (vs.height - height); wr.size.width = width + diff_x; wr.size.height = height + diff_y; [window setFrame:wr display:YES]; } void window_move_resize(NSWindow *window, int x, int y, int width, int height) { CGRect wr = window.frame; CGSize vs = ((NSView *)window.contentView).frame.size; int diff_x = wr.size.width - vs.width; int diff_y = wr.size.height - vs.height; wr.origin.y = [[window screen] visibleFrame].size.height - y - height; wr.origin.x = x; wr.size.width = width + diff_x; wr.size.height = height + diff_y; [window setFrame:wr display:YES]; } void window_accepts_mouse_moved_events(NSWindow *window, int accept) { window.acceptsMouseMovedEvents = (accept ? YES : NO); } void window_set_normal_hints(NSWindow *window, u_int width_inc, u_int height_inc) { [window setResizeIncrements:NSMakeSize(width_inc, height_inc)]; } void window_get_position(NSWindow *window, int *x, int *y) { *x = window.frame.origin.x; *y = [[window screen] visibleFrame].size.height - window.frame.origin.y - [window.contentView frame].size.height; } void window_set_title(NSWindow *window, const char *title /* utf8 */) { NSString *ns_title = [NSString stringWithCString:title encoding:NSUTF8StringEncoding]; [window setTitle:ns_title]; } void app_urgent_bell(int on) { if (on) { [[NSApplication sharedApplication] requestUserAttention:NSCriticalRequest]; } else { [[NSApplication sharedApplication] cancelUserAttentionRequest:NSCriticalRequest]; } } void scroller_update(NSScroller *scroller, float pos, float knob) { #if 1 [scroller setFloatValue:pos knobProportion:knob]; /* Deprecated since 10.6 */ #else scroller.knobProportion = knob; scroller.doubleValue = pos; #endif } CGFontRef cocoa_create_font(const char *font_family) { NSString *ns_font_family = [NSString stringWithCString:font_family encoding:NSUTF8StringEncoding]; return CGFontCreateWithFontName(ns_font_family); } #ifdef USE_OT_LAYOUT char *cocoa_get_font_path(CGFontRef cg_font) { CTFontDescriptorRef desc = CTFontDescriptorCreateWithNameAndSize(CGFontCopyFullName(cg_font), 14); CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(desc, kCTFontURLAttribute); const char *urlstr = [((NSString *)CFURLGetString(url))UTF8String]; if (strncmp(urlstr, "file://localhost", 16) == 0) { urlstr += 16; } char *path = strdup(urlstr); CFRelease(url); CFRelease(desc); return path; } #endif /* USE_OT_LAYOUT */ void cocoa_release_font(CGFontRef cg_font) { CFRelease(cg_font); } u_int cocoa_font_get_advance(CGFontRef cg_font, u_int fontsize, int size_attr, unichar *utf16, u_int len, CGGlyph glyph) { if (utf16) { CGFontGetGlyphsForUnichars(cg_font, &utf16, &glyph, 1); } int advance; if (!CGFontGetGlyphAdvances(cg_font, &glyph, 1, &advance) || advance < 0) { return 0; } if (size_attr >= DOUBLE_HEIGHT_TOP) { fontsize *= 2; } return advance * fontsize / CGFontGetUnitsPerEm(cg_font); } void cocoa_clipboard_own(MLTermView *view) { NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; [pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:view]; } void cocoa_clipboard_set(const u_char *utf8, size_t len) { NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; NSString *str = [[NSString alloc] initWithBytes:utf8 length:len encoding:NSUTF8StringEncoding]; [pasteboard setString:str forType:NSPasteboardTypeString]; [str release]; } const char *cocoa_clipboard_get(void) { NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; NSString *available; available = [pasteboard availableTypeFromArray:[NSArray arrayWithObject:NSPasteboardTypeString]]; if ([available isEqualToString:NSPasteboardTypeString]) { NSString *str = [pasteboard stringForType:NSPasteboardTypeString]; if (str != nil) { return [str UTF8String]; } } return NULL; } void cocoa_beep(void) { NSBeep(); } CGImageRef cocoa_load_image(const char *path, u_int *width, u_int *height) { NSString *nspath = [NSString stringWithCString:path encoding:NSUTF8StringEncoding]; NSImage *nsimg = [[NSImage alloc] initWithContentsOfFile:nspath]; if (!nsimg) { return nil; } CGImageRef cgimg = [nsimg CGImageForProposedRect:NULL context:nil hints:nil]; CGImageRetain(cgimg); *width = nsimg.size.width; *height = nsimg.size.height; [nsimg release]; return cgimg; } const char *cocoa_get_bundle_path(void) { return [[[NSBundle mainBundle] bundlePath] UTF8String]; } char *cocoa_dialog_password(const char *msg) { NSAlert *alert = create_dialog(msg, 1); if (alert == nil) { return NULL; } NSTextField *text = [[MLSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)]; [text autorelease]; [alert setAccessoryView:text]; if ([alert runModal] == NSAlertFirstButtonReturn) { return strdup([[text stringValue] UTF8String]); } else { return NULL; } } int cocoa_dialog_okcancel(const char *msg) { NSAlert *alert = create_dialog(msg, 1); if (alert == nil) { return 0; } if ([alert runModal] == NSAlertFirstButtonReturn) { return 1; } else { return 0; } } int cocoa_dialog_alert(const char *msg) { NSAlert *alert = create_dialog(msg, 0); if ([alert runModal] == NSAlertFirstButtonReturn) { return 1; } else { return 0; } } mlterm-3.8.9/uitoolkit/quartz/cocoatouch.m010064400017600000144000001315341356600660700174270ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #import #include "ui_window.h" #include "ui_scrollbar.h" #include #include /* bl_getuid/bl_getgid */ #include #include /* bl_compare_str */ #include "../ui_screen_manager.h" #include "../ui_event_source.h" #include "../ui_selection_encoding.h" @interface Application : UIApplication @end @interface AppDelegate : NSObject { UIWindow *window; } @property (nonatomic, retain) IBOutlet UIWindow *window; @end @interface TextPosition : UITextPosition { int position; } @property (nonatomic) int position; @end @interface TextRange : UITextRange { TextPosition *start; TextPosition *end; } @property (nonatomic, readonly) UITextPosition *start; @property (nonatomic, readonly) UITextPosition *end; @end @interface MLTermView : UIView { ui_window_t *uiwindow; CGContextRef ctx; CGLayerRef layer; int forceExpose; /* 2 = visual bell */ BOOL ignoreKeyDown; NSString *markedText; TextRange *selectedTextRange; TextRange *markedTextRange; int cand_x; int cand_y; NSArray *cmds; } @property (readwrite, copy) UITextRange *selectedTextRange; @property (nonatomic, readonly) UITextRange *markedTextRange; - (void)drawString:(ui_font_t *)font :(ui_color_t *)fg_color :(int)x :(int)y :(u_char *)str :(size_t)len; - (void)drawString16:(ui_font_t *)font :(ui_color_t *)fg_color :(int)x :(int)y :(XChar2b *)str :(size_t)len; - (void)fillWith:(ui_color_t *)color:(int)x:(int)y:(u_int)width:(u_int)height; - (void)drawRectFrame:(ui_color_t *)color:(int)x1:(int)y1:(int)x2:(int)y2; - (void)copyArea:(Pixmap)src :(int)src_x :(int)src_y :(u_int)width :(u_int)height :(int)dst_x :(int)dst_y; #if 0 - (void)scroll:(int)src_x:(int)src_y:(u_int)width:(u_int)height:(int)dst_x:(int)dst_y; #endif - (void)setClip:(int)x:(int)y:(u_int)width:(u_int)height; - (void)unsetClip; - (void)update:(int)flag; - (void)bgColorChanged; @end /* --- static variables --- */ static ui_window_t *uiwindow_for_mlterm_view; static int keyboard_margin; static u_int key_code; static u_int key_mod; /* --- static functions --- */ #define set_fill_color(color) \ CGContextSetRGBFillColor(ctx, (((color)->pixel >> 16) & 0xff) / 255.0, \ (((color)->pixel >> 8) & 0xff) / 255.0, \ ((color)->pixel & 0xff) / 255.0, 1.0); #if 0 #define IS_OPAQUE \ ((uiwindow->bg_color.pixel & 0xff000000) == 0xff000000 || \ ui_window_has_wall_picture(uiwindow)) #else #define IS_OPAQUE 1 #endif #ifdef DEBUG int main_loop_final(void); #endif static void exit_program(void) { #ifdef DEBUG main_loop_final(); bl_alloca_garbage_collect(); bl_mem_free_all(); bl_dl_close_all(); #endif } static void monitor_pty(void) { #if 0 /* normal user (Don't call before UIApplicationMain()) */ bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); #endif dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ ui_event_source_process(); }); } /* Undocumented */ bool CGFontGetGlyphsForUnichars(CGFontRef, unichar[], CGGlyph[], size_t); static void drawUnistr(CGContextRef ctx, ui_font_t *font, unichar *str, u_int len, int x, int y) { CGGlyph glyphs_buf[len]; CGGlyph *glyphs; #ifdef USE_OT_LAYOUT if (font->use_ot_layout /* && font->otf */) { glyphs = str; } else #endif { glyphs = memset(glyphs_buf, 0, sizeof(CGGlyph) * len); CGFontGetGlyphsForUnichars(font->xfont->cg_font, str, glyphs_buf, len); for (; len > 0 && glyphs[len - 1] == 0; len--) ; } CGContextSetFont(ctx, font->xfont->cg_font); CGAffineTransform t; if (font->xfont->is_italic) { CGFloat f = -tanf(-12.0 * acosf(0) / 90); t = CGAffineTransformMake(1.0, 0.0, f, 1.0, -y * f, 0.0); } else { t = CGAffineTransformIdentity; } u_int width = font->width; u_int fontsize = font->xfont->size; switch (font->size_attr) { case DOUBLE_WIDTH: width /= 2; x = (x + 1) / 2; t = CGAffineTransformScale(t, 2.0, 1.0); break; case DOUBLE_HEIGHT_TOP: case DOUBLE_HEIGHT_BOTTOM: fontsize *= 2; break; } CGContextSetTextMatrix(ctx, t); CGPoint points[len]; if (font->is_proportional) { int advances[len]; if (!CGFontGetGlyphAdvances(font->xfont->cg_font, glyphs, len, advances)) { return; } int units = CGFontGetUnitsPerEm(font->xfont->cg_font); int cur_x = x; u_int count; for (count = 0; count < len; count++) { points[count] = CGPointMake(cur_x, y); if (advances[count] > 0) { cur_x += (advances[count] * fontsize / units); } } } else { u_int count; x += font->x_off; for (count = 0; count < len; count++) { points[count] = CGPointMake((x + width * count), y); } } CGContextSetFontSize(ctx, fontsize); CGContextShowGlyphsAtPositions(ctx, glyphs, points, len); if (font->double_draw_gap) { int gap = font->double_draw_gap; font->double_draw_gap = 0; drawUnistr(ctx, font, str, len, x + font->double_draw_gap, y); font->double_draw_gap = gap; } } static void update_ime_text(ui_window_t *uiwindow, const char *preedit_text, const char *cur_preedit_text) { (*uiwindow->preedit)(uiwindow, preedit_text, cur_preedit_text); } static void show_dialog(const char *msg) { if (![NSThread isMainThread]) { return; } NSString *ns_msg = [NSString stringWithCString:msg encoding:NSUTF8StringEncoding]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:ns_msg delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil]; [alert autorelease]; [alert show]; /* XXX This doesn't stop. */ } static ui_window_t *search_focused_window(ui_window_t *win) { u_int count; ui_window_t *focused; /* * *parent* - *child* * ^^^^^^^ => Hit this window instead of the parent window. * - child * - child * (**: is_focused == 1) */ for (count = 0; count < win->num_children; count++) { if ((focused = search_focused_window(win->children[count]))) { return focused; } } if (win->is_focused) { return win; } return NULL; } /* --- class --- */ int cocoa_dialog_alert(const char *msg); @implementation Application - (void)sendEvent:(UIEvent *)event { [super sendEvent:event]; if ([event respondsToSelector:@selector(_gsEvent)]) { u_int32_t *buf = [event performSelector:@selector(_gsEvent)]; if (buf && buf[2] == 10 /* Event type */) { u_int num; ui_display_t **disps = ui_get_opened_displays(&num); ui_window_t *win = search_focused_window(disps[0]->roots[0]); if (win) { MLTermView *view = win->my_window; if (![view hasText]) { key_mod = buf[12]; key_code = (buf[15] >> 16) & 0xffff; [self sendAction:@selector(keyEvent) to:view from:nil forEvent:nil]; } } } } } @end @implementation AppDelegate @synthesize window; #pragma mark - #pragma mark Application lifecycle - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; [self.window makeKeyAndVisible]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil]; CGRect r = [self.window screen].applicationFrame; MLTermView *view = [[MLTermView alloc] initWithFrame:CGRectMake(0, 0, r.size.width, r.size.height)]; [self.window addSubview:view]; [self.window makeKeyAndVisible]; return YES; } - (void)keyboardDidShow:(NSNotification *)note { CGRect r = [[[note userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; keyboard_margin = r.size.height; self.window.frame = self.window.frame; /* call observeValueForKeyPath */ } - (void)keyboardDidHide:(NSNotification *)note { keyboard_margin = 0; self.window.frame = self.window.frame; } - (void)applicationWillResignActive:(UIApplication *)application { } - (void)applicationDidEnterBackground:(UIApplication *)application { } - (void)applicationWillEnterForeground:(UIApplication *)application { } - (void)applicationDidBecomeActive:(UIApplication *)application { } - (void)applicationWillTerminate:(UIApplication *)application { } #pragma mark - #pragma mark Memory management - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; exit_program(); [super dealloc]; } @end @implementation TextPosition @synthesize position; @end @implementation TextRange @synthesize start; @synthesize end; - (id)init { [super init]; start = [TextPosition alloc]; end = [TextPosition alloc]; return self; } - (void)dealloc { [super dealloc]; [start release]; [end release]; } @end @implementation MLTermView @synthesize selectedTextRange; @synthesize markedTextRange; @synthesize tokenizer; @synthesize inputDelegate; @synthesize endOfDocument; @synthesize beginningOfDocument; @synthesize markedTextStyle; - (id)initWithFrame:(CGRect)frame { if (uiwindow_for_mlterm_view) { uiwindow = uiwindow_for_mlterm_view; } else { char args[] = "mlclient"; ui_mlclient(args, NULL); ui_screen_t **screens; u_int num = ui_get_all_screens(&screens); if (num == 0) { cocoa_dialog_alert("Failed to open screen"); exit(1); } uiwindow = &screens[num - 1]->window; } uiwindow->my_window = (UIView *)self; forceExpose = 1; self.clearsContextBeforeDrawing = NO; [super initWithFrame:frame]; ignoreKeyDown = FALSE; markedText = nil; markedTextRange = [UITextRange alloc]; selectedTextRange = [UITextRange alloc]; UILongPressGestureRecognizer *longpress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)]; longpress.minimumPressDuration = 2.0; [longpress autorelease]; [self addGestureRecognizer:longpress]; if (uiwindow_for_mlterm_view) { uiwindow_for_mlterm_view = NULL; } static int app_init; if (!app_init) { app_init = 1; monitor_pty(); } return self; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [self.window removeObserver:self forKeyPath:@"frame"]; [markedTextRange release]; [selectedTextRange release]; if (layer) { CGLayerRelease(layer); layer = nil; } if (cmds) { [cmds release]; } [super dealloc]; } - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (action == @selector(configMenu:) || action == @selector(pasteMenu:) || action == @selector(keyEvent:)) { return YES; } else { return NO; } } - (void)configMenu:(id)sender { cocoa_dialog_alert("Configuration menu is not supported."); } - (void)pasteMenu:(id)sender { /* if by any change */ if (((ui_screen_t *)uiwindow)->term) { ui_screen_exec_cmd((ui_screen_t *)uiwindow, "paste"); } } - (void)setFrame:(CGRect)r { if (layer) { CGLayerRelease(layer); layer = nil; } CGRect sr = [self.window screen].applicationFrame; r.origin.x += sr.origin.x; r.origin.y += sr.origin.y; #if 0 NSLog(@"setFrame %@ %f %f %f %f", self, r.origin.x, r.origin.y, r.size.width, r.size.height); #endif [super setFrame:r]; } - (void)windowResized { if (!uiwindow->parent || !((ui_screen_t *)uiwindow)->term) { /* It has been already removed from ui_layout or term has been detached. */ return; } CGRect sr = [self.window screen].applicationFrame; uiwindow->parent->width = sr.size.width - uiwindow->parent->hmargin * 2; uiwindow->parent->height = sr.size.height - uiwindow->parent->vmargin * 2 - keyboard_margin; (*uiwindow->parent->window_resized)(uiwindow->parent); u_int count; for (count = 0; count < uiwindow->num_children; count++) { ui_window_t *child = uiwindow->children[count]; if (child->my_window) { [((UIView *)child->my_window) setFrame:CGRectMake(child->x, child->y, ACTUAL_WIDTH(child), ACTUAL_HEIGHT(child))]; } } } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { [self windowResized]; } - (void)didMoveToWindow { if ([self window] == nil) { /* just before being deallocated */ return; } #if 0 if (!uiwindow->parent->my_window) { [[self window] orderOut:self]; if (uiwindow->event_mask & PointerMotionMask) { [self window].acceptsMouseMovedEvents = YES; } } #endif [self.window addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil]; /* Change view size */ if (!uiwindow->parent->my_window) { CGRect sr = [self.window screen].applicationFrame; uiwindow->disp->width = sr.size.width; uiwindow->disp->height = sr.size.height; #if 0 [[self window] useOptimizedDrawing:YES]; #endif uiwindow->parent->my_window = [self window]; if (!IS_OPAQUE) { [self bgColorChanged]; } /* XXX TODO: Support color change */ u_long pixel = uiwindow->fg_color.pixel; /* See window_exposed() in ui_layout.c */ self.window.backgroundColor = [UIColor colorWithRed:((pixel >> 16) & 0xff) / 255.0 green:((pixel >> 8) & 0xff) / 255.0 blue:(pixel & 0xff) / 255.0 alpha:((pixel >> 24) & 0xff) / 255.0]; } [self windowResized]; [self becomeFirstResponder]; } - (void)drawRect:(CGRect)rect { if (!uiwindow->parent || !((ui_screen_t *)uiwindow)->term) { /* It has been already removed from ui_layout or term has been detached. */ return; } XExposeEvent ev; CGContextRef screen_ctx = UIGraphicsGetCurrentContext(); CGContextSaveGState(screen_ctx); CGContextTranslateCTM(screen_ctx, 0.0, self.bounds.size.height); CGContextScaleCTM(screen_ctx, 1.0, -1.0); CGContextSetBlendMode(screen_ctx, kCGBlendModeCopy); #if 0 CGAffineTransform t = CGContextGetCTM(ctx); bl_debug_printf("%f %f %f %f %f %f\n", t.a, t.b, t.c, t.d, t.tx, t.ty); #endif if (!layer) { layer = CGLayerCreateWithContext(screen_ctx, self.bounds.size, NULL); ctx = CGLayerGetContext(layer); CGContextSetBlendMode(ctx, kCGBlendModeCopy); if (uiwindow->update_window_flag == 0) { uiwindow->update_window_flag = 3; /* UPDATE_SCREEN|UPDATE_CURSOR (ui_screen.c) */ } forceExpose = 1; } CGPoint p = CGPointMake(0, 0); if (forceExpose & 2) { /* Visual bell */ [self fillWith:&uiwindow->fg_color :uiwindow->hmargin :uiwindow->vmargin :uiwindow->width :uiwindow->height]; CGContextFlush(ctx); CGContextDrawLayerAtPoint(screen_ctx, p, layer); [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; forceExpose &= ~2; uiwindow->update_window_flag = 0; } ev.type = UI_EXPOSE; ev.x = rect.origin.x; ev.width = rect.size.width; ev.height = rect.size.height; ev.y = ACTUAL_HEIGHT(uiwindow) - rect.origin.y - ev.height; ev.force_expose = forceExpose; ui_window_receive_event(uiwindow, (XEvent *)&ev); forceExpose = 0; uiwindow->update_window_flag = 0; CGContextDrawLayerAtPoint(screen_ctx, p, layer); CGContextRestoreGState(screen_ctx); } - (BOOL)isOpaque { return IS_OPAQUE ? YES : NO; } - (BOOL)wantsDefaultClipping { return IS_OPAQUE ? YES : NO; } static ui_window_t *get_current_window(ui_window_t *win) { u_int count; if (win->inputtable > 0) { return win; } for (count = 0; count < win->num_children; count++) { ui_window_t *hit; if ((hit = get_current_window(win->children[count]))) { return hit; } } return NULL; } - (BOOL)acceptsFirstResponder { return YES; } - (BOOL)becomeFirstResponder { if ([super becomeFirstResponder] != YES) { return NO; } [self.window bringSubviewToFront:self]; XEvent ev; ev.type = UI_KEY_FOCUS_IN; ui_window_receive_event(uiwindow, &ev); return YES; } - (BOOL)canBecomeFirstResponder { return YES; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint loc = [touch locationInView:self]; XButtonEvent bev; bev.type = UI_BUTTON_PRESS; bev.time = touch.timestamp * 1000; bev.x = loc.x; bev.y = loc.y; bev.state = 0; bev.button = 1; bev.click_count = touch.tapCount; ui_window_receive_event(uiwindow, (XEvent *)&bev); if (!uiwindow->is_focused || keyboard_margin == 0) { [self becomeFirstResponder]; } } - (void)longPress:(id)sender { UIMenuController *menuctl = [UIMenuController sharedMenuController]; CGPoint loc = [sender locationOfTouch:0 inView:self]; [menuctl setTargetRect:CGRectMake(loc.x, loc.y, 0, 0) inView:self]; menuctl.arrowDirection = UIMenuControllerArrowDown; NSMutableArray *items = [NSMutableArray array]; UIMenuItem *item; item = [[[UIMenuItem alloc] initWithTitle:@"Paste" action:@selector(pasteMenu:)] autorelease]; [items addObject:item]; item = [[[UIMenuItem alloc] initWithTitle:@"Config" action:@selector(configMenu:)] autorelease]; [items addObject:item]; menuctl.menuItems = items; [menuctl setMenuVisible:NO animated:NO]; [menuctl setMenuVisible:YES animated:YES]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint loc = [touch locationInView:self]; XButtonEvent bev; bev.type = UI_BUTTON_RELEASE; bev.time = touch.timestamp * 1000; bev.x = loc.x; bev.y = loc.y; bev.state = 0; bev.button = 1; bev.click_count = touch.tapCount; ui_window_receive_event(uiwindow, (XEvent *)&bev); } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; CGPoint loc = [touch locationInView:self]; XMotionEvent mev; mev.type = UI_BUTTON_MOTION; mev.time = touch.timestamp * 1000; mev.x = loc.x; mev.y = loc.y; mev.state = Button1Mask; ui_window_receive_event(uiwindow, (XEvent *)&mev); } #if 0 - (void)scrollWheel:(NSEvent *)event { NSPoint loc = [event locationInWindow]; XButtonEvent bevPress; XButtonEvent bevRelease; bevPress.type = UI_BUTTON_PRESS; bevRelease.type = UI_BUTTON_RELEASE; bevPress.time = event.timestamp * 1000; bevRelease.time = (event.timestamp * 1000) + 1; bevPress.x = loc.x - self.frame.origin.x; bevRelease.x = loc.x - self.frame.origin.x; bevPress.y = ACTUAL_HEIGHT(uiwindow->parent) - loc.y - /* self.frame.origin.y - */ 1; bevRelease.y = ACTUAL_HEIGHT(uiwindow->parent) - loc.y - /* self.frame.origin.y - */ 1; bevPress.state = event.modifierFlags & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask); bevRelease.state = event.modifierFlags & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask); bevPress.click_count = 1; if (event.deltaY > 1) { bevPress.button = 4; bevRelease.button = 4; } if (event.deltaY < -1) { bevPress.button = 5; bevRelease.button = 5; } if (event.deltaY < -1 || event.deltaY > 1) { ui_window_receive_event(uiwindow, (XEvent *)&bevPress); ui_window_receive_event(uiwindow, (XEvent *)&bevRelease); } } #endif - (void)keyEvent { XKeyEvent kev; #if 0 NSLog(@"Key event: mod %x keycode %x", key_mod, key_code); #endif if (0xf700 <= key_code && key_code <= 0xf8ff) { /* do nothing (Function keys) */ } else if (key_code == 0x1b) { /* do nothing */ } else if ((key_mod & NSControlKeyMask) || (key_mod & NSCommandKeyMask)) { if ('a' <= key_code && key_code <= 'z') { key_code -= 0x60; } else if (0x40 <= key_code && key_code < 0x60) { key_code -= 0x40; } else { return; } } else { return; } kev.type = UI_KEY_PRESS; kev.state = key_mod; kev.keysym = key_code; kev.utf8 = NULL; ui_window_receive_event(uiwindow, (XEvent *)&kev); } #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 /* iOS 7.0 or later */ - (NSArray *)keyCommands { if (!cmds) { UIKeyModifierFlags flags[] = { 0, UIKeyModifierShift, UIKeyModifierShift | UIKeyModifierControl, UIKeyModifierShift | UIKeyModifierAlternate, UIKeyModifierShift | UIKeyModifierCommand, UIKeyModifierShift | UIKeyModifierControl | UIKeyModifierAlternate, UIKeyModifierShift | UIKeyModifierControl | UIKeyModifierAlternate | UIKeyModifierCommand, UIKeyModifierShift | UIKeyModifierControl | UIKeyModifierCommand, UIKeyModifierShift | UIKeyModifierAlternate | UIKeyModifierCommand, UIKeyModifierShift | UIKeyModifierCommand, UIKeyModifierControl, UIKeyModifierControl | UIKeyModifierAlternate, UIKeyModifierControl | UIKeyModifierAlternate | UIKeyModifierCommand, UIKeyModifierControl | UIKeyModifierCommand, UIKeyModifierAlternate, UIKeyModifierAlternate | UIKeyModifierCommand, UIKeyModifierCommand }; NSMutableArray *mutable = [[NSMutableArray alloc] init]; u_char c[] = "\x60"; size_t count; for (; c[0] < 0x80; c[0]++) { [mutable addObject:[UIKeyCommand keyCommandWithInput:[NSString stringWithUTF8String:c] modifierFlags:UIKeyModifierControl action:@selector(keyEvent:)]]; } for (count = 0; count < sizeof(flags) / sizeof(flags[0]); count++) { [mutable addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow modifierFlags:flags[count] action:@selector(keyEvent:)]]; [mutable addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow modifierFlags:flags[count] action:@selector(keyEvent:)]]; [mutable addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputLeftArrow modifierFlags:flags[count] action:@selector(keyEvent:)]]; [mutable addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputRightArrow modifierFlags:flags[count] action:@selector(keyEvent:)]]; [mutable addObject:[UIKeyCommand keyCommandWithInput:UIKeyInputEscape modifierFlags:flags[count] action:@selector(keyEvent:)]]; [mutable addObject:[UIKeyCommand keyCommandWithInput:@"\x01" modifierFlags:flags[count] action:@selector(keyEvent:)]]; [mutable addObject:[UIKeyCommand keyCommandWithInput:@"\x04" modifierFlags:flags[count] action:@selector(keyEvent:)]]; [mutable addObject:[UIKeyCommand keyCommandWithInput:@"\x0b" modifierFlags:flags[count] action:@selector(keyEvent:)]]; [mutable addObject:[UIKeyCommand keyCommandWithInput:@"\x0c" modifierFlags:flags[count] action:@selector(keyEvent:)]]; [mutable addObject:[UIKeyCommand keyCommandWithInput:@"\x10" modifierFlags:flags[count] action:@selector(keyEvent:)]]; } cmds = mutable; } return cmds; } - (void)keyEvent:(UIKeyCommand *)keyCommand { key_mod = keyCommand.modifierFlags; #if 0 NSLog(@"KeyCmd: %x %x\n", key_mod, [keyCommand.input characterAtIndex:0]); NSLog(keyCommand.input); #endif if ([keyCommand.input compare:UIKeyInputUpArrow] == NSOrderedSame) { key_code = NSUpArrowFunctionKey; } else if ([keyCommand.input compare:UIKeyInputDownArrow] == NSOrderedSame) { key_code = NSDownArrowFunctionKey; } else if ([keyCommand.input compare:UIKeyInputLeftArrow] == NSOrderedSame) { key_code = NSLeftArrowFunctionKey; } else if ([keyCommand.input compare:UIKeyInputRightArrow] == NSOrderedSame) { key_code = NSRightArrowFunctionKey; } else if ([keyCommand.input compare:UIKeyInputEscape] == NSOrderedSame) { key_code = 0x1b; } else { key_code = [keyCommand.input characterAtIndex:0]; switch (key_code) { case 0x1: key_code = NSHomeFunctionKey; break; case 0x4: key_code = NSEndFunctionKey; break; case 0xb: key_code = NSPageUpFunctionKey; break; case 0xc: key_code = NSPageDownFunctionKey; break; case 0x10: /* iOS sends 0x10 for all function keys. It's impossible to distinguish them. */ key_code = NSF1FunctionKey; break; default: break; } } [self keyEvent]; } #endif - (UITextRange *)characterRangeAtPoint:(CGPoint)point { return nil; } - (UITextPosition *)closestPositionToPoint:(CGPoint)point { return nil; } - (UITextPosition *)closestPositionToPoint:(CGPoint)point withinRange:(UITextRange *)range { return nil; } - (CGRect)firstRectForRange:(UITextRange *)range { #if 0 int x = cand_x + uiwindow->x + uiwindow->hmargin; int y = ACTUAL_HEIGHT(uiwindow->parent) - (cand_y + uiwindow->y + uiwindow->vmargin); if (vt_term_get_vertical_mode(((ui_screen_t*)uiwindow)->term)) { /* * XXX Adjust candidate window position. * * +-+-+------ * | |1|ABCDE * * <-->^ * 25 x */ x += 25; } CGRect r = CGRectMake(x, y, ui_col_width((ui_screen_t *)uiwindow), ui_line_height((ui_screen_t *)uiwindow)); #endif return CGRectMake(0, 0, 1, 1); } - (CGRect)caretRectForPosition:(UITextPosition *)position { return CGRectMake(0, 0, 1, 1); } - (void)setBaseWritingDirection:(UITextWritingDirection)writingDirection forRange:(UITextRange *)range { } - (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction { return UITextWritingDirectionLeftToRight; } - (UITextRange *)characterRangeByExtendingPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction { return nil; } - (UITextPosition *)positionWithinRange:(UITextRange *)range farthestInDirection:(UITextLayoutDirection)direction { return nil; } - (NSInteger)offsetFromPosition:(UITextPosition *)from toPosition:(UITextPosition *)toPosition { return ((TextPosition*)toPosition).position - ((TextPosition*)from).position; } - (NSComparisonResult)comparePosition:(UITextPosition *)position toPosition:(UITextPosition *)other { int p = ((TextPosition *)position).position; int o = ((TextPosition *)other).position; if (p < o) { return NSOrderedAscending; } else if (p > 0) { return NSOrderedDescending; } else { return NSOrderedSame; } } - (UITextPosition *)positionFromPosition:(UITextPosition *)position offset:(NSInteger)offset { TextPosition *pos = [[TextPosition alloc] autorelease]; pos.position = ((TextPosition *)position).position + offset; return pos; } - (UITextPosition *)positionFromPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction offset:(NSInteger)offset { return nil; } - (UITextRange *)textRangeFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition { TextRange *range = [[TextRange alloc] autorelease]; ((TextPosition *)range.start).position = ((TextPosition *)fromPosition).position; ((TextPosition *)range.end).position = ((TextPosition *)toPosition).position; return range; } - (void)showMarkedText:(id)string selectedRange:(NSRange)selectedRange { if ([string length] > 0) { char *p; if (!(p = alloca(strlen([string UTF8String]) + 10))) { return; } *p = '\0'; if (selectedRange.location > 0) { strcpy(p, [[string substringWithRange: NSMakeRange(0, selectedRange.location)] UTF8String]); } if (selectedRange.length > 0) { sprintf(p + strlen(p), "\x1b[7m%s\x1b[27m", [[string substringWithRange:selectedRange] UTF8String]); } if (selectedRange.location + selectedRange.length < [string length]) { strcat(p, [[string substringWithRange: NSMakeRange( selectedRange.location + selectedRange.length, [string length] - selectedRange.location - selectedRange.length)] UTF8String]); } if (!markedText) { if (!uiwindow->xim_listener || !(*uiwindow->xim_listener->get_spot)(uiwindow->xim_listener->self, &cand_x, &cand_y)) { cand_x = cand_y = 0; } } update_ime_text(uiwindow, p, markedText ? markedText.UTF8String : NULL); } else if (markedText) { update_ime_text(uiwindow, "", markedText.UTF8String); } } - (void)setMarkedText:(id)string selectedRange:(NSRange)selectedRange { if ([string isKindOfClass:[NSAttributedString class]]) { string = [string string]; } ((TextPosition *)selectedTextRange.start).position = 0; ((TextPosition *)selectedTextRange.end).position = selectedRange.location + selectedRange.length; [self showMarkedText:string selectedRange:selectedRange]; if (markedText) { [markedText release]; markedText = nil; } if ([string length] > 0) { markedText = [string copy]; ((TextPosition *)markedTextRange.end).position = [string length]; } else { ((TextPosition *)markedTextRange.end).position = 0; } ((TextPosition *)markedTextRange.start).position = 0; } - (void)unmarkText { if (markedText) { update_ime_text(uiwindow, "", NULL); [self insertText:markedText]; [markedText release]; markedText = nil; } } - (void)replaceRange:(UITextRange *)range withText:(NSString *)text { if (!markedText) { NSRange range = NSMakeRange(0, [text length]); [self setMarkedText:text selectedRange:range]; return; } int start = ((TextPosition *)range.start).position; int length = ((TextPosition *)range.end).position - start; NSMutableString *nsstr = [NSMutableString stringWithString:markedText]; [nsstr replaceCharactersInRange:NSMakeRange(start, length) withString:text]; [markedText release]; markedText = [NSString stringWithString:nsstr]; [nsstr release]; ((TextPosition *)selectedTextRange.start).position = start; ((TextPosition *)selectedTextRange.start).position = start + [text length]; [self showMarkedText:markedText selectedRange:NSMakeRange(start, [text length])]; } - (NSString *)textInRange:(UITextRange *)range { return markedText; } - (BOOL)hasText { if (markedText) { return YES; } else { return NO; } } - (void)insertText:(NSString *)string { if ([string length] > 0) { unichar c = [string characterAtIndex:0]; if (0xf700 <= c && c <= 0xf8ff) { /* Function keys (See keyEvent or keyEvent:) */ return; } XKeyEvent kev; kev.type = UI_KEY_PRESS; kev.state = 0; kev.keysym = c; kev.utf8 = [string UTF8String]; ui_window_receive_event(uiwindow, (XEvent *)&kev); ignoreKeyDown = TRUE; } } - (void)deleteBackward { XKeyEvent kev; kev.type = UI_KEY_PRESS; kev.state = 0; kev.keysym = 0x08; kev.utf8 = "\x08"; ui_window_receive_event(uiwindow, (XEvent *)&kev); } - (void)drawString:(ui_font_t *)font :(ui_color_t *)fg_color :(int)x :(int)y :(u_char *)str :(size_t)len { set_fill_color(fg_color); #if 0 u_char *p = alloca(len + 1); memcpy(p, str, len); p[len] = '\0'; bl_debug_printf("%d %d %s %x\n", x, y, p, p[len - 1]); #endif #if 0 CGContextSelectFont(ctx, "Menlo", 16, kCGEncodingMacRoman); CGContextShowTextAtPoint(ctx, x, ACTUAL_HEIGHT(uiwindow) - y - 1, str, len); #else unichar ustr[len]; int count; for (count = 0; count < len; count++) { ustr[count] = str[count]; } drawUnistr(ctx, font, ustr, len, x, ACTUAL_HEIGHT(uiwindow) - y - 1); #endif } - (void)drawString16:(ui_font_t *)font :(ui_color_t *)fg_color :(int)x :(int)y :(XChar2b *)str :(size_t)len { set_fill_color(fg_color); drawUnistr(ctx, font, (unichar *)str, len, x, ACTUAL_HEIGHT(uiwindow) - y - 1); } - (void)fillWith:(ui_color_t *)color:(int)x:(int)y:(u_int)width:(u_int)height { #if 0 static int count = 0; color->pixel += (0x10 * (count++)); #endif if (IS_OPAQUE) { set_fill_color(color); CGRect rect = CGRectMake(x, ACTUAL_HEIGHT(uiwindow) - y - height, width, height); CGContextAddRect(ctx, rect); CGContextFillPath(ctx); } else { [[UIColor colorWithRed:((color->pixel >> 16) & 0xff) / 255.0 green:((color->pixel >> 8) & 0xff) / 255.0 blue:(color->pixel & 0xff) / 255.0 alpha:((color->pixel >> 24) & 0xff) / 255.0] set]; #if 0 NSRectFillUsingOperation( NSMakeRect(x, ACTUAL_HEIGHT(uiwindow) - y - height, width, height), NSCompositeCopy); #endif } } - (void)drawRectFrame:(ui_color_t *)color:(int)x1:(int)y1:(int)x2:(int)y2 { set_fill_color(color); CGRect rect = CGRectMake(x1, ACTUAL_HEIGHT(uiwindow) - y2 - 1, 1, y2 - y1); CGContextAddRect(ctx, rect); rect = CGRectMake(x1, ACTUAL_HEIGHT(uiwindow) - y2 - 1, x2 - x1, 1); CGContextAddRect(ctx, rect); rect = CGRectMake(x2, ACTUAL_HEIGHT(uiwindow) - y2 - 1, 1, y2 - y1); CGContextAddRect(ctx, rect); rect = CGRectMake(x1, ACTUAL_HEIGHT(uiwindow) - y1 - 1, x2 - x1 + 1, 1); CGContextAddRect(ctx, rect); CGContextFillPath(ctx); } - (void)copyArea:(Pixmap)src :(int)src_x :(int)src_y :(u_int)width :(u_int)height :(int)dst_x :(int)dst_y { CGImageRef clipped = CGImageCreateWithImageInRect( src, CGRectMake(src_x, src_y, width, height)); CGContextDrawImage( ctx, CGRectMake(dst_x, ACTUAL_HEIGHT(uiwindow) - dst_y - height, width, height), clipped); CGImageRelease(clipped); } #if 0 - (void)scroll:(int)src_x:(int)src_y:(u_int)width:(u_int)height:(int)dst_x:(int)dst_y { CGContextFlush(ctx); /* Don't release this CGImage */ CGRect src_r = CGRectMake(src_x, ACTUAL_HEIGHT(uiwindow) - src_y - height, width, height); UIBitmapImageRep *bir = [self bitmapImageRepForCachingDisplayInRect:src_r]; [self cacheDisplayInRect:src_r toBitmapImageRep:bir]; CGImageRef image = bir.CGImage; CGRect dst_r = CGRectMake(dst_x, ACTUAL_HEIGHT(uiwindow) - dst_y - height, width, height); CGContextDrawImage(ctx, dst_r, image); static int i; if (i == 0) { CFURLRef url = [UIURL fileURLWithPath:@"/Users/ken/kallist/log.png"]; CGImageDestinationRef dest = CGImageDestinationCreateWithURL( url, kUTTypePNG, 1, NULL); CGImageDestinationAddImage(dest, image, nil); CGImageDestinationFinalize(dest); CFRelease( dest); i++; } else if (i == 1) { UIImage * nsimage = [[[UIImage alloc]initWithSize:src_r.size] autorelease]; [nsimage addRepresentation:bir]; [[nsimage TIFFRepresentation] writeToFile:@"/Users/ken/kallist/log.tiff" atomically:YES]; i++; } } #endif - (void)update:(int)flag { forceExpose |= flag; if (IS_OPAQUE || forceExpose) { [self setNeedsDisplay]; } else { int x; int y; if (!uiwindow->xim_listener || !(*uiwindow->xim_listener->get_spot)(uiwindow->xim_listener->self, &x, &y)) { x = y = 0; } x += (uiwindow->hmargin); y += (uiwindow->vmargin); [self setNeedsDisplayInRect:CGRectMake(x, ACTUAL_HEIGHT(uiwindow) - y, 1, 1)]; } } - (void)setClip:(int)x:(int)y:(u_int)width:(u_int)height { CGContextSaveGState(ctx); y = ACTUAL_HEIGHT(uiwindow) - y; CGContextBeginPath(ctx); CGContextMoveToPoint(ctx, x, y); CGContextAddLineToPoint(ctx, x + width, y); CGContextAddLineToPoint(ctx, x + width, y - height); CGContextAddLineToPoint(ctx, x, y - height); CGContextClosePath(ctx); CGContextClip(ctx); } - (void)unsetClip { CGContextRestoreGState(ctx); } - (void)bgColorChanged { if (IS_OPAQUE) { [[self window] setBackgroundColor:[UIColor whiteColor]]; [[self window] setOpaque:YES]; } else { [[self window] setBackgroundColor:[UIColor clearColor]]; [[self window] setOpaque:NO]; } } @end /* --- global functions --- */ void view_alloc(ui_window_t *uiwindow) { uiwindow_for_mlterm_view = uiwindow; MLTermView *view = [[MLTermView alloc] initWithFrame:CGRectMake(0, 0, 400, 400)]; [((UIWindow *)uiwindow->parent->my_window) addSubview:view]; } void view_dealloc(UIView *view) { /* removeFromSuperview() can hide keyboard and change the frame of UIWindow. */ [view.window removeObserver:view forKeyPath:@"frame"]; [view removeFromSuperview]; [view release]; } void view_update(MLTermView *view, int flag) { [view update:flag]; } void view_set_clip(MLTermView *view, int x, int y, u_int width, u_int height) { [view setClip:x:y:width:height]; } void view_unset_clip(MLTermView *view) { [view unsetClip]; } void view_draw_string(MLTermView *view, ui_font_t *font, ui_color_t *fg_color, int x, int y, char *str, size_t len) { [view drawString:font:fg_color:x:y:str:len]; } void view_draw_string16(MLTermView *view, ui_font_t *font, ui_color_t *fg_color, int x, int y, XChar2b *str, size_t len) { [view drawString16:font:fg_color:x:y:str:len]; } void view_fill_with(MLTermView *view, ui_color_t *color, int x, int y, u_int width, u_int height) { [view fillWith:color:x:y:width:height]; } void view_draw_rect_frame(MLTermView *view, ui_color_t *color, int x1, int y1, int x2, int y2) { [view drawRectFrame:color:x1:y1:x2:y2]; } void view_copy_area(MLTermView *view, Pixmap src, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y) { [view copyArea:src:src_x:src_y:width:height:dst_x:dst_y]; } void view_scroll(MLTermView *view, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y) { #if 0 [view scroll:src_x:src_y:width:height:dst_x:dst_y]; #endif } void view_bg_color_changed(MLTermView *view) { [view bgColorChanged]; } void view_visual_bell(MLTermView *view) { [view update:2]; } void view_set_input_focus(UIView *view) { [view becomeFirstResponder]; } void view_set_rect(UIView *view, int x, int y, /* The origin is left-botom. */ u_int width, u_int height) { [view setFrame:CGRectMake(x,y,width,height)]; } void view_set_hidden(UIView *view, int flag) { [view setHidden:flag]; } void window_alloc(ui_window_t *root) { uiwindow_for_mlterm_view = root->children[1]; UINib *nib = [[UINib alloc] nibWithNibName:@"Main" bundle:nil]; [nib instantiateWithOwner:nil options:nil]; [nib release]; } void window_dealloc(UIWindow *window) { [window release]; } void window_resize(UIWindow *window, int width, int height) {} void window_move_resize(UIWindow *window, int x, int y, int width, int height) {} void window_accepts_mouse_moved_events(UIWindow *window, int accept) { #if 0 window.acceptsMouseMovedEvents = (accept ? YES : NO); #endif } void window_set_normal_hints(UIWindow *window, u_int width_inc, u_int height_inc) { #if 0 [window setResizeIncrements:NSMakeSize(width_inc, height_inc)]; #endif } void window_get_position(UIWindow *window, int *x, int *y) { *x = 0; *y = 0; } void window_set_title(UIWindow *window, const char *title /* utf8 */) { #if 0 NSString *ns_title = [NSString stringWithCString:title encoding:NSUTF8StringEncoding]; [window setTitle:ns_title]; #endif } void app_urgent_bell(int on) { #if 0 if (on) { [[NSApplication sharedApplication] requestUserAttention:NSCriticalRequest]; } else { [[NSApplication sharedApplication] cancelUserAttentionRequest:NSCriticalRequest]; } #endif } void scroller_update(UIScrollView *scroller, float pos, float knob) { #if 0 #if 1 [scroller setFloatValue:pos knobProportion:knob]; /* Deprecated since 10.6 */ #else scroller.knobProportion = knob; scroller.doubleValue = pos; #endif #endif } CGFontRef cocoa_create_font(const char *font_family) { NSString *ns_font_family = [NSString stringWithCString:font_family encoding:NSUTF8StringEncoding]; return CGFontCreateWithFontName(ns_font_family); } #ifdef USE_OT_LAYOUT char *cocoa_get_font_path(CGFontRef cg_font) { #if 0 CTFontDescriptorRef desc = CTFontDescriptorCreateWithNameAndSize(CGFontCopyFullName(cg_font), 14); CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(desc, kCTFontURLAttribute); const char *urlstr = [((NSString *)CFURLGetString(url))UTF8String]; if (strncmp(urlstr, "file://localhost", 16) == 0) { urlstr += 16; } char *path = strdup(urlstr); CFRelease(url); CFRelease(desc); return path; #else return NULL; #endif } #endif /* USE_OT_LAYOUT */ void cocoa_release_font(CGFontRef cg_font) { CFRelease(cg_font); } u_int cocoa_font_get_advance(CGFontRef cg_font, u_int fontsize, int size_attr, unichar *utf16, u_int len, CGGlyph glyph) { if (utf16) { CGFontGetGlyphsForUnichars(cg_font, &utf16, &glyph, 1); } int advance; if (!CGFontGetGlyphAdvances(cg_font, &glyph, 1, &advance) || advance < 0) { return 0; } if (size_attr >= DOUBLE_HEIGHT_TOP) { fontsize *= 2; } return advance * fontsize / CGFontGetUnitsPerEm(cg_font); } void cocoa_clipboard_own(MLTermView *view) { #if 0 UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; [pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:view]; #endif } void cocoa_clipboard_set(const u_char *utf8, size_t len) { UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; NSString *str = [[NSString alloc] initWithBytes:utf8 length:len encoding:NSUTF8StringEncoding]; pasteboard.string = str; [str release]; } const char *cocoa_clipboard_get(void) { UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; NSString *str = pasteboard.string; if (str != nil) { return [str UTF8String]; } return NULL; } void cocoa_beep(void) {} CGImageRef cocoa_load_image(const char *path, u_int *width, u_int *height) { NSString *nspath = [NSString stringWithCString:path encoding:NSUTF8StringEncoding]; UIImage *uiimg = [[UIImage alloc] initWithContentsOfFile:nspath]; if (!uiimg) { return nil; } CGImageRef cgimg = uiimg.CGImage; CGImageRetain(cgimg); *width = uiimg.size.width; *height = uiimg.size.height; [uiimg release]; return cgimg; } const char *cocoa_get_bundle_path(void) { return [[[NSBundle mainBundle] bundlePath] UTF8String]; } char *cocoa_dialog_password(const char *msg) { #if 0 NSAlert *alert = create_dialog(msg, 1); if (alert == nil) { return NULL; } NSTextField *text = [[MLSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)]; [text autorelease]; [alert setAccessoryView:text]; if ([alert runModal] == NSAlertFirstButtonReturn) { return strdup([[text stringValue] UTF8String]); } else #endif { return NULL; } } int cocoa_dialog_okcancel(const char *msg) { return -1; } int cocoa_dialog_alert(const char *msg) { show_dialog(msg); return 1; } mlterm-3.8.9/uitoolkit/quartz/ui.c012075500017600000144000000000001356600660700176252../win32/ui.custar kenusersmlterm-3.8.9/uitoolkit/quartz/ui.h010064400017600000144000000355721356600660700157150ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_H__ #define ___UI_H__ /* If MAX_OS_X_VERSION_MAX_ALLOWED is defined, has been already included. */ #if defined(COCOA_TOUCH) || !defined(MAC_OS_X_VERSION_MAX_ALLOWED) /* NSText.h */ /* Various important Unicode code points */ enum { NSEnterCharacter = 0x0003, NSBackspaceCharacter = 0x0008, NSTabCharacter = 0x0009, NSNewlineCharacter = 0x000a, NSFormFeedCharacter = 0x000c, NSCarriageReturnCharacter = 0x000d, NSBackTabCharacter = 0x0019, NSDeleteCharacter = 0x007f, NSLineSeparatorCharacter = 0x2028, NSParagraphSeparatorCharacter = 0x2029 }; /* NSObjCRuntime.h */ #include #define NSUIntegerMax ULONG_MAX /* NSEvent.h */ enum { /* various types of events */ NSLeftMouseDown = 1, NSLeftMouseUp = 2, NSRightMouseDown = 3, NSRightMouseUp = 4, NSMouseMoved = 5, NSLeftMouseDragged = 6, NSRightMouseDragged = 7, NSMouseEntered = 8, NSMouseExited = 9, NSKeyDown = 10, NSKeyUp = 11, NSFlagsChanged = 12, NSAppKitDefined = 13, NSSystemDefined = 14, NSApplicationDefined = 15, NSPeriodic = 16, NSCursorUpdate = 17, NSScrollWheel = 22, #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 NSTabletPoint = 23, NSTabletProximity = 24, #endif NSOtherMouseDown = 25, NSOtherMouseUp = 26, NSOtherMouseDragged = 27, #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 /* The following event types are available on some hardware on 10.5.2 and later */ NSEventTypeGesture = 29, NSEventTypeMagnify = 30, NSEventTypeSwipe = 31, NSEventTypeRotate = 18, NSEventTypeBeginGesture = 19, NSEventTypeEndGesture = 20 #endif }; enum { /* masks for the types of events */ NSLeftMouseDownMask = 1 << NSLeftMouseDown, NSLeftMouseUpMask = 1 << NSLeftMouseUp, NSRightMouseDownMask = 1 << NSRightMouseDown, NSRightMouseUpMask = 1 << NSRightMouseUp, NSMouseMovedMask = 1 << NSMouseMoved, NSLeftMouseDraggedMask = 1 << NSLeftMouseDragged, NSRightMouseDraggedMask = 1 << NSRightMouseDragged, NSMouseEnteredMask = 1 << NSMouseEntered, NSMouseExitedMask = 1 << NSMouseExited, NSKeyDownMask = 1 << NSKeyDown, NSKeyUpMask = 1 << NSKeyUp, NSFlagsChangedMask = 1 << NSFlagsChanged, NSAppKitDefinedMask = 1 << NSAppKitDefined, NSSystemDefinedMask = 1 << NSSystemDefined, NSApplicationDefinedMask = 1 << NSApplicationDefined, NSPeriodicMask = 1 << NSPeriodic, NSCursorUpdateMask = 1 << NSCursorUpdate, NSScrollWheelMask = 1 << NSScrollWheel, #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 NSTabletPointMask = 1 << NSTabletPoint, NSTabletProximityMask = 1 << NSTabletProximity, #endif NSOtherMouseDownMask = 1 << NSOtherMouseDown, NSOtherMouseUpMask = 1 << NSOtherMouseUp, NSOtherMouseDraggedMask = 1 << NSOtherMouseDragged, #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 /* The following event masks are available on some hardware on 10.5.2 and later */ NSEventMaskGesture = 1 << NSEventTypeGesture, NSEventMaskMagnify = 1 << NSEventTypeMagnify, NSEventMaskSwipe = 1U << NSEventTypeSwipe, NSEventMaskRotate = 1 << NSEventTypeRotate, NSEventMaskBeginGesture = 1 << NSEventTypeBeginGesture, NSEventMaskEndGesture = 1 << NSEventTypeEndGesture, #endif NSAnyEventMask = NSUIntegerMax }; /* Device-independent bits found in event modifier flags */ enum { NSAlphaShiftKeyMask = 1 << 16, NSShiftKeyMask = 1 << 17, NSControlKeyMask = 1 << 18, NSAlternateKeyMask = 1 << 19, NSCommandKeyMask = 1 << 20, NSNumericPadKeyMask = 1 << 21, NSHelpKeyMask = 1 << 22, NSFunctionKeyMask = 1 << 23, #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 NSDeviceIndependentModifierFlagsMask = 0xffff0000UL #endif }; /* Unicodes we reserve for function keys on the keyboard, OpenStep reserves the * range 0xF700-0xF8FF for this purpose. The availability of various keys will * be system dependent. */ enum { NSUpArrowFunctionKey = 0xF700, NSDownArrowFunctionKey = 0xF701, NSLeftArrowFunctionKey = 0xF702, NSRightArrowFunctionKey = 0xF703, NSF1FunctionKey = 0xF704, NSF2FunctionKey = 0xF705, NSF3FunctionKey = 0xF706, NSF4FunctionKey = 0xF707, NSF5FunctionKey = 0xF708, NSF6FunctionKey = 0xF709, NSF7FunctionKey = 0xF70A, NSF8FunctionKey = 0xF70B, NSF9FunctionKey = 0xF70C, NSF10FunctionKey = 0xF70D, NSF11FunctionKey = 0xF70E, NSF12FunctionKey = 0xF70F, NSF13FunctionKey = 0xF710, NSF14FunctionKey = 0xF711, NSF15FunctionKey = 0xF712, NSF16FunctionKey = 0xF713, NSF17FunctionKey = 0xF714, NSF18FunctionKey = 0xF715, NSF19FunctionKey = 0xF716, NSF20FunctionKey = 0xF717, NSF21FunctionKey = 0xF718, NSF22FunctionKey = 0xF719, NSF23FunctionKey = 0xF71A, NSF24FunctionKey = 0xF71B, NSF25FunctionKey = 0xF71C, NSF26FunctionKey = 0xF71D, NSF27FunctionKey = 0xF71E, NSF28FunctionKey = 0xF71F, NSF29FunctionKey = 0xF720, NSF30FunctionKey = 0xF721, NSF31FunctionKey = 0xF722, NSF32FunctionKey = 0xF723, NSF33FunctionKey = 0xF724, NSF34FunctionKey = 0xF725, NSF35FunctionKey = 0xF726, NSInsertFunctionKey = 0xF727, NSDeleteFunctionKey = 0xF728, NSHomeFunctionKey = 0xF729, NSBeginFunctionKey = 0xF72A, NSEndFunctionKey = 0xF72B, NSPageUpFunctionKey = 0xF72C, NSPageDownFunctionKey = 0xF72D, NSPrintScreenFunctionKey = 0xF72E, NSScrollLockFunctionKey = 0xF72F, NSPauseFunctionKey = 0xF730, NSSysReqFunctionKey = 0xF731, NSBreakFunctionKey = 0xF732, NSResetFunctionKey = 0xF733, NSStopFunctionKey = 0xF734, NSMenuFunctionKey = 0xF735, NSUserFunctionKey = 0xF736, NSSystemFunctionKey = 0xF737, NSPrintFunctionKey = 0xF738, NSClearLineFunctionKey = 0xF739, NSClearDisplayFunctionKey = 0xF73A, NSInsertLineFunctionKey = 0xF73B, NSDeleteLineFunctionKey = 0xF73C, NSInsertCharFunctionKey = 0xF73D, NSDeleteCharFunctionKey = 0xF73E, NSPrevFunctionKey = 0xF73F, NSNextFunctionKey = 0xF740, NSSelectFunctionKey = 0xF741, NSExecuteFunctionKey = 0xF742, NSUndoFunctionKey = 0xF743, NSRedoFunctionKey = 0xF744, NSFindFunctionKey = 0xF745, NSHelpFunctionKey = 0xF746, NSModeSwitchFunctionKey = 0xF747 }; #endif typedef struct { int fd; } Display; typedef int XIC; typedef int XID; typedef void *Window; /* NSView */ typedef int Drawable; typedef struct CGImage *Pixmap; typedef struct CGImage *PixmapMask; typedef int GC; typedef int Font; #ifndef __QUICKDRAWTYPES__ typedef int Cursor; #endif typedef int KeyCode; typedef int KeySym; typedef struct /* Same as definition in X11/X.h */ { int max_keypermod; KeyCode *modifiermap; } XModifierKeymap; typedef struct /* Same as definition in X11/X.h */ { unsigned char byte1; unsigned char byte2; } XChar2b; #define UI_FOCUS_IN 1 #define UI_FOCUS_OUT 2 #define UI_BUTTON_PRESS 3 #define UI_BUTTON_RELEASE 4 #define UI_BUTTON_MOTION 5 #define UI_KEY_PRESS 6 #define UI_EXPOSE 7 #define UI_SELECTION_REQUESTED 8 #define UI_CLOSE_WINDOW 9 #define UI_KEY_FOCUS_IN 10 #define UI_SELECTION_NOTIFIED 11 #define UI_POINTER_MOTION 12 typedef struct { int type; } XEvent; typedef struct { int type; unsigned int state; KeySym keysym; const char *utf8; } XKeyEvent; typedef unsigned long Time; /* Same as definition in X11/X.h */ typedef unsigned long Atom; /* Same as definition in X11/X.h */ typedef struct { int type; int time; int x; int y; unsigned int state; unsigned int button; int click_count; } XButtonEvent; typedef struct { int type; int time; int x; int y; unsigned int state; } XMotionEvent; typedef struct { int type; int x; int y; unsigned int width; unsigned int height; int force_expose; } XExposeEvent; typedef struct { int type; void *sender; } XSelectionRequestEvent; typedef struct { int type; char *data; unsigned int len; } XSelectionNotifyEvent; typedef struct { void *cg_font; unsigned int size; int is_italic; } XFontStruct; typedef int XFontSet; /* dummy */ #define None 0L /* Same as definition in X11/X.h */ #define NoSymbol 0L /* Same as definition in X11/X.h */ #define CurrentTime 0L /* Same as definition in X11/X.h */ /* Same as definition in X11/X.h */ #define NoEventMask 0L #define KeyPressMask (1L << 0) #define KeyReleaseMask (1L << 1) #define ButtonPressMask (1L << 2) #define ButtonReleaseMask (1L << 3) #define EnterWindowMask (1L << 4) #define LeaveWindowMask (1L << 5) #define PointerMotionMask (1L << 6) #define PointerMotionHintMask (1L << 7) #define Button1MotionMask (1L << 8) #define Button2MotionMask (1L << 9) #define Button3MotionMask (1L << 10) #define Button4MotionMask (1L << 11) #define Button5MotionMask (1L << 12) #define ButtonMotionMask (1L << 13) #define KeymapStateMask (1L << 14) #define ExposureMask (1L << 15) #define VisibilityChangeMask (1L << 16) #define StructureNotifyMask (1L << 17) #define ResizeRedirectMask (1L << 18) #define SubstructureNotifyMask (1L << 19) #define SubstructureRedirectMask (1L << 20) #define FocusChangeMask (1L << 21) #define PropertyChangeMask (1L << 22) #define ColormapChangeMask (1L << 23) #define OwnerGrabButtonMask (1L << 24) #define ShiftMask NSShiftKeyMask #define LockMask 0 #define ControlMask NSControlKeyMask #define Mod1Mask NSAlternateKeyMask #define Mod2Mask NSCommandKeyMask #define Mod3Mask 0 #define Mod4Mask 0 #define Mod5Mask 0 #define CommandMask NSCommandKeyMask #define Button1Mask NSLeftMouseDownMask #define Button2Mask 0 #define Button3Mask NSRightMouseDownMask #define Button4Mask 0 #define Button5Mask 0 #define Button1 1 #define Button2 2 #define Button3 3 #define Button4 4 #define Button5 5 #define XK_Super_L 0xfffe /* dummy */ #define XK_Super_R 0xfffd /* dummy */ #define XK_Hyper_L 0xfffc /* dummy */ #define XK_Hyper_R 0xfffb /* dummy */ #define XK_BackSpace NSDeleteCharacter #define XK_Tab NSTabCharacter #define XK_Clear NSClearDisplayFunctionKey #define XK_Linefeed 0xfffa /* dummy */ #define XK_Return NSCarriageReturnCharacter #define XK_Shift_L 0xfff9 /* dummy */ #define XK_Control_L 0xfff8 /* dummy */ #define XK_Alt_L 0xfff7 /* dummy */ #define XK_Shift_R 0xfff6 /* dummy */ #define XK_Control_R 0xfff5 /* dummy */ #define XK_Alt_R 0xfff4 /* dummy */ #define XK_Meta_L 0xfff3 /* dummy */ #define XK_Meta_R 0xfff2 /* dummy */ #define XK_Pause NSPauseFunctionKey #define XK_Shift_Lock 0xfff1 /* dummy */ #define XK_Caps_Lock 0xfff0 /* dummy */ #define XK_Escape 0x1b #define XK_Prior NSPageUpFunctionKey #define XK_Next NSPageDownFunctionKey #define XK_End NSEndFunctionKey #define XK_Home NSHomeFunctionKey #define XK_Left NSLeftArrowFunctionKey #define XK_Up NSUpArrowFunctionKey #define XK_Right NSRightArrowFunctionKey #define XK_Down NSDownArrowFunctionKey #define XK_Select NSSelectFunctionKey #define XK_Print NSPrintFunctionKey #define XK_Execute NSExecuteFunctionKey #define XK_Insert NSHelpFunctionKey #define XK_Delete NSDeleteFunctionKey #define XK_Help NSHelpFunctionKey #define XK_F1 NSF1FunctionKey #define XK_F2 NSF2FunctionKey #define XK_F3 NSF3FunctionKey #define XK_F4 NSF4FunctionKey #define XK_F5 NSF5FunctionKey #define XK_F6 NSF6FunctionKey #define XK_F7 NSF7FunctionKey #define XK_F8 NSF8FunctionKey #define XK_F9 NSF9FunctionKey #define XK_F10 NSF10FunctionKey #define XK_F11 NSF11FunctionKey #define XK_F12 NSF12FunctionKey #define XK_F13 NSF13FunctionKey #define XK_F14 NSF14FunctionKey #define XK_F15 NSF15FunctionKey #define XK_F16 NSF16FunctionKey #define XK_F17 NSF17FunctionKey #define XK_F18 NSF18FunctionKey #define XK_F19 NSF19FunctionKey #define XK_F20 NSF20FunctionKey #define XK_F21 NSF21FunctionKey #define XK_F22 NSF22FunctionKey #define XK_F23 NSF23FunctionKey #define XK_F24 NSF24FunctionKey #define XK_FMAX XK_F24 #define XK_Num_Lock 0xffef /* dummy */ #define XK_Scroll_Lock NSScrollLockFunctionKey #define XK_Find NSFindFunctionKey #define XK_Menu NSMenuFunctionKey #define XK_Begin NSBeginFunctionKey #define XK_Muhenkan 0xffee /* dummy */ #define XK_Henkan_Mode 0xffed /* dummy */ #define XK_Zenkaku_Hankaku 0xffec /* dummy */ #define XK_KP_Prior 0xffe8 /* dummy */ #define XK_KP_Next 0xffe7 /* dummy */ #define XK_KP_End 0xffe6 /* dummy */ #define XK_KP_Home 0xffe5 /* dummy */ #define XK_KP_Left 0xffe4 /* dummy */ #define XK_KP_Up 0xffe3 /* dummy */ #define XK_KP_Right 0xffe2 /* dummy */ #define XK_KP_Down 0xffe1 /* dummy */ #define XK_KP_Insert 0xffe0 /* dummy */ #define XK_KP_Delete 0xffdf /* dummy */ #define XK_KP_F1 0xffde /* dummy */ #define XK_KP_F2 0xffdd /* dummy */ #define XK_KP_F3 0xffdc /* dummy */ #define XK_KP_F4 0xffdb /* dummy */ #define XK_KP_Begin 0xffda /* dummy */ #define XK_KP_Multiply 0xffd9 /* dummy */ #define XK_KP_Add 0xffd8 /* dummy */ #define XK_KP_Separator 0xffd7 /* dummy */ #define XK_KP_Subtract 0xffd6 /* dummy */ #define XK_KP_Decimal 0xffd5 /* dummy */ #define XK_KP_Divide 0xffd4 /* dummy */ #define XK_KP_0 0xffd3 /* dummy */ #define XK_KP_1 0xffd2 /* dummy */ #define XK_KP_2 0xffd1 /* dummy */ #define XK_KP_3 0xffd0 /* dummy */ #define XK_KP_4 0xffcf /* dummy */ #define XK_KP_5 0xffce /* dummy */ #define XK_KP_6 0xffcd /* dummy */ #define XK_KP_7 0xffcc /* dummy */ #define XK_KP_8 0xffcb /* dummy */ #define XK_KP_9 0xffca /* dummy */ #define IsKeypadKey(ksym) (0) #define IsModifierKey(ksym) (0) #define XK_ISO_Left_Tab NSBackTabCharacter /* XPoint(short x, short y) in Xlib. POINT(float x, float y) in win32. */ #define XPoint NSPoint /* XXX dummy */ #define XKeysymToKeycode(disp, ks) (ks) #define XKeycodeToKeysym(disp, kc, i) (kc) #define XKeysymToString(ks) "" #define DefaultScreen(disp) (0) #define BlackPixel(disp, screen) (0xff000000) #define WhitePixel(disp, screen) (0xffffffff) /* Same as definition in X11/cursorfont.h */ #define XC_xterm 152 #define XC_left_ptr 68 /* Same as definition in X11/Xutil.h */ #define NoValue 0x0000 #define XValue 0x0001 #define YValue 0x0002 #define WidthValue 0x0004 #define HeightValue 0x0008 #define AllValues 0x000F #define XNegative 0x0010 #define YNegative 0x0020 int XParseGeometry(char *str, int *x, int *y, unsigned int *width, unsigned int *height); KeySym XStringToKeysym(char *str); /* === Platform dependent options === */ #undef UI_COLOR_HAS_RGB #define SUPPORT_TRUE_TRANSPARENT_BG #define TYPE_XCORE_SCALABLE #undef MANAGE_ROOT_WINDOWS_BY_MYSELF #undef MANAGE_SUB_WINDOWS_BY_MYSELF #undef INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS #define SUPPORT_POINT_SIZE_FONT #undef XIM_SPOT_IS_LINE_TOP #undef USE_GC #undef CHANGEABLE_CURSOR #undef PLUGIN_MODULE_SUFFIX #undef KEY_REPEAT_BY_MYSELF #undef ROTATABLE_DISPLAY #undef PSEUDO_COLOR_DISPLAY #undef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE #define SUPPORT_URGENT_BELL #define FORCE_UNICODE #undef NEED_DISPLAY_SYNC_EVERY_TIME #undef DRAW_SCREEN_IN_PIXELS #define NO_DRAW_IMAGE_STRING /* libpthread is not linked to mlterm explicitly for now. */ #undef HAVE_PTHREAD #undef COMPOSE_DECSP_FONT #undef USE_REAL_VERTICAL_FONT #undef NO_DISPLAY_FD #ifdef COCOA_TOUCH #define FLICK_SCROLL #else #undef FLICK_SCROLL #endif #define UIWINDOW_SUPPORTS_PREEDITING #endif mlterm-3.8.9/uitoolkit/quartz/ui_color.c010064400017600000144000000044541356600660700171010ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_color.h" #include /* memcpy,strcmp */ #include /* sscanf */ #include #include #include /* --- global functions --- */ int ui_load_named_xcolor(ui_display_t *disp, ui_color_t *xcolor, char *name) { vt_color_t color; u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; if (vt_color_parse_rgb_name(&red, &green, &blue, &alpha, name)) { return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, alpha); } if ((color = vt_get_color(name)) != VT_UNKNOWN_COLOR && IS_VTSYS_BASE_COLOR(color)) { /* * 0 : 0x00, 0x00, 0x00 * 1 : 0xff, 0x00, 0x00 * 2 : 0x00, 0xff, 0x00 * 3 : 0xff, 0xff, 0x00 * 4 : 0x00, 0x00, 0xff * 5 : 0xff, 0x00, 0xff * 6 : 0x00, 0xff, 0xff * 7 : 0xe5, 0xe5, 0xe5 */ red = (color & 0x1) ? 0xff : 0; green = (color & 0x2) ? 0xff : 0; blue = (color & 0x4) ? 0xff : 0; } else { if (strcmp(name, "gray") == 0) { red = green = blue = 190; } else if (strcmp(name, "lightgray") == 0) { red = green = blue = 211; } else { return 0; } } return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, 0xff); } int ui_load_rgb_xcolor(ui_display_t *disp, ui_color_t *xcolor, u_int8_t red, u_int8_t green, u_int8_t blue, u_int8_t alpha) { xcolor->pixel = (red << 16) | (green << 8) | blue | (alpha << 24); return 1; } void ui_unload_xcolor(ui_display_t *disp, ui_color_t *xcolor) {} void ui_get_xcolor_rgba(u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_int8_t *alpha /* can be NULL */, ui_color_t *xcolor) { if (alpha) { *alpha = (xcolor->pixel >> 24) & 0xff; } *red = (xcolor->pixel >> 16) & 0xff; *green = (xcolor->pixel >> 8) & 0xff; *blue = xcolor->pixel & 0xff; } int ui_xcolor_fade(ui_display_t *disp, ui_color_t *xcolor, u_int fade_ratio) { u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; ui_get_xcolor_rgba(&red, &green, &blue, &alpha, xcolor); red = (red * fade_ratio) / 100; green = (green * fade_ratio) / 100; blue = (blue * fade_ratio) / 100; ui_unload_xcolor(disp, xcolor); return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, alpha); } mlterm-3.8.9/uitoolkit/quartz/ui_connect_dialog.c010064400017600000144000000023261356600660700207270ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ /* Note that protocols except ssh aren't supported if USE_LIBSSH2 is defined. */ #ifdef USE_LIBSSH2 #include "../ui_connect_dialog.h" #include #include /* strdup */ #include /* alloca */ #include "cocoa.h" /* --- global functions --- */ int ui_connect_dialog(char **uri, /* Should be free'ed by those who call this. */ char **pass, /* Same as uri. If pass is not input, "" is set. */ char **exec_cmd, /* Same as uri. If exec_cmd is not input, NULL is set. */ char **privkey, /* in/out */ int *x11_fwd, /* in/out */ char *display_name, Window parent_window, char *def_server /* (@)(:)(:). */) { char *msg; if (!(*uri = strdup(def_server))) { return 0; } if ((msg = alloca(19 + strlen(*uri) + 1))) { char *p; sprintf(msg, "Enter password for %s", *uri); if ((p = cocoa_dialog_password(msg))) { *pass = p; *exec_cmd = NULL; return 1; } } free(*uri); *uri = NULL; return 0; } #endif mlterm-3.8.9/uitoolkit/quartz/ui_display.c010064400017600000144000000111321356600660700174170ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_display.h" #include /* sprintf */ #include /* memset/memcpy */ #include /* getenv */ #include /* USE_WIN32API */ #include #include #include #include #include "ui.h" #include "../ui_window.h" #include "../ui_picture.h" #include "cocoa.h" #define DISP_IS_INITED (_disp.display) #if 0 #define __DEBUG #endif /* --- static variables --- */ static ui_display_t _disp; /* Singleton */ static Display _display; static ui_display_t *opened_disp = &_disp; /* --- static functions --- */ static int dialog_cb(bl_dialog_style_t style, const char *msg) { if (style == BL_DIALOG_OKCANCEL) { return cocoa_dialog_okcancel(msg); } else if (style == BL_DIALOG_ALERT) { return cocoa_dialog_alert(msg); } else { return -1; } } /* --- global functions --- */ ui_display_t *ui_display_open(char *disp_name, /* Ignored */ u_int depth /* Ignored */ ) { if (DISP_IS_INITED) { /* Already opened. */ return &_disp; } /* Callback should be set before bl_dialog() is called. */ bl_dialog_set_callback(dialog_cb); /* _disp.width and _disp.height are set in viewDidMoveToWindow */ _disp.depth = 32; if (!(_disp.name = getenv("DISPLAY"))) { _disp.name = ":0.0"; } /* _disp is initialized successfully. */ _display.fd = -1; _disp.display = &_display; return &_disp; } void ui_display_close(ui_display_t *disp) { if (disp == &_disp) { ui_display_close_all(); } } void ui_display_close_all(void) { u_int count; if (!DISP_IS_INITED) { return; } ui_picture_display_closed(_disp.display); ui_gc_destroy(_disp.gc); for (count = 0; count < _disp.num_roots; count++) { ui_window_unmap(_disp.roots[count]); ui_window_final(_disp.roots[count]); } free(_disp.roots); _disp.display = NULL; } ui_display_t **ui_get_opened_displays(u_int *num) { if (!DISP_IS_INITED) { *num = 0; return NULL; } *num = 1; return &opened_disp; } int ui_display_fd(ui_display_t *disp) { return disp->display->fd; } int ui_display_show_root(ui_display_t *disp, ui_window_t *root, int x, int y, int hint, char *app_name, Window parent_window /* Ignored */ ) { void *p; if ((p = realloc(disp->roots, sizeof(ui_window_t*) * (disp->num_roots + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } disp->roots = p; root->disp = disp; root->parent = NULL; root->parent_window = disp->my_window; root->gc = disp->gc; root->x = x; root->y = y; if (app_name) { root->app_name = app_name; } disp->roots[disp->num_roots++] = root; if (ui_window_show(root, hint)) { if (disp->num_roots > 1) { window_alloc(root); } return 1; } else { return 0; } } int ui_display_remove_root(ui_display_t *disp, ui_window_t *root) { u_int count; for (count = 0; count < disp->num_roots; count++) { if (disp->roots[count] == root) { ui_window_unmap(root); ui_window_final(root); disp->num_roots--; if (count == disp->num_roots) { disp->roots[count] = NULL; } else { disp->roots[count] = disp->roots[disp->num_roots]; } return 1; } } return 0; } void ui_display_idling(ui_display_t *disp) { u_int count; for (count = 0; count < _disp.num_roots; count++) { ui_window_idling(_disp.roots[count]); } } int ui_display_receive_next_event(ui_display_t *disp) { return 1; } /* * Folloing functions called from ui_window.c */ int ui_display_own_selection(ui_display_t *disp, ui_window_t *win) { if (disp->selection_owner) { ui_display_clear_selection(disp, disp->selection_owner); } disp->selection_owner = win; return 1; } int ui_display_clear_selection(ui_display_t *disp, ui_window_t *win) { if (disp->selection_owner == NULL || disp->selection_owner != win) { return 0; } if (disp->selection_owner->selection_cleared) { (*disp->selection_owner->selection_cleared)(disp->selection_owner); } disp->selection_owner = NULL; return 1; } XModifierKeymap *ui_display_get_modifier_mapping(ui_display_t *disp) { return disp->modmap.map; } void ui_display_update_modifier_mapping(ui_display_t *disp, u_int serial) { /* dummy */ } Cursor ui_display_get_cursor(ui_display_t *disp, u_int shape) { return None; } XID ui_display_get_group_leader(ui_display_t *disp) { return None; } mlterm-3.8.9/uitoolkit/quartz/ui_display.h010064400017600000144000000003331356600660700174250ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_DISPLAY_H__ #define ___UI_DISPLAY_H__ #include "../ui_display.h" Cursor ui_display_get_cursor(ui_display_t *disp, u_int shape); #endif mlterm-3.8.9/uitoolkit/quartz/ui_dnd.c010064400017600000144000000006671356600660700165320ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef DISABLE_XDND #include "../ui_window.h" #include "../ui_dnd.h" /* --- global functions --- */ /* * XFilterEvent(event, w) analogue. * return 0 if the event should be processed in the mlterm mail loop. * return 1 if nothing to be done is left for the event. */ int ui_dnd_filter_event(XEvent *event, ui_window_t *win) { return 0; } #endif /* DISABLE_XDND */ mlterm-3.8.9/uitoolkit/quartz/ui_font.c010064400017600000144000000263331356600660700167310ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifdef COCOA_TOUCH #include #else #include #endif #include "../ui_font.h" #include #include /* memset/strncasecmp */ #include #include /* alloca */ #include /* bl_str_to_uint */ #include #include #include /* ui_convert_to_xft_ucs4 */ #ifdef USE_OT_LAYOUT #include #endif #ifdef COCOA_TOUCH #define DEFAULT_FONT "Courier" #else #define DEFAULT_FONT "Menlo" #endif #include "cocoa.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static int use_point_size; /* --- static functions --- */ static int parse_font_name( char **font_family, double *font_size, /* if size is not specified in font_name, not changed. */ int *is_bold, /* if bold is not specified in font_name, not changed. */ int *is_italic, /* if italic is not specified in font_name, not changed. */ u_int *percent, /* if percent is not specified in font_name , not changed. */ char *font_name /* modified by this function. */ ) { char *p; size_t len; /* * Format. * [Family]( [WEIGHT] [SLANT] [SIZE]:[Percentage]) */ *font_family = font_name; if ((p = strrchr(font_name, ':'))) { /* Parsing ":[Percentage]" */ if (bl_str_to_uint(percent, p + 1)) { *p = '\0'; } #ifdef DEBUG else { bl_warn_printf(BL_DEBUG_TAG " Percentage(%s) is illegal.\n", p + 1); } #endif } /* * Parsing "[Family] [WEIGHT] [SLANT] [SIZE]". * Following is the same as ui_font.c:parse_xft_font_name() * except FW_* and is_italic. */ #if 0 bl_debug_printf("Parsing %s for [Family] [Weight] [Slant]\n", *font_family); #endif p = bl_str_chop_spaces(*font_family); len = strlen(p); while (len > 0) { size_t step = 0; if (*p == ' ') { char *orig_p; orig_p = p; do { p++; len--; } while (*p == ' '); if (len == 0) { *orig_p = '\0'; break; } else { int count; /* * XXX * "medium" is necessary because GTK font selection dialog (mlconfig) * returns "Osaka medium" */ char *styles[] = { "italic", "bold", "medium", "oblique", "light", "semi-bold", "heavy", "semi-condensed", }; for (count = 0; count < sizeof(styles) / sizeof(styles[0]); count++) { size_t len_v; len_v = strlen(styles[count]); /* XXX strncasecmp is not portable? */ if (len >= len_v && strncasecmp(p, styles[count], len_v) == 0) { /* [WEIGHT] [SLANT] */ *orig_p = '\0'; step = len_v; if (count <= 1) { if (count == 0) { *is_italic = 1; } else { *is_bold = 1; } } goto next_char; } } if (*p != '0' || /* In case of "DevLys 010" font family. */ *(p + 1) == '\0') /* "MS Gothic 0" => "MS Gothic" + "0" */ { char *end; double size; size = strtod(p, &end); if (*end == '\0') { /* p has no more parameters. */ *orig_p = '\0'; if (size > 0) { *font_size = size; } break; } } step = 1; } } else { step = 1; } next_char: p += step; len -= step; } return 1; } /* --- global functions --- */ void ui_compose_dec_special_font(void) { /* Do nothing for now in quartz. */ } /* Undocumented */ bool CGFontGetGlyphsForUnichars(CGFontRef, u_int16_t[], CGGlyph[], size_t); ui_font_t *ui_font_new(Display *display, vt_font_t id, int size_attr, ui_type_engine_t type_engine, ui_font_present_t font_present, const char *fontname, u_int fontsize, u_int col_width, int use_medium_for_bold, u_int letter_space /* Ignored for now. */ ) { ui_font_t *font; char *font_family; u_int percent; u_int cols; if (type_engine != TYPE_XCORE || (font = calloc(1, sizeof(ui_font_t) + sizeof(XFontStruct))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc() failed.\n"); #endif return NULL; } font->xfont = font + 1; font->display = display; font->id = id; if (font->id & FONT_FULLWIDTH) { cols = 2; } else { cols = 1; } if (IS_ISCII(FONT_CS(font->id)) || FONT_CS(font->id) == ISO10646_UCS4_1_V) { /* * For exampe, 'W' width and 'l' width of OR-TTSarala font for ISCII_ORIYA * are the same by chance, though it is actually a proportional font. */ font->is_var_col_width = font->is_proportional = 1; } else if (font_present & FONT_VAR_WIDTH) { font->is_var_col_width = 1; } if (font_present & FONT_VERTICAL) { font->is_vertical = 1; } font_family = NULL; percent = 0; if (fontname) { char *p; if ((p = alloca(strlen(fontname) + 1)) == NULL) { free(font); return NULL; } strcpy(p, fontname); double fontsize_d = 0; int is_bold = 0; int is_italic = 0; parse_font_name(&font_family, &fontsize_d, &is_bold, &is_italic, &percent, p); if (fontsize_d > 0.0) { fontsize = fontsize_d; } if (is_bold) { font->double_draw_gap = 1; } if (is_italic) { font->xfont->is_italic = 1; } } else { /* Default font */ font_family = DEFAULT_FONT; } if (font->id & FONT_BOLD) { font->double_draw_gap = 1; } if (font->id & FONT_ITALIC) { font->xfont->is_italic = 1; } while (!(font->xfont->cg_font = cocoa_create_font(font_family))) { bl_warn_printf("%s font is not found.\n", font_family); if (col_width == 0 && strcmp(font_family, DEFAULT_FONT) != 0) { /* * standard(usascii) font * Fall back to default font. */ font_family = DEFAULT_FONT; } else { free(font); return NULL; } } #if 0 bl_debug_printf("%d %d %d %d %d %d\n", CGFontGetAscent(font->xfont->cg_font), CGFontGetDescent(font->xfont->cg_font), CGFontGetLeading(font->xfont->cg_font), CGFontGetCapHeight(font->xfont->cg_font), CGFontGetXHeight(font->xfont->cg_font), CGFontGetUnitsPerEm(font->xfont->cg_font)); #endif font->xfont->size = fontsize; int ascent = CGFontGetAscent(font->xfont->cg_font); int descent = CGFontGetDescent(font->xfont->cg_font); /* minus value */ int units = CGFontGetUnitsPerEm(font->xfont->cg_font); font->height = ((float)fontsize * (ascent - descent)) / ((float)units) + 0.5; font->ascent = (font->height * ascent) / (ascent - descent); CGGlyph glyphs[1]; u_int16_t ch = 'M'; int advance; CGFontGetGlyphsForUnichars(font->xfont->cg_font, &ch, glyphs, 1); CGFontGetGlyphAdvances(font->xfont->cg_font, glyphs, 1, &advance); fontsize = ((float)fontsize * advance * 2) / ((float)units) + 0.5; /* * Following processing is same as ui_font.c:set_xfont() */ font->x_off = 0; if (col_width == 0) { /* standard(usascii) font */ if (percent > 0) { u_int ch_width; if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ ch_width = font->height * percent / 100; } else { ch_width = font->height * percent / 200; } font->width = ch_width; } else if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ font->width = fontsize; font->x_off += (fontsize / 4); } else { font->width = fontsize * cols / 2; } font->width += letter_space; } else { /* not a standard(usascii) font */ if (font->is_vertical) { font->width = col_width; } else { font->width = col_width * cols; } } font->decsp_font = NULL; if (size_attr) { font->width *= 2; font->x_off *= 2; if (size_attr >= DOUBLE_HEIGHT_TOP) { font->height *= 2; font->ascent *= 2; } } font->size_attr = size_attr; #ifdef DEBUG ui_font_dump(font); #endif return font; } void ui_font_destroy(ui_font_t *font) { #ifdef USE_OT_LAYOUT if (font->ot_font) { otl_close(font->ot_font); } #endif cocoa_release_font(font->xfont->cg_font); free(font); } #ifdef USE_OT_LAYOUT int ui_font_has_ot_layout_table(ui_font_t *font) { if (!font->ot_font) { #ifdef USE_HARFBUZZ if (font->ot_font_not_found) { return 0; } font->ot_font = otl_open(font->xfont->cg_font, 0); #else char *path; if (font->ot_font_not_found || !(path = cocoa_get_font_path(font->xfont->cg_font))) { return 0; } font->ot_font = otl_open(path, 0); free(path); #endif if (!font->ot_font) { font->ot_font_not_found = 1; return 0; } } return 1; } u_int ui_convert_text_to_glyphs(ui_font_t *font, u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features) { return otl_convert_text_to_glyphs(font->ot_font, shaped, shaped_len, offsets, widths, cmapped, src, src_len, script, features, font->xfont->size * (font->size_attr >= DOUBLE_WIDTH ? 2 : 1)); } #endif /* USE_OT_LAYOUT */ u_int ui_calculate_char_width(ui_font_t *font, u_int32_t ch, ef_charset_t cs, int *draw_alone) { if (draw_alone) { *draw_alone = 0; } if (font->is_proportional) { #ifdef USE_OT_LAYOUT if (font->use_ot_layout /* && font->ot_font */) { return cocoa_font_get_advance(font->xfont->cg_font, font->xfont->size, font->size_attr, NULL, 0, ch); } else #endif { u_int16_t utf16[2]; u_int len; if ((len = ui_convert_ucs4_to_utf16(utf16, ch) / 2) > 0) { return cocoa_font_get_advance(font->xfont->cg_font, font->xfont->size, font->size_attr, utf16, len, 0); } else { return 0; } } } return font->width; } void ui_font_use_point_size(int use) { use_point_size = use; } /* Return written size */ size_t ui_convert_ucs4_to_utf16(u_char *dst, /* 4 bytes. Little endian. */ u_int32_t src) { if (src < 0x10000) { dst[1] = (src >> 8) & 0xff; dst[0] = src & 0xff; return 2; } else if (src < 0x110000) { /* surrogate pair */ u_char c; src -= 0x10000; c = (u_char)(src / (0x100 * 0x400)); src -= (c * 0x100 * 0x400); dst[1] = c + 0xd8; c = (u_char)(src / 0x400); src -= (c * 0x400); dst[0] = c; c = (u_char)(src / 0x100); src -= (c * 0x100); dst[3] = c + 0xdc; dst[2] = (u_char)src; return 4; } return 0; } #ifdef DEBUG void ui_font_dump(ui_font_t *font) { bl_msg_printf(" id %x: Font %p", font->id, font->xfont->cg_font); if (font->is_proportional) { bl_msg_printf(" (proportional)"); } bl_msg_printf("\n"); } #endif mlterm-3.8.9/uitoolkit/quartz/ui_gc.c012075500017600000144000000000001356600660700203742../fb/ui_gc.custar kenusersmlterm-3.8.9/uitoolkit/quartz/ui_im_status_screen-cocoa.m010064400017600000144000000122131356600660700224160ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifdef USE_IM_PLUGIN #import #endif #include "../ui_im_status_screen.h" #ifdef USE_IM_PLUGIN #include #include /* --- static functions --- */ /* * methods of ui_im_status_screen_t */ static int destroy(ui_im_status_screen_t* stat_screen) { NSWindow* window = stat_screen->window.my_window; [window release]; free(stat_screen); return 1; } static int show(ui_im_status_screen_t* stat_screen) { NSWindow* window = stat_screen->window.my_window; [window orderFront:window]; return 1; } static int hide(ui_im_status_screen_t* stat_screen) { NSWindow* window = stat_screen->window.my_window; [window orderOut:window]; return 1; } static int set_spot(ui_im_status_screen_t* stat_screen, int x, int y) { NSWindow* window = stat_screen->window.my_window; [window setFrameOrigin:NSMakePoint(x, [[window screen] visibleFrame].size.height - [window.contentView frame].size.height - y)]; stat_screen->x = x; stat_screen->y = y; return 1; } static int set(ui_im_status_screen_t* stat_screen, ef_parser_t* parser, u_char* str) { size_t len; u_char* utf8; ef_char_t ch; u_int count; len = strlen(str); (*parser->init)(parser); (*parser->set_str)(parser, str, len); for (count = 0; (*parser->next_char)(parser, &ch); count++) ; if (!(utf8 = alloca(count * UTF_MAX_SIZE + 1))) { return 0; } (*parser->init)(parser); (*parser->set_str)(parser, str, len); len = vt_char_encoding_convert_with_parser(utf8, count * UTF_MAX_SIZE, VT_UTF8, parser); utf8[len] = '\0'; NSWindow* window = stat_screen->window.my_window; NSTextField* label = window.contentView; label.stringValue = [NSString stringWithCString:utf8 encoding:NSUTF8StringEncoding]; [label sizeToFit]; [window setContentSize:label.frame.size]; /* XXX (see ui_im_status_screen_new()) */ if (stat_screen->filled_len == 1) { [window orderFront:window]; set_spot(stat_screen, stat_screen->x, stat_screen->y); stat_screen->filled_len = 0; } return 1; } /* --- global functions --- */ ui_im_status_screen_t *ui_im_status_screen_new(ui_display_t* disp, ui_font_manager_t* font_man, ui_color_manager_t* color_man, void *vtparser, int is_vertical, u_int line_height, int x, int y) { ui_im_status_screen_t* stat_screen; if ((stat_screen = calloc(1, sizeof(ui_im_status_screen_t))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc failed.\n"); #endif return NULL; } stat_screen->font_man = font_man; stat_screen->color_man = color_man; stat_screen->vtparser = vtparser; stat_screen->x = x; stat_screen->y = y; stat_screen->line_height = line_height; stat_screen->is_vertical = is_vertical; NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 100, 0, 0) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]; [window setLevel:NSStatusWindowLevel]; NSTextField* label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 10, 10)]; label.drawsBackground = YES; [label setEditable:NO]; [label setSelectable:NO]; ui_color_t* fg = ui_get_xcolor(stat_screen->color_man, VT_FG_COLOR); ui_color_t* bg = ui_get_xcolor(stat_screen->color_man, VT_BG_COLOR); [label setTextColor:[NSColor colorWithCalibratedRed:((fg->pixel >> 16) & 0xff) / 255.0 green:((fg->pixel >> 8) & 0xff) / 255.0 blue:(fg->pixel & 0xff) / 255.0 alpha:1.0]]; [label setBackgroundColor: [NSColor colorWithCalibratedRed:((bg->pixel >> 16) & 0xff) / 255.0 green:((bg->pixel >> 8) & 0xff) / 255.0 blue:(bg->pixel & 0xff) / 255.0 alpha:1.0]]; [window setContentView:label]; stat_screen->window.my_window = window; /* methods of ui_im_status_screen_t */ stat_screen->destroy = destroy; stat_screen->show = show; stat_screen->hide = hide; stat_screen->set_spot = set_spot; stat_screen->set = set; /* XXX (see set()) */ stat_screen->filled_len = 1; return stat_screen; } #else /* ! USE_IM_PLUGIN */ ui_im_status_screen_t *ui_im_status_screen_new(ui_display_t* disp, ui_font_manager_t* font_man, ui_color_manager_t* color_man, void *vtparser, int is_vertical, u_int line_height, int x, int y) { return NULL; } #endif mlterm-3.8.9/uitoolkit/quartz/ui_imagelib.c010064400017600000144000000200371356600660700175270ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef NO_IMAGE #ifdef COCOA_TOUCH #include #else #include #endif #include "../ui_imagelib.h" #include /* sprintf */ #include /* pow */ #include /* DIGIT_STR_LEN */ #include #include #include /* bl_get_user_rc_path */ #include "cocoa.h" #if 1 #define BUILTIN_SIXEL #endif /* --- static functions --- */ #define CARD_HEAD_SIZE 0 #include "../../common/c_sixel.c" #include "../../common/c_regis.c" #include "../../common/c_animgif.c" static void value_table_refresh(u_char *value_table, /* 256 bytes */ ui_picture_modifier_t *mod) { int i, tmp; double real_gamma, real_brightness, real_contrast; real_gamma = (double)(mod->gamma) / 100; real_contrast = (double)(mod->contrast) / 100; real_brightness = (double)(mod->brightness) / 100; for (i = 0; i < 256; i++) { tmp = real_contrast * (255 * pow(((double)i + 0.5) / 255, real_gamma) - 128) + 128 * real_brightness; if (tmp >= 255) { break; } else if (tmp < 0) { value_table[i] = 0; } else { value_table[i] = tmp; } } for (; i < 256; i++) { value_table[i] = 255; } } static void adjust_pixmap(u_char *image, u_int width, u_int height, ui_picture_modifier_t *pic_mod) { u_char *value_table; u_int y; u_int x; u_char r, g, b, a; u_int32_t pixel; if (!ui_picture_modifier_is_normal(pic_mod) && (value_table = alloca(256))) { value_table_refresh(value_table, pic_mod); } else { return; } for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixel = *(((u_int32_t *)image) + (y * width + x)); a = (pixel >> 24) & 0xff; r = (pixel >> 16) & 0xff; g = (pixel >> 8) & 0xff; b = pixel & 0xff; r = (value_table[r] * (255 - pic_mod->alpha) + pic_mod->blend_red * pic_mod->alpha) / 255; g = (value_table[g] * (255 - pic_mod->alpha) + pic_mod->blend_green * pic_mod->alpha) / 255; b = (value_table[b] * (255 - pic_mod->alpha) + pic_mod->blend_blue * pic_mod->alpha) / 255; pixel = (a << 24) | (r << 16) | (g << 8) | b; *(((u_int32_t *)image) + (y * width + x)) = pixel; } } } static void adjust_cgimage(u_char *image, u_int width, u_int height, ui_picture_modifier_t *pic_mod) { u_char *value_table; u_int y; u_int x; u_char r, g, b; if (!ui_picture_modifier_is_normal(pic_mod) && (value_table = alloca(256))) { value_table_refresh(value_table, pic_mod); } else { return; } for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { r = image[0]; g = image[1]; b = image[2]; image[0] = (value_table[r] * (255 - pic_mod->alpha) + pic_mod->blend_red * pic_mod->alpha) / 255; image[1] = (value_table[g] * (255 - pic_mod->alpha) + pic_mod->blend_green * pic_mod->alpha) / 255; image[2] = (value_table[b] * (255 - pic_mod->alpha) + pic_mod->blend_blue * pic_mod->alpha) / 255; image += 4; } } } static int check_has_alpha(u_char *image, u_int width, u_int height) { u_int x; u_int y; u_char *p = image + 3; for (y = 0; y < height; y++) { for (x = 0; x < width; x++, p += 4) { if (*p != 0xff) { return 1; } } } return 0; } static int load_file(char *path, /* must be UTF-8 */ u_int *width, u_int *height, ui_picture_modifier_t *pic_mod, Pixmap *pixmap, PixmapMask *mask) { char *suffix; u_char *image; CGImageAlphaInfo info; suffix = path + strlen(path) - 4; #ifdef BUILTIN_SIXEL if (strcasecmp(suffix, ".six") == 0 && *width == 0 && *height == 0 && (image = load_sixel_from_file(path, width, height))) { adjust_pixmap(image, *width, *height, pic_mod); info = check_has_alpha(image, *width, *height) ? kCGImageAlphaPremultipliedLast : kCGImageAlphaNoneSkipLast; CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); CGContextRef ctx = CGBitmapContextCreate(image, *width, *height, 8, *width * 4, cs, info); CGColorSpaceRelease(cs); *pixmap = CGBitmapContextCreateImage(ctx); CGContextRelease(ctx); } else #endif { if (strcmp(suffix, ".gif") == 0) { char *dir; if (!strstr(path, "mlterm/anim") && /* is animation gif */ (dir = bl_get_user_rc_path("mlterm/"))) { split_animation_gif(path, dir, hash_path(path)); free(dir); } } else if (strcasecmp(suffix, ".rgs") == 0) { convert_regis_to_bmp(path); } /* XXX pic_mod is ignored */ if (!(*pixmap = cocoa_load_image(path, width, height))) { return 0; } info = CGImageGetAlphaInfo(*pixmap); if (!ui_picture_modifier_is_normal(pic_mod)) { CGDataProviderRef provider = CGImageGetDataProvider(*pixmap); CFDataRef data = CGDataProviderCopyData(provider); image = (u_char *)CFDataGetBytePtr(data); adjust_cgimage(image, *width, *height, pic_mod); CFDataRef new_data = CFDataCreate(NULL, image, CFDataGetLength(data)); CGDataProviderRef new_provider = CGDataProviderCreateWithCFData(new_data); CGImageRef new_image = CGImageCreate( *width, *height, CGImageGetBitsPerComponent(*pixmap), CGImageGetBitsPerPixel(*pixmap), CGImageGetBytesPerRow(*pixmap), CGImageGetColorSpace(*pixmap), CGImageGetBitmapInfo(*pixmap), new_provider, NULL, CGImageGetShouldInterpolate(*pixmap), CGImageGetRenderingIntent(*pixmap)); CGImageRelease(*pixmap); CFRelease(new_provider); CFRelease(data); CFRelease(new_data); *pixmap = new_image; } } if (info == kCGImageAlphaPremultipliedLast || info == kCGImageAlphaPremultipliedFirst || info == kCGImageAlphaLast || info == kCGImageAlphaFirst) { *mask = 1L; /* dummy */ } return 1; } static Pixmap resize(Pixmap pixmap, u_int new_width, u_int new_height) { CGColorSpaceRef cs = CGImageGetColorSpace(pixmap); CGContextRef ctx = CGBitmapContextCreate(NULL, new_width, new_height, CGImageGetBitsPerComponent(pixmap), 0, cs, CGImageGetAlphaInfo(pixmap)); CGContextDrawImage(ctx, CGRectMake(0, 0, new_width, new_height), pixmap); CGImageRelease(pixmap); Pixmap resized = CGBitmapContextCreateImage(ctx); CGContextRelease(ctx); return resized; } /* --- global functions --- */ void ui_imagelib_display_opened(Display *display) {} void ui_imagelib_display_closed(Display *display) {} Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, ui_picture_modifier_t *pic_mod) { Pixmap pixmap; u_int width = 0; u_int height = 0; if (!load_file(path, &width, &height, pic_mod, &pixmap, NULL)) { return None; } if (ACTUAL_WIDTH(win) != width || ACTUAL_HEIGHT(win) != height) { pixmap = resize(pixmap, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); } return pixmap; } int ui_imagelib_root_pixmap_available(Display *display) { return 0; } Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modifier_t *pic_mod) { return None; } int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) { u_int pix_width = 0; u_int pix_height = 0; if (cardinal) { return 0; } if (!load_file(path, &pix_width, &pix_height, NULL, pixmap, mask)) { return 0; } if ((*width > 0 && pix_width != *width) || (*height > 0 && pix_height != *height)) { *pixmap = resize(*pixmap, *width, *height); } else { *width = pix_width; *height = pix_height; } return 1; } void ui_destroy_image(Display *display, Pixmap pixmap) { CGImageRelease(pixmap); } void ui_destroy_mask(Display *display, PixmapMask mask /* can be NULL */) {} #endif /* NO_IMAGE */ mlterm-3.8.9/uitoolkit/quartz/ui_sb_view_factory.c010064400017600000144000000001021356600660700211320ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ mlterm-3.8.9/uitoolkit/quartz/ui_scrollbar.c010064400017600000144000000106411356600660700177410ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_scrollbar.h" #include #include "cocoa.h" /* --- static functions --- */ static void update_scroller(ui_scrollbar_t *sb) { scroller_update(sb->window.my_window, sb->num_filled_log_lines == 0 ? 1.0 : ((float)(sb->current_row + sb->num_filled_log_lines)) / ((float)sb->num_filled_log_lines), ((float)sb->num_scr_lines) / ((float)(sb->num_filled_log_lines + sb->num_scr_lines))); } /* * callbacks of ui_window_t events. */ static void window_resized(ui_window_t *win) { ui_scrollbar_t *sb; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " scrollbar resized.\n"); #endif sb = (ui_scrollbar_t*)win; sb->num_scr_lines = sb->window.height / sb->line_height; update_scroller(sb); } /* --- global functions --- */ int ui_scrollbar_init(ui_scrollbar_t *sb, ui_scrollbar_event_listener_t *sb_listener, char *view_name, char *fg_color, char *bg_color, u_int height, u_int line_height, u_int num_log_lines, u_int num_filled_log_lines, int use_transbg, ui_picture_modifier_t *pic_mod) { sb->view_name = "simple"; sb->view = NULL; sb->fg_color = NULL; sb->bg_color = NULL; sb->sb_listener = sb_listener; if (!ui_window_init(&sb->window, 10, height, 10, 0, 0, 0, 0, 0, 0, 0)) { return 0; } sb->line_height = line_height; sb->num_scr_lines = height / line_height; sb->num_log_lines = num_log_lines; sb->num_filled_log_lines = num_filled_log_lines; sb->window.window_resized = window_resized; return 1; } void ui_scrollbar_final(ui_scrollbar_t *sb) {} void ui_scrollbar_set_num_log_lines(ui_scrollbar_t *sb, u_int num_log_lines) { if (sb->num_log_lines == num_log_lines) { return; } sb->num_log_lines = num_log_lines; if (sb->num_filled_log_lines > sb->num_log_lines) { sb->num_filled_log_lines = sb->num_log_lines; } update_scroller(sb); } void ui_scrollbar_set_num_filled_log_lines(ui_scrollbar_t *sb, u_int lines) { if (lines > sb->num_log_lines) { lines = sb->num_log_lines; } if (sb->num_filled_log_lines == lines) { return; } sb->num_filled_log_lines = lines; update_scroller(sb); } int ui_scrollbar_line_is_added(ui_scrollbar_t *sb) { if ((*sb->sb_listener->screen_is_static)(sb->sb_listener->self)) { if (sb->num_filled_log_lines < sb->num_log_lines) { sb->num_filled_log_lines++; } sb->current_row--; } else if (sb->num_filled_log_lines == sb->num_log_lines) { return 0; } else { sb->num_filled_log_lines++; } update_scroller(sb); return 1; } void ui_scrollbar_reset(ui_scrollbar_t *sb) { sb->current_row = 0; update_scroller(sb); } int ui_scrollbar_move_upward(ui_scrollbar_t *sb, u_int size) { /* * XXX Adhoc solution * Fix ui_screen.c:bs_{half_}page_{up|down}ward() instead. */ if (sb->current_row + sb->num_filled_log_lines == 0) { return 0; } return ui_scrollbar_move(sb, sb->current_row - size); } int ui_scrollbar_move_downward(ui_scrollbar_t *sb, u_int size) { if (sb->current_row >= 0) { return 0; } return ui_scrollbar_move(sb, sb->current_row + size); } int ui_scrollbar_move(ui_scrollbar_t *sb, int row) { if (0 < row) { row = 0; } else if (row + (int)sb->num_filled_log_lines < 0) { row = -(sb->num_filled_log_lines); } if (sb->current_row == row) { return 0; } sb->current_row = row; update_scroller(sb); return 1; } int ui_scrollbar_set_line_height(ui_scrollbar_t *sb, u_int line_height) { if (sb->line_height == line_height) { return 0; } sb->line_height = line_height; return 1; } int ui_scrollbar_set_fg_color(ui_scrollbar_t *sb, char *fg_color) { return 1; } int ui_scrollbar_set_bg_color(ui_scrollbar_t *sb, char *bg_color) { return 1; } int ui_scrollbar_change_view(ui_scrollbar_t *sb, char *name) { return 1; } int ui_scrollbar_set_transparent(ui_scrollbar_t *sb, ui_picture_modifier_t *pic_mod, int force) { return 1; } int ui_scrollbar_unset_transparent(ui_scrollbar_t *sb) { return 1; } void ui_scrollbar_is_moved(ui_scrollbar_t *sb, float pos) { sb->current_row = sb->num_filled_log_lines * pos - sb->num_filled_log_lines; if (sb->sb_listener->screen_scroll_to) { (*sb->sb_listener->screen_scroll_to)(sb->sb_listener->self, sb->current_row); } } mlterm-3.8.9/uitoolkit/quartz/ui_scrollbar.h010064400017600000144000000003341356600660700177440ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_SCROLLBAR_H__ #define ___UI_SCROLLBAR_H__ #include "../ui_scrollbar.h" void ui_scrollbar_is_moved(ui_scrollbar_t *sb, float pos); #endifmlterm-3.8.9/uitoolkit/quartz/ui_selection_encoding.c012075500017600000144000000000001356600660700274472../xlib/ui_selection_encoding.custar kenusersmlterm-3.8.9/uitoolkit/quartz/ui_simple_sb_view.c010064400017600000144000000001021356600660700207540ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ mlterm-3.8.9/uitoolkit/quartz/ui_window.c010064400017600000144000001004751356600660700172720ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_window.h" #include /* abs */ #include /* memset/memcpy */ #include #include /* realloc/free */ #include "../ui_xic.h" #include "../ui_picture.h" #include "../ui_imagelib.h" #ifndef DISABLE_XDND #include "../ui_dnd.h" #endif #include "ui_display.h" /* ui_display_get_cursor */ #include "cocoa.h" /* win->width is not multiples of (win)->width_inc if window is maximized. */ #define RIGHT_MARGIN(win) \ ((win)->width_inc ? ((win)->width - (win)->min_width) % (win)->width_inc : 0) #define BOTTOM_MARGIN(win) \ ((win)->height_inc ? ((win)->height - (win)->min_height) % (win)->height_inc : 0) #define ParentRelative (1L) #define IS_UISCREEN(win) ((win)->selection_cleared) #define IS_UILAYOUT(win) ((win)->child_window_resized) #if 0 #define DEBUG_SCROLLABLE #endif #if 0 #define __DEBUG #endif /* --- static variables --- */ static int use_urgent_bell; /* --- static functions --- */ static void urgent_bell(ui_window_t *win, int on) { if (use_urgent_bell && (!win->is_focused || !on)) { win = ui_get_root_window(win); app_urgent_bell(on); } } static void notify_focus_in_to_children(ui_window_t *win) { u_int count; if (!win->is_focused) { if (win->inputtable > 0 || win->parent == NULL) /* check_scrollable checks root->is_focused */ { win->is_focused = 1; } if (win->inputtable > 0) { ui_xic_set_focus(win); if (win->window_focused) { (*win->window_focused)(win); } } } for (count = 0; count < win->num_children; count++) { notify_focus_in_to_children(win->children[count]); } } static void notify_focus_out_to_children(ui_window_t *win) { u_int count; if (win->is_focused) { win->is_focused = 0; ui_xic_unset_focus(win); if (win->window_unfocused) { (*win->window_unfocused)(win); } } for (count = 0; count < win->num_children; count++) { notify_focus_out_to_children(win->children[count]); } } static void notify_move_to_children(ui_window_t *win) { int count; for (count = 0; count < win->num_children; count++) { notify_move_to_children(win->children[count]); } } static u_int max_width_inc(ui_window_t *win) { u_int count; u_int width_inc; width_inc = win->width_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_WIDTH)) { u_int sub_inc; /* * XXX * we should calculate least common multiple of width_inc and sub_inc. */ if ((sub_inc = max_width_inc(win->children[count])) > width_inc) { width_inc = sub_inc; } } } return width_inc; } static u_int max_height_inc(ui_window_t *win) { u_int count; u_int height_inc; height_inc = win->height_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_HEIGHT)) { u_int sub_inc; /* * XXX * we should calculate least common multiple of width_inc and sub_inc. */ if ((sub_inc = max_height_inc(win->children[count])) > height_inc) { height_inc = sub_inc; } } } return height_inc; } static void reset_input_focus(ui_window_t *win) { u_int count; if (win->inputtable) { win->inputtable = -1; } else { win->inputtable = 0; } for (count = 0; count < win->num_children; count++) { reset_input_focus(win->children[count]); } } static void clear_margin_area(ui_window_t *win) { u_int right_margin; u_int bottom_margin; u_int win_width; u_int win_height; right_margin = RIGHT_MARGIN(win); bottom_margin = BOTTOM_MARGIN(win); win_width = win->width - right_margin; win_height = win->height - bottom_margin; if (win->wall_picture) { Pixmap pic; int src_x; int src_y; if (win->wall_picture == ParentRelative) { pic = win->parent->wall_picture; src_x = win->x; src_y = win->y; } else { pic = win->wall_picture; src_x = src_y = 0; } if (win->hmargin > 0 || right_margin > 0) { view_copy_area(win->my_window, pic, src_x, src_y, win->hmargin, ACTUAL_HEIGHT(win), 0, 0); view_copy_area(win->my_window, pic, src_x + win_width + win->hmargin, src_y, win->hmargin + right_margin, ACTUAL_HEIGHT(win), win_width + win->hmargin, 0); } if (win->vmargin > 0 || bottom_margin > 0) { view_copy_area(win->my_window, pic, src_x + win->hmargin, src_y, win_width, win->vmargin, win->hmargin, 0); view_copy_area(win->my_window, pic, src_x + win->hmargin, src_y + win_height + win->vmargin, win_width, win->vmargin + bottom_margin, win->hmargin, win_height + win->vmargin); } } else { if (win->hmargin > 0 || right_margin > 0) { view_fill_with(win->my_window, &win->bg_color, 0, 0, win->hmargin, ACTUAL_HEIGHT(win)); view_fill_with(win->my_window, &win->bg_color, win_width + win->hmargin, 0, ACTUAL_WIDTH(win) - win_width - win->hmargin, ACTUAL_HEIGHT(win)); } if (win->vmargin > 0 || bottom_margin > 0) { view_fill_with(win->my_window, &win->bg_color, win->hmargin, 0, win_width, win->vmargin); view_fill_with(win->my_window, &win->bg_color, win->hmargin, win_height + win->vmargin, win_width, ACTUAL_HEIGHT(win) - win_height - win->vmargin); } } } static void expose(ui_window_t *win, XExposeEvent *event) { int clear_margin; if (win->update_window_flag) { if (!event->force_expose) { if (win->update_window) { (*win->update_window)(win, win->update_window_flag); } return; } event->x = win->hmargin; event->y = win->vmargin; event->width = win->width; event->height = win->height; clear_margin = 1; } else { clear_margin = 0; if (event->x < win->hmargin) { event->width -= (win->hmargin - event->x); event->x = win->hmargin; clear_margin = 1; } if (event->y < win->vmargin) { event->height -= (win->vmargin - event->y); event->y = win->vmargin; clear_margin = 1; } if (!clear_margin && (event->x + event->width > win->hmargin + win->width || event->y + event->height > win->vmargin + win->height)) { clear_margin = 1; } } if (clear_margin) { clear_margin_area(win); } if (win->window_exposed) { (*win->window_exposed)(win, event->x - win->hmargin, event->y - win->vmargin, event->width, event->height); } } static int need_pointer_motion_mask(ui_window_t *win) { u_int count; if (win->event_mask & PointerMotionMask) { return 1; } for (count = 0; count < win->num_children; count++) { if (need_pointer_motion_mask(win->children[count])) { return 1; } } return 0; } /* --- global functions --- */ int ui_window_init(ui_window_t *win, u_int width, u_int height, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc, u_int hmargin, u_int vmargin, int create_gc, /* ignored */ int inputtable) { memset(win, 0, sizeof(ui_window_t)); win->fg_color.pixel = 0xff000000; win->bg_color.pixel = 0xffffffff; win->is_scrollable = 0; win->is_focused = 0; win->inputtable = inputtable; /* This flag will map window automatically in ui_window_show(). */ win->is_mapped = 1; win->create_gc = create_gc; win->width = width; win->height = height; win->min_width = min_width; win->min_height = min_height; win->width_inc = width_inc; win->height_inc = height_inc; win->sizehint_flag = SIZEHINT_WIDTH|SIZEHINT_HEIGHT; win->hmargin = hmargin; win->vmargin = vmargin; win->prev_clicked_button = -1; win->app_name = "mlterm"; return 1; } void ui_window_final(ui_window_t *win) { u_int count; Window my_window; #ifdef __DEBUG bl_debug_printf("[deleting child windows]\n"); ui_window_dump_children(win); #endif my_window = win->my_window; for (count = 0; count < win->num_children; count++) { ui_window_final(win->children[count]); } free(win->children); win->num_children = 0; ui_display_clear_selection(win->disp, win); ui_xic_deactivate(win); if (my_window) { /* * win->parent may be NULL because this function is called * from ui_layout after ui_window_remove_child(), * not only win->parent but also IS_UILAYOUT(win) is necessary. */ if (!win->parent && IS_UILAYOUT(win)) { window_dealloc(my_window); } else { view_dealloc(my_window); } } if (win->window_finalized) { (*win->window_finalized)(win); } } void ui_window_set_type_engine(ui_window_t *win, ui_type_engine_t type_engine) {} void ui_window_add_event_mask(ui_window_t *win, long event_mask) { if (event_mask & PointerMotionMask) { win->event_mask = PointerMotionMask; if (ui_get_root_window(win)->my_window) { window_accepts_mouse_moved_events(ui_get_root_window(win)->my_window, 1); } } } void ui_window_remove_event_mask(ui_window_t *win, long event_mask) { if (event_mask & PointerMotionMask) { ui_window_t *root; win->event_mask = 0; root = ui_get_root_window(win); if (root->my_window && !need_pointer_motion_mask(root)) { window_accepts_mouse_moved_events(root->my_window, 0); } } } void ui_window_ungrab_pointer(ui_window_t *win) {} int ui_window_set_wall_picture(ui_window_t *win, Pixmap pic, int do_expose) { u_int count; win->wall_picture = pic; if (win->my_window != None && do_expose) { #if 1 view_update(win->my_window, 1); #endif } for (count = 0; count < win->num_children; count++) { ui_window_set_wall_picture(win->children[count], ParentRelative, do_expose); } return 1; } int ui_window_unset_wall_picture(ui_window_t *win, int do_expose) { u_int count; win->wall_picture = None; if (win->my_window != None) { #if 0 InvalidateRect(win->my_window, NULL, FALSE); #endif } for (count = 0; count < win->num_children; count++) { ui_window_unset_wall_picture(win->children[count], do_expose); } return 1; } int ui_window_set_transparent(ui_window_t *win, ui_picture_modifier_t *pic_mod) { return 0; } int ui_window_unset_transparent(ui_window_t *win) { return 0; } void ui_window_set_cursor(ui_window_t *win, u_int cursor_shape) { win->cursor_shape = cursor_shape; } int ui_window_set_fg_color(ui_window_t *win, ui_color_t *fg_color) { if (win->fg_color.pixel == fg_color->pixel) { return 0; } win->fg_color = *fg_color; return 1; } int ui_window_set_bg_color(ui_window_t *win, ui_color_t *bg_color) { if (win->bg_color.pixel == bg_color->pixel) { return 0; } win->bg_color = *bg_color; if (win->my_window && IS_UISCREEN(win)) { view_bg_color_changed(win->my_window); ui_window_update_all(win); } return 1; } int ui_window_add_child(ui_window_t *win, ui_window_t *child, int x, int y, int map) { void *p; if ((p = realloc(win->children, sizeof(*win->children) * (win->num_children + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } win->children = p; child->parent = win; child->x = x + win->hmargin; child->y = y + win->vmargin; if (!(child->is_mapped = map) && child->inputtable > 0) { child->inputtable = -1; } win->children[win->num_children++] = child; return 1; } int ui_window_remove_child(ui_window_t *win, ui_window_t *child) { u_int count; for (count = 0; count < win->num_children; count++) { if (win->children[count] == child) { child->parent = NULL; win->children[count] = win->children[--win->num_children]; return 1; } } return 0; } ui_window_t *ui_get_root_window(ui_window_t *win) { while (win->parent != NULL) { win = win->parent; } return win; } int ui_window_show(ui_window_t *win, int hint /* If win->parent(_window) is None, specify XValue|YValue to localte window at win->x/win->y. */ ) { u_int count; if (win->my_window) { /* already shown */ return 0; } if (win->parent) { win->disp = win->parent->disp; win->parent_window = win->parent->my_window; win->gc = win->parent->gc; } #ifndef USE_QUARTZ if (hint & XNegative) { win->x += (win->disp->width - ACTUAL_WIDTH(win)); } if (hint & YNegative) { win->y += (win->disp->height - ACTUAL_HEIGHT(win)); } #endif #ifndef DISABLE_XDND /* DragAcceptFiles( win->my_window , TRUE) ; */ #endif if (win->parent && !win->parent->is_transparent && win->parent->wall_picture) { ui_window_set_wall_picture(win, ParentRelative, 0); } /* * This should be called after Window Manager settings, because * ui_set_{window|icon}_name() can be called in win->window_realized(). */ if (win->window_realized) { (*win->window_realized)(win); } /* * showing child windows. */ for (count = 0; count < win->num_children; count++) { ui_window_show(win->children[count], 0); } /* * really visualized. */ if (win->is_mapped) { if (win->inputtable > 0) { reset_input_focus(ui_get_root_window(win)); win->inputtable = 1; } } if (win->is_transparent) { ui_window_set_transparent(win, win->pic_mod); } if (IS_UISCREEN(win) && win->parent->my_window) { view_alloc(win); } return 1; } void ui_window_map(ui_window_t *win) { if (win->is_mapped) { return; } if (win->parent) { view_set_hidden(win->my_window, 0); } win->is_mapped = 1; } void ui_window_unmap(ui_window_t *win) { if (!win->is_mapped) { return; } if (win->parent) { view_set_hidden(win->my_window, 1); /* Scrollbar position is corrupt without this. */ ui_window_move(win, -1, -1); } win->is_mapped = 0; } int ui_window_resize(ui_window_t *win, u_int width, /* excluding margin */ u_int height, /* excluding margin */ ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */ ) { if (win->width == width && win->height == height) { return 0; } #ifdef COCOA_TOUCH if (!win->parent) { /* Don't allow to change the size of a root window. */ flag |= NOTIFY_TO_MYSELF; goto end; } #endif /* Max width of each window is screen width. */ if ((flag & LIMIT_RESIZE) && win->disp->width < width) { win->width = win->disp->width - win->hmargin * 2; } else { win->width = width; } /* Max.height of each window is screen height. */ if ((flag & LIMIT_RESIZE) && win->disp->height < height) { win->height = win->disp->height - win->vmargin * 2; } else { win->height = height; } if (win->parent) { #ifdef COCOA_TOUCH view_set_rect(win->my_window, win->x, win->y, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); #else view_set_rect(win->my_window, win->x, ACTUAL_HEIGHT(win->parent) - ACTUAL_HEIGHT(win) - win->y, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); #endif if ((flag & NOTIFY_TO_PARENT) && win->parent->child_window_resized) { (*win->parent->child_window_resized)(win->parent, win); } } else { /* * win->parent may be NULL because this function is called * from ui_layout after ui_window_remove_child(), * not only win->parent but also IS_UILAYOUT(win) is necessary. */ if (IS_UILAYOUT(win)) { window_resize(win->my_window, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); } } #ifdef COCOA_TOUCH end: #endif if ((flag & NOTIFY_TO_MYSELF) && win->window_resized) { (*win->window_resized)(win); win->update_window_flag = 0; /* force redraw */ } return 1; } /* * !! Notice !! * This function is not recommended. * Use ui_window_resize if at all possible. */ int ui_window_resize_with_margin(ui_window_t *win, u_int width, u_int height, ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */ ) { return ui_window_resize(win, width - win->hmargin * 2, height - win->vmargin * 2, flag); } void ui_window_set_maximize_flag(ui_window_t *win, ui_maximize_flag_t flag) { if (flag) { u_int w; u_int h; int x; int y; win = ui_get_root_window(win); window_get_position(win->my_window, &x, &y); if (flag & MAXIMIZE_HORIZONTAL) { w = win->disp->width; x = 0; } else { w = win->width; } if (flag & MAXIMIZE_VERTICAL) { h = win->disp->height; y = 0; } else { h = win->height; } window_move_resize(win->my_window, x, y, w, h); /* Same processing as ui_window_resize() */ if (win->window_resized) { (*win->window_resized)(win); win->update_window_flag = 0; /* force redraw */ } } else { /* XXX MAXIMIZE_RESTORE is not supported for now. */ } } void ui_window_set_normal_hints(ui_window_t *win, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc) { ui_window_t *root; win->min_width = min_width; win->min_height = min_height; win->width_inc = width_inc; win->height_inc = height_inc; /* root is always ui_layout_t (use_mdi is always true) on macosx/cocoa. */ root = ui_get_root_window(win); window_set_normal_hints(root->my_window, max_width_inc(root), max_height_inc(root)); } void ui_window_set_override_redirect(ui_window_t *win, int flag) {} int ui_window_set_borderless_flag(ui_window_t *win, int flag) { return 0; } int ui_window_move(ui_window_t *win, int x, int y) { if (win->parent) { x += win->parent->hmargin; y += win->parent->vmargin; } if (win->x == x && win->y == y) { return 0; } win->x = x; win->y = y; if (win->parent) { #ifdef COCOA_TOUCH view_set_rect(win->my_window, x, y, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); #else view_set_rect(win->my_window, x, ACTUAL_HEIGHT(win->parent) - ACTUAL_HEIGHT(win) - y, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); #endif } return 1; } /* * This function can be used in context except window_exposed and update_window * events. */ void ui_window_clear(ui_window_t *win, int x, int y, u_int width, u_int height) { #ifdef AUTO_CLEAR_MARGIN if (x + width >= win->width) { /* Clearing margin area */ width += win->hmargin; } if (x > 0) #endif { x += win->hmargin; } #ifdef AUTO_CLEAR_MARGIN else { /* Clearing margin area */ width += win->hmargin; } if (y + height >= win->height) { /* Clearing margin area */ height += win->vmargin; } if (y > 0) #endif { y += win->vmargin; } #ifdef AUTO_CLEAR_MARGIN else { /* Clearing margin area */ height += win->vmargin; } #endif if (win->wall_picture) { Pixmap pic; int src_x; int src_y; if (win->wall_picture == ParentRelative) { pic = win->parent->wall_picture; src_x = win->x; src_y = win->y; } else { pic = win->wall_picture; src_x = src_y = 0; } view_copy_area(win->my_window, pic, src_x + x, src_y + y, width, height, x, y); } else { view_fill_with(win->my_window, &win->bg_color, x, y, width, height); } } void ui_window_clear_all(ui_window_t *win) { ui_window_clear(win, 0, 0, win->width, win->height); } void ui_window_fill(ui_window_t *win, int x, int y, u_int width, u_int height) { ui_window_fill_with(win, &win->fg_color, x, y, width, height); } void ui_window_fill_with(ui_window_t *win, ui_color_t *color, int x, int y, u_int width, u_int height) { view_fill_with(win->my_window, color, x + win->hmargin, y + win->vmargin, width, height); } /* * This function can be used in context except window_exposed and update_window * events. */ void ui_window_blank(ui_window_t *win) {} #if 0 /* * XXX * at the present time , not used and not maintained. */ void ui_window_fill_all_with(ui_window_t *win, ui_color_t *color) {} #endif void ui_window_update(ui_window_t *win, int flag) { if (win->update_window_flag) { win->update_window_flag |= flag; } else { win->update_window_flag = flag; view_update(win->my_window, 0); } } void ui_window_update_all(ui_window_t *win) { u_int count; if (IS_UISCREEN(win)) { view_update(win->my_window, 1); } for (count = 0; count < win->num_children; count++) { ui_window_update_all(win->children[count]); } } void ui_window_idling(ui_window_t *win) { u_int count; for (count = 0; count < win->num_children; count++) { ui_window_idling(win->children[count]); } #ifdef __DEBUG if (win->button_is_pressing) { bl_debug_printf(BL_DEBUG_TAG " button is pressing...\n"); } #endif if (win->button_is_pressing && win->button_press_continued) { (*win->button_press_continued)(win, &win->prev_button_press_event); } else if (win->idling) { (*win->idling)(win); } } /* * Return value: 0 => different window. * 1 => finished processing. * -1 => continuing default processing. */ int ui_window_receive_event(ui_window_t *win, XEvent *event) { switch (event->type) { case UI_KEY_FOCUS_IN: reset_input_focus(ui_get_root_window(win)); win->inputtable = 1; win = ui_get_root_window(win); notify_focus_out_to_children(win); /* Fall through */ case UI_FOCUS_IN: urgent_bell(win, 0); notify_focus_in_to_children(win); break; case UI_FOCUS_OUT: notify_focus_out_to_children(win); break; case UI_BUTTON_PRESS: if (win->button_pressed) { XButtonEvent *bev; bev = (XButtonEvent*)event; bev->x -= win->hmargin; bev->y -= win->vmargin; (*win->button_pressed)(win, bev, bev->click_count); win->button_is_pressing = 1; win->prev_button_press_event = *bev; } break; case UI_BUTTON_RELEASE: if (win->button_released) { XButtonEvent *bev; bev = (XButtonEvent*)event; bev->x -= win->hmargin; bev->y -= win->vmargin; (*win->button_released)(win, bev); win->button_is_pressing = 0; } break; case UI_BUTTON_MOTION: if (win->button_motion) { XMotionEvent *mev; mev = (XMotionEvent*)event; mev->x -= win->hmargin; mev->y -= win->vmargin; (*win->button_motion)(win, mev); /* following button motion ... */ win->prev_button_press_event.x = mev->x; win->prev_button_press_event.y = mev->y; win->prev_button_press_event.time = mev->time; } break; case UI_POINTER_MOTION: if (win->pointer_motion) { XMotionEvent *mev; mev = (XMotionEvent*)event; mev->x -= win->hmargin; mev->y -= win->vmargin; (*win->pointer_motion)(win, mev); } break; case UI_KEY_PRESS: if (win->key_pressed) { (*win->key_pressed)(win, (XKeyEvent*)event); } break; case UI_EXPOSE: expose(win, (XExposeEvent*)event); break; case UI_SELECTION_REQUESTED: if (win->utf_selection_requested) { (*win->utf_selection_requested)(win, (XSelectionRequestEvent*)event, 0); } break; case UI_SELECTION_NOTIFIED: if (win->utf_selection_notified) { (*win->utf_selection_notified)(win, ((XSelectionNotifyEvent*)event)->data, ((XSelectionNotifyEvent*)event)->len); } break; case UI_CLOSE_WINDOW: /* root window */ win->my_window = None; if (win->window_destroyed) { (*win->window_destroyed)(win); } break; } return 1; } size_t ui_window_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { return ui_xic_get_str(win, seq, seq_len, parser, keysym, event); } /* * Scroll functions. * The caller side should clear the scrolled area. */ int ui_window_scroll_upward(ui_window_t *win, u_int height) { return ui_window_scroll_upward_region(win, 0, win->height, height); } int ui_window_scroll_upward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d in window((h) %d (w) %d)\n", boundary_start, boundary_end, height, win->height, win->width); #endif return 0; } view_scroll(win->my_window, win->hmargin, win->vmargin + boundary_start + height, /* src */ win->width, boundary_end - boundary_start - height, /* size */ win->hmargin, win->vmargin + boundary_start); /* dst */ return 1; } int ui_window_scroll_downward(ui_window_t *win, u_int height) { return ui_window_scroll_downward_region(win, 0, win->height, height); } int ui_window_scroll_downward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d\n", boundary_start, boundary_end, height); #endif return 0; } view_scroll(win->my_window, win->hmargin, win->vmargin + boundary_start, /* src */ win->width, boundary_end - boundary_start - height, /* size */ win->hmargin, win->vmargin + boundary_start + height); /* dst */ return 1; } int ui_window_scroll_leftward(ui_window_t *win, u_int width) { return ui_window_scroll_leftward_region(win, 0, win->width, width); } int ui_window_scroll_leftward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d in window((h) %d (w) %d)\n", boundary_start, boundary_end, width, win->height, win->width); #endif return 0; } view_scroll(win->my_window, win->hmargin + boundary_start + width, win->vmargin, /* src */ boundary_end - boundary_start - width, win->height, /* size */ win->hmargin + boundary_start, win->vmargin); /* dst */ return 1; } int ui_window_scroll_rightward(ui_window_t *win, u_int width) { return ui_window_scroll_rightward_region(win, 0, win->width, width); } int ui_window_scroll_rightward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d\n", boundary_start, boundary_end, width); #endif return 0; } view_scroll(win->my_window, win->hmargin + boundary_start, win->vmargin, /* src */ boundary_end - boundary_start - width, win->height, /* size */ win->hmargin + boundary_start + width, win->vmargin); /* dst */ return 1; } int ui_window_copy_area(ui_window_t *win, Pixmap src, PixmapMask mask, int src_x, /* >= 0 */ int src_y, /* >= 0 */ u_int width, u_int height, int dst_x, /* >= 0 */ int dst_y /* >= 0 */ ) { if (dst_x >= win->width || dst_y >= win->height) { return 0; } if (dst_x + width > win->width) { width = win->width - dst_x; } if (dst_y + height > win->height) { height = win->height - dst_y; } view_copy_area(win->my_window, src, src_x, src_y, width, height, dst_x + win->hmargin, dst_y + win->vmargin); return 1; } void ui_window_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height) { view_set_clip(win->my_window, x + win->hmargin, y + win->vmargin, width, height); } void ui_window_unset_clip(ui_window_t *win) { view_unset_clip(win->my_window); } void ui_window_draw_decsp_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int len) { ui_window_draw_string(win, font, fg_color, x, y, str, len); } void ui_window_draw_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int len) { view_draw_string(win->my_window, font, fg_color, x + win->hmargin, y + win->vmargin, str, len); } void ui_window_draw_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, XChar2b *str, u_int len) { view_draw_string16(win->my_window, font, fg_color, x + win->hmargin, y + win->vmargin, str, len); } void ui_window_draw_rect_frame(ui_window_t *win, int x1, int y1, int x2, int y2) { view_draw_rect_frame(win->my_window, &win->fg_color, x1 + win->hmargin, y1 + win->vmargin, x2 + win->hmargin, y2 + win->vmargin); } void ui_set_use_clipboard_selection(int use_it) {} int ui_is_using_clipboard_selection(void) { return 0; } int ui_window_set_selection_owner(ui_window_t *win, Time time) { #ifdef COCOA_TOUCH if (win->utf_selection_requested) { (*win->utf_selection_requested)(win, NULL, time); } #else if (ui_window_is_selection_owner(win)) { /* Already owner */ return 1; } #if 0 bl_debug_printf(BL_DEBUG_TAG " ui_window_set_selection_owner.\n"); #endif cocoa_clipboard_own(win->my_window); #endif return 1; } int ui_window_xct_selection_request(ui_window_t *win, Time time) { return 0; } int ui_window_utf_selection_request(ui_window_t *win, Time time) { if (win->utf_selection_notified) { const char *str; if ((str = cocoa_clipboard_get())) { (*win->utf_selection_notified)(win, str, strlen(str)); return 1; } } return 0; } void ui_window_send_picture_selection(ui_window_t *win, Pixmap pixmap, u_int width, u_int height) {} void ui_window_send_text_selection(ui_window_t *win, XSelectionRequestEvent *req_ev, u_char *sel_data, size_t sel_len, Atom sel_type) { cocoa_clipboard_set(sel_data, sel_len); } void ui_set_window_name(ui_window_t *win, u_char *name) { ui_window_t *root = ui_get_root_window(win); if (name == NULL) { name = root->app_name; } /* name is utf8 (see vt_parser.c) */ window_set_title(root->my_window, name); } void ui_set_icon_name(ui_window_t *win, u_char *name) {} void ui_window_set_icon(ui_window_t *win, ui_icon_picture_t *icon) {} void ui_window_remove_icon(ui_window_t *win) {} void ui_window_reset_group(ui_window_t *win) {} void ui_set_click_interval(int interval) {} int ui_get_click_interval(void) { return 250; /* dummy */ } u_int ui_window_get_mod_ignore_mask(ui_window_t *win, KeySym *keysyms) { return ~0; } u_int ui_window_get_mod_meta_mask(ui_window_t *win, char *mod_key) { return ModMask; } void ui_set_use_urgent_bell(int use) { use_urgent_bell = use; } void ui_window_bell(ui_window_t *win, ui_bel_mode_t mode) { urgent_bell(win, 1); if (mode & BEL_VISUAL) { view_visual_bell(win->my_window); } if (mode & BEL_SOUND) { cocoa_beep(); } } void ui_window_translate_coordinates(ui_window_t *win, int x, int y, int *global_x, int *global_y) { win = ui_get_root_window(win); window_get_position(win->my_window, global_x, global_y); *global_x += x; *global_y += y; } void ui_window_set_input_focus(ui_window_t *win) { reset_input_focus(ui_get_root_window(win)); win->inputtable = 1; view_set_input_focus(win->my_window); } #ifdef DEBUG void ui_window_dump_children(ui_window_t *win) { u_int count; bl_msg_printf("%p(%li) => ", win, win->my_window); for (count = 0; count < win->num_children; count++) { bl_msg_printf("%p(%li) ", win->children[count], win->children[count]->my_window); } bl_msg_printf("\n"); for (count = 0; count < win->num_children; count++) { ui_window_dump_children(win->children[count]); } } #endif mlterm-3.8.9/uitoolkit/quartz/ui_window.h010064400017600000144000000002211356600660700172630ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_window.h" int ui_window_clear_margin_area(ui_window_t *win); mlterm-3.8.9/uitoolkit/quartz/ui_xic.c010064400017600000144000000050221356600660700165360ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_xic.h" #include #include #include /* malloc */ /* --- global functions --- */ int ui_xic_activate(ui_window_t *win, char *xim_name, char *xim_locale) { if (win->xic) { /* already activated */ return 0; } if ((win->xic = malloc(sizeof(ui_xic_t))) == NULL) { return 0; } if ((win->xic->parser = vt_char_encoding_parser_new(VT_UTF8)) == NULL) { free(win->xic); win->xic = NULL; return 0; } ui_xic_font_set_changed(win); return 1; } int ui_xic_deactivate(ui_window_t *win) { if (win->xic == NULL) { /* already deactivated */ return 0; } (*win->xic->parser->destroy)(win->xic->parser); free(win->xic); win->xic = NULL; return 1; } char *ui_xic_get_xim_name(ui_window_t *win) { return ""; } char *ui_xic_get_default_xim_name(void) { return ""; } int ui_xic_fg_color_changed(ui_window_t *win) { return 0; } int ui_xic_bg_color_changed(ui_window_t *win) { return 0; } int ui_xic_font_set_changed(ui_window_t *win) { return 0; } int ui_xic_resized(ui_window_t *win) { return 0; } int ui_xic_set_spot(ui_window_t *win) { return 0; } size_t ui_xic_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { if ((*keysym = event->keysym) >= 0xf700) { *parser = NULL; return 0; } else if (event->utf8 == NULL) { *seq = event->keysym; *parser = NULL; return 1; } else { size_t len = strlen(event->utf8); if (len == 0 && (event->state & ControlMask)) { *seq = '\0'; len = 1; *parser = NULL; } else if (len <= seq_len) { memcpy(seq, event->utf8, seq_len); *parser = win->xic->parser; } return len; } } size_t ui_xic_get_utf8_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { return 0; } int ui_xic_filter_event(ui_window_t *win, /* Should be root window. */ XEvent *event) { return 0; } int ui_xic_set_focus(ui_window_t *win) { return 1; } int ui_xic_unset_focus(ui_window_t *win) { return 1; } int ui_xic_is_active(ui_window_t *win) { return 0; } int ui_xic_switch_mode(ui_window_t *win) { return 0; } #if 0 /* * ui_xim.c <-> ui_xic.c communication functions * Not necessary in fb. */ int ui_xim_activated(ui_window_t *win) { return 1; } int ui_xim_destroyed(ui_window_t *win) { return 1; } #endif mlterm-3.8.9/uitoolkit/quartz/cocoa.h010064400017600000144000000053371356600660700163600ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __COCOA_H__ #define __COCOA_H__ #ifdef __UI_WINDOW_H__ /* for MLTermView */ void view_alloc(ui_window_t *uiwindow); void view_dealloc(void *view); void view_update(void *view, int flag); void view_set_clip(void *view, int x, int y, u_int width, u_int height); void view_unset_clip(void *view); void view_draw_string(void *view, ui_font_t *font, ui_color_t *fg_color, int x, int y, char *str, size_t len); void view_draw_string16(void *view, ui_font_t *font, ui_color_t *fg_color, int x, int y, XChar2b *str, size_t len); void view_fill_with(void *view, ui_color_t *color, int x, int y, u_int width, u_int height); void view_draw_rect_frame(void *view, ui_color_t *color, int x1, int y1, int x2, int y2); void view_copy_area(void *view, Pixmap src, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y); void view_scroll(void *view, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y); void view_bg_color_changed(void *view); void view_visual_bell(void *view); /* for NSView */ void view_set_input_focus(void *view); void view_set_rect(void *view, int x, int y, u_int width, u_int height); void view_set_hidden(void *view, int flag); /* for NSWindow */ void window_alloc(ui_window_t *root); void window_dealloc(void *window); void window_resize(void *window, int width, int height); void window_move_resize(void *window, int x, int y, int width, int height); void window_accepts_mouse_moved_events(void *window, int accept); void window_set_normal_hints(void *window, u_int width_inc, u_int height_inc); void window_get_position(void *window, int *x, int *y); void window_set_title(void *window, const char *title); /* for NSApp */ void app_urgent_bell(int on); /* for NSScroller */ void scroller_update(void *scroller, float pos, float knob); /* for Clipboard */ void cocoa_clipboard_own(void *view); void cocoa_clipboard_set(const u_char *utf8, size_t len); const char *cocoa_clipboard_get(void); void cocoa_beep(void); #endif /* __UI_WINDOW_H__ */ #ifdef __UI_FONT_H__ /* for CGFont */ void *cocoa_create_font(const char *font_family); char *cocoa_get_font_path(void *cg_font); void cocoa_release_font(void *cg_font); u_int cocoa_font_get_advance(void *cg_font, u_int fontsize, int size_attr, u_int16_t *utf16, u_int len, u_int32_t glyph); #endif #ifdef __UI_IMAGELIB_H__ /* for CGImage */ Pixmap cocoa_load_image(const char *path, u_int *width, u_int *height); #endif /* Utility */ char *cocoa_dialog_password(const char *msg); int cocoa_dialog_okcancel(const char *msg); int cocoa_dialog_alert(const char *msg); #endif mlterm-3.8.9/uitoolkit/win32004075500017600000144000000000001356600660700144535ustar kenusersmlterm-3.8.9/uitoolkit/win32/winrs.rs010064400017600000144000000030501356600660700162350ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ MLTERM_ICON ICON "mlterm-icon-win32.ico" #include /* USE_WIN32API */ #if defined(USE_WIN32API) || defined(USE_LIBSSH2) #ifdef USE_SDL2 #define USE_WIN32GUI #undef USE_SDL2 #include "../win32/ui_connect_dialog.h" #else #include "ui_connect_dialog.h" #endif ConnectDialog DIALOG 20, 20, 151, 138 STYLE WS_POPUP | WS_DLGFRAME | DS_CENTER { GROUPBOX "Protocol", -1, 4, 4, 143, 24 RADIOBUTTON "&SSH", IDD_SSH, 8, 14, 28, 12 RADIOBUTTON "&MOSH", IDD_MOSH, 36, 14, 35, 12 RADIOBUTTON "&TELNET", IDD_TELNET, 71, 14, 35, 12 RADIOBUTTON "&RLOGIN", IDD_RLOGIN, 106, 14, 35, 12 LTEXT "Server", -1, 4, 30, 30, 8 EDITTEXT IDD_SERVER, 38, 30, 96, 10, ES_AUTOHSCROLL LTEXT "Port", -1, 4, 41, 30, 8 EDITTEXT IDD_PORT, 38, 41, 96, 10, ES_AUTOHSCROLL LTEXT "User", -1, 4, 52, 30, 8 EDITTEXT IDD_USER, 38, 52, 96, 10, ES_AUTOHSCROLL LTEXT "Pass", -1, 4, 63, 30, 8 EDITTEXT IDD_PASS, 38, 63, 96, 10, ES_PASSWORD | ES_AUTOHSCROLL LTEXT "Encoding", -1, 4, 74, 30, 8 EDITTEXT IDD_ENCODING, 38, 74, 96, 10, ES_AUTOHSCROLL LTEXT "ExecCmd",-1, 4, 85, 30, 8 EDITTEXT IDD_EXEC_CMD, 38, 85, 96, 10, ES_AUTOHSCROLL LTEXT "PrivKey", -1, 4, 96, 30, 8 EDITTEXT IDD_SSH_PRIVKEY, 38, 96, 96, 10, ES_AUTOHSCROLL CONTROL "X11 forwarding", IDD_X11, "Button", BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP, 4, 107, 126, 8 DEFPUSHBUTTON "OK", IDOK, 20, 119, 40, 12 PUSHBUTTON "Cancel", IDCANCEL, 80, 119, 40, 12 } #endif /* USE_WIN32API */ mlterm-3.8.9/uitoolkit/win32/ui.h010064400017600000144000000322011356600660700153130ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_H__ #define ___UI_H__ #undef WINVER #define WINVER 0x0500 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0500 /* for WS_EX_LAYERED , LWA_XXX , SetLayeredWindowAttributes */ #if defined(__CYGWIN__) || defined(__MSYS__) #define _WINSOCK2_H /* Don't include winsock2.h which conflicts with \ cygwin/msys types. */ #endif #define _WINSOCK_H /* Don't include winsock.h instead of winsock2.h. */ #include #include /* for msys-1.0 dvlpr */ #ifndef WM_MOUSEHWHEEL #define WM_MOUSEHWHEEL 0x20e #endif typedef struct { HINSTANCE hinst; int fd; } Display; typedef HIMC XIC; typedef HANDLE XID; typedef HANDLE Window; typedef HDC Drawable; typedef HDC Pixmap; typedef HBITMAP PixmapMask; typedef HDC GC; typedef HFONT Font; typedef HCURSOR Cursor; typedef WORD KeyCode; /* Same as type of wparam */ typedef WORD KeySym; /* Same as type of wparam */ typedef struct /* Same as definition in X11/X.h */ { int max_keypermod; KeyCode *modifiermap; } XModifierKeymap; typedef struct /* Same as definition in X11/X.h */ { unsigned char byte1; unsigned char byte2; } XChar2b; typedef struct { Window window; UINT msg; WPARAM wparam; LPARAM lparam; } XEvent; typedef struct { unsigned int state; WORD ch; /* unsigned short(16bit) defined in windef.h */ } XKeyEvent; typedef unsigned long Time; /* Same as definition in X11/X.h */ typedef unsigned long Atom; /* Same as definition in X11/X.h */ typedef struct { Time time; int x; int y; unsigned int state; unsigned int button; } XButtonEvent; typedef struct { Time time; int x; int y; unsigned int state; } XMotionEvent; typedef int XSelectionRequestEvent; /* dummy */ typedef struct { Font fid; struct ef_conv *conv; unsigned int size; /* font size */ } XFontStruct; typedef LPLOGFONT XFontSet; #define None 0L /* Same as definition in X11/X.h */ #define NoSymbol 0L /* Same as definition in X11/X.h */ #define CurrentTime 0L /* Same as definition in X11/X.h */ /* Same as definition in X11/X.h */ #define NoEventMask 0L #define KeyPressMask (1L << 0) #define KeyReleaseMask (1L << 1) #define ButtonPressMask (1L << 2) #define ButtonReleaseMask (1L << 3) #define EnterWindowMask (1L << 4) #define LeaveWindowMask (1L << 5) #define PointerMotionMask (1L << 6) #define PointerMotionHintMask (1L << 7) #define Button1MotionMask (1L << 8) #define Button2MotionMask (1L << 9) #define Button3MotionMask (1L << 10) #define Button4MotionMask (1L << 11) #define Button5MotionMask (1L << 12) #define ButtonMotionMask (1L << 13) #define KeymapStateMask (1L << 14) #define ExposureMask (1L << 15) #define VisibilityChangeMask (1L << 16) #define StructureNotifyMask (1L << 17) #define ResizeRedirectMask (1L << 18) #define SubstructureNotifyMask (1L << 19) #define SubstructureRedirectMask (1L << 20) #define FocusChangeMask (1L << 21) #define PropertyChangeMask (1L << 22) #define ColormapChangeMask (1L << 23) #define OwnerGrabButtonMask (1L << 24) #define ShiftMask (1 << 0) #define LockMask (1 << 1) #define ControlMask (1 << 2) #define Mod1Mask (1 << 3) #define Mod2Mask (1 << 4) #define Mod3Mask (1 << 5) #define Mod4Mask (1 << 6) #define Mod5Mask (1 << 7) #define Button1Mask (1 << 8) #define Button2Mask (1 << 9) #define Button3Mask (1 << 10) #define Button4Mask (1 << 11) #define Button5Mask (1 << 12) #define Button1 1 #define Button2 2 #define Button3 3 #define Button4 4 #define Button5 5 /* For msys-dtk */ #ifndef VK_OEM_1 #define VK_OEM_1 0xba #endif #ifndef VK_OEM_MINUS #define VK_OEM_MINUS 0xbd #endif #ifndef VK_OEM_2 #define VK_OEM_2 0xbf #endif #ifndef VK_OEM_3 #define VK_OEM_3 0xc0 #endif #ifndef VK_OEM_4 #define VK_OEM_4 0xdb #endif #ifndef VK_OEM_5 #define VK_OEM_5 0xdc #endif #ifndef VK_OEM_6 #define VK_OEM_6 0xdd #endif #ifndef VK_OEM_7 #define VK_OEM_7 0xde #endif #ifndef VK_OEM_AX #define VK_OEM_AX 0xe1 #endif #ifndef VK_OEM_102 #define VK_OEM_102 0xe2 #endif #ifndef VK_NONCONVERT #define VK_NONCONVERT 0x1d #endif #define XK_Super_L 0xfffe /* dummy */ #define XK_Super_R 0xfffd /* dummy */ #define XK_Hyper_L 0xfffc /* dummy */ #define XK_Hyper_R 0xfffb /* dummy */ #define XK_BackSpace VK_BACK #define XK_Tab VK_TAB #define XK_Clear VK_CLEAR #define XK_Linefeed 0xfffa /* dummy */ #define XK_Return VK_RETURN /* * VK_L... and VK_R... are available by GetKeyState(VK_SHIFT, VK_CONTROL or * VK_MENU), * but mlerm doesn't support fow now. */ #if 1 #define XK_Shift_L VK_SHIFT #define XK_Control_L VK_CONTROL #define XK_Alt_L VK_MENU #else #define XK_Shift_L VK_LSHIFT #define XK_Control_L VK_LCONTROL #define XK_Alt_L VK_LMENU #endif #define XK_Shift_R VK_RSHIFT #define XK_Control_R VK_RCONTROL #define XK_Alt_R VK_RMENU #define XK_Meta_L 0xfff9 /* dummy */ #define XK_Meta_R 0xfff8 /* dummy */ #define XK_Pause VK_PAUSE #define XK_Shift_Lock 0xfff7 /* dummy */ #define XK_Caps_Lock VK_CAPITAL #define XK_Escape VK_ESCAPE /* #define XXX VK_SPACE */ #define XK_Prior VK_PRIOR #define XK_Next VK_NEXT #define XK_End VK_END #define XK_Home VK_HOME #define XK_Left VK_LEFT #define XK_Up VK_UP #define XK_Right VK_RIGHT #define XK_Down VK_DOWN #define XK_Select VK_SELECT #define XK_Print VK_PRINT #define XK_Execute VK_EXECUTE /* #define XXX VK_SNAPSHOT ... PrintScreen key */ #define XK_Insert VK_INSERT #define XK_Delete VK_DELETE #define XK_Help VK_HELP #define XK_F1 (VK_F1 + 0xff00) /* 0xff70 (avoid to conflict with 'p') */ #define XK_F2 (VK_F2 + 0xff00) /* 0xff71 (avoid to conflict with 'q') */ #define XK_F3 (VK_F3 + 0xff00) /* 0xff72 (avoid to conflict with 'r') */ #define XK_F4 (VK_F4 + 0xff00) /* 0xff73 (avoid to conflict with 's') */ #define XK_F5 (VK_F5 + 0xff00) /* 0xff74 (avoid to conflict with 't') */ #define XK_F6 (VK_F6 + 0xff00) /* 0xff75 (avoid to conflict with 'u') */ #define XK_F7 (VK_F7 + 0xff00) /* 0xff76 (avoid to conflict with 'v') */ #define XK_F8 (VK_F8 + 0xff00) /* 0xff77 (avoid to conflict with 'w') */ #define XK_F9 (VK_F9 + 0xff00) /* 0xff78 (avoid to conflict with 'x') */ #define XK_F10 (VK_F10 + 0xff00) /* 0xff79 (avoid to conflict with 'y') */ #define XK_F11 (VK_F11 + 0xff00) /* 0xff7a (avoid to conflict with 'z') */ #define XK_F12 (VK_F12 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_F13 (VK_F13 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_F14 (VK_F14 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_F15 (VK_F15 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_F16 (VK_F16 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_F17 (VK_F17 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_F18 (VK_F18 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_F19 (VK_F19 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_F20 (VK_F20 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_F21 (VK_F21 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_F22 (VK_F22 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_F23 (VK_F23 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_F24 (VK_F24 + 0xff00) /* Add 0xff00 to be sequential number. */ #define XK_FMAX XK_F24 #define XK_Num_Lock VK_NUMLOCK #define XK_Scroll_Lock VK_SCROLL #define XK_Find 0xffeb /* dummy */ #define XK_Menu 0xffea /* dummy */ #define XK_Begin VK_CLEAR #define XK_Muhenkan VK_NONCONVERT #define XK_Henkan_Mode 0xe5 #define XK_Zenkaku_Hankaku 0xe5 /* #define XXX VK_PLAY */ /* #define XXX VK_ZOOM */ #define XK_KP_Prior 0xffe8 /* dummy */ #define XK_KP_Next 0xffe7 /* dummy */ #define XK_KP_End 0xffe6 /* dummy */ #define XK_KP_Home 0xffe5 /* dummy */ #define XK_KP_Left 0xffe4 /* dummy */ #define XK_KP_Up 0xffe3 /* dummy */ #define XK_KP_Right 0xffe2 /* dummy */ #define XK_KP_Down 0xffe1 /* dummy */ #define XK_KP_Insert 0xffe0 /* dummy */ #define XK_KP_Delete 0xffdf /* dummy */ #define XK_KP_F1 0xffde /* dummy */ #define XK_KP_F2 0xffdd /* dummy */ #define XK_KP_F3 0xffdc /* dummy */ #define XK_KP_F4 0xffdb /* dummy */ #define XK_KP_Begin 0xffda /* dummy */ #define XK_KP_Multiply (VK_MULTIPLY + 0xff00) /* 0xff6a (avoid to conflict with 'j') */ #define XK_KP_Add (VK_ADD + 0xff00) /* 0xff6b (avoid to conflict with 'k') */ #define XK_KP_Separator (VK_SEPARATOR + 0xff00) /* 0xff6c (avoid to conflict with 'l') */ #define XK_KP_Subtract (VK_SUBTRACT + 0xff00) /* 0xff6d (avoid to conflict with 'm') */ #define XK_KP_Decimal (VK_DECIMAL + 0xff00) /* 0xff6e (avoid to conflict with 'n') */ #define XK_KP_Divide (VK_DIVIDE + 0xff00) /* 0xff6f (avoid to conflict with 'o') */ #define XK_KP_0 VK_NUMPAD0 #define XK_KP_1 \ (VK_NUMPAD1 + 0xff00) /* 0xff61 (avoid to conflict with 'a') \ */ #define XK_KP_2 \ (VK_NUMPAD2 + 0xff00) /* 0xff62 (avoid to conflict with 'b') \ */ #define XK_KP_3 \ (VK_NUMPAD3 + 0xff00) /* 0xff63 (avoid to conflict with 'c') \ */ #define XK_KP_4 \ (VK_NUMPAD4 + 0xff00) /* 0xff64 (avoid to conflict with 'd') \ */ #define XK_KP_5 \ (VK_NUMPAD5 + 0xff00) /* 0xff65 (avoid to conflict with 'e') \ */ #define XK_KP_6 \ (VK_NUMPAD6 + 0xff00) /* 0xff66 (avoid to conflict with 'f') \ */ #define XK_KP_7 \ (VK_NUMPAD7 + 0xff00) /* 0xff67 (avoid to conflict with 'g') \ */ #define XK_KP_8 \ (VK_NUMPAD8 + 0xff00) /* 0xff68 (avoid to conflict with 'h') \ */ #define XK_KP_9 \ (VK_NUMPAD9 + 0xff00) /* 0xff69 (avoid to conflict with 'i') \ */ /* VK_NUMPAD0 = 0x60, VK_DIVIDE = 0x6f */ #define IsKeypadKey(ksym) ((ksym) == XK_KP_0 || (XK_KP_1 <= (ksym) && (ksym) <= XK_KP_Divide)) #define IsModifierKey(ksym) (0) #define XK_ISO_Left_Tab 0xffd9 /* XPoint(short x, short y) in Xlib. POINT(long x, long y) in win32. */ #define XPoint POINT /* XXX dummy */ #define XKeysymToKeycode(disp, ks) (ks) #define XKeycodeToKeysym(disp, kc, i) (kc) #define XKeysymToString(ks) "" #define DefaultScreen(disp) (0) #define BlackPixel(disp, screen) (0xff000000 | RGB(0, 0, 0)) #define WhitePixel(disp, screen) (0xff000000 | RGB(0xff, 0xff, 0xff)) /* Same as definition in X11/cursorfont.h */ #define XC_xterm 152 #define XC_left_ptr 68 /* Same as definition in X11/Xutil.h */ #define NoValue 0x0000 #define XValue 0x0001 #define YValue 0x0002 #define WidthValue 0x0004 #define HeightValue 0x0008 #define AllValues 0x000F #define XNegative 0x0010 #define YNegative 0x0020 /* tchar.h doesn't exist in /usr/include/w32api in cygwin. */ #ifndef _T #if defined(_UNICODE) || defined(UNICODE) #define _T(a) L##a #else #define _T(a) a #endif #endif /* _T */ #if 1 /* Use xxxxW functions for RegisterClass etc. */ #define UTF16_IME_CHAR #endif #ifdef UTF16_IME_CHAR #undef GetMessage #define GetMessage(a, b, c, d) GetMessageW(a, b, c, d) #undef DispatchMessage #define DispatchMessage(a) DispatchMessageW(a) #undef PeekMessage #define PeekMessage(a, b, c, d, e) PeekMessageW(a, b, c, d, e) #undef DefWindowProc #define DefWindowProc(a, b, c, d) DefWindowProcW(a, b, c, d) #undef WNDCLASS #define WNDCLASS WNDCLASSW #undef RegisterClass #define RegisterClass(a) RegisterClassW(a) #undef CreateWindowEx #define CreateWindowEx(a, b, c, d, e, f, g, h, i, j, k, l) \ CreateWindowExW(a, b, c, d, e, f, g, h, i, j, k, l) #define __(a) L##a #else /* UTF16_IME_CHAR */ #define __(a) _T(a) #endif /* UTF16_IME_CHAR */ int XParseGeometry(char *str, int *x, int *y, unsigned int *width, unsigned int *height); KeySym XStringToKeysym(char *str); /* === Platform dependent options === */ #undef UI_COLOR_HAS_RGB #define SUPPORT_TRUE_TRANSPARENT_BG #define TYPE_XCORE_SCALABLE #undef MANAGE_ROOT_WINDOWS_BY_MYSELF #undef MANAGE_SUB_WINDOWS_BY_MYSELF #undef INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS #define SUPPORT_POINT_SIZE_FONT #define XIM_SPOT_IS_LINE_TOP #define USE_GC #define CHANGEABLE_CURSOR #undef PLUGIN_MODULE_SUFFIX #undef KEY_REPEAT_BY_MYSELF #undef ROTATABLE_DISPLAY #undef PSEUDO_COLOR_DISPLAY #undef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE #define SUPPORT_URGENT_BELL #undef FORCE_UNICODE #undef NEED_DISPLAY_SYNC_EVERY_TIME #undef DRAW_SCREEN_IN_PIXELS #undef NO_DRAW_IMAGE_STRING /* for ui_picture.c */ #ifdef __CYGWIN__ #define HAVE_PTHREAD #else /* libpthread is not linked to mlterm explicitly for now. */ #undef HAVE_PTHREAD #endif #undef COMPOSE_DECSP_FONT #undef USE_REAL_VERTICAL_FONT #if !defined(__CYGWIN__) && !defined(__MSYS__) #define NO_DISPLAY_FD #endif #undef FLICK_SCROLL #undef UIWINDOW_SUPPORTS_PREEDITING #endif mlterm-3.8.9/uitoolkit/win32/ui_color.c010064400017600000144000000044341356600660700165130ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_color.h" #include /* memcpy,strcmp */ #include /* sscanf */ #include #include #include /* --- global functions --- */ int ui_load_named_xcolor(ui_display_t *disp, ui_color_t *xcolor, char *name) { vt_color_t color; u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; if (vt_color_parse_rgb_name(&red, &green, &blue, &alpha, name)) { return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, alpha); } if ((color = vt_get_color(name)) != VT_UNKNOWN_COLOR && IS_VTSYS_BASE_COLOR(color)) { /* * 0 : 0x00, 0x00, 0x00 * 1 : 0xff, 0x00, 0x00 * 2 : 0x00, 0xff, 0x00 * 3 : 0xff, 0xff, 0x00 * 4 : 0x00, 0x00, 0xff * 5 : 0xff, 0x00, 0xff * 6 : 0x00, 0xff, 0xff * 7 : 0xe5, 0xe5, 0xe5 */ red = (color & 0x1) ? 0xff : 0; green = (color & 0x2) ? 0xff : 0; blue = (color & 0x4) ? 0xff : 0; } else { if (strcmp(name, "gray") == 0) { red = green = blue = 190; } else if (strcmp(name, "lightgray") == 0) { red = green = blue = 211; } else { return 0; } } return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, 0xff); } int ui_load_rgb_xcolor(ui_display_t *disp, ui_color_t *xcolor, u_int8_t red, u_int8_t green, u_int8_t blue, u_int8_t alpha) { xcolor->pixel = RGB(red, green, blue) | (alpha << 24); return 1; } void ui_unload_xcolor(ui_display_t *disp, ui_color_t *xcolor) {} void ui_get_xcolor_rgba(u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_int8_t *alpha /* can be NULL */, ui_color_t *xcolor) { *red = GetRValue(xcolor->pixel); *green = GetGValue(xcolor->pixel); *blue = GetBValue(xcolor->pixel); if (alpha) { *alpha = (xcolor->pixel >> 24) & 0xff; } } int ui_xcolor_fade(ui_display_t *disp, ui_color_t *xcolor, u_int fade_ratio) { u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; ui_get_xcolor_rgba(&red, &green, &blue, &alpha, xcolor); red = (red * fade_ratio) / 100; green = (green * fade_ratio) / 100; blue = (blue * fade_ratio) / 100; ui_unload_xcolor(disp, xcolor); return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, alpha); } mlterm-3.8.9/uitoolkit/win32/ui_connect_dialog.c010064400017600000144000000321721356600660700203450ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include /* USE_WIN32API */ /* Note that protocols except ssh aren't supported if USE_LIBSSH2 is defined.*/ #if defined(USE_WIN32API) || defined(USE_LIBSSH2) #include "ui_connect_dialog.h" #include /* sprintf */ #include /* malloc */ #include /* strdup */ #include #include /* bl_parse_uri */ #ifdef USE_WIN32API #define USE_DRAGDROP #endif /* --- static variables --- */ static int selected_proto = -1; static char *default_server; /* These variables are set in IDOK. If empty string is input, nothing is set * (==NULL). */ static char *selected_server; static char *selected_port; static char *selected_user; static char *selected_pass; static char *selected_encoding; static char *selected_exec_cmd; static char *selected_ssh_privkey; static int use_x11_forwarding; #ifdef USE_DRAGDROP static WNDPROC default_edit_text_proc; #endif /* --- static functions --- */ /* * Parsing "://@::". */ static int parse(int *protoid, /* If seq doesn't have proto, -1 is set. */ char **user, /* If seq doesn't have user, NULL is set. */ char **host, char **port, char **encoding, /* If seq doesn't have encoding, NULL is set. */ char *seq /* broken in this function. */ ) { char *proto; if (!bl_parse_uri(&proto, user, host, port, NULL, encoding, seq)) { return 0; } if (proto) { if (strcmp(proto, "ssh") == 0) { *protoid = IDD_SSH; } else if (strcmp(proto, "mosh") == 0) { *protoid = IDD_MOSH; } else if (strcmp(proto, "telnet") == 0) { *protoid = IDD_TELNET; } else if (strcmp(proto, "rlogin") == 0) { *protoid = IDD_RLOGIN; } else { *protoid = -1; } } else { *protoid = -1; } return 1; } /* Return UTF-8 or MB text */ static char *get_window_text(HWND win) { WCHAR *wstr; int wlen; if ((wlen = GetWindowTextLengthW(win)) > 0 && (wstr = alloca((wlen + 1) * sizeof(WCHAR)))) { if (GetWindowTextW(win, wstr, wlen + 1) > 0) { int nbytes; char *str; UINT cp; #ifdef USE_WIN32API cp = CP_THREAD_ACP; #else cp = CP_UTF8; #endif nbytes = WideCharToMultiByte(cp, 0, wstr, wlen, NULL, 0, NULL, NULL); if (nbytes > 0 && (str = malloc(nbytes + 1))) { if ((nbytes = WideCharToMultiByte(cp, 0, wstr, wlen, str, nbytes, NULL, NULL)) > 0) { str[nbytes] = '\0'; return str; } free(str); } } } return NULL; } static void set_window_text(HWND win, char *str /* utf8 */) { WCHAR *wstr; int wlen; size_t len = strlen(str); wlen = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0); if (wlen > 0 && (wstr = alloca((wlen + 1) * sizeof(WCHAR)))) { if ((wlen = MultiByteToWideChar(CP_UTF8, 0, str, len, wstr, wlen)) > 0) { wstr[wlen] = 0; SetWindowTextW(win, wstr); } } } #ifdef USE_DRAGDROP LRESULT CALLBACK edit_text_proc(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) { switch(msg) { case WM_DROPFILES: { HDROP drop = (HDROP)wparam; if (DragQueryFile(drop, 0xffffffff, NULL, 0) > 0) { WCHAR *wpath; UINT len; if ((len = DragQueryFileW(drop, 0, NULL, 0)) > 0 && (wpath = alloca(sizeof(WCHAR) * (len + 1)))) { DragQueryFileW(drop, 0, wpath, len + 1); wpath[len] = 0; SetWindowTextW(window, wpath); } } DragFinish(drop); break; } } return CallWindowProc((WNDPROC)default_edit_text_proc, window, msg, wparam, lparam); } #endif LRESULT CALLBACK dialog_proc(HWND dlgwin, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { case WM_INITDIALOG: { char *user_env; int item; item = selected_proto = IDD_SSH; user_env = getenv("USERNAME"); #if 1 if (selected_ssh_privkey) { set_window_text(GetDlgItem(dlgwin, IDD_SSH_PRIVKEY), selected_ssh_privkey); selected_ssh_privkey = NULL; } #endif if (default_server) { char *default_server_dup; char *user; int proto; char *server; char *port; char *encoding; #if 1 if (selected_exec_cmd) { SetWindowText(GetDlgItem(dlgwin, IDD_EXEC_CMD), selected_exec_cmd); selected_exec_cmd = NULL; } #endif if ((default_server_dup = alloca(strlen(default_server) + 1)) && parse(&proto, &user, &server, &port, &encoding, strcpy(default_server_dup, default_server))) { SetWindowText(GetDlgItem(dlgwin, IDD_SERVER), server); item = IDD_USER; if (port) { SetWindowText(GetDlgItem(dlgwin, IDD_PORT), port); } if (user || (user = user_env)) { SetWindowText(GetDlgItem(dlgwin, IDD_USER), user); item = IDD_PASS; } #ifdef USE_LIBSSH2 if (proto == IDD_SSH || proto == IDD_MOSH) { selected_proto = proto; } #else if (proto != -1) { selected_proto = proto; } #endif if (encoding) { SetWindowText(GetDlgItem(dlgwin, IDD_ENCODING), encoding); } } } else if (user_env) { SetWindowText(GetDlgItem(dlgwin, IDD_USER), user_env); } #ifdef USE_LIBSSH2 EnableWindow(GetDlgItem(dlgwin, IDD_TELNET), FALSE); EnableWindow(GetDlgItem(dlgwin, IDD_RLOGIN), FALSE); #ifdef NO_DYNAMIC_LOAD_SSH EnableWindow(GetDlgItem(dlgwin, IDD_MOSH), FALSE); #endif #endif CheckRadioButton(dlgwin, IDD_SSH, IDD_RLOGIN, selected_proto); #ifdef USE_LIBSSH2 if (use_x11_forwarding) { SendMessage(GetDlgItem(dlgwin, IDD_X11), BM_SETCHECK, BST_CHECKED, 0); } #else EnableWindow(GetDlgItem(dlgwin, IDD_X11), FALSE); #endif #ifdef USE_DRAGDROP DragAcceptFiles(GetDlgItem(dlgwin, IDD_SSH_PRIVKEY), TRUE); default_edit_text_proc = (WNDPROC)GetWindowLongPtr(GetDlgItem(dlgwin, IDD_SSH_PRIVKEY), GWLP_WNDPROC); SetWindowLongPtr(GetDlgItem(dlgwin, IDD_SSH_PRIVKEY), GWLP_WNDPROC, edit_text_proc); #endif if (item == IDD_SSH) { item = selected_proto; } SetFocus(GetDlgItem(dlgwin, item)); return FALSE; } case WM_COMMAND: switch (LOWORD(wparam)) { case IDOK: selected_server = get_window_text(GetDlgItem(dlgwin, IDD_SERVER)); selected_port = get_window_text(GetDlgItem(dlgwin, IDD_PORT)); selected_user = get_window_text(GetDlgItem(dlgwin, IDD_USER)); selected_pass = get_window_text(GetDlgItem(dlgwin, IDD_PASS)); selected_encoding = get_window_text(GetDlgItem(dlgwin, IDD_ENCODING)); selected_exec_cmd = get_window_text(GetDlgItem(dlgwin, IDD_EXEC_CMD)); selected_ssh_privkey = get_window_text(GetDlgItem(dlgwin, IDD_SSH_PRIVKEY)); EndDialog(dlgwin, IDOK); break; case IDCANCEL: selected_proto = -1; EndDialog(dlgwin, IDCANCEL); break; case IDD_SSH: case IDD_MOSH: case IDD_TELNET: case IDD_RLOGIN: selected_proto = LOWORD(wparam); CheckRadioButton(dlgwin, IDD_SSH, IDD_RLOGIN, selected_proto); break; case IDD_X11: use_x11_forwarding = (SendMessage(GetDlgItem(dlgwin, IDD_X11), BM_GETCHECK, 0, 0) == BST_CHECKED); break; default: return FALSE; } return TRUE; #ifdef USE_DRAGDROP case WM_CLOSE: DragAcceptFiles(GetDlgItem(dlgwin, IDD_SSH_PRIVKEY), FALSE); /* Fall through */ #endif default: return FALSE; } return TRUE; } static char *exec_servman(char *server, DWORD server_len) { HANDLE input_write; HANDLE input_read_tmp; HANDLE input_read; SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; STARTUPINFO si; DWORD len; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; if (!CreatePipe(&input_read_tmp, &input_write, &sa, 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreatePipe() failed.\n"); #endif return NULL; } if (!DuplicateHandle(GetCurrentProcess(), input_read_tmp, GetCurrentProcess(), &input_read /* Address of new handle. */, 0, FALSE /* Make it uninheritable. */, DUPLICATE_SAME_ACCESS)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " DuplicateHandle() failed.\n"); #endif CloseHandle(input_read_tmp); goto error; } CloseHandle(input_read_tmp); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES | STARTF_FORCEOFFFEEDBACK; si.hStdOutput = input_write; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); /* * Use this if you want to hide the child: * si.wShowWindow = SW_HIDE; * Note that dwFlags must include STARTF_USESHOWWINDOW if you want to * use the wShowWindow flags. */ /* * Win32 environmental variables are cleared in a cygwin program. * servman.exe (which works without cygwin APIs) needs HOMEPATH environmental variable. */ #ifndef USE_WIN32API SetEnvironmentVariable("HOMEPATH", getenv("HOMEPATH")); #endif if (!CreateProcess("servman.exe", "servman.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreateProcess() failed.\n"); #endif goto error; } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); CloseHandle(input_write); if (!ReadFile(input_read, server, server_len - 1, &len, NULL)) { CloseHandle(input_read); return NULL; } server[len] = '\0'; CloseHandle(input_read); return server; error: CloseHandle(input_write); CloseHandle(input_read); return NULL; } /* --- global functions --- */ int ui_connect_dialog(char **uri, /* Should be free'ed by those who call this. */ char **pass, /* Same as uri. If pass is not input, "" is set. */ char **exec_cmd, /* Same as uri. If exec_cmd is not input, NULL is set. */ char **privkey, /* in/out */ int *x11_fwd, /* in/out */ char *display_name, Window parent_window, char *def_server /* (@)(:)(:). */ ) { int ret; char *proto; use_x11_forwarding = *x11_fwd; if ((!def_server || *def_server == '\0' || strcmp(def_server, "?") == 0) && (default_server = alloca(1024))) { if ((default_server = exec_servman(default_server, 1024))) { size_t len = strlen(default_server); char *p; if (len > 4 && strcmp(default_server + len - 4, " x11") == 0) { default_server[(len -= 4)] = '\0'; use_x11_forwarding = 1; } #if 1 if ((p = strchr(default_server, ' '))) { *p = '\0'; selected_exec_cmd = p + 1; } #endif } } else { default_server = def_server; } if (!(selected_ssh_privkey = *privkey)) { char *home; char *p; if ((home = bl_get_home_dir()) && (p = alloca(strlen(home) + 14 + 1))) { #ifdef USE_WIN32API sprintf(p, "%s\\mlterm\\id_rsa", home); #else sprintf(p, "%s/.ssh/id_rsa", home); #endif selected_ssh_privkey = p; } } #ifdef DEBUG bl_debug_printf("DEFAULT server %s\n", default_server); #endif DialogBox(GetModuleHandle(NULL), "ConnectDialog", #ifdef USE_SDL2 NULL, #else parent_window, #endif (DLGPROC)dialog_proc); ret = 0; if (selected_server == NULL) { goto end; } else if (selected_proto == IDD_SSH) { proto = "ssh://"; } else if (selected_proto == IDD_MOSH) { proto = "mosh://"; } else if (selected_proto == IDD_TELNET) { proto = "telnet://"; } else if (selected_proto == IDD_RLOGIN) { proto = "rlogin://"; } else { goto end; } if (!(*uri = malloc(strlen(proto) + (selected_user ? strlen(selected_user) + 1 : 0) + strlen(selected_server) + 1 + (selected_port ? strlen(selected_port) + 1 : 0) + (selected_encoding ? strlen(selected_encoding) + 1 : 0)))) { goto end; } (*uri)[0] = '\0'; strcat(*uri, proto); if (selected_user) { strcat(*uri, selected_user); strcat(*uri, "@"); } strcat(*uri, selected_server); if (selected_port) { strcat(*uri, ":"); strcat(*uri, selected_port); } if (selected_encoding) { strcat(*uri, ":"); strcat(*uri, selected_encoding); } *pass = selected_pass ? selected_pass : strdup(""); *exec_cmd = selected_exec_cmd; *privkey = selected_ssh_privkey; *x11_fwd = use_x11_forwarding; /* Successfully */ ret = 1; end: selected_proto = -1; default_server = NULL; free(selected_server); selected_server = NULL; free(selected_port); selected_port = NULL; free(selected_user); selected_user = NULL; free(selected_encoding); selected_encoding = NULL; if (ret == 0) { free(selected_pass); free(selected_exec_cmd); free(selected_ssh_privkey); } selected_pass = NULL; selected_exec_cmd = NULL; selected_ssh_privkey = NULL; return ret; } #endif mlterm-3.8.9/uitoolkit/win32/ui_connect_dialog.h010064400017600000144000000007211356600660700203450ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_CONNECT_DIALOG_H__ #define ___UI_CONNECT_DIALOG_H__ #include "../ui_connect_dialog.h" /* Exported for winrs.rs. */ #define IDD_SSH 10 #define IDD_MOSH 11 #define IDD_TELNET 12 #define IDD_RLOGIN 13 #define IDD_SERVER 14 #define IDD_PORT 15 #define IDD_USER 16 #define IDD_PASS 17 #define IDD_ENCODING 18 #define IDD_EXEC_CMD 19 #define IDD_SSH_PRIVKEY 20 #define IDD_X11 21 #endif mlterm-3.8.9/uitoolkit/win32/ui_display.c010064400017600000144000000213031356600660700170340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_display.h" #include /* sprintf */ #include /* memset/memcpy */ #include /* getenv */ #include /* USE_WIN32API */ #ifndef USE_WIN32API #include /* open */ #endif #include /* close */ #include #include #include #include #include "../ui_window.h" #include "../ui_picture.h" #include "ui_gdiobj_pool.h" #define DISP_IS_INITED (_disp.display) #if 0 #define __DEBUG #endif /* --- static variables --- */ static ui_display_t _disp; /* Singleton */ static Display _display; #ifdef USE_WIN32API static DWORD main_tid; /* XXX set in main(). */ #endif /* --- static functions --- */ #ifdef USE_WIN32API static VOID CALLBACK timer_proc(HWND hwnd, UINT msg, UINT timerid, DWORD time) { ui_display_idling(&_disp); } #endif static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { XEvent event; int count; event.window = hwnd; event.msg = msg; event.wparam = wparam; event.lparam = lparam; for (count = 0; count < _disp.num_roots; count++) { int val; val = ui_window_receive_event(_disp.roots[count], &event); if (val == 1) { return 0; } else if (val == -1) { break; } } return DefWindowProc(hwnd, msg, wparam, lparam); } static int dialog_cb(bl_dialog_style_t style, const char *msg) { if (style == BL_DIALOG_OKCANCEL) { if (MessageBoxA(NULL, msg, "", MB_OKCANCEL) == IDOK) { return 1; } else { return 0; } } else if (style == BL_DIALOG_ALERT) { MessageBoxA(NULL, msg, "", MB_ICONSTOP); return 1; } else { return -1; } } /* --- global functions --- */ ui_display_t *ui_display_open(char *disp_name, /* Ignored */ u_int depth /* Ignored */ ) { #ifndef UTF16_IME_CHAR WNDCLASS wc; #else WNDCLASSW wc; #endif int fd; if (DISP_IS_INITED) { /* Already opened. */ return &_disp; } #if 0 SetDllDirectory(""); { HMODULE module; #if 1 if ((module = LoadLibrary("Shcore"))) { typedef HRESULT (*func)(int); func set_process_dpi_awareness; if ((set_process_dpi_awareness = (func)GetProcAddress(module, "SetProcessDpiAwareness"))) { (*set_process_dpi_awareness)(1 /*PROCESS_SYSTEM_DPI_AWARE*/); } FreeLibrary(module); } #else if ((module = LoadLibrary("User32"))) { typedef HRESULT (*func)(int); func set_process_dpi_awareness; if ((set_process_dpi_awareness = (func)GetProcAddress(module, "SetProcessDpiAwarenessContext"))) { (*set_process_dpi_awareness)(-2 /*DPI_AWARENESS_CONTEXT_SYSTEM_AWARE*/); } FreeLibrary(module); } #endif } #endif #ifdef USE_WIN32API /* * XXX * vt_pty_ssh_new() isn't called from the main thread, so main_tid * must be set here, not in vt_pty_ssh_new(). */ main_tid = GetCurrentThreadId(); #endif /* Callback should be set before bl_dialog() is called. */ bl_dialog_set_callback(dialog_cb); _display.hinst = GetModuleHandle(NULL); /* Prepare window class */ ZeroMemory(&wc, sizeof(WNDCLASS)); wc.lpfnWndProc = window_proc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.hInstance = _display.hinst; wc.hIcon = LoadIcon(_display.hinst, "MLTERM_ICON"); _disp.cursors[2] = wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = 0; wc.lpszClassName = __("MLTERM"); if (!RegisterClass(&wc)) { bl_dialog(BL_DIALOG_ALERT, "Failed to register class"); return NULL; } _disp.width = GetSystemMetrics(SM_CXSCREEN); _disp.height = GetSystemMetrics(SM_CYSCREEN); _disp.depth = 24; if ((_disp.gc = ui_gc_new(&_display, None)) == NULL) { return NULL; } if (!(_disp.name = getenv("DISPLAY"))) { _disp.name = ":0.0"; } #ifdef USE_WIN32API fd = -1; #else if ((fd = open("/dev/windows", O_NONBLOCK, 0)) == -1) { ui_gc_destroy(_disp.gc); return NULL; } bl_file_set_cloexec(fd); #endif ui_gdiobj_pool_init(); /* _disp is initialized successfully. */ _display.fd = fd; _disp.display = &_display; #ifdef USE_WIN32API /* ui_window_manager_idling() called in 0.1sec. */ SetTimer(NULL, 0, 100, timer_proc); #endif return &_disp; } void ui_display_close(ui_display_t *disp) { if (disp == &_disp) { ui_display_close_all(); } } void ui_display_close_all(void) { u_int count; if (!DISP_IS_INITED) { return; } ui_picture_display_closed(_disp.display); ui_gc_destroy(_disp.gc); for (count = 0; count < _disp.num_roots; count++) { ui_window_unmap(_disp.roots[count]); ui_window_final(_disp.roots[count]); } free(_disp.roots); #if 0 for (count = 0; count < (sizeof(_disp.cursors) / sizeof(_disp.cursors[0])); count++) { if (_disp.cursors[count]) { CloseHandle(_disp.cursors[count]); } } #endif if (_display.fd != -1) { close(_display.fd); } _disp.display = NULL; ui_gdiobj_pool_final(); } ui_display_t **ui_get_opened_displays(u_int *num) { static ui_display_t *opened_disp = &_disp; if (!DISP_IS_INITED) { *num = 0; return NULL; } *num = 1; return &opened_disp; } int ui_display_fd(ui_display_t *disp) { return disp->display->fd; } int ui_display_show_root(ui_display_t *disp, ui_window_t *root, int x, int y, int hint, char *app_name, Window parent_window /* Ignored */ ) { void *p; if ((p = realloc(disp->roots, sizeof(ui_window_t*) * (disp->num_roots + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } disp->roots = p; root->disp = disp; root->parent = NULL; root->parent_window = disp->my_window; root->gc = disp->gc; root->x = x; root->y = y; if (app_name) { root->app_name = app_name; } disp->roots[disp->num_roots++] = root; return ui_window_show(root, hint); } int ui_display_remove_root(ui_display_t *disp, ui_window_t *root) { u_int count; for (count = 0; count < disp->num_roots; count++) { if (disp->roots[count] == root) { ui_window_unmap(root); ui_window_final(root); disp->num_roots--; if (count == disp->num_roots) { disp->roots[count] = NULL; } else { disp->roots[count] = disp->roots[disp->num_roots]; } return 1; } } return 0; } void ui_display_idling(ui_display_t *disp) { u_int count; for (count = 0; count < disp->num_roots; count++) { ui_window_idling(disp->roots[count]); } } /* * * 0: Receive WM_QUIT * 1: Receive other messages. */ int ui_display_receive_next_event(ui_display_t *disp) { MSG msg; #ifdef USE_WIN32API /* 0: WM_QUIT, -1: Error */ if (GetMessage(&msg, NULL, 0, 0) <= 0) { return 0; } TranslateMessage(&msg); DispatchMessage(&msg); #endif while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { return 0; } TranslateMessage(&msg); DispatchMessage(&msg); } return 1; } /* * Folloing functions called from ui_window.c */ int ui_display_own_selection(ui_display_t *disp, ui_window_t *win) { if (disp->selection_owner) { ui_display_clear_selection(disp, disp->selection_owner); } disp->selection_owner = win; return 1; } int ui_display_clear_selection(ui_display_t *disp, ui_window_t *win) { if (disp->selection_owner == NULL || disp->selection_owner != win) { return 0; } disp->selection_owner->is_sel_owner = 0; if (disp->selection_owner->selection_cleared) { (*disp->selection_owner->selection_cleared)(disp->selection_owner); } disp->selection_owner = NULL; return 1; } XModifierKeymap *ui_display_get_modifier_mapping(ui_display_t *disp) { return disp->modmap.map; } void ui_display_update_modifier_mapping(ui_display_t *disp, u_int serial) { /* dummy */ } Cursor ui_display_get_cursor(ui_display_t *disp, u_int shape) { int idx; LPCTSTR name; /* * XXX * cursor[0] == XC_xterm / cursor[1] == XC_left_ptr / cursor[2] == not used * Mlterm uses only these shapes. */ if (shape == XC_xterm) { idx = 0; name = IDC_IBEAM; } else if (shape == XC_left_ptr) { idx = 1; name = IDC_ARROW; /* already loaded in ui_display_open() */ } else { return None; } if (!disp->cursors[idx]) { disp->cursors[idx] = LoadCursor(NULL, name); } return disp->cursors[idx]; } XID ui_display_get_group_leader(ui_display_t *disp) { return None; } #ifdef USE_WIN32API void ui_display_trigger_pty_read(void) { /* Exit GetMessage() in x_display_receive_next_event(). */ PostThreadMessage(main_tid, WM_APP, 0, 0); } #endif mlterm-3.8.9/uitoolkit/win32/ui_display.h010064400017600000144000000003331356600660700170410ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_DISPLAY_H__ #define ___UI_DISPLAY_H__ #include "../ui_display.h" Cursor ui_display_get_cursor(ui_display_t *disp, u_int shape); #endif mlterm-3.8.9/uitoolkit/win32/ui_dnd.c010064400017600000144000000072301356600660700161370ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef DISABLE_XDND #include "../ui_window.h" #include "../ui_dnd.h" #include /* USE_WIN32API */ #if defined(__CYGWIN__) || defined(__MSYS__) #include /* bl_conv_to_posix_path */ #endif #include #include #ifndef USE_WIN32API #include #include #endif /* --- static functions --- */ static size_t conv_utf16_to_utf8(u_char *dst, size_t dst_len, u_char *src, size_t src_len) { size_t conv_len; ef_parser_t *utf16_parser; ef_conv_t *utf8_conv; utf16_parser = ef_utf16le_parser_new(); utf8_conv = ef_utf8_conv_new(); (*utf16_parser->init)(utf16_parser); (*utf16_parser->set_str)(utf16_parser, src, src_len); (*utf8_conv->init)(utf8_conv); if ((conv_len = (*utf8_conv->convert)(utf8_conv, dst, dst_len, utf16_parser)) == dst_len) { conv_len--; } dst[conv_len] = '\0'; (*utf16_parser->destroy)(utf16_parser); (*utf8_conv->destroy)(utf8_conv); return conv_len; } /* --- global functions --- */ /* * XFilterEvent(event, w) analogue. * return 0 if the event should be processed in the mlterm mail loop. * return 1 if nothing to be done is left for the event. */ int ui_dnd_filter_event(XEvent *event, ui_window_t *win) { HDROP drop; UINT num; int count; int do_scp; #ifndef USE_WIN32API ef_conv_t *utf16_conv; ef_parser_t *utf8_parser; #endif if (event->msg != WM_DROPFILES) { return 0; } /* Shift+DnD => SCP */ do_scp = (GetKeyState(VK_SHIFT) < 0); #ifndef USE_WIN32API utf8_parser = ef_utf8_parser_new(); utf16_conv = ef_utf16le_conv_new(); #endif drop = (HDROP)event->wparam; num = DragQueryFile(drop, 0xffffffff, NULL, 0); for (count = 0; count < num; count++) { WCHAR utf16_path[MAX_PATH]; UINT path_len; if ((path_len = DragQueryFileW(drop, count, utf16_path, sizeof(utf16_path) / sizeof(utf16_path[0]))) > 0) { u_char utf8_path[MAX_PATH]; #ifdef USE_WIN32API if (do_scp) { path_len++; /* NULL terminator */ if (win->set_xdnd_config && conv_utf16_to_utf8(utf8_path, sizeof(utf8_path), utf16_path, path_len * sizeof(utf16_path[0])) > 0) { (*win->set_xdnd_config)(win, NULL, "scp", utf8_path); } } else { path_len *= sizeof(utf16_path[0]); if (win->utf_selection_notified) { (*win->utf_selection_notified)(win, (u_char*)utf16_path, path_len); } } #else u_char posix_path[MAX_PATH]; path_len++; /* NULL terminator */ if (conv_utf16_to_utf8(utf8_path, sizeof(utf8_path), utf16_path, path_len * sizeof(utf16_path[0])) == 0 || bl_conv_to_posix_path(utf8_path, posix_path, sizeof(posix_path)) < 0) { continue; } if (do_scp) { if (win->set_xdnd_config) { (*win->set_xdnd_config)(win, NULL, "scp", posix_path); } } else if (win->utf_selection_notified) { (*utf8_parser->init)(utf8_parser); (*utf8_parser->set_str)(utf8_parser, posix_path, strlen(posix_path) + 1); (*utf16_conv->init)(utf16_conv); if ((path_len = (*utf16_conv->convert)(utf16_conv, (u_char*)utf16_path, sizeof(utf16_path), utf8_parser)) > 0) { (*win->utf_selection_notified)(win, (u_char*)utf16_path, path_len); } } #endif } } #ifndef USE_WIN32API (*utf8_parser->destroy)(utf8_parser); (*utf16_conv->destroy)(utf16_conv); #endif DragFinish(drop); return 1; } #endif /* DISABLE_XDND */ mlterm-3.8.9/uitoolkit/win32/ui_font.c010064400017600000144000000546541356600660700163540ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_font.h" #include #include /* memset/strncasecmp */ #include #include /* bl_snprintf */ #include /* alloca */ #include /* bl_str_sep/bl_str_to_int */ #include /* bl_get_lang() */ #include #include #include /* ui_convert_to_xft_ucs4 */ #ifdef USE_OT_LAYOUT #include "otl.h" #endif #define FOREACH_FONT_ENCODINGS(csinfo, font_encoding_p) \ for ((font_encoding_p) = &csinfo->encoding_names[0]; *(font_encoding_p); (font_encoding_p)++) #if 0 #define __DEBUG #endif typedef struct wincs_info { DWORD cs; vt_char_encoding_t encoding; } wincs_info_t; typedef struct cs_info { ef_charset_t cs; DWORD wincs; } cs_info_t; /* --- static variables --- */ static wincs_info_t wincs_info_table[] = { { DEFAULT_CHARSET, VT_UNKNOWN_ENCODING, }, { SYMBOL_CHARSET, VT_UNKNOWN_ENCODING, }, { OEM_CHARSET, VT_UNKNOWN_ENCODING, }, { ANSI_CHARSET, VT_CP1252, }, { RUSSIAN_CHARSET, VT_CP1251, }, { GREEK_CHARSET, VT_CP1253, }, { TURKISH_CHARSET, VT_CP1254, }, { BALTIC_CHARSET, VT_CP1257, }, { HEBREW_CHARSET, VT_CP1255, }, { ARABIC_CHARSET, VT_CP1256, }, { SHIFTJIS_CHARSET, VT_SJIS, }, { HANGEUL_CHARSET, VT_UHC, }, { GB2312_CHARSET, VT_GBK, }, { CHINESEBIG5_CHARSET, VT_BIG5}, { JOHAB_CHARSET, VT_JOHAB, }, { THAI_CHARSET, VT_TIS620, }, { EASTEUROPE_CHARSET, VT_ISO8859_3, }, { MAC_CHARSET, VT_UNKNOWN_ENCODING, }, }; static cs_info_t cs_info_table[] = { { ISO10646_UCS4_1, DEFAULT_CHARSET, }, { ISO10646_UCS4_1_V, DEFAULT_CHARSET, }, { DEC_SPECIAL, SYMBOL_CHARSET, }, { ISO8859_1_R, ANSI_CHARSET, }, { ISO8859_2_R, DEFAULT_CHARSET, }, { ISO8859_3_R, EASTEUROPE_CHARSET, }, { ISO8859_4_R, DEFAULT_CHARSET, }, { ISO8859_5_R, RUSSIAN_CHARSET, }, { ISO8859_6_R, ARABIC_CHARSET, }, { ISO8859_7_R, GREEK_CHARSET, }, { ISO8859_8_R, HEBREW_CHARSET, }, { ISO8859_9_R, TURKISH_CHARSET, }, { ISO8859_10_R, DEFAULT_CHARSET, }, { TIS620_2533, THAI_CHARSET, }, { ISO8859_13_R, DEFAULT_CHARSET, }, { ISO8859_14_R, DEFAULT_CHARSET, }, { ISO8859_15_R, DEFAULT_CHARSET, }, { ISO8859_16_R, DEFAULT_CHARSET, }, { TCVN5712_3_1993, VIETNAMESE_CHARSET, }, { ISCII_ASSAMESE, DEFAULT_CHARSET, }, { ISCII_BENGALI, DEFAULT_CHARSET, }, { ISCII_GUJARATI, DEFAULT_CHARSET, }, { ISCII_HINDI, DEFAULT_CHARSET, }, { ISCII_KANNADA, DEFAULT_CHARSET, }, { ISCII_MALAYALAM, DEFAULT_CHARSET, }, { ISCII_ORIYA, DEFAULT_CHARSET, }, { ISCII_PUNJABI, DEFAULT_CHARSET, }, { ISCII_TAMIL, DEFAULT_CHARSET, }, { ISCII_TELUGU, DEFAULT_CHARSET, }, { VISCII, VIETNAMESE_CHARSET, }, { KOI8_R, RUSSIAN_CHARSET, }, { KOI8_U, RUSSIAN_CHARSET, }, { KOI8_T, RUSSIAN_CHARSET, }, { GEORGIAN_PS, DEFAULT_CHARSET, }, { CP1250, EASTEUROPE_CHARSET, }, { CP1251, RUSSIAN_CHARSET, }, { CP1252, ANSI_CHARSET, }, { CP1253, GREEK_CHARSET, }, { CP1254, TURKISH_CHARSET, }, { CP1255, HEBREW_CHARSET, }, { CP1256, ARABIC_CHARSET, }, { CP1257, BALTIC_CHARSET, }, { CP1258, VIETNAMESE_CHARSET, }, { JISX0201_KATA, SHIFTJIS_CHARSET, }, { JISX0201_ROMAN, SHIFTJIS_CHARSET, }, { JISC6226_1978, SHIFTJIS_CHARSET, }, { JISX0208_1983, SHIFTJIS_CHARSET, }, { JISX0208_1990, SHIFTJIS_CHARSET, }, { JISX0212_1990, SHIFTJIS_CHARSET, }, { JISX0213_2000_1, SHIFTJIS_CHARSET, }, { JISX0213_2000_2, SHIFTJIS_CHARSET, }, { KSC5601_1987, HANGEUL_CHARSET, }, { UHC, HANGEUL_CHARSET, }, { JOHAB, JOHAB_CHARSET, }, { GB2312_80, GB2312_CHARSET, }, { GBK, GB2312_CHARSET, }, { BIG5, CHINESEBIG5_CHARSET, }, { HKSCS, DEFAULT_CHARSET, }, { CNS11643_1992_1, GB2312_CHARSET, }, { CNS11643_1992_2, GB2312_CHARSET, }, { CNS11643_1992_3, GB2312_CHARSET, }, { CNS11643_1992_4, GB2312_CHARSET, }, { CNS11643_1992_5, GB2312_CHARSET, }, { CNS11643_1992_6, GB2312_CHARSET, }, { CNS11643_1992_7, GB2312_CHARSET, }, }; static GC display_gc; static int use_point_size; /* --- static functions --- */ static wincs_info_t *get_wincs_info(ef_charset_t cs) { int count; for (count = 0; count < sizeof(cs_info_table) / sizeof(cs_info_t); count++) { if (cs_info_table[count].cs == cs) { DWORD wincs; wincs = cs_info_table[count].wincs; for (count = 0; count < sizeof(wincs_info_table) / sizeof(wincs_info_t); count++) { if (wincs_info_table[count].cs == wincs) { return &wincs_info_table[count]; } } break; } } #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " not supported cs(%x).\n", cs); #endif return NULL; } static int parse_font_name( char **font_family, int *font_weight, /* if weight is not specified in font_name , not changed. */ int *is_italic, /* if slant is not specified in font_name , not changed. */ double *font_size, /* if size is not specified in font_name , not changed. */ u_int *percent, /* if percent is not specified in font_name , not changed. */ char *font_name /* modified by this function. */ ) { char *p; size_t len; /* * Format. * [Family]( [WEIGHT] [SLANT] [SIZE]:[Percentage]) */ *font_family = font_name; if ((p = strrchr(font_name, ':'))) { /* Parsing ":[Percentage]" */ if (bl_str_to_uint(percent, p + 1)) { *p = '\0'; } #ifdef DEBUG else { bl_warn_printf(BL_DEBUG_TAG " Percentage(%s) is illegal.\n", p + 1); } #endif } /* * Parsing "[Family] [WEIGHT] [SLANT] [SIZE]". * Following is the same as libtype/ui_font_ft.c and fb/ui_font.c. * except FW_* and is_italic. */ #if 0 bl_debug_printf("Parsing %s for [Family] [Weight] [Slant]\n", *font_family); #endif p = bl_str_chop_spaces(*font_family); len = strlen(p); while (len > 0) { size_t step = 0; if (*p == ' ') { char *orig_p; orig_p = p; do { p++; len--; } while (*p == ' '); if (len == 0) { *orig_p = '\0'; break; } else { int count; struct { char *style; int weight; int is_italic; } styles[] = { /* * Portable styles. */ /* slant */ { "italic", 0, 1, }, /* weight */ { "bold", FW_BOLD, 0, }, /* * Hack for styles which can be returned by * gtk_font_selection_dialog_get_font_name(). */ /* slant */ { "oblique", /* XXX This style is ignored. */ 0, 0, }, /* weight */ { "light", /* e.g. "Bookman Old Style Light" */ FW_LIGHT, 0, }, { "semi-bold", FW_SEMIBOLD, 0, }, { "heavy", /* e.g. "Arial Black Heavy" */ FW_HEAVY, 0, }, /* other */ { "semi-condensed", /* XXX This style is ignored. */ 0, 0, }, }; for (count = 0; count < sizeof(styles) / sizeof(styles[0]); count++) { size_t len_v; len_v = strlen(styles[count].style); /* XXX strncasecmp is not portable? */ if (len >= len_v && strncasecmp(p, styles[count].style, len_v) == 0) { *orig_p = '\0'; step = len_v; if (styles[count].weight) { *font_weight = styles[count].weight; } else if (styles[count].is_italic) { *is_italic = 1; } goto next_char; } } if (*p != '0' || /* In case of "DevLys 010" font family. */ *(p + 1) == '\0') /* "MS Gothic 0" => "MS Gothic" + "0" */ { char *end; double size; size = strtod(p, &end); if (*end == '\0') { /* p has no more parameters. */ *orig_p = '\0'; if (size > 0) { *font_size = size; } break; } } step = 1; } } else { step = 1; } next_char: p += step; len -= step; } return 1; } static u_int calculate_char_width(ui_font_t *font, u_int32_t ch, ef_charset_t cs) { SIZE sz; if (!display_gc) { /* * Cached as far as ui_caculate_char_width is called. * display_gc is destroyed in ui_font_new or ui_font_destroy. */ display_gc = CreateIC("Display", NULL, NULL, NULL); } SelectObject(display_gc, font->xfont->fid); if (cs != US_ASCII && !IS_ISCII(cs)) { u_int32_t ucs4_code; u_char utf16[4]; int len; BOOL ret; if (IS_ISO10646_UCS4(cs)) { ucs4_code = ch; } else { ef_char_t non_ucs; ef_char_t ucs4; non_ucs.size = CS_SIZE(cs); non_ucs.property = 0; non_ucs.cs = cs; ef_int_to_bytes(non_ucs.ch, non_ucs.size, ch); if (vt_is_msb_set(cs)) { u_int count; for (count = 0; count < non_ucs.size; count++) { non_ucs.ch[count] &= 0x7f; } } if (ef_map_to_ucs4(&ucs4, &non_ucs)) { ucs4_code = ef_bytes_to_int(ucs4.ch, 4); } else { return 0; } } len = ui_convert_ucs4_to_utf16(utf16, ucs4_code) / 2; #ifdef USE_OT_LAYOUT if (font->use_ot_layout /* && font->ot_font */) { #ifdef USE_WIN32API /* GetTextExtentPointI doesn't exist on mingw-i686-pc-mingw */ static BOOL (*func)(HDC, LPWORD, int, LPSIZE); if (!func) { func = GetProcAddress(GetModuleHandleA("GDI32.DLL"), "GetTextExtentPointI"); } ret = (*func)(display_gc, utf16, len, &sz); #else ret = GetTextExtentPointI(display_gc, utf16, len, &sz); #endif } else #endif { ret = GetTextExtentPoint32W(display_gc, utf16, len, &sz); } if (!ret) { return 0; } } else { u_char c; c = ch; if (!GetTextExtentPoint32A(display_gc, &c, 1, &sz)) { return 0; } } if (sz.cx < 0) { return 0; } else { return sz.cx; } } /* --- global functions --- */ void ui_compose_dec_special_font(void) { /* Do nothing for now in win32. */ } ui_font_t *ui_font_new(Display *display, vt_font_t id, int size_attr, ui_type_engine_t type_engine, ui_font_present_t font_present, const char *fontname, u_int fontsize, u_int col_width, int use_medium_for_bold, u_int letter_space /* Ignored for now. */ ) { ui_font_t *font; u_int cols; wincs_info_t *wincsinfo; char *font_family; wchar_t *w_font_family; int wlen; int weight; int is_italic; int width; int height; double fontsize_d; u_int percent; if (type_engine != TYPE_XCORE || (font = calloc(1, sizeof(ui_font_t) + sizeof(XFontStruct))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc() failed.\n"); #endif return NULL; } font->xfont = font + 1; font->display = display; font->id = id; if (font->id & FONT_FULLWIDTH) { cols = 2; } else { cols = 1; } if (IS_ISCII(FONT_CS(font->id)) || FONT_CS(font->id) == ISO10646_UCS4_1_V) { /* * For exampe, 'W' width and 'l' width of OR-TTSarala font for ISCII_ORIYA * are the same by chance, though it is actually a proportional font. */ font->is_var_col_width = font->is_proportional = 1; } else if (font_present & FONT_VAR_WIDTH) { font->is_var_col_width = 1; } if (font_present & FONT_VERTICAL) { font->is_vertical = 1; } if ((wincsinfo = get_wincs_info(FONT_CS(font->id))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " charset(0x%.2x) is not supported.\n", FONT_CS(font->id)); #endif free(font); return NULL; } if (font->id & FONT_BOLD) { #if 0 weight = FW_BOLD; #else /* * XXX * Width of bold font is not necessarily the same as * that of normal font in win32. * So ignore weight and if font->id is bold use double- * drawing method for now. */ weight = FW_DONTCARE; #endif } else { weight = FW_MEDIUM; } if (font->id & FONT_ITALIC) { is_italic = TRUE; } else { is_italic = FALSE; } if (size_attr) { if (size_attr >= DOUBLE_HEIGHT_TOP) { fontsize *= 2; } col_width *= 2; } font_family = NULL; percent = 0; fontsize_d = (double)fontsize; if (FONT_CS(font->id) == DEC_SPECIAL) { font_family = "Tera Special"; } else if (fontname) { char *p; if ((p = alloca(strlen(fontname) + 1)) == NULL) { free(font); return NULL; } strcpy(p, fontname); parse_font_name(&font_family, &weight, &is_italic, &fontsize_d, &percent, p); } else { /* Default font */ font_family = "Courier New"; } wlen = MultiByteToWideChar(CP_UTF8, 0, font_family, -1, NULL, 0); if ((w_font_family = alloca(wlen)) == NULL) { free(font); return NULL; } MultiByteToWideChar(CP_UTF8, 0, font_family, -1, w_font_family, wlen); if (!display_gc) { display_gc = CreateIC("Display", NULL, NULL, NULL); } height = fontsize_d; #if 0 if (col_width > 0) { if (size_attr == DOUBLE_WIDTH) { width = fontsize_d; } else { width = (font->is_vertical ? col_width / 2 : col_width); } } #else if (size_attr == DOUBLE_WIDTH) { width = fontsize_d; } #endif else { width = 0; } if (use_point_size) { height = -MulDiv(height, GetDeviceCaps(display_gc, LOGPIXELSY), 72); width = -MulDiv(width, GetDeviceCaps(display_gc, LOGPIXELSX), 72); } font->xfont->fid = CreateFontW(height, /* Height */ width, /* Width (0=auto) */ 0, /* text angle */ 0, /* char angle */ weight, /* weight */ is_italic, /* italic */ FALSE, /* underline */ FALSE, /* eraseline */ DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, (font_present & FONT_AA) ? ANTIALIASED_QUALITY : DEFAULT_QUALITY /* PROOF_QUALITY */, FIXED_PITCH | FF_DONTCARE, w_font_family); if (!font->xfont->fid) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreateFont failed.\n"); free(font); #endif return NULL; } else { TEXTMETRIC tm; SIZE w_sz; SIZE l_sz; SelectObject(display_gc, font->xfont->fid); GetTextMetrics(display_gc, &tm); /* * Note that fixed pitch font containing both Hankaku and Zenkaku characters * like * MS Gothic is regarded as VARIABLE_PITCH. (tm.tmPitchAndFamily) * So "w" and "l" width is compared to check if font is proportional or not. */ GetTextExtentPoint32A(display_gc, "w", 1, &w_sz); GetTextExtentPoint32A(display_gc, "l", 1, &l_sz); #if 0 bl_debug_printf( "Family %s Size %d CS %x => AveCharWidth %d MaxCharWidth %d 'w' width " "%d 'l' width %d Height %d Ascent %d ExLeading %d InLeading %d " "Pitch&Family %d Weight %d\n", font_family, fontsize, wincsinfo->cs, tm.tmAveCharWidth, tm.tmMaxCharWidth, w_sz.cx, l_sz.cx, tm.tmHeight, tm.tmAscent, tm.tmExternalLeading, tm.tmInternalLeading, tm.tmPitchAndFamily, tm.tmWeight); #endif if (w_sz.cx != l_sz.cx) { font->is_proportional = 1; font->width = tm.tmAveCharWidth * cols; } else { SIZE sp_sz; WORD sp = 0x3000; /* wide space */ if (cols == 2 && GetTextExtentPoint32W(display_gc, &sp, 1, &sp_sz) && sp_sz.cx != l_sz.cx * 2) { font->is_proportional = 1; font->width = sp_sz.cx; } else { font->width = w_sz.cx * cols; } } font->height = tm.tmHeight; font->ascent = tm.tmAscent; if ((font->id & FONT_BOLD) && tm.tmWeight <= FW_MEDIUM) { font->double_draw_gap = 1; } } font->xfont->size = fontsize; /* * Following processing is same as ui_font.c:set_xfont() */ if (col_width == 0) { /* standard(usascii) font */ if (percent > 0) { u_int ch_width; if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ ch_width = fontsize * percent / 100; } else { ch_width = fontsize * percent / 200; } if (use_point_size) { ch_width = -MulDiv(ch_width, GetDeviceCaps(display_gc, LOGPIXELSX), 72); } if (!font->is_var_col_width && font->width != ch_width) { font->is_proportional = 1; if (font->width < ch_width) { font->x_off = (ch_width - font->width) / 2; } font->width = ch_width; } } else if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ font->is_proportional = 1; font->x_off = font->width / 2; font->width *= 2; } /* letter_space is ignored in variable column width mode. */ if (!font->is_var_col_width && letter_space > 0) { font->is_proportional = 1; font->width += letter_space; font->x_off += (letter_space / 2); } } else { /* not a standard(usascii) font */ /* * XXX hack * forcibly conforming non standard font width to standard font width. */ if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ if (font->width != col_width) { font->is_proportional = 1; /* is_var_col_width is always false if is_vertical is true. */ if (/* ! font->is_var_col_width && */ font->width < col_width) { font->x_off = (col_width - font->width) / 2; } font->width = col_width; } } else { if (font->width != col_width * cols) { bl_msg_printf( "Font width(%d) is not matched with " "standard width(%d).\n", font->width, col_width * cols); font->is_proportional = 1; if (!font->is_var_col_width && font->width < col_width * cols) { font->x_off = (col_width * cols - font->width) / 2; } font->width = col_width * cols; } } } font->size_attr = size_attr; if (wincsinfo->cs != ANSI_CHARSET && wincsinfo->cs != SYMBOL_CHARSET && !IS_ISO10646_UCS4(FONT_CS(font->id))) { if (!(font->xfont->conv = vt_char_encoding_conv_new(wincsinfo->encoding))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_char_encoding_conv_new(font id %x) failed.\n", font->id); #endif } } if (font->is_proportional && !font->is_var_col_width) { bl_msg_printf("Characters (cs %x) are drawn *one by one* to arrange column width.\n", FONT_CS(font->id)); } return font; } void ui_font_destroy(ui_font_t *font) { #ifdef USE_OT_LAYOUT if (font->ot_font) { otl_close(font->ot_font); } #endif if (font->xfont->fid) { DeleteObject(font->xfont->fid); } if (font->xfont->conv) { (*font->xfont->conv->destroy)(font->xfont->conv); } free(font); if (display_gc) { DeleteDC(display_gc); display_gc = None; } } #ifdef USE_OT_LAYOUT int ui_font_has_ot_layout_table(ui_font_t *font) { if (!font->ot_font) { u_char buf[4]; void *font_data; u_int size; int is_ttc; if (font->ot_font_not_found) { return 0; } if (!display_gc) { /* * Cached as far as ui_caculate_char_width is called. * display_gc is destroyed in ui_font_new or ui_font_destroy. */ display_gc = CreateIC("Display", NULL, NULL, NULL); } SelectObject(display_gc, font->xfont->fid); #define TTC_TAG ('t' << 0) + ('t' << 8) + ('c' << 16) + ('f' << 24) if (GetFontData(display_gc, TTC_TAG, 0, &buf, 1) == 1) { is_ttc = 1; size = GetFontData(display_gc, TTC_TAG, 0, NULL, 0); } else { is_ttc = 0; size = GetFontData(display_gc, 0, 0, NULL, 0); } if (!(font_data = malloc(size))) { font->ot_font = NULL; } else { if (is_ttc) { GetFontData(display_gc, TTC_TAG, 0, font_data, size); } else { GetFontData(display_gc, 0, 0, font_data, size); } font->ot_font = otl_open(font_data, size); } if (!font->ot_font) { font->ot_font_not_found = 1; return 0; } } return 1; } u_int ui_convert_text_to_glyphs(ui_font_t *font, u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features) { u_int size; if (use_point_size) { if (!display_gc) { display_gc = CreateIC("Display", NULL, NULL, NULL); } size = MulDiv((int)font->xfont->size, GetDeviceCaps(display_gc, LOGPIXELSY), 72); } else { size = font->xfont->size; } return otl_convert_text_to_glyphs(font->ot_font, shaped, shaped_len, offsets, widths, cmapped, src, src_len, script, features, size * (font->size_attr >= DOUBLE_WIDTH ? 2 : 1)); } #endif /* USE_OT_LAYOUT */ u_int ui_calculate_char_width(ui_font_t *font, u_int32_t ch, ef_charset_t cs, int *draw_alone) { if (draw_alone) { *draw_alone = 0; } if (font->is_proportional) { if (font->is_var_col_width) { u_int width; return width = calculate_char_width(font, ch, cs); } if (draw_alone) { *draw_alone = 1; } } else if (draw_alone && /* ISO10646_UCS4_1_V is always proportional */ cs == ISO10646_UCS4_1 #ifdef USE_OT_LAYOUT && (!font->use_ot_layout /* || ! font->ot_font */) #endif ) { if (ef_get_ucs_property(ch) & EF_AWIDTH) { if (calculate_char_width(font, ch, cs) != font->width) { *draw_alone = 1; } } } return font->width; } void ui_font_use_point_size(int use) { use_point_size = use; } /* Return written size */ size_t ui_convert_ucs4_to_utf16(u_char *dst, /* 4 bytes. Little endian. */ u_int32_t src) { if (src < 0x10000) { dst[1] = (src >> 8) & 0xff; dst[0] = src & 0xff; return 2; } else if (src < 0x110000) { /* surrogate pair */ u_char c; src -= 0x10000; c = (u_char)(src / (0x100 * 0x400)); src -= (c * 0x100 * 0x400); dst[1] = c + 0xd8; c = (u_char)(src / 0x400); src -= (c * 0x400); dst[0] = c; c = (u_char)(src / 0x100); src -= (c * 0x100); dst[3] = c + 0xdc; dst[2] = (u_char)src; return 4; } return 0; } #ifdef DEBUG void ui_font_dump(ui_font_t *font) { bl_msg_printf(" id %x: Font %p", font->id, font->xfont->fid); if (font->is_proportional) { bl_msg_printf(" (proportional)"); } bl_msg_printf("\n"); } #endif mlterm-3.8.9/uitoolkit/win32/ui_gc.c010064400017600000144000000033721356600660700157660ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_gc.h" #include /* malloc */ #include "../ui_color.h" #define ARGB_TO_RGB(pixel) ((pixel)&0x00ffffff) /* --- global functions --- */ ui_gc_t *ui_gc_new(Display *display, Drawable drawable) { ui_gc_t *gc; if ((gc = calloc(1, sizeof(ui_gc_t))) == NULL) { return NULL; } gc->display = display; /* Default value of GC. */ gc->fg_color = RGB(0, 0, 0); gc->bg_color = RGB(0xff, 0xff, 0xff); return gc; } void ui_gc_destroy(ui_gc_t *gc) { free(gc); } void ui_set_gc(ui_gc_t *gc, GC _gc) { gc->gc = _gc; SetTextAlign(gc->gc, TA_LEFT | TA_BASELINE); gc->fg_color = RGB(0, 0, 0); /* black */ #if 0 /* black is default value */ SetTextColor(gc->gc, gc->fg_color); #endif gc->bg_color = RGB(0xff, 0xff, 0xff); /* white */ #if 0 /* white is default value */ SetBkColor(gc->gc, gc->bg_color); #endif gc->fid = None; gc->pen = None; gc->brush = None; } void ui_gc_set_fg_color(ui_gc_t *gc, u_long fg_color) { if (ARGB_TO_RGB(fg_color) != gc->fg_color) { SetTextColor(gc->gc, (gc->fg_color = ARGB_TO_RGB(fg_color))); } } void ui_gc_set_bg_color(ui_gc_t *gc, u_long bg_color) { if (ARGB_TO_RGB(bg_color) != gc->bg_color) { SetBkColor(gc->gc, (gc->bg_color = ARGB_TO_RGB(bg_color))); } } void ui_gc_set_fid(ui_gc_t *gc, Font fid) { if (gc->fid != fid) { SelectObject(gc->gc, fid); gc->fid = fid; } } HPEN ui_gc_set_pen(ui_gc_t *gc, HPEN pen) { if (gc->pen != pen) { gc->pen = pen; return SelectObject(gc->gc, pen); } return None; } HBRUSH ui_gc_set_brush(ui_gc_t *gc, HBRUSH brush) { if (gc->brush != brush) { gc->brush = brush; return SelectObject(gc->gc, brush); } return None; } mlterm-3.8.9/uitoolkit/win32/ui_gdiobj_pool.c010064400017600000144000000071331356600660700176630ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_gdiobj_pool.h" #include typedef struct stock_pen { HPEN pen; u_long rgb; int ref_count; } stock_pen_t; typedef struct stock_brush { HBRUSH brush; u_long rgb; int ref_count; } stock_brush_t; /* --- static variables --- */ static stock_pen_t *stock_pens; static u_int num_stock_pens; static stock_brush_t *stock_brushes; static u_int num_stock_brushes; /* --- static functions --- */ static int garbage_unused_objects(void) { int count; for (count = 0; count < num_stock_pens;) { if (stock_pens[count].ref_count <= 0) { DeleteObject(stock_pens[count].pen); stock_pens[count] = stock_pens[--num_stock_pens]; } else { count++; } } for (count = 0; count < num_stock_brushes;) { if (stock_brushes[count].ref_count <= 0) { DeleteObject(stock_brushes[count].brush); stock_brushes[count] = stock_brushes[--num_stock_brushes]; } else { count++; } } return 1; } /* --- global functions --- */ int ui_gdiobj_pool_init(void) { return 1; } int ui_gdiobj_pool_final(void) { u_int count; for (count = 0; count < num_stock_pens; count++) { DeleteObject(stock_pens[count].pen); } for (count = 0; count < num_stock_brushes; count++) { DeleteObject(stock_brushes[count].brush); } free(stock_pens); free(stock_brushes); return 1; } HPEN ui_acquire_pen(u_long rgb) { u_int count; /* Remove alpha */ rgb &= 0xffffff; for (count = 0; count < num_stock_pens; count++) { if (rgb == stock_pens[count].rgb) { stock_pens[count].ref_count++; return stock_pens[count].pen; } } if (rgb == RGB(0, 0, 0)) { return GetStockObject(BLACK_PEN); } else if (rgb == RGB(0xff, 0xff, 0xff)) { return GetStockObject(WHITE_PEN); } else { void *p; if (num_stock_pens % 10 == 9) { garbage_unused_objects(); } if ((p = realloc(stock_pens, sizeof(stock_pen_t) * (num_stock_pens + 1))) == NULL) { return None; } stock_pens = p; stock_pens[num_stock_pens].rgb = rgb; stock_pens[num_stock_pens].pen = CreatePen(PS_SOLID, 1, rgb); stock_pens[num_stock_pens].ref_count = 1; return stock_pens[num_stock_pens++].pen; } } int ui_release_pen(HPEN pen) { u_int count; for (count = 0; count < num_stock_pens; count++) { if (pen == stock_pens[count].pen) { --stock_pens[count].ref_count; return 1; } } return 0; } HBRUSH ui_acquire_brush(u_long rgb) { u_int count; /* Remove alpha */ rgb &= 0xffffff; for (count = 0; count < num_stock_brushes; count++) { if (rgb == stock_brushes[count].rgb) { stock_brushes[count].ref_count++; return stock_brushes[count].brush; } } if (rgb == RGB(0, 0, 0)) { return GetStockObject(BLACK_BRUSH); } else if (rgb == RGB(0xff, 0xff, 0xff)) { return GetStockObject(WHITE_BRUSH); } else { void *p; if (num_stock_brushes % 10 == 9) { garbage_unused_objects(); } if ((p = realloc(stock_brushes, sizeof(stock_brush_t) * (num_stock_brushes + 1))) == NULL) { return None; } stock_brushes = p; stock_brushes[num_stock_brushes].rgb = rgb; stock_brushes[num_stock_brushes].brush = CreateSolidBrush(rgb); stock_brushes[num_stock_brushes].ref_count = 1; return stock_brushes[num_stock_brushes++].brush; } } int ui_release_brush(HBRUSH brush) { u_int count; for (count = 0; count < num_stock_brushes; count++) { if (brush == stock_brushes[count].brush) { --stock_brushes[count].ref_count; return 1; } } return 0; } mlterm-3.8.9/uitoolkit/win32/ui_gdiobj_pool.h010064400017600000144000000005771356600660700176750ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_GDIOBJ_POOL_H__ #define __UI_GDIOBJ_POOL_H__ #include #include "ui.h" int ui_gdiobj_pool_init(void); int ui_gdiobj_pool_final(void); HPEN ui_acquire_pen(u_long rgb); int ui_release_pen(HPEN pen); HBRUSH ui_acquire_brush(u_long rgb); int ui_release_brush(HBRUSH brush); #endif mlterm-3.8.9/uitoolkit/win32/ui_imagelib.c010064400017600000144000000245501356600660700171470ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef NO_IMAGE #include "../ui_imagelib.h" #include /* sprintf */ #include /* pow */ #include /* DIGIT_STR_LEN */ #include #include #if defined(__CYGWIN__) || defined(__MSYS__) #include /* bl_conv_to_win32_path */ #endif #if 1 #define BUILTIN_SIXEL #endif /* --- static functions --- */ #define CARD_HEAD_SIZE 0 #include "../../common/c_sixel.c" #include "../../common/c_regis.c" static void value_table_refresh(u_char *value_table, /* 256 bytes */ ui_picture_modifier_t *mod) { int i, tmp; double real_gamma, real_brightness, real_contrast; real_gamma = (double)(mod->gamma) / 100; real_contrast = (double)(mod->contrast) / 100; real_brightness = (double)(mod->brightness) / 100; for (i = 0; i < 256; i++) { tmp = real_contrast * (255 * pow(((double)i + 0.5) / 255, real_gamma) - 128) + 128 * real_brightness; if (tmp >= 255) { break; } else if (tmp < 0) { value_table[i] = 0; } else { value_table[i] = tmp; } } for (; i < 256; i++) { value_table[i] = 255; } } static void adjust_pixmap(u_char *image, u_int width, u_int height, ui_picture_modifier_t *pic_mod) { u_char *value_table; u_int y; u_int x; u_char r, g, b, a; u_int32_t pixel; if (!ui_picture_modifier_is_normal(pic_mod) && (value_table = alloca(256))) { value_table_refresh(value_table, pic_mod); } else { return; } for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixel = *(((u_int32_t *)image) + (y * width + x)); a = (pixel >> 24) & 0xff; r = (pixel >> 16) & 0xff; g = (pixel >> 8) & 0xff; b = pixel & 0xff; r = (value_table[r] * (255 - pic_mod->alpha) + pic_mod->blend_red * pic_mod->alpha) / 255; g = (value_table[g] * (255 - pic_mod->alpha) + pic_mod->blend_green * pic_mod->alpha) / 255; b = (value_table[b] * (255 - pic_mod->alpha) + pic_mod->blend_blue * pic_mod->alpha) / 255; pixel = (a << 24) | (r << 16) | (g << 8) | b; *(((u_int32_t *)image) + (y * width + x)) = pixel; } } } static int load_file(char *path, /* must be UTF-8 */ u_int *width, u_int *height, int keep_aspect, ui_picture_modifier_t *pic_mod, HBITMAP *hbmp, HBITMAP *hbmp_mask) { char *suffix; char *cmd_line; WCHAR *w_cmd_line; int num; SECURITY_ATTRIBUTES sa; HANDLE output_write; HANDLE output_read; PROCESS_INFORMATION pi; STARTUPINFO si; u_int32_t tmp; DWORD n_rd; DWORD size; BITMAPINFOHEADER header; HDC hdc; BYTE *image; suffix = path + strlen(path) - 4; #ifdef BUILTIN_SIXEL if (strcasecmp(suffix, ".six") == 0 && *width == 0 && *height == 0 && /* XXX fopen() in load_sixel_from_file() on win32api doesn't support UTF-8. */ (image = (u_int32_t *)load_sixel_from_file(path, width, height))) { goto loaded; } #endif if (strcasecmp(suffix, ".rgs") == 0) { convert_regis_to_bmp(path); } #define CMD_LINE_FMT "mlimgloader.exe 0 %u %u \"%s\" stdout%s" if (!(cmd_line = alloca(sizeof(CMD_LINE_FMT) + DIGIT_STR_LEN(int)*2 + strlen(path) + 3 /* " -a" */))) { return 0; } sprintf(cmd_line, CMD_LINE_FMT, *width, *height, path, keep_aspect ? " -a" : ""); /* Assume that path is UTF-8 */ if ((num = MultiByteToWideChar(CP_UTF8, 0, cmd_line, strlen(cmd_line) + 1, NULL, 0)) == 0 || !(w_cmd_line = alloca(sizeof(WCHAR) * num))) { return 0; } MultiByteToWideChar(CP_UTF8, 0, cmd_line, strlen(cmd_line) + 1, w_cmd_line, num); /* Set up the security attributes struct. */ sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* Create the child output pipe. */ if (!CreatePipe(&output_read, &output_write, &sa, 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreatePipe() failed.\n"); #endif return 0; } ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES | STARTF_FORCEOFFFEEDBACK; si.hStdOutput = output_write; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); if (!CreateProcessW(NULL, w_cmd_line, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { #if defined(__CYGWIN__) || defined(__MSYS__) #ifndef BINDIR #define BINDIR "/bin" #endif /* MAX_PATH which is 260 (3+255+1+1) is defined in win32 alone. */ char bindir[MAX_PATH]; char *new_cmd_line; if (bl_conv_to_win32_path(BINDIR, bindir, sizeof(bindir)) == 0 && (new_cmd_line = alloca(strlen(bindir) + 1 + strlen(cmd_line) + 1))) { sprintf(new_cmd_line, "%s\\%s", bindir, cmd_line); num = MultiByteToWideChar(CP_UTF8, 0, new_cmd_line, strlen(new_cmd_line) + 1, NULL, 0); if ((w_cmd_line = alloca(sizeof(WCHAR) * num))) { MultiByteToWideChar(CP_UTF8, 0, new_cmd_line, strlen(new_cmd_line) + 1, w_cmd_line, num); if (CreateProcessW(NULL, w_cmd_line, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { goto executed; } } } #endif #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " CreateProcess() failed.\n"); #endif CloseHandle(output_write); goto error; } executed: CloseHandle(output_write); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); if (!ReadFile(output_read, &tmp, sizeof(u_int32_t), &n_rd, NULL) || n_rd != sizeof(u_int32_t)) { goto error; } size = (*width = tmp) * sizeof(u_int32_t); if (!ReadFile(output_read, &tmp, sizeof(u_int32_t), &n_rd, NULL) || n_rd != sizeof(u_int32_t)) { goto error; } size *= (*height = tmp); if (!(image = malloc(size))) { goto error; } else { BYTE *p; p = image; while (ReadFile(output_read, p, size, &n_rd, NULL) && n_rd > 0) { p += n_rd; size -= n_rd; } if (size > 0) { free(image); goto error; } } CloseHandle(output_read); loaded: adjust_pixmap(image, *width, *height, pic_mod); if (hbmp_mask) { int x; int y; u_int data_width; BYTE *mask_data; BYTE *dst; *hbmp_mask = None; /* align each line by short. */ data_width = ((*width) + 15) / 16 * 2; if ((dst = mask_data = calloc(data_width * (*height), 1))) { int has_tp; u_int32_t *src; has_tp = 0; src = (u_int32_t *)image; for (y = 0; y < *height; y++) { for (x = 0; x < *width; x++) { if (*src >= 0x80000000) { dst[x / 8] |= (1 << (7 - x % 8)); } else { has_tp = 1; } src++; } dst += data_width; } if (has_tp) { *hbmp_mask = CreateBitmap(*width, *height, 1, 1, mask_data); } free(mask_data); } } header.biSize = sizeof(BITMAPINFOHEADER); header.biWidth = *width; header.biHeight = -(*height); header.biPlanes = 1; header.biBitCount = 32; header.biCompression = BI_RGB; header.biSizeImage = (*width) * (*height) * 4; header.biXPelsPerMeter = 0; header.biYPelsPerMeter = 0; header.biClrUsed = 0; header.biClrImportant = 0; hdc = GetDC(NULL); *hbmp = CreateDIBitmap(hdc, &header, CBM_INIT, image, (BITMAPINFO *)&header, DIB_RGB_COLORS); ReleaseDC(NULL, hdc); free(image); return 1; error: CloseHandle(output_read); return 0; } /* --- global functions --- */ void ui_imagelib_display_opened(Display *display) {} void ui_imagelib_display_closed(Display *display) {} Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, ui_picture_modifier_t *pic_mod) { u_int width; u_int height; HBITMAP hbmp; HBITMAP hbmp_w; HDC hdc; HDC hmdc_tmp; HDC hmdc; width = height = 0; if (!load_file(path, &width, &height, 0, pic_mod, &hbmp, NULL)) { BITMAP bmp; #if defined(__CYGWIN__) || defined(__MSYS__) /* MAX_PATH which is 260 (3+255+1+1) is defined in win32 alone. */ char winpath[MAX_PATH]; if (bl_conv_to_win32_path(path, winpath, sizeof(winpath)) < 0) { return None; } path = winpath; #endif if (!(hbmp = LoadImage(0, path, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE))) { return None; } GetObject(hbmp, sizeof(BITMAP), &bmp); width = bmp.bmWidth; height = bmp.bmHeight; } hdc = GetDC(win->my_window); hmdc_tmp = CreateCompatibleDC(hdc); SelectObject(hmdc_tmp, hbmp); hbmp_w = CreateCompatibleBitmap(hdc, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); hmdc = CreateCompatibleDC(hdc); SelectObject(hmdc, hbmp_w); ReleaseDC(win->my_window, hdc); SetStretchBltMode(hmdc, COLORONCOLOR); StretchBlt(hmdc, 0, 0, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), hmdc_tmp, 0, 0, width, height, SRCCOPY); DeleteDC(hmdc_tmp); DeleteObject(hbmp); return hmdc; } int ui_imagelib_root_pixmap_available(Display *display) { return 0; } Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modifier_t *pic_mod) { return None; } int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) { HBITMAP hbmp; HDC hdc; HDC hmdc; if (cardinal) { return 0; } if (!load_file(path, width, height, keep_aspect, NULL, &hbmp, mask)) { BITMAP bmp; #if defined(__CYGWIN__) || defined(__MSYS__) /* MAX_PATH which is 260 (3+255+1+1) is defined in win32 alone. */ char winpath[MAX_PATH]; if (bl_conv_to_win32_path(path, winpath, sizeof(winpath)) < 0) { return 0; } path = winpath; #endif if (!(hbmp = LoadImage(0, path, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE))) { return 0; } GetObject(hbmp, sizeof(BITMAP), &bmp); *width = bmp.bmWidth; *height = bmp.bmHeight; if (mask) { *mask = NULL; } } hdc = GetDC(NULL); hmdc = CreateCompatibleDC(hdc); SelectObject(hmdc, hbmp); ReleaseDC(NULL, hdc); DeleteObject(hbmp); *pixmap = hmdc; return 1; } void ui_destroy_image(Display *display, Pixmap pixmap) { HBITMAP bmp; bmp = CreateBitmap(1, 1, 1, 1, NULL); DeleteObject(SelectObject(pixmap, bmp)); DeleteDC(pixmap); DeleteObject(bmp); } void ui_destroy_mask(Display *display, PixmapMask mask /* can be NULL */) { if (mask) { DeleteObject(mask); } } #endif /* NO_IMAGE */ mlterm-3.8.9/uitoolkit/win32/ui_selection_encoding.c010064400017600000144000000034141356600660700212250ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_selection_encoding.h" #include /* NULL */ #include #include #include #include /* --- static varaiables --- */ static ef_parser_t *utf_parser; /* leaked */ static ef_parser_t *parser; /* leaked */ static ef_conv_t *utf_conv; /* leaked */ static ef_conv_t *conv; /* leaked */ /* --- static functions --- */ /* See utf8_illegal_char() in vt_char_encoding.c */ static size_t utf16le_illegal_char(ef_conv_t *conv, u_char *dst, size_t dst_size, int *is_full, ef_char_t *ch) { *is_full = 0; if (ch->cs == DEC_SPECIAL) { u_int16_t utf16; if (dst_size < 2) { *is_full = 1; } else if ((utf16 = vt_convert_decsp_to_ucs(ef_char_to_int(ch)))) { memcpy(dst, utf16, 2); /* little endian */ return 2; } } return 0; } /* --- global functions --- */ ef_parser_t *ui_get_selection_parser(int utf) { if (utf) { if (!utf_parser) { if (!(utf_parser = ef_utf16le_parser_new())) { return NULL; } } return utf_parser; } else { if (!parser) { if (!(parser = vt_char_encoding_parser_new(vt_get_char_encoding(bl_get_codeset_win32())))) { return NULL; } } return parser; } } ef_conv_t *ui_get_selection_conv(int utf) { if (utf) { if (!utf_conv) { if (!(utf_conv = ef_utf16le_conv_new())) { return NULL; } utf_conv->illegal_char = utf16le_illegal_char; } return utf_conv; } else { if (!conv) { if (!(conv = vt_char_encoding_conv_new(vt_get_char_encoding(bl_get_codeset_win32())))) { return NULL; } } return conv; } } mlterm-3.8.9/uitoolkit/win32/ui_window.c010064400017600000144000002147301356600660700167060ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_window.h" #include /* abs */ #include /* memset/memcpy */ #include #include /* realloc/free */ #include /* BL_MIN/BL_MAX */ #include #include #include /* UTF_MAX_SIZE */ #include #if !defined(USE_WIN32API) && defined(HAVE_PTHREAD) #include #endif #include "../ui_xic.h" #include "../ui_picture.h" #include "../ui_imagelib.h" #include "../ui_selection_encoding.h" #ifndef DISABLE_XDND #include "../ui_dnd.h" #endif #include "ui_display.h" /* ui_display_get_cursor */ #include "ui_gdiobj_pool.h" #define MAX_CLICK 3 /* max is triple click */ #define WM_APP_PAINT (WM_APP + 0x0) #define WM_APP_PASTE (WM_APP + 0x1) #define WM_APP_WPASTE (WM_APP + 0x2) /* * ACTUAL_(WIDTH|HEIGHT) is the width of client area, * ACTUAL_WINDOW_(WIDTH|HEIGHT) is * that of window area. */ #if 1 #define ACTUAL_WINDOW_WIDTH(win) (ACTUAL_WIDTH(win) + decorate_width) #define ACTUAL_WINDOW_HEIGHT(win) (ACTUAL_HEIGHT(win) + decorate_height) #else #define ACTUAL_WINDOW_WIDTH(win) \ ACTUAL_WIDTH(win) + GetSystemMetrics(SM_CXEDGE) * 2 + \ /* GetSystemMetrics(SM_CXBORDER) * 2 + */ GetSystemMetrics(SM_CXFRAME) #define ACTUAL_WINDOW_HEIGHT(win) \ ACTUAL_HEIGHT(win) + GetSystemMetrics(SM_CYEDGE) * 2 + \ /* GetSystemMetrics(SM_CXBORDER) * 2 + */ GetSystemMetrics(SM_CYFRAME) + \ GetSystemMetrics(SM_CYCAPTION) #endif /* win->width is not multiples of (win)->width_inc if window is maximized. */ #define RIGHT_MARGIN(win) \ ((win)->width_inc ? ((win)->width - (win)->min_width) % (win)->width_inc : 0) #define BOTTOM_MARGIN(win) \ ((win)->height_inc ? ((win)->height - (win)->min_height) % (win)->height_inc : 0) #define ParentRelative (1L) #if 0 #define DEBUG_SCROLLABLE #endif #if 0 #define __DEBUG #endif /* --- static variables --- */ static int click_interval = 250; /* millisecond, same as xterm. */ static ef_parser_t *m_cp_parser; static LONG decorate_width; static LONG decorate_height; /* Height of Title bar etc. */ static int use_urgent_bell; static int pointer_hidden; /* --- static functions --- */ #ifdef FLASHW_ALL static void urgent_bell(ui_window_t *win, int on) { if (use_urgent_bell && (!win->is_focused || !on)) { win = ui_get_root_window(win); if (on) { FLASHWINFO info; info.cbSize = sizeof(info); info.hwnd = win->my_window; info.dwFlags = FLASHW_ALL; info.uCount = 5; info.dwTimeout = 0; /* standard */ FlashWindowEx(&info); } else { FlashWindow(win->my_window, FALSE); } } } #else #define urgent_bell(win, on) (0) #endif static int set_transparent(ui_window_t *win, int alpha) { /* * XXX * LWA_ALPHA and SetLayeredWindowAttributes() are not defined * in older winuser.h and libuser32.a(e.g. MSYS-DTK 1.0.1). */ #if defined(WS_EX_LAYERED) && defined(LWA_ALPHA) if ((win = ui_get_root_window(win))->my_window) { LONG style; style = GetWindowLong(win->my_window, GWL_EXSTYLE); SetWindowLong(win->my_window, GWL_EXSTYLE, style | WS_EX_LAYERED); #if 1 SetLayeredWindowAttributes(win->my_window, 0, alpha, LWA_ALPHA); #else SetLayeredWindowAttributes(win->my_window, ARGB_TO_RGB(win->bg_color.pixel), 0, LWA_COLORKEY); #endif } return 1; #else return 0; #endif } static int unset_transparent(ui_window_t *win) { /* * XXX * LWA_ALPHA and SetLayeredWindowAttributes() are not defined * in older winuser.h and libuser32.a(e.g. MSYS-DTK 1.0.1). */ #if defined(WS_EX_LAYERED) && defined(LWA_ALPHA) if ((win = ui_get_root_window(win))->my_window) { LONG style; style = GetWindowLong(win->my_window, GWL_EXSTYLE); SetWindowLong(win->my_window, GWL_EXSTYLE, style & ~WS_EX_LAYERED); } return 1; #else return 0; #endif } /* * XXX * Adhoc alternative of VisibilityNotify event. */ static int check_scrollable(ui_window_t *win /* Assume root window. */ ) { if (win->is_focused) { #ifdef DEBUG_SCROLLABLE bl_debug_printf("SCREEN W %d H %d WINDOW W %d H %d X %d Y %d ", win->disp->width, win->disp->height, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), win->x, win->y); #endif /* * If window is outside of screen partially, is_scrollable = 0. */ if (win->y < 0 || win->x < 0) { #ifdef DEBUG_SCROLLABLE bl_debug_printf("NOT SCROLLABLE(1)\n"); #endif return 0; } else { if (win->y + ACTUAL_HEIGHT(win) > win->disp->height) { #ifdef DEBUG_SCROLLABLE bl_debug_printf("NOT SCROLLABLE(2)\n"); #endif return 0; } else { if (win->x + ACTUAL_WIDTH(win) > win->disp->width) { #ifdef DEBUG_SCROLLABLE bl_debug_printf("NOT SCROLLABLE(3)\n"); #endif return 0; } else { APPBARDATA barinfo; ZeroMemory(&barinfo, sizeof(barinfo)); barinfo.cbSize = sizeof(barinfo); barinfo.hWnd = win->my_window; SHAppBarMessage(ABM_GETTASKBARPOS, &barinfo); #ifdef DEBUG_SCROLLABLE bl_debug_printf("TASKBAR t %d b %d l %d r %d ", barinfo.rc.top, barinfo.rc.bottom, barinfo.rc.left, barinfo.rc.right); #endif if (barinfo.rc.top <= 0) { if (barinfo.rc.left <= 0) { if (barinfo.rc.right >= win->disp->width) { /* North */ if (win->y < barinfo.rc.bottom) { #ifdef DEBUG_SCROLLABLE bl_debug_printf("NOT SCROLLABLE(4)\n"); #endif return 0; } } else { /* West */ if (win->x < barinfo.rc.right) { #ifdef DEBUG_SCROLLABLE bl_debug_printf("NOT SCROLLABLE(5)\n"); #endif return 0; } } } else { /* East */ if (win->x + ACTUAL_WIDTH(win) > barinfo.rc.left) { #ifdef DEBUG_SCROLLABLE bl_debug_printf("NOT SCROLLABLE(6)\n"); #endif return 0; } } } else { /* South */ if (win->y + ACTUAL_HEIGHT(win) > barinfo.rc.top) { #ifdef DEBUG_SCROLLABLE bl_debug_printf("NOT SCROLLABLE(7)\n"); #endif return 0; } } #ifdef DEBUG_SCROLLABLE bl_debug_printf("SCROLLABLE\n"); #endif return 1; } } } } else { #ifdef DEBUG_SCROLLABLE bl_debug_printf("NOT SCROLLABLE(4)\n"); #endif return 0; } } static void notify_focus_in_to_children(ui_window_t *win) { u_int count; if (!win->is_focused) { if (win->inputtable > 0 || win->parent == NULL) /* check_scrollable checks root->is_focused */ { win->is_focused = 1; } /* If win->wall_picture is set, is_scrollable is always 0. */ if (!win->wall_picture) { if (!win->parent) { win->is_scrollable = check_scrollable(win); } else { win->is_scrollable = win->parent->is_scrollable; } } if (win->inputtable > 0) { ui_xic_set_focus(win); if (win->window_focused) { (*win->window_focused)(win); } } } for (count = 0; count < win->num_children; count++) { notify_focus_in_to_children(win->children[count]); } } static void notify_focus_out_to_children(ui_window_t *win) { u_int count; if (win->is_focused) { win->is_focused = 0; win->is_scrollable = 0; ui_xic_unset_focus(win); if (win->window_unfocused) { (*win->window_unfocused)(win); } } for (count = 0; count < win->num_children; count++) { notify_focus_out_to_children(win->children[count]); } } static void notify_move_to_children(ui_window_t *win) { int count; if (win->wall_picture) { /* If win->wall_picture is set, is_scrollable is always 0. */ } else if (!win->parent) { int is_scrollable; if ((is_scrollable = check_scrollable(win)) == win->is_scrollable) { /* * If is_scrollable is not changed, nothing should be * notified to children. */ return; } win->is_scrollable = is_scrollable; } else { win->is_scrollable = win->parent->is_scrollable; } for (count = 0; count < win->num_children; count++) { notify_move_to_children(win->children[count]); } } #if 0 /* * Not used for now in win32. */ static int is_descendant_window(ui_window_t *win, Window window) { int count; if (win->my_window == window) { return 1; } for (count = 0; count < win->num_children; count++) { if (is_descendant_window(win->children[count], window)) { return 1; } } return 0; } /* * Not used for now in win32. */ static int is_in_the_same_window_family(ui_window_t *win, Window window) { return is_descendant_window(ui_get_root_window(win), window); } #endif /* RIGHT_MARGIN is not added. (See WM_SIZE) */ static u_int total_min_width(ui_window_t *win) { u_int count; u_int min_width; min_width = win->min_width + win->hmargin * 2; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_WIDTH)) { min_width += total_min_width(win->children[count]); } } return min_width; } /* BOTTOM_MARGIN is not added. (See WM_SIZE) */ static u_int total_min_height(ui_window_t *win) { u_int count; u_int min_height; min_height = win->min_height + win->vmargin * 2; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_HEIGHT)) { min_height += total_min_height(win->children[count]); } } return min_height; } static u_int max_width_inc(ui_window_t *win) { u_int count; u_int width_inc; width_inc = win->width_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_WIDTH)) { u_int sub_inc; /* * XXX * we should calculate least common multiple of width_inc and sub_inc. */ if ((sub_inc = max_width_inc(win->children[count])) > width_inc) { width_inc = sub_inc; } } } return width_inc; } static u_int max_height_inc(ui_window_t *win) { u_int count; u_int height_inc; height_inc = win->height_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_HEIGHT)) { u_int sub_inc; /* * XXX * we should calculate least common multiple of width_inc and sub_inc. */ if ((sub_inc = max_height_inc(win->children[count])) > height_inc) { height_inc = sub_inc; } } } return height_inc; } static u_int get_key_state(void) { u_int state; state = 0; if (GetKeyState(VK_SHIFT) < 0) { state |= ShiftMask; } if (GetKeyState(VK_CONTROL) < 0) { state |= ControlMask; } if (GetKeyState(VK_MENU) < 0) { state |= Mod1Mask; } return state; } static BOOL text_out(GC gc, int x, int y, u_char *str, u_int len, ef_charset_t cs, /* FONT_CS(font->id) */ int is_glyph, int is_ucs) { if (is_ucs) { if (is_glyph) { return ExtTextOutW(gc, x, y, ETO_GLYPH_INDEX, NULL, (WCHAR*)str, len / 2, NULL); } else { /* TextOutW is supported in windows 9x. */ return TextOutW(gc, x, y, (WCHAR*)str, len / 2); } } else if (cs == ISCII_BENGALI || cs == ISCII_ASSAMESE) { u_int count; u_int16_t *str2; str2 = alloca(len * 2); /* char code -> glyph index in BN-TTDurga and AS-TTDurga fonts. */ for (count = 0; count < len; count++) { if (str[count] <= 0x7e) { str2[count] = str[count] - 0x1d; } else { str2[count] = str[count] - 0x1e; } } /* ExtTextOutA doesn't work correctly. */ return ExtTextOutW(gc, x, y, ETO_GLYPH_INDEX, NULL, str2, len, NULL); } else { return TextOutA(gc, x, y, str, len); } } static void draw_string(ui_window_t *win, ui_font_t *font, int x, int y, u_char *str, u_int len, int is_tp, int is_ucs) { u_char *str2; int is_glyph; str2 = NULL; if (font->xfont->conv) { if ((str2 = alloca(len * UTF_MAX_SIZE))) /* assume utf8 */ { (*m_cp_parser->init)(m_cp_parser); /* 3rd argument of cp_parser->set_str is len(16bit) + cs(16bit) */ (*m_cp_parser->set_str)(m_cp_parser, str, len | (FONT_CS(font->id) << 16)); (*font->xfont->conv->init)(font->xfont->conv); if ((len = (*font->xfont->conv->convert)(font->xfont->conv, str2, len* UTF_MAX_SIZE, m_cp_parser)) > 0) { str = str2; } } } if (is_tp) { SetBkMode(win->gc->gc, TRANSPARENT); } #ifdef USE_OT_LAYOUT is_glyph = (font->use_ot_layout /* && font->ot_font */); #else is_glyph = 0; #endif text_out(win->gc->gc, x + (font->is_var_col_width ? 0 : font->x_off) + win->hmargin, y + win->vmargin, str, len, FONT_CS(font->id), is_glyph, is_ucs); if (font->double_draw_gap) { SetBkMode(win->gc->gc, TRANSPARENT); text_out(win->gc->gc, x + (font->is_var_col_width ? 0 : font->x_off) + win->hmargin + font->double_draw_gap, y + win->vmargin, str, len, FONT_CS(font->id), is_glyph, is_ucs); SetBkMode(win->gc->gc, OPAQUE); } else if (is_tp) { SetBkMode(win->gc->gc, OPAQUE); } } /* * Return 1 => decorate size is changed. * 0 => decorate size is not changed. */ static int update_decorate_size(ui_window_t *win) { RECT wr; RECT cr; LONG width; LONG height; if (win->parent) { return 0; } GetWindowRect(win->my_window, &wr); GetClientRect(win->my_window, &cr); width = wr.right - wr.left - cr.right + cr.left; height = wr.bottom - wr.top - cr.bottom + cr.top; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " DECORATE W %d H %d -> W %d H %d\n", decorate_width, decorate_height, width, height); #endif if (width != decorate_width || height != decorate_height) { decorate_width = width; decorate_height = height; return 1; } else { return 0; } } static void clear_margin_area(ui_window_t *win) { u_int right_margin; u_int bottom_margin; u_int win_width; u_int win_height; if (win->gc->gc == None) { return; } right_margin = RIGHT_MARGIN(win); bottom_margin = BOTTOM_MARGIN(win); win_width = win->width - right_margin; win_height = win->height - bottom_margin; if (win->wall_picture) { Pixmap pic; int src_x; int src_y; if (win->wall_picture == ParentRelative) { pic = win->parent->wall_picture; src_x = win->x; src_y = win->y; } else { pic = win->wall_picture; src_x = src_y = 0; } if (win->hmargin > 0 || right_margin > 0) { BitBlt(win->gc->gc, 0, 0, win->hmargin, ACTUAL_HEIGHT(win), pic, src_x, src_y, SRCCOPY); BitBlt(win->gc->gc, win_width + win->hmargin, 0, win->hmargin + right_margin, ACTUAL_HEIGHT(win), pic, src_x + win_width + win->hmargin, src_y, SRCCOPY); } if (win->vmargin > 0 || bottom_margin > 0) { BitBlt(win->gc->gc, win->hmargin, 0, win_width, win->vmargin, pic, src_x + win->hmargin, src_y, SRCCOPY); BitBlt(win->gc->gc, win->hmargin, win_height + win->vmargin, win_width, win->vmargin + bottom_margin, pic, src_x + win->hmargin, src_y + win_height + win->vmargin, SRCCOPY); } } else { HBRUSH brush; RECT r; brush = ui_acquire_brush(win->bg_color.pixel); if (win->hmargin > 0 || right_margin > 0) { SetRect(&r, 0, 0, win->hmargin, ACTUAL_HEIGHT(win)); FillRect(win->gc->gc, &r, brush); SetRect(&r, win_width + win->hmargin, 0, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); FillRect(win->gc->gc, &r, brush); } if (win->vmargin > 0 || bottom_margin > 0) { SetRect(&r, win->hmargin, 0, win_width + win->hmargin, win->vmargin); FillRect(win->gc->gc, &r, brush); SetRect(&r, win->hmargin, win_height + win->vmargin, win_width + win->hmargin, ACTUAL_HEIGHT(win)); FillRect(win->gc->gc, &r, brush); } ui_release_brush(brush); } } static WORD oem_key_to_char(WORD wparam) { if (VK_OEM_1 <= wparam && wparam <= VK_OEM_2) { /* * VK_OEM_1 0xba * VK_OEM_PLUS 0xbb * VK_OEM_COMMA 0xbc * VK_OEM_MINUS 0xbd * VK_OEM_PERIOD 0xbe * VK_OEM_2 0xbf */ return '*' + wparam - VK_OEM_1; } else if (wparam == VK_OEM_3) { return '@'; } else if (VK_OEM_4 <= wparam && wparam <= VK_OEM_7) { /* * VK_OEM_4 0xdb * VK_OEM_5 0xdc * VK_OEM_6 0xdd * VK_OEM_7 0xde */ return '[' + wparam - VK_OEM_4; } else if (wparam == VK_OEM_102) { return '_'; } else { return 0; } } static int selection_request(ui_window_t *win, UINT format) { HGLOBAL hmem; u_char *l_data; u_char *g_data; size_t len; #if !defined(USE_WIN32API) && defined(HAVE_PTHREAD) pthread_detach(pthread_self()); #endif if (OpenClipboard(win->my_window) == FALSE) { return 0; } g_data = NULL; if ((hmem = GetClipboardData(format)) == NULL || (g_data = GlobalLock(hmem)) == NULL || (len = (format == CF_TEXT ? strlen(g_data) : lstrlenW(g_data))) == 0 || (l_data = malloc((len + 1) * (format == CF_TEXT ? 1 : 2))) == NULL) { if (g_data) { GlobalUnlock(hmem); } CloseClipboard(); return 0; } if (format == CF_TEXT) { strcpy(l_data, g_data); } else { lstrcpyW(l_data, g_data); } GlobalUnlock(hmem); CloseClipboard(); #if 0 bl_debug_printf("%s SELECTION: %d\n", format == CF_TEXT ? "XCT" : "UTF", len); #endif PostMessage(win->my_window, format == CF_TEXT ? WM_APP_PASTE : WM_APP_WPASTE, len, l_data); return 0; } #ifdef USE_WIN32API static u_int __stdcall #else static void* #endif xct_selection_request(LPVOID thr_param) { return selection_request(thr_param, CF_TEXT); } #ifdef USE_WIN32API static u_int __stdcall #else static void* #endif utf_selection_request(LPVOID thr_param) { return selection_request(thr_param, CF_UNICODETEXT); } /* * Request selection from another thread for x11 applications on x11 forwarding. */ static int invoke_selection_request(ui_window_t *win, UINT format, #ifdef USE_WIN32API u_int (*selection_request)(LPVOID) #else void* (*selection_request)(LPVOID) #endif ) { if (IsClipboardFormatAvailable(format)) { #if defined(USE_WIN32API) HANDLE thrd; u_int tid; if (!(thrd = _beginthreadex(NULL, 0, selection_request, win, 0, &tid))) { return 0; } CloseHandle(thrd); #elif defined(HAVE_PTHREAD) pthread_t thrd; pthread_create(&thrd, NULL, selection_request, win); #else selection_request(win); #endif return 1; } return 0; } static void reset_input_focus(ui_window_t *win) { u_int count; if (win->inputtable) { win->inputtable = -1; } else { win->inputtable = 0; } for (count = 0; count < win->num_children; count++) { reset_input_focus(win->children[count]); } } /* --- global functions --- */ int ui_window_init(ui_window_t *win, u_int width, u_int height, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc, u_int hmargin, u_int vmargin, int create_gc, /* ignored */ int inputtable) { memset(win, 0, sizeof(ui_window_t)); win->fg_color.pixel = 0xff000000; win->bg_color.pixel = 0xffffffff; /* if visibility is partially obscured , scrollable will be 0. */ win->is_scrollable = 1; win->inputtable = inputtable; /* This flag will map window automatically in ui_window_show(). */ win->is_mapped = 1; win->create_gc = create_gc; win->width = width; win->height = height; win->min_width = min_width; win->min_height = min_height; win->width_inc = width_inc; win->height_inc = height_inc; win->sizehint_flag = SIZEHINT_WIDTH|SIZEHINT_HEIGHT; win->hmargin = hmargin; win->vmargin = vmargin; /* Not freed explicitly. Expect to be freed on process exited. */ if (!m_cp_parser && (m_cp_parser = ef_codepoint_parser_new()) == NULL) { return 0; } win->prev_clicked_button = -1; win->app_name = __("mlterm"); win->cmd_show = SW_SHOWNORMAL; return 1; } void ui_window_final(ui_window_t *win) { u_int count; #ifdef __DEBUG bl_debug_printf("[deleting child windows]\n"); ui_window_dump_children(win); #endif for (count = 0; count < win->num_children; count++) { ui_window_final(win->children[count]); } free(win->children); ui_display_clear_selection(win->disp, win); /* * DestroyWindow() is not called here because DestroyWindow internally sends * WM_DESTROY message which causes window_destroyed event again. * If you want to close window, call SendMessage( WM_CLOSE ) instead of * ui_window_final(). */ ui_xic_deactivate(win); #if 0 (*m_cp_parser.destroy)(&m_cp_parser); #endif if (win->window_finalized) { (*win->window_finalized)(win); } } void ui_window_set_type_engine(ui_window_t *win, ui_type_engine_t type_engine) {} void ui_window_add_event_mask(ui_window_t *win, long event_mask) { win->event_mask |= event_mask; } void ui_window_remove_event_mask(ui_window_t *win, long event_mask) { win->event_mask &= ~event_mask; } void ui_window_ungrab_pointer(ui_window_t *win) {} int ui_window_set_wall_picture(ui_window_t *win, Pixmap pic, int do_expose) { u_int count; win->is_scrollable = 0; win->wall_picture = pic; if (win->my_window != None && do_expose) { InvalidateRect(win->my_window, NULL, FALSE); } for (count = 0; count < win->num_children; count++) { ui_window_set_wall_picture(win->children[count], ParentRelative, do_expose); } return 1; } int ui_window_unset_wall_picture(ui_window_t *win, int do_expose) { u_int count; win->is_scrollable = check_scrollable(win); win->wall_picture = None; if (win->my_window != None) { InvalidateRect(win->my_window, NULL, FALSE); } for (count = 0; count < win->num_children; count++) { ui_window_unset_wall_picture(win->children[count], do_expose); } return 1; } int ui_window_set_transparent(ui_window_t *win, ui_picture_modifier_t *pic_mod) { return 0; } int ui_window_unset_transparent(ui_window_t *win) { return 0; } void ui_window_set_cursor(ui_window_t *win, u_int cursor_shape) { if (win->my_window != None) { if (cursor_shape == XC_nil) { if (!pointer_hidden) { ShowCursor(FALSE); pointer_hidden = 1; } } else if (win->cursor_shape == XC_nil) { if (pointer_hidden) { ShowCursor(TRUE); pointer_hidden = 0; } } } win->cursor_shape = cursor_shape; } int ui_window_set_fg_color(ui_window_t *win, ui_color_t *fg_color) { if (win->fg_color.pixel == fg_color->pixel) { return 0; } win->fg_color = *fg_color; return 1; } int ui_window_set_bg_color(ui_window_t *win, ui_color_t *bg_color) { int alpha; if (win->bg_color.pixel == bg_color->pixel) { return 0; } if ((alpha = ((bg_color->pixel >> 24) & 0xff)) != 0xff) { set_transparent(win, alpha); } else if (((win->bg_color.pixel >> 24) & 0xff) != 0xff) { /* * If alpha is changed from less than 0xff to 0xff, * transparent is disabled. * XXX It is assumed that alpha is changed by only one window. */ unset_transparent(win); } win->bg_color = *bg_color; if (win->my_window != None) { InvalidateRect(win->my_window, NULL, FALSE); } return 1; } int ui_window_add_child(ui_window_t *win, ui_window_t *child, int x, int y, int map) { void *p; if ((p = realloc(win->children, sizeof(*win->children) * (win->num_children + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } win->children = p; child->parent = win; child->x = x + win->hmargin; child->y = y + win->vmargin; if (!(child->is_mapped = map) && child->inputtable > 0) { child->inputtable = -1; } win->children[win->num_children++] = child; return 1; } int ui_window_remove_child(ui_window_t *win, ui_window_t *child) { u_int count; for (count = 0; count < win->num_children; count++) { if (win->children[count] == child) { child->parent = NULL; win->children[count] = win->children[--win->num_children]; return 1; } } return 0; } ui_window_t *ui_get_root_window(ui_window_t *win) { while (win->parent != NULL) { win = win->parent; } return win; } GC ui_window_get_fg_gc(ui_window_t *win) { if (win->gc->gc == None) { return None; } #if 0 ui_gc_set_fg_color(win->gc, win->fg_color.pixel); ui_gc_set_bg_color(win->gc, win->bg_color.pixel); #endif ui_release_pen(ui_gc_set_pen(win->gc, ui_acquire_pen(win->fg_color.pixel))); ui_release_brush(ui_gc_set_brush(win->gc, ui_acquire_brush(win->fg_color.pixel))); return win->gc->gc; } GC ui_window_get_bg_gc(ui_window_t *win) { if (win->gc->gc == None) { return None; } #if 0 ui_gc_set_fg_color(win->gc, win->bg_color.pixel); ui_gc_set_bg_color(win->gc, win->fg_color.pixel); #endif ui_release_pen(ui_gc_set_pen(win->gc, GetStockObject(NULL_PEN))); ui_release_brush(ui_gc_set_brush(win->gc, ui_acquire_brush(win->bg_color.pixel))); return win->gc->gc; } int ui_window_show(ui_window_t *win, int hint /* If win->parent(_window) is None, specify XValue|YValue to localte window at win->x/win->y. */ ) { u_int count; if (win->my_window) { /* already shown */ return 0; } if (win->parent) { win->disp = win->parent->disp; win->parent_window = win->parent->my_window; win->gc = win->parent->gc; } #ifndef USE_WIN32GUI if (hint & XNegative) { win->x += (win->disp->width - ACTUAL_WIDTH(win)); } if (hint & YNegative) { win->y += (win->disp->height - ACTUAL_HEIGHT(win)); } #endif #ifdef __DEBUG bl_debug_printf("X: EDGE%d BORDER%d FRAME%d Y: EDGE%d BORDER%d FRAME%d CAPTION%d\n", GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYEDGE), GetSystemMetrics(SM_CYBORDER), GetSystemMetrics(SM_CYFRAME), GetSystemMetrics(SM_CYCAPTION)); #endif win->my_window = CreateWindowEx(0, __("MLTERM"), win->app_name, PARENT_WINDOWID_IS_TOP(win) ? WS_OVERLAPPEDWINDOW : WS_CHILD | WS_VISIBLE, PARENT_WINDOWID_IS_TOP(win) && !(hint & XValue) ? CW_USEDEFAULT : win->x, PARENT_WINDOWID_IS_TOP(win) && !(hint & YValue) ? CW_USEDEFAULT : win->y, PARENT_WINDOWID_IS_TOP(win) ? ACTUAL_WINDOW_WIDTH(win) : ACTUAL_WIDTH(win), PARENT_WINDOWID_IS_TOP(win) ? ACTUAL_WINDOW_HEIGHT(win) : ACTUAL_HEIGHT(win), win->parent_window, NULL, win->disp->display->hinst, NULL); if (!win->my_window) { bl_dialog(BL_DIALOG_ALERT, "Failed to create window."); return 0; } #ifndef DISABLE_XDND DragAcceptFiles(win->my_window, TRUE); #endif if (win->parent && !win->parent->is_transparent && win->parent->wall_picture) { ui_window_set_wall_picture(win, ParentRelative, 0); } /* * This should be called after Window Manager settings, because * ui_set_{window|icon}_name() can be called in win->window_realized(). */ if (win->window_realized) { (*win->window_realized)(win); } /* * showing child windows. */ for (count = 0; count < win->num_children; count++) { ui_window_show(win->children[count], 0); } /* * really visualized. */ /* Don't place this before ui_window_show(children). */ if (update_decorate_size(win)) { SetWindowPos(win->my_window, win->cmd_show == SW_SHOWNA ? HWND_TOPMOST : 0, 0, 0, ACTUAL_WINDOW_WIDTH(win), ACTUAL_WINDOW_HEIGHT(win), (win->cmd_show == SW_SHOWNA ? SWP_NOACTIVATE : 0) | SWP_NOMOVE | SWP_NOZORDER); } /* * XXX * Some area in a main screen is not correctly drawn without this * in showing a status screen. * stat_screen is shown in im->stat_screen->show() in ui_im_redraw_preedit() */ if (win->app_name && strstr(win->app_name, "mlterm-")) /* mlterm-{candidate|status}-window" */ { win->is_mapped = 0; } if (win->is_mapped) { ShowWindow(win->my_window, win->cmd_show); if (win->inputtable > 0) { reset_input_focus(ui_get_root_window(win)); win->inputtable = 1; } #if 0 ui_window_clear_all(win); #endif } else { ShowWindow(win->my_window, SW_HIDE); } if (win->is_transparent) { ui_window_set_transparent(win, win->pic_mod); } return 1; } void ui_window_map(ui_window_t *win) { if (win->is_mapped) { return; } ShowWindow(win->my_window, win->cmd_show); win->is_mapped = 1; } void ui_window_unmap(ui_window_t *win) { if (!win->is_mapped) { return; } ShowWindow(win->my_window, SW_HIDE); win->is_mapped = 0; } int ui_window_resize(ui_window_t *win, u_int width, /* excluding margin */ u_int height, /* excluding margin */ ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */ ) { if (win->width == width && win->height == height) { return 0; } /* Max width of each window is screen width. */ if ((flag & LIMIT_RESIZE) && win->disp->width < width) { win->width = win->disp->width - win->hmargin * 2; } else { win->width = width; } /* Maui.height of each window is screen height. */ if ((flag & LIMIT_RESIZE) && win->disp->height < height) { win->height = win->disp->height - win->vmargin * 2; } else { win->height = height; } if ((flag & NOTIFY_TO_PARENT) && win->parent && win->parent->child_window_resized) { (*win->parent->child_window_resized)(win->parent, win); } update_decorate_size(win); SetWindowPos(win->my_window, win->cmd_show == SW_SHOWNA ? HWND_TOPMOST : 0, 0, 0, win->parent ? ACTUAL_WIDTH(win) : ACTUAL_WINDOW_WIDTH(win), win->parent ? ACTUAL_HEIGHT(win) : ACTUAL_WINDOW_HEIGHT(win), (win->cmd_show == SW_SHOWNA ? SWP_NOACTIVATE : 0) | SWP_NOMOVE | SWP_NOZORDER); if ((flag & NOTIFY_TO_MYSELF) && win->window_resized) { (*win->window_resized)(win); } return 1; } /* * !! Notice !! * This function is not recommended. * Use ui_window_resize if at all possible. */ int ui_window_resize_with_margin(ui_window_t *win, u_int width, u_int height, ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */ ) { return ui_window_resize(win, width - win->hmargin * 2, height - win->vmargin * 2, flag); } void ui_window_set_maximize_flag(ui_window_t *win, ui_maximize_flag_t flag) { if (flag == MAXIMIZE_FULL) { ShowWindow(ui_get_root_window(win)->my_window, SW_MAXIMIZE); } else if (flag == MAXIMIZE_RESTORE) { ShowWindow(ui_get_root_window(win)->my_window, SW_NORMAL); } else { /* XXX */ } } void ui_window_set_normal_hints(ui_window_t *win, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc) { win->min_width = min_width; win->min_height = min_height; win->width_inc = width_inc; win->height_inc = height_inc; } void ui_window_set_override_redirect(ui_window_t *win, int flag) { ui_window_t *root; if ((root = ui_get_root_window(win))->my_window) { #if 0 if (root->is_mapped) { ShowWindow(root->my_window, SW_HIDE); } #endif if (flag) { SetWindowLong(root->my_window, GWL_STYLE, 0); win->cmd_show = SW_SHOWNA; SetWindowPos(root->my_window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); } else { SetWindowLong(root->my_window, GWL_STYLE, !win->parent ? WS_OVERLAPPEDWINDOW : WS_CHILD | WS_VISIBLE); win->cmd_show = SW_SHOWNORMAL; } #if 0 if (root->is_mapped) { ShowWindow(root->my_window, win->cmd_show); } #endif } } int ui_window_set_borderless_flag(ui_window_t *win, int flag) { return 0; } int ui_window_move(ui_window_t *win, int x, int y) { if (win->parent) { x += win->parent->hmargin; y += win->parent->vmargin; } if (win->x == x && win->y == y) { return 0; } win->x = x; win->y = y; update_decorate_size(win); SetWindowPos(win->my_window, 0, win->x, win->y, win->parent ? ACTUAL_WIDTH(win) : ACTUAL_WINDOW_WIDTH(win), win->parent ? ACTUAL_HEIGHT(win) : ACTUAL_WINDOW_HEIGHT(win), (win->cmd_show == SW_SHOWNA ? SWP_NOACTIVATE : 0) | SWP_NOSIZE | SWP_NOZORDER); return 1; } /* * This function can be used in context except window_exposed and update_window * events. */ void ui_window_clear(ui_window_t *win, int x, int y, u_int width, u_int height) { RECT r; #ifdef AUTO_CLEAR_MARGIN if (x + width >= win->width) { /* Clearing margin area */ width += win->hmargin; } if (x > 0) #endif { x += win->hmargin; } #ifdef AUTO_CLEAR_MARGIN else { /* Clearing margin area */ width += win->hmargin; } if (y + height >= win->height) { /* Clearing margin area */ height += win->vmargin; } if (y > 0) #endif { y += win->vmargin; } #ifdef AUTO_CLEAR_MARGIN else { /* Clearing margin area */ height += win->vmargin; } #endif r.left = x; r.top = y; /* XXX Garbage is left in screen in scrolling without +1 due to NULL_PEN ? */ r.right = x + width /* + 1 */; r.bottom = y + height /* + 1 */; if (win->gc->gc == None) { InvalidateRect(win->my_window, &r, TRUE); } else { if (win->wall_picture) { Pixmap pic; int src_x; int src_y; if (win->wall_picture == ParentRelative) { pic = win->parent->wall_picture; src_x = win->x; src_y = win->y; } else { pic = win->wall_picture; src_x = src_y = 0; } BitBlt(win->gc->gc, r.left, r.top, r.right - r.left, r.bottom - r.top, pic, src_x + r.left, src_y + r.top, SRCCOPY); } else { HBRUSH brush; brush = ui_acquire_brush(win->bg_color.pixel); FillRect(win->gc->gc, &r, brush); ui_release_brush(brush); } } } void ui_window_clear_all(ui_window_t *win) { ui_window_clear(win, 0, 0, win->width, win->height); } void ui_window_fill(ui_window_t *win, int x, int y, u_int width, u_int height) { ui_window_fill_with(win, &win->fg_color, x, y, width, height); } void ui_window_fill_with(ui_window_t *win, ui_color_t *color, int x, int y, u_int width, u_int height) { if (win->gc->gc == None) { return; } if (height == 1 || width == 1) { ui_release_pen(ui_gc_set_pen(win->gc, ui_acquire_pen(color->pixel))); MoveToEx(win->gc->gc, win->hmargin + x, win->vmargin + y, NULL); LineTo(win->gc->gc, win->hmargin + x + (width == 1 ? 0 : width), win->vmargin + y + (width == 1 ? height : 0)); } else { HBRUSH brush; RECT r; brush = ui_acquire_brush(color->pixel); SetRect(&r, win->hmargin + x, win->vmargin + y, win->hmargin + x + width, win->vmargin + y + height); FillRect(win->gc->gc, &r, brush); ui_release_brush(brush); } } /* * This function can be used in context except window_exposed and update_window * events. */ void ui_window_blank(ui_window_t *win) { int get_dc; HBRUSH brush; RECT r; if (win->gc->gc == None) { ui_set_gc(win->gc, GetDC(win->my_window)); get_dc = 1; } else { get_dc = 0; } brush = ui_acquire_brush(win->fg_color.pixel); SetRect(&r, win->hmargin, win->vmargin, win->width - RIGHT_MARGIN(win), win->height - BOTTOM_MARGIN(win)); FillRect(win->gc->gc, &r, brush); ui_release_brush(brush); if (get_dc) { ReleaseDC(win->my_window, win->gc->gc); ui_set_gc(win->gc, None); } } #if 0 /* * XXX * at the present time , not used and not maintained. */ void ui_window_blank_with(ui_window_t *win, ui_color_t *color) {} #endif void ui_window_update(ui_window_t *win, int flag) { if (win->update_window_flag) { /* WM_APP_PAINT has been already posted. */ win->update_window_flag |= flag; return; } else { win->update_window_flag = flag; } /* * WM_APP_PAINT message is posted only when update_window_flag is 0. */ PostMessage(win->my_window, WM_APP_PAINT, 0, 0); } void ui_window_update_all(ui_window_t *win) { u_int count; InvalidateRect(win->my_window, NULL, FALSE); for (count = 0; count < win->num_children; count++) { ui_window_update_all(win->children[count]); } } void ui_window_idling(ui_window_t *win) { u_int count; for (count = 0; count < win->num_children; count++) { ui_window_idling(win->children[count]); } #ifdef __DEBUG if (win->button_is_pressing) { bl_debug_printf(BL_DEBUG_TAG " button is pressing...\n"); } #endif if (win->button_is_pressing && win->button_press_continued) { (*win->button_press_continued)(win, &win->prev_button_press_event); } else if (win->idling) { (*win->idling)(win); } } /* * Return value: 0 => different window. * 1 => finished processing. * -1 => continuing default processing. */ int ui_window_receive_event(ui_window_t *win, XEvent *event) { u_int count; for (count = 0; count < win->num_children; count++) { int val; if ((val = ui_window_receive_event(win->children[count], event)) != 0) { return val; } } if (event->window != win->my_window) { return 0; } #ifndef DISABLE_XDND if (ui_dnd_filter_event(event, win)) { /* event was consumed by xdnd handler. */ return 1; } #endif switch (event->msg) { case WM_DESTROY: if (win->window_destroyed) { (*win->window_destroyed)(win); } return 1; case WM_APP_PASTE: if (win->xct_selection_notified) { (*win->xct_selection_notified)(win, event->lparam, event->wparam); free(event->lparam); } return 1; case WM_APP_WPASTE: if (win->utf_selection_notified) { (*win->utf_selection_notified)(win, event->lparam, event->wparam * 2); free(event->lparam); } return 1; case WM_APP_PAINT: if (win->update_window) { ui_set_gc(win->gc, GetDC(win->my_window)); (*win->update_window)(win, win->update_window_flag); ReleaseDC(win->my_window, win->gc->gc); ui_set_gc(win->gc, None); win->update_window_flag = 0; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "WM_APP_PAINT_END\n"); #endif } return 1; case WM_PAINT: if (win->window_exposed) { PAINTSTRUCT ps; int margin_area_exposed; int x; int y; u_int width; u_int height; ui_set_gc(win->gc, BeginPaint(win->my_window, &ps)); margin_area_exposed = 0; if (ps.rcPaint.left < win->hmargin) { margin_area_exposed = 1; x = 0; } else { x = ps.rcPaint.left - win->hmargin; } if (ps.rcPaint.top < win->vmargin) { margin_area_exposed = 1; y = 0; } else { y = ps.rcPaint.top - win->vmargin; } if (ps.rcPaint.right > win->width - win->hmargin) { margin_area_exposed = 1; width = win->width - win->hmargin - x; } else { /* +1 is not necessary ? */ width = ps.rcPaint.right - x /* + 1 */; } if (ps.rcPaint.bottom > win->height - win->vmargin) { margin_area_exposed = 1; height = win->height - win->vmargin - y; } else { /* +1 is not necessary ? */ height = ps.rcPaint.bottom - y /* + 1 */; } if (margin_area_exposed) { clear_margin_area(win); } (*win->window_exposed)(win, x, y, width, height); EndPaint(win->my_window, &ps); ui_set_gc(win->gc, None); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "WM_PAINT_END\n"); #endif } return 1; case WM_ERASEBKGND: { RECT rt; HBRUSH old; if (win->parent != NULL) /* XXX Hack for not flashing. */ { old = SelectObject((HDC)event->wparam, ui_acquire_brush(win->bg_color.pixel)); GetClientRect(win->my_window, &rt); PatBlt((HDC)event->wparam, rt.left, rt.top, rt.right - rt.left, rt.bottom - rt.top, PATCOPY); ui_release_brush(SelectObject((HDC)event->wparam, old)); } return 1; } case WM_KEYDOWN: /* * Dispatch event to all windows in case key was pressed in the * scrollbar window but should be shown in the text area. */ ui_xic_filter_event(ui_get_root_window(win), event); case WM_SYSKEYDOWN: if (win->key_pressed) { XKeyEvent kev; kev.state = get_key_state(); if ((0x30 <= event->wparam && event->wparam <= VK_DIVIDE) || event->wparam == VK_BACK || event->wparam == VK_RETURN || event->wparam == VK_ESCAPE || event->wparam == VK_SPACE) { kev.ch = event->wparam; if (kev.state & ModMask) { if (event->msg == WM_SYSKEYDOWN) { /* * Alt+key (which doesn't cause WM_*_CHAR message) */ if ('A' <= kev.ch && kev.ch <= 'Z') { /* * Upper case => Lower case. * event->wparam is always upper case * if alt key is pressed together. */ kev.ch += 0x20; } } else { /* wait for WM_*_CHAR message. */ break; } } else if ((kev.state & ControlMask) && '0' <= kev.ch && kev.ch <= '9') { /* * - See ui_xic_get_str() in win32/ui_xic.c. * - Control+0-9 doesn't cause WM_*_CHAR message. */ } else { /* wait for WM_*_CHAR message. */ break; } } else if (event->wparam == VK_TAB) { kev.ch = event->wparam; if (kev.state & ShiftMask) { event->wparam = XK_ISO_Left_Tab; ui_xic_filter_event(ui_get_root_window(win), event); } if (kev.state & ControlMask) { /* (Shift+)Control+Tab doesn't cause WM_*_CHAR message. */ } else { /* wait for WM_*_CHAR message. */ break; } } else if (event->msg == WM_SYSKEYDOWN) { if (kev.state & ModMask) { /* * VK_OEM_XXX doesn't cause WM_*_CHAR message * in WM_SYSKEYDOWN. */ if ((kev.ch = oem_key_to_char(event->wparam))) { event->wparam = kev.ch; ui_xic_filter_event(ui_get_root_window(win), event); } } else { kev.ch = 0; } if (kev.ch == 0 && event->wparam != VK_F10 /* Menu */) { break; } } else if (VK_SHIFT <= event->wparam && event->wparam <= VK_MENU) { /* Don't call key_pressed event */ break; } else { kev.ch = 0; /* * - See ui_xic_get_str() in win32/ui_xic.c. * - Ctrl+Alt+key(AltGr+key) can cause WM_*_CHAR message later. */ if (!(kev.state & ModMask) && (kev.state & ControlMask)) { if ((kev.ch = oem_key_to_char(event->wparam))) { /* * VK_OEM_1 <= event->wparam && * event->wparam <= VK_OEM_102 */ int orig_wparam; orig_wparam = event->wparam; event->wparam = kev.ch; ui_xic_filter_event(ui_get_root_window(win), event); if (orig_wparam == VK_OEM_4 || /* Ctl+[ */ orig_wparam == VK_OEM_5 || /* Ctl+\ */ orig_wparam == VK_OEM_6 || /* Ctl+] */ (orig_wparam == VK_OEM_102 && /* Ctl+_ */ !(kev.state & ShiftMask)) || (orig_wparam == VK_OEM_MINUS && /* Ctrl+- */ (kev.state & ShiftMask))) { break; } else { /* * keys except VK_OEM_{4|5|6} and * Shift+VK_OEM_102 don't * cause WM_*_CHAR message. */ } } } else if ((VK_OEM_1 /* 0xba */ <= event->wparam && event->wparam <= VK_OEM_3 /* 0xc0 */) || (VK_OEM_4 /* 0xdb */ <= event->wparam && event->wparam <= VK_OEM_8 /* 0xdf */) || (VK_OEM_AX /* 0xe1 */ <= event->wparam && event->wparam <= VK_OEM_102 /* 0xe2 */)) { /* wait for WM_*_CHAR message. */ break; } } if (event->msg == WM_SYSKEYDOWN) { event->msg = WM_KEYDOWN; ui_xic_filter_event(ui_get_root_window(win), event); } (*win->key_pressed)(win, &kev); return 1; } /* Continue default processing. */ break; case WM_IME_CHAR: case WM_CHAR: if (win->key_pressed) { XKeyEvent kev; kev.state = get_key_state(); if ((kev.state & (ControlMask | Mod1Mask)) == (ControlMask | Mod1Mask) && 0x20 < event->wparam && event->wparam != 0x7f) { /* AltGr+key sends Ctrl+Alt+char */ kev.state &= ~(ControlMask | Mod1Mask); } #if 0 /* * XXX * For cmd.exe. If not converted '\r' to '\n', cmd prompt * never goes to next line. */ if (event->wparam == '\r') { kev.ch = '\n'; } else #endif { kev.ch = event->wparam; } (*win->key_pressed)(win, &kev); } return 1; case WM_SETFOCUS: #if 0 bl_debug_printf("FOCUS IN %p\n", win->my_window); #endif urgent_bell(win, 0); notify_focus_in_to_children(ui_get_root_window(win)); break; case WM_KILLFOCUS: #if 0 bl_debug_printf("FOCUS OUT %p\n", win->my_window); #endif notify_focus_out_to_children(ui_get_root_window(win)); break; case WM_MOUSEWHEEL: case WM_MOUSEHWHEEL: case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: if (!win->button_pressed) { return 1; } goto BUTTON_MSG; case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: if (!win->button_released) { return 1; } BUTTON_MSG : { XButtonEvent bev; bev.time = GetMessageTime(); bev.state = get_key_state(); #if 0 if (event->wparam & MK_LBUTTON) { bev.state |= Button1Mask; } if (event->wparam & MK_MBUTTON) { bev.state |= Button2Mask; } if (event->wparam & MK_RBUTTON) { bev.state |= Button3Mask; } #endif if (event->wparam & MK_SHIFT) { bev.state |= ShiftMask; } if (event->wparam & MK_CONTROL) { bev.state |= ControlMask; } if (event->msg == WM_MOUSEWHEEL || event->msg == WM_MOUSEHWHEEL) { /* Note that WM_MOUSEWHEEL event is reported to top window. */ POINT p; p.x = LOWORD(event->lparam); p.y = HIWORD(event->lparam); ScreenToClient(win->my_window, &p); bev.x = p.x - win->hmargin; bev.y = p.y - win->vmargin; if (((SHORT)HIWORD(event->wparam)) > 0) { if (event->msg == WM_MOUSEHWHEEL) { /* Right */ bev.button = Button7; } else { /* Up */ bev.button = Button4; } } else { if (event->msg == WM_MOUSEHWHEEL) { /* Left */ bev.button = Button6; } else { /* Down */ bev.button = Button5; } } } else { bev.x = LOWORD(event->lparam) - win->hmargin; bev.y = HIWORD(event->lparam) - win->vmargin; if (event->msg == WM_LBUTTONDOWN || event->msg == WM_LBUTTONUP) { bev.button = Button1; } else if (event->msg == WM_MBUTTONDOWN || event->msg == WM_MBUTTONUP) { bev.button = Button2; } else /* if( event->msg == WM_RBUTTONDOWN || event->msg == WM_RBUTTONUP) */ { bev.button = Button3; } } /* XXX grandchild windows aren't regarded for now. */ for (count = 0; count < win->num_children; count++) { if (bev.x <= win->children[count]->x && bev.y <= win->children[count]->y && win->children[count]->x + ACTUAL_WIDTH(win->children[count]) <= bev.x + 1 && win->children[count]->y + ACTUAL_HEIGHT(win->children[count]) <= bev.y + 1) { win = win->children[count]; bev.x -= win->x; bev.y -= win->y; break; } } if (event->msg == WM_MOUSEWHEEL || event->msg == WM_LBUTTONDOWN || event->msg == WM_RBUTTONDOWN || event->msg == WM_MBUTTONDOWN) { /* XXX If button is released outside screen, WM_*BUTTONUP event might not happen. */ if (win->button_is_pressing) { if (win->button_released) { (*win->button_released)(win, &bev); } win->button_is_pressing = 0; } if (win->click_num == MAX_CLICK) { win->click_num = 0; } if (win->prev_clicked_time + click_interval >= bev.time && bev.button == win->prev_clicked_button) { win->click_num++; win->prev_clicked_time = bev.time; } else { win->click_num = 1; win->prev_clicked_time = bev.time; win->prev_clicked_button = bev.button; } (*win->button_pressed)(win, &bev, win->click_num); win->button_is_pressing = 1; win->prev_button_press_event = bev; #if 0 bl_debug_printf(BL_DEBUG_TAG " mouse pressed btn %d stat %d x %d y %d click_num %d\n", bev.button, bev.state, bev.x, bev.y, win->click_num); #endif } else /* if( event->msg == WM_LBUTTONUP || event->msg == WM_RBUTTONUP || event->msg == WM_MBUTTONUP) */ { (*win->button_released)(win, &bev); win->button_is_pressing = 0; #if 0 bl_debug_printf(BL_DEBUG_TAG " mouse released... state %d x %d y %d\n", bev.state, bev.x, bev.y); #endif } if (!win->is_focused && win->inputtable && bev.button == Button1 && !bev.state) { ui_window_set_input_focus(win); } } return 1; case WM_MOUSEMOVE: if (pointer_hidden) { ShowCursor(TRUE); pointer_hidden = 0; } if (win->button_is_pressing || ((win->event_mask & PointerMotionMask) && win->pointer_motion)) { XMotionEvent mev; mev.time = GetMessageTime(); mev.x = LOWORD(event->lparam) - win->hmargin; mev.y = HIWORD(event->lparam) - win->vmargin; mev.state = get_key_state(); if (event->wparam & MK_LBUTTON) { mev.state |= Button1Mask; } if (event->wparam & MK_MBUTTON) { mev.state |= Button2Mask; } if (event->wparam & MK_RBUTTON) { mev.state |= Button3Mask; } if (!mev.state) { win->button_is_pressing = 0; } if (event->wparam & MK_SHIFT) { mev.state |= ShiftMask; } if (event->wparam & MK_CONTROL) { mev.state |= ControlMask; } if (win->button_is_pressing) { /* * prev_button_press_event.{x|y} can be the same * as mev.{x|y} when window is pressed and focused. */ if (win->button_motion && (win->prev_button_press_event.x != mev.x || win->prev_button_press_event.y != mev.y)) { (*win->button_motion)(win, &mev); } /* following button motion ... */ win->prev_button_press_event.x = mev.x; win->prev_button_press_event.y = mev.y; win->prev_button_press_event.time = mev.time; #if 0 bl_debug_printf(BL_DEBUG_TAG " button motion... state %d x %d y %d\n", mev.state, mev.x, mev.y); #endif } /* * win->pointer_motion should be checked again here because * win->button_is_pressing was changed from 1 to 0 above. */ else if (win->pointer_motion) { (*win->pointer_motion)(win, &mev); #if 0 bl_debug_printf(BL_DEBUG_TAG " pointer motion... state %d x %d y %d\n", mev.state, mev.x, mev.y); #endif } } return 1; case WM_SETCURSOR: { Cursor cursor; if (win->cursor_shape == XC_nil) { SetCursor(NULL); } else if ((cursor = ui_display_get_cursor(win->disp, win->cursor_shape))) { SetCursor(cursor); } else { break; } return 1; } case WM_RENDERALLFORMATS: OpenClipboard(win->my_window); EmptyClipboard(); case WM_RENDERFORMAT: if (event->wparam == CF_UNICODETEXT) { if (win->utf_selection_requested) { (*win->utf_selection_requested)(win, NULL, CF_UNICODETEXT); #if 0 bl_debug_printf(BL_DEBUG_TAG "utf_selection_requested\n"); #endif } } else if (event->wparam == CF_TEXT) { if (win->xct_selection_requested) { (*win->xct_selection_requested)(win, NULL, CF_TEXT); } } if (event->msg == WM_RENDERALLFORMATS) { CloseClipboard(); } return 1; case WM_DESTROYCLIPBOARD: if (win->is_sel_owner == 1) { /* * Call win->selection_cleared and win->is_sel_owner is set 0 * in ui_display_clear_selection. */ ui_display_clear_selection(win->disp, win); } else if (win->is_sel_owner > 1) { win->is_sel_owner--; } return 1; case WM_MOVE: if (win->parent == NULL) { win->x = LOWORD(event->lparam); win->y = HIWORD(event->lparam); #if 0 bl_debug_printf("WM_MOVE x %d y %d\n", win->x, win->y); #endif notify_move_to_children(win); } return 1; case WM_SIZE: if (win->window_resized && !IsIconic(win->my_window)) { /* * Assume that win == root. */ u_int width; u_int height; u_int min_width; u_int min_height; width = LOWORD(event->lparam); height = HIWORD(event->lparam); min_width = total_min_width(win); min_height = total_min_height(win); if (width < min_width || height < min_height) { ui_window_resize(win, BL_MAX(min_width, width) - win->hmargin * 2, BL_MAX(min_height, height) - win->vmargin * 2, NOTIFY_TO_MYSELF); } else if (width != ACTUAL_WIDTH(win) || height != ACTUAL_HEIGHT(win)) { u_int width_surplus; u_int height_surplus; if (IsZoomed(ui_get_root_window(win)->my_window)) { width_surplus = height_surplus = 0; } else { width_surplus = (width - min_width - win->hmargin * 2) % max_width_inc(win); height_surplus = (height - min_height - win->vmargin * 2) % max_height_inc(win); } win->width = width - win->hmargin * 2; win->height = height - win->vmargin * 2; if (width_surplus > 0 || height_surplus > 0) { ui_window_resize(win, width - win->hmargin * 2 - width_surplus, height - win->vmargin * 2 - height_surplus, NOTIFY_TO_MYSELF); } else { ui_window_clear_all(win); (*win->window_resized)(win); } } notify_move_to_children(win); } return 1; /* Not necessary */ #if 0 case WM_THEMECHANGED: update_decorate_size(win); return 1; #endif } return -1; } size_t ui_window_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { return ui_xic_get_str(win, seq, seq_len, parser, keysym, event); } /* * Scroll functions. * The caller side should clear the scrolled area. */ int ui_window_scroll_upward(ui_window_t *win, u_int height) { return ui_window_scroll_upward_region(win, 0, win->height, height); } int ui_window_scroll_upward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d in window((h) %d (w) %d)\n", boundary_start, boundary_end, height, win->height, win->width); #endif return 0; } BitBlt(win->gc->gc, win->hmargin, win->vmargin + boundary_start, /* dst */ win->width, boundary_end - boundary_start - height, /* size */ win->gc->gc, win->hmargin, win->vmargin + boundary_start + height, /* src */ SRCCOPY); return 1; } int ui_window_scroll_downward(ui_window_t *win, u_int height) { return ui_window_scroll_downward_region(win, 0, win->height, height); } int ui_window_scroll_downward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d\n", boundary_start, boundary_end, height); #endif return 0; } BitBlt(win->gc->gc, win->hmargin, win->vmargin + boundary_start + height, /* dst */ win->width, boundary_end - boundary_start - height, /* size */ win->gc->gc, win->hmargin, win->vmargin + boundary_start, /* src */ SRCCOPY); return 1; } int ui_window_scroll_leftward(ui_window_t *win, u_int width) { return ui_window_scroll_leftward_region(win, 0, win->width, width); } int ui_window_scroll_leftward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d in window((h) %d (w) %d)\n", boundary_start, boundary_end, width, win->height, win->width); #endif return 0; } BitBlt(win->gc->gc, win->hmargin + boundary_start, win->vmargin, /* dst */ boundary_end - boundary_start - width, win->height, /* size */ win->gc->gc, win->hmargin + boundary_start + width, win->vmargin, /* src */ SRCCOPY); return 1; } int ui_window_scroll_rightward(ui_window_t *win, u_int width) { return ui_window_scroll_rightward_region(win, 0, win->width, width); } int ui_window_scroll_rightward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d\n", boundary_start, boundary_end, width); #endif return 0; } BitBlt(win->gc->gc, win->hmargin + boundary_start + width, win->vmargin, /* dst */ boundary_end - boundary_start - width, win->height, /* size */ win->gc->gc, win->hmargin + boundary_start, win->vmargin, /* src */ SRCCOPY); return 1; } int ui_window_copy_area(ui_window_t *win, Pixmap src, PixmapMask mask, int src_x, /* >= 0 */ int src_y, /* >= 0 */ u_int width, u_int height, int dst_x, /* >= 0 */ int dst_y /* >= 0 */ ) { #ifndef DONT_OPTIMIZE_DRAWING_PICTURE int tmp_gc; #endif if (dst_x >= win->width || dst_y >= win->height) { return 0; } /* for xterm_show_picture() */ #ifndef DONT_OPTIMIZE_DRAWING_PICTURE if (win->gc->gc == None) { ui_set_gc(win->gc, GetDC(win->my_window)); tmp_gc = 1; } else { tmp_gc = 0; } #endif if (dst_x + width > win->width) { width = win->width - dst_x; } if (dst_y + height > win->height) { height = win->height - dst_y; } if (mask) { MaskBlt(win->gc->gc, win->hmargin + dst_x, win->vmargin + dst_y, width, height, src, src_x, src_y, mask, src_x, src_y, MAKEROP4(SRCCOPY, 0x00aa0029)); } else { BitBlt(win->gc->gc, win->hmargin + dst_x, win->vmargin + dst_y, width, height, src, src_x, src_y, SRCCOPY); } #ifndef DONT_OPTIMIZE_DRAWING_PICTURE if (tmp_gc) { ReleaseDC(win->my_window, win->gc->gc); ui_set_gc(win->gc, None); } #endif return 1; } void ui_window_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height) { HRGN r = CreateRectRgn(x + win->hmargin, y + win->vmargin, x + width + win->hmargin, y + height + win->vmargin); SelectClipRgn(win->gc->gc, r); DeleteObject(r); } void ui_window_unset_clip(ui_window_t *win) { SelectClipRgn(win->gc->gc, NULL); } void ui_window_draw_decsp_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int len) { ui_window_draw_string(win, font, fg_color, x, y, str, len); } void ui_window_draw_decsp_image_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, u_char *str, u_int len) { ui_window_draw_image_string(win, font, fg_color, bg_color, x, y, str, len); } void ui_window_draw_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int len) { if (win->gc->gc == None) { return; } /* Removing trailing spaces. */ while (1) { if (len == 0) { return; } if (*(str + len - 1) == ' ') { len--; } else { break; } } ui_gc_set_fid(win->gc, font->xfont->fid); ui_gc_set_fg_color(win->gc, fg_color->pixel); /* * XXX Hack * In case US_ASCII characters is drawn by Unicode font. * 8 bit charcter => 16 bit character. */ if (IS_ISO10646_UCS4(FONT_CS(font->id))) { u_char *dbl_str; if ((dbl_str = alloca(len * 2))) { u_int count; for (count = 0; count < len; count++) { /* Little Endian */ dbl_str[count * 2] = str[count]; dbl_str[count * 2 + 1] = 0x0; } draw_string(win, font, x, y, dbl_str, len * 2, 1, 1); } } else { draw_string(win, font, x, y, str, len, 1, 0); } } void ui_window_draw_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, XChar2b *str, u_int len) { if (win->gc->gc == None) { return; } ui_gc_set_fid(win->gc, font->xfont->fid); ui_gc_set_fg_color(win->gc, fg_color->pixel); draw_string(win, font, x, y, (u_char*)str, len * 2, 1, IS_ISO10646_UCS4(FONT_CS(font->id))); } void ui_window_draw_image_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, u_char *str, u_int len) { if (win->gc->gc == None) { return; } ui_gc_set_fid(win->gc, font->xfont->fid); ui_gc_set_fg_color(win->gc, fg_color->pixel); ui_gc_set_bg_color(win->gc, bg_color->pixel); /* * XXX Hack * In case US_ASCII characters is drawn by Unicode font. * 8 bit charcter => 16 bit character. */ if (IS_ISO10646_UCS4(FONT_CS(font->id))) { u_char *dbl_str; if ((dbl_str = alloca(len * 2))) { u_int count; for (count = 0; count < len; count++) { /* Little Endian */ dbl_str[count * 2] = str[count]; dbl_str[count * 2 + 1] = 0x0; } draw_string(win, font, x, y, dbl_str, len * 2, 0, 1); } } else { draw_string(win, font, x, y, str, len, 0, 0); } } void ui_window_draw_image_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, XChar2b *str, u_int len) { if (win->gc->gc == None) { return; } ui_gc_set_fid(win->gc, font->xfont->fid); ui_gc_set_fg_color(win->gc, fg_color->pixel); ui_gc_set_bg_color(win->gc, bg_color->pixel); draw_string(win, font, x, y, (u_char*)str, len * 2, 0, IS_ISO10646_UCS4(FONT_CS(font->id))); } void ui_window_draw_rect_frame(ui_window_t *win, int x1, int y1, int x2, int y2) { if (win->gc->gc == None) { return; } ui_release_pen(ui_gc_set_pen(win->gc, ui_acquire_pen(win->fg_color.pixel))); ui_release_brush(ui_gc_set_brush(win->gc, GetStockObject(NULL_BRUSH))); Rectangle(win->gc->gc, x1 + win->hmargin, y1 + win->vmargin, x2 + win->hmargin, y2 + win->vmargin); } void ui_set_use_clipboard_selection(int use_it) {} int ui_is_using_clipboard_selection(void) { return 0; } int ui_window_set_selection_owner(ui_window_t *win, Time time) { #if 0 bl_debug_printf(BL_DEBUG_TAG " ui_window_set_selection_owner.\n"); #endif if ((!win->is_sel_owner && !ui_display_own_selection(win->disp, win)) || OpenClipboard(win->my_window) == FALSE) { return 0; } /* * If win->is_sel_owner is already 1, win->is_sel_owner++ prevents * WM_DESTROYCLIPBOARD by EmtpyClipboard() from calling * ui_display_clear_selection(). */ win->is_sel_owner++; EmptyClipboard(); /* Own clipboard. Create WM_DESTROYCLIPBOARD message */ SetClipboardData(CF_TEXT, NULL); SetClipboardData(CF_UNICODETEXT, NULL); CloseClipboard(); return 1; } int ui_window_xct_selection_request(ui_window_t *win, Time time) { return invoke_selection_request(win, CF_TEXT, xct_selection_request); } int ui_window_utf_selection_request(ui_window_t *win, Time time) { return invoke_selection_request(win, CF_UNICODETEXT, utf_selection_request); } void ui_window_send_picture_selection(ui_window_t *win, Pixmap pixmap, u_int width, u_int height) { HBITMAP hbmp; HGDIOBJ old; HDC hdc; if (MessageBox(win->my_window, "Set this picture to the clipboard.", "", MB_OKCANCEL) != IDOK) { return; } hbmp = CreateCompatibleBitmap(pixmap, width, height); hdc = CreateCompatibleDC(pixmap); old = SelectObject(hdc, hbmp); BitBlt(hdc, 0, 0, width, height, pixmap, 0, 0, SRCCOPY); SelectObject(hdc, old); DeleteDC(hdc); if ((!win->is_sel_owner && !ui_display_own_selection(win->disp, win)) || OpenClipboard(win->my_window) == FALSE) { return; } /* * If win->is_sel_owner is already 1, win->is_sel_owner++ prevents * WM_DESTROYCLIPBOARD by EmtpyClipboard() from calling * ui_display_clear_selection(). */ win->is_sel_owner++; EmptyClipboard(); SetClipboardData(CF_BITMAP, hbmp); CloseClipboard(); DeleteObject(hbmp); } void ui_window_send_text_selection(ui_window_t *win, XSelectionRequestEvent *req_ev, u_char *sel_data, size_t sel_len, Atom sel_type) { HGLOBAL hmem; u_char *g_data; size_t count; if (sel_data == NULL || sel_len == 0) { return; } /* +1 for 0x00, +2 for 0x0000(UTF16) */ if ((hmem = GlobalAlloc(GHND, sel_len + (sel_type == CF_UNICODETEXT ? 2 : 1))) == NULL) { return; } if ((g_data = GlobalLock(hmem)) == NULL) { GlobalFree(hmem); return; } for (count = 0; count < sel_len; count++) { *(g_data++) = *(sel_data++); } /* *(g_data++) = 0x0 is not necessary because GlobalAlloc already cleared * memory. */ GlobalUnlock(hmem); SetClipboardData(sel_type, hmem); #if 0 bl_debug_printf(BL_DEBUG_TAG " ui_window_send_selection.\n"); #endif } void ui_set_window_name(ui_window_t *win, u_char *name) { ui_window_t *root; root = ui_get_root_window(win); if (name == NULL) { name = root->app_name; } #ifdef UTF16_IME_CHAR else { u_char *buf; size_t len; vt_char_encoding_t encoding; ef_conv_t *utf_conv; ef_parser_t *parser; /* See parse_title() in vt_parser.c */ encoding = vt_get_char_encoding("auto"); /* 4 == UTF16 surrogate pair. */ if (!(buf = alloca((len = strlen(name)) * 4 + 2)) || !(utf_conv = ui_get_selection_conv(1)) /* UTF16LE */ || !(parser = vt_char_encoding_parser_new(encoding))) { return; } if (len > 0) { (*parser->init)(parser); (*parser->set_str)(parser, name, len); (*utf_conv->init)(utf_conv); len = (*utf_conv->convert)(utf_conv, buf, len * 4, parser); } (*parser->destroy)(parser); buf[len] = '\0'; buf[len + 1] = '\0'; name = buf; } #endif #ifndef UTF16_IME_CHAR SetWindowTextA(root->my_window, name); #else SetWindowTextW(root->my_window, name); #endif } void ui_set_icon_name(ui_window_t *win, u_char *name) {} void ui_window_set_icon(ui_window_t *win, ui_icon_picture_t *icon) {} void ui_window_remove_icon(ui_window_t *win) {} void ui_window_reset_group(ui_window_t *win) {} void ui_set_click_interval(int interval) { click_interval = interval; } int ui_get_click_interval(void) { return click_interval; } u_int ui_window_get_mod_ignore_mask(ui_window_t *win, KeySym *keysyms) { return ~0; } u_int ui_window_get_mod_meta_mask(ui_window_t *win, char *mod_key) { return ModMask; } void ui_set_use_urgent_bell(int use) { use_urgent_bell = use; } void ui_window_bell(ui_window_t *win, ui_bel_mode_t mode) { urgent_bell(win, 1); if (mode & BEL_VISUAL) { int count; ui_set_gc(win->gc, GetDC(win->my_window)); /* win->gc is used in ui_window_blank(). */ ui_window_blank(win); for (count = 0; count < 10; count++) { Sleep(10); } (*win->window_exposed)(win, 0, 0, win->width, win->height); ReleaseDC(win->my_window, win->gc->gc); ui_set_gc(win->gc, None); } if (mode & BEL_SOUND) { Beep(800, 200); } } void ui_window_translate_coordinates(ui_window_t *win, int x, int y, int *global_x, int *global_y) { POINT p; p.x = x; p.y = y; ClientToScreen(win->my_window, &p); *global_x = p.x; *global_y = p.y; } void ui_window_set_input_focus(ui_window_t *win) { reset_input_focus(ui_get_root_window(win)); win->inputtable = 1; SetFocus(win->my_window); } #ifdef DEBUG void ui_window_dump_children(ui_window_t *win) { u_int count; bl_msg_printf("%p(%li) => ", win, win->my_window); for (count = 0; count < win->num_children; count++) { bl_msg_printf("%p(%li) ", win->children[count], win->children[count]->my_window); } bl_msg_printf("\n"); for (count = 0; count < win->num_children; count++) { ui_window_dump_children(win->children[count]); } } #endif mlterm-3.8.9/uitoolkit/win32/ui_xic.c010064400017600000144000000140571356600660700161620ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_xic.h" #include #include /* malloc */ #include /* bl_get_locale */ #ifdef UTF16_IME_CHAR #include #endif #define HAS_XIM_LISTENER(win, function) ((win)->xim_listener && (win)->xim_listener->function) /* --- static functions --- */ static int get_spot(ui_window_t *win, XPoint *spot) { int x; int y; if (!HAS_XIM_LISTENER(win, get_spot) || win->xim_listener->get_spot(win->xim_listener->self, &x, &y) == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " xim_listener->get_spot() failed.\n"); #endif return 0; } spot->x = x + win->hmargin; spot->y = y + win->vmargin; if (win->parent && GetFocus() == ui_get_root_window(win)->my_window) { spot->x += win->x; spot->y += win->y; } return 1; } /* --- global functions --- */ int ui_xic_activate(ui_window_t *win, char *xim_name, char *xim_locale) { if (win->xic) { /* already activated */ return 0; } if ((win->xic = malloc(sizeof(ui_xic_t))) == NULL) { return 0; } #ifndef UTF16_IME_CHAR if ((win->xic->parser = vt_char_encoding_parser_new(vt_get_char_encoding(bl_get_codeset_win32()))) == NULL) #else /* UTF16LE => UTF16BE in ui_xic_get_str. */ if ((win->xic->parser = ef_utf16_parser_new()) == NULL) #endif { free(win->xic); win->xic = NULL; return 0; } win->xic->ic = ImmGetContext(win->my_window); win->xic->prev_keydown_wparam = 0; ui_xic_font_set_changed(win); return 1; } int ui_xic_deactivate(ui_window_t *win) { if (win->xic == NULL) { /* already deactivated */ return 0; } ImmReleaseContext(win->my_window, win->xic->ic); (*win->xic->parser->destroy)(win->xic->parser); free(win->xic); win->xic = NULL; return 1; } char *ui_xic_get_xim_name(ui_window_t *win) { return ""; } char *ui_xic_get_default_xim_name(void) { return ""; } int ui_xic_fg_color_changed(ui_window_t *win) { return 0; } int ui_xic_bg_color_changed(ui_window_t *win) { return 0; } int ui_xic_font_set_changed(ui_window_t *win) { if (win->xic && HAS_XIM_LISTENER(win, get_fontset)) { if (ImmSetCompositionFont(win->xic->ic, (*win->xim_listener->get_fontset)(win->xim_listener->self))) { return 1; } } return 0; } int ui_xic_resized(ui_window_t *win) { return 0; } int ui_xic_set_spot(ui_window_t *win) { XPoint spot; COMPOSITIONFORM cf; if (win->xic == NULL || /* * Multiple windows can share the same input context, so windows except * the focused one don't call ImmSetCompositionWindow(). */ !win->is_focused) { return 0; } if (get_spot(win, &spot) == 0) { return 0; } cf.ptCurrentPos = spot; cf.dwStyle = CFS_FORCE_POSITION; return ImmSetCompositionWindow(win->xic->ic, &cf); } size_t ui_xic_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { size_t len; if (win->xic == NULL) { goto zero_return; } *keysym = win->xic->prev_keydown_wparam; if ('a' <= *keysym && *keysym <= VK_F24) { /* * Avoid to conflict 'a' - 'z' with VK_NUMPAD1..9, * VK_MULTIPLY..VK_DIVIDE, VK_F1..VK_F11. * (0x61 - 0x7a) */ *keysym += 0xff00; } win->xic->prev_keydown_wparam = 0; if (seq_len == 0 || event->ch == 0) { goto zero_return; } else if ((event->state & ShiftMask) && *keysym == XK_ISO_Left_Tab) { goto zero_return; } else if (event->state & ControlMask) { if (event->ch == '2' || event->ch == ' ' || event->ch == '@') { event->ch = 0; } else if ('3' <= event->ch && event->ch <= '7') { /* '3' => 0x1b '4' => 0x1c '5' => 0x1d '6' => 0x1e '7' => 0x1f */ event->ch -= 0x18; } else if (event->ch == '8') { event->ch = 0x7f; } else if (event->ch == '0' || event->ch == '1' || event->ch == '9') { /* For modifyOtherKeys */ goto zero_return; } else if (event->ch == '^') { event->ch = 0x1e; } else if (event->ch == '_' || event->ch == '/') { event->ch = 0x1f; } } #ifndef UTF16_IME_CHAR len = 1; if (event->ch > 0xff) { *(seq++) = (char)((event->ch >> 8) & 0xff); if (seq_len == 1) { goto zero_return; } len++; } *seq = (char)(event->ch & 0xff); #else if (seq_len == 1) { goto zero_return; } *(seq++) = (char)((event->ch >> 8) & 0xff); *seq = (char)(event->ch & 0xff); len = 2; #endif /* wparam doesn't tell upper case from lower case. */ if ('A' <= *keysym && *keysym <= 'Z') { if (event->ch < 'A' || 'Z' < event->ch) { /* Upper to Lower case */ *keysym += 0x20; } } *parser = win->xic->parser; return len; zero_return: *parser = NULL; return 0; } size_t ui_xic_get_utf8_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { return 0; } int ui_xic_filter_event(ui_window_t *win, /* Should be root window. */ XEvent *event) { u_int count; if (event->msg != WM_KEYDOWN) { return 0; } for (count = 0; count < win->num_children; count++) { ui_xic_filter_event(win->children[count], event); } if (!win->xic) { return 0; } win->xic->prev_keydown_wparam = event->wparam; return 1; } int ui_xic_set_focus(ui_window_t *win) { /* The composition font can be changed by the connection dialog box. */ ui_xic_font_set_changed(win); return 1; } int ui_xic_unset_focus(ui_window_t *win) { return 1; } int ui_xic_is_active(ui_window_t *win) { if (win->xic == NULL) { return 0; } return ImmGetOpenStatus(win->xic->ic); } int ui_xic_switch_mode(ui_window_t *win) { if (win->xic == NULL) { return 0; } return ImmSetOpenStatus(win->xic->ic, (ImmGetOpenStatus(win->xic->ic) == FALSE)); } #if 0 /* * ui_xim.c <-> ui_xic.c communication functions * Not necessary in win32. */ int ui_xim_activated(ui_window_t *win) { return 1; } int ui_xim_destroyed(ui_window_t *win) { return 1; } #endif mlterm-3.8.9/uitoolkit/win32/ui.c010064400017600000144000000103041356600660700153060ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui.h" #include /* sscanf */ #include /* strcmp */ #include /* size_t */ #if 0 #define SELF_TEST #endif #define TABLE_SIZE (sizeof(keysym_table) / sizeof(keysym_table[0])) static struct { char *str; KeySym /* WORD */ ksym; /* 16bit */ } keysym_table[] = { {"0", '0'}, {"1", '1'}, {"2", '2'}, {"3", '3'}, {"4", '4'}, {"5", '5'}, {"6", '6'}, {"7", '7'}, {"8", '8'}, {"9", '9'}, {"BackSpace", XK_BackSpace}, {"Delete", XK_Delete}, {"Down", XK_Down}, {"End", XK_End}, {"Escape", XK_Escape}, {"F1", XK_F1}, {"F10", XK_F10}, {"F11", XK_F11}, {"F12", XK_F12}, {"F13", XK_F13}, {"F14", XK_F14}, {"F15", XK_F15}, {"F16", XK_F16}, {"F17", XK_F17}, {"F18", XK_F18}, {"F19", XK_F19}, {"F2", XK_F2}, {"F20", XK_F20}, {"F21", XK_F21}, {"F22", XK_F22}, {"F23", XK_F23}, {"F24", XK_F24}, {"F3", XK_F3}, {"F4", XK_F4}, {"F5", XK_F5}, {"F6", XK_F6}, {"F7", XK_F7}, {"F8", XK_F8}, {"F9", XK_F9}, {"Henkan_Mode", XK_Henkan_Mode}, {"Home", XK_Home}, {"Insert", XK_Insert}, {"Left", XK_Left}, {"Muhenkan", XK_Muhenkan}, {"Next", XK_Next}, {"Prior", XK_Prior}, {"Return", XK_Return}, {"Right", XK_Right}, {"Tab", XK_Tab}, {"Up", XK_Up}, {"Zenkaku_Hankaku", XK_Zenkaku_Hankaku}, {"a", 'a'}, {"b", 'b'}, {"c", 'c'}, {"d", 'd'}, {"e", 'e'}, {"f", 'f'}, {"g", 'g'}, {"h", 'h'}, {"i", 'i'}, {"j", 'j'}, {"k", 'k'}, {"l", 'l'}, {"m", 'm'}, {"n", 'n'}, {"o", 'o'}, {"p", 'p'}, {"q", 'q'}, {"r", 'r'}, {"s", 's'}, {"space", ' '}, {"t", 't'}, {"u", 'u'}, {"v", 'v'}, {"w", 'w'}, {"x", 'x'}, {"y", 'y'}, {"z", 'z'}, }; /* --- global functions --- */ int XParseGeometry(char *str, int *xpos, int *ypos, unsigned int *width, unsigned int *height) { int x, y, w, h; if (sscanf(str, "%ux%u+%d+%d", &w, &h, &x, &y) == 4) { *xpos = x; *ypos = y; *width = w; *height = h; return XValue | YValue | WidthValue | HeightValue; } else if (sscanf(str, "%ux%u", &w, &h) == 2) { *width = w; *height = h; return WidthValue | HeightValue; } else if (sscanf(str, "+%d+%d", &x, &y) == 2) { *xpos = x; *ypos = y; return XValue | YValue; } else { return 0; } } KeySym XStringToKeysym(char *str) { #ifdef SELF_TEST int debug_count = 0; #endif size_t prev_idx; size_t idx; size_t distance; prev_idx = -1; /* +1 => roundup */ idx = (TABLE_SIZE + 1) / 2; /* idx + distance == TABLE_SIZE - 1 */ distance = TABLE_SIZE - idx - 1; while (1) { int cmp; if ((cmp = strcmp(keysym_table[idx].str, str)) == 0) { #ifdef SELF_TEST fprintf(stderr, "%.2d/%.2d:", debug_count, TABLE_SIZE); #endif return keysym_table[idx].ksym; } else { size_t next_idx; #ifdef SELF_TEST debug_count++; #endif /* +1 => roundup */ if ((distance = (distance + 1) / 2) == 0) { break; } if (cmp > 0) { if (idx < distance) { /* idx - distance == 0 */ distance = idx; } next_idx = idx - distance; } else /* if( cmp < 0) */ { if (idx + distance >= TABLE_SIZE) { /* idx + distance == TABLE_SIZE - 1 */ distance = TABLE_SIZE - idx - 1; } next_idx = idx + distance; } if (next_idx == prev_idx) { break; } prev_idx = idx; idx = next_idx; } } return NoSymbol; } #ifdef BL_DEBUG #include void TEST_xstringtokeysym(void) { size_t count; struct { char *str; KeySym ksym; } array[] = { { "a", 'a' }, { "hoge", NoSymbol }, { "zzzz", NoSymbol } }; for (count = 0; count < TABLE_SIZE; count++) { assert(XStringToKeysym(keysym_table[count].str) == keysym_table[count].ksym); } for (count = 0; count < sizeof(array) / sizeof(array[0]); count++) { assert(XStringToKeysym(array[count].str) == array[count].ksym); } bl_msg_printf("PASS XStringToKeysym() test.\n"); } #endif mlterm-3.8.9/uitoolkit/libotl004075500017600000144000000000001356600660700147765ustar kenusersmlterm-3.8.9/uitoolkit/libotl/Makefile.in010064400017600000144000000030111356600660700171120ustar kenuserstop_builddir = ../.. top_srcdir = @top_srcdir@ prefix = @prefix@ sysconfdir = @sysconfdir@ exec_prefix = @exec_prefix@ datadir = @datadir@ bindir = @bindir@ libdir = @libdir@ libexecdir = @libexecdir@ CC = @CC@ LIBTOOL = @LIBTOOL@ INSTALL = @INSTALL@ LIBDIR = $(DESTDIR)$(libdir)/mlterm VPATH = $(top_srcdir)/uitoolkit/libotl OBJ = @OT_LAYOUT_OBJ@ LPOBL = @LPOBL@ LPOBL_DEB = -lpobl_deb # XDATADIR is to avoid conflicting with DATADIR structure in w32api/objidl.h. CFLAGS = $(CFLAGS_LOCAL) @POBL_CFLAGS@ @DEB_CFLAGS@ @GUI_CFLAGS@ @CFLAGS@ @CPPFLAGS@ \ @OT_LAYOUT_CFLAGS@ -I/usr/local/include LIBS = $(LIBS_LOCAL) @OT_LAYOUT_LIBS@ $(LPOBL) -L/usr/local/lib -R/usr/local/lib TARGET_win32 = libotl-win32.la TARGET_xlib = libotl.la TARGET_quartz = libotl-quartz.la TARGET_fb = libotl.la TARGET_console = libotl.la TARGET_wayland = libotl.la TARGET_sdl2 = libotl.la TARGET = $(TARGET_@GUI@) LIBTOOL_CC = $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) all: $(TARGET) $(TARGET): $(OBJ) $(LIBTOOL_LINK) -o $(TARGET) $(OBJ:.o=.lo) -rpath $(libdir)/mlterm \ -module -avoid-version @NO_UNDEFINED_FLAG@ $(LIBS) .SUFFIXES: .c .o .c.o: $(LIBTOOL_CC) -c $< install : $(LIBDIR) $(LIBTOOL_INSTALL) $(TARGET) $(LIBDIR) uninstall : rm -f $(LIBDIR)/*otl* $(LIBDIR) : mkdir -p $(LIBDIR) wc : find . -name "*.[ch]" -a \! -name "test_*" | xargs wc -l clean: rm -rf $(TARGET) $(OBJ) $(OBJ:.o=.lo) .libs distclean: clean rm -f Makefile mlterm-3.8.9/uitoolkit/libotl/hb.c010064400017600000144000000316551356600660700156210ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #ifdef USE_QUARTZ #include #else #include #endif #include /* hb_ot_layout_has_substitution */ #include /* isalpha */ #include #include #include #ifndef HB_VERSION_ATLEAST #define HB_VERSION_ATLEAST(a,b,c) !HB_VERSION_CHECK(a,b,c) #endif /* --- static functions --- */ static hb_feature_t *get_hb_features(const char *features, u_int *num) { static const char *prev_features; static hb_feature_t *hbfeatures; static u_int num_features; if (features != prev_features) { char *str; void *p; if ((str = alloca(strlen(features) + 1)) && (p = realloc(hbfeatures, sizeof(hb_feature_t) * (bl_count_char_in_str(features, ',') + 1)))) { hbfeatures = p; strcpy(str, features); num_features = 0; while ((p = bl_str_sep(&str, ","))) { if (hb_feature_from_string(p, -1, &hbfeatures[num_features])) { num_features++; } } if (num_features == 0) { free(hbfeatures); hbfeatures = NULL; } } prev_features = features; } *num = num_features; return hbfeatures; } static u_int convert_text_to_glyphs(void *hbfont, u_int32_t *shaped /* never NULL */, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src /* never NULL */, u_int src_len, hb_script_t hbscript, hb_feature_t *hbfeatures, u_int hbfeatures_num) { static hb_buffer_t *buf; hb_glyph_info_t *info; hb_glyph_position_t *pos; u_int count; u_int num; if (!buf) { buf = hb_buffer_create(); } else { hb_buffer_reset(buf); } hb_buffer_add_utf32(buf, src, src_len, 0, src_len); #if 0 hb_buffer_guess_segment_properties(buf); #else hb_buffer_set_script(buf, hbscript); hb_buffer_set_direction(buf, hb_script_get_horizontal_direction(hbscript)); hb_buffer_set_language(buf, hb_language_get_default()); #endif hb_shape(hbfont, buf, hbfeatures, hbfeatures_num); info = hb_buffer_get_glyph_infos(buf, &num); pos = hb_buffer_get_glyph_positions(buf, &num); if (!cmapped) { /* src -> shaped (called from vt_shape.c) */ int32_t prev_offset; prev_offset = 0; shaped[0] = info[0].codepoint; #if 0 if (offsets && widths) #endif { offsets[0] = widths[0] = 0; } for (count = 1; count < num; count++) { shaped[count] = info[count].codepoint; #if 0 if (!offsets || !widths) { /* do nothing */ } else #endif { if (abs(pos[count].x_offset) >= 64) { int32_t offset; prev_offset = offset = pos[count].x_offset + pos[count - 1].x_advance + prev_offset; if (offset >= 0) { offset = ((offset >> 6) & 0x7f); } else { offset = ((offset >> 6) | 0x80); } offsets[count] = offset; widths[count] = ((pos[count].x_advance >> 6) & 0xff); if (offsets[count] == 0 && widths[count] == 0) { offsets[count] = -1; /* XXX */ } } else { offsets[count] = widths[count] = 0; prev_offset = 0; } } } } else { /* * cmapped -> shaped (called from vt_ot_layout.c) * (offsets and widths are not set) */ u_int minus = 0; shaped[0] = info[0].codepoint; for (count = 1; count < num; count++) { if (abs(pos[count].x_offset) >= 64) { minus++; } shaped[count] = info[count].codepoint; } num -= minus; } #if 0 hb_buffer_destroy(buf); #endif return num; } #ifdef USE_WIN32GUI #include static FT_Library ftlib; static u_int ref_count; static void done_ft_face(void *p) { FT_Face face; face = p; free(face->generic.data); face->generic.data = NULL; FT_Done_Face(face); if (--ref_count == 0) { FT_Done_FreeType(ftlib); ftlib = NULL; } } #endif /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_OTL static #endif void *otl_open(void *obj, u_int size) { #if defined(USE_WIN32GUI) FT_Face face; if (!ftlib) { if (FT_Init_FreeType(&ftlib) != 0) { free(obj); return NULL; } } if (FT_New_Memory_Face(ftlib, obj, size, 0, &face) == 0) { hb_font_t *hbfont; if ((hbfont = hb_ft_font_create(face, done_ft_face))) { #if 1 if (hb_ot_layout_has_substitution(hb_font_get_face(hbfont))) #endif { face->generic.data = obj; ref_count++; return hbfont; } hb_font_destroy(hbfont); } FT_Done_Face(face); } free(obj); if (ref_count == 0) { FT_Done_FreeType(ftlib); ftlib = NULL; } return NULL; #elif defined(USE_QUARTZ) hb_face_t *face; if ((face = hb_coretext_face_create(obj /* CGFont */))) { hb_font_t *font; /* XXX hb_ot_layout_has_substitution() of harfbuzz 1.1.3 always returns 0 */ if (/* hb_ot_layout_has_substitution(face) && */ (font = hb_font_create(face))) { hb_ot_font_set_funcs(font); hb_face_destroy(face); return font; } hb_face_destroy(face); } return NULL; #else hb_font_t *font; if ((font = hb_ft_font_create(obj, NULL))) { #if 1 if (hb_ot_layout_has_substitution(hb_font_get_face(font))) #endif { return font; } hb_font_destroy(font); } return NULL; #endif } #ifdef NO_DYNAMIC_LOAD_OTL static #endif void otl_close(void *hbfont) { hb_font_destroy(hbfont); } static hb_script_t get_hb_script(u_int32_t code, int *is_rtl, hb_script_t default_hbscript) { hb_script_t hbscript; *is_rtl = 0; if (code < 0x590) { hbscript = default_hbscript; } else if (code < 0x900) { if (code < 0x600) { hbscript = HB_SCRIPT_HEBREW; *is_rtl = 1; } else if (code < 0x700) { hbscript = HB_SCRIPT_ARABIC; *is_rtl = 1; } else if (code < 0x750) { hbscript = HB_SCRIPT_SYRIAC; *is_rtl = 1; } else if (code < 0x780) { hbscript = HB_SCRIPT_ARABIC; *is_rtl = 1; } else if (code < 0x7c0) { hbscript = HB_SCRIPT_THAANA; *is_rtl = 1; } else if (code < 0x800) { hbscript = HB_SCRIPT_NKO; *is_rtl = 1; } else if (code < 0x840) { hbscript = HB_SCRIPT_SAMARITAN; *is_rtl = 1; } else if (code < 0x860) { hbscript = HB_SCRIPT_MANDAIC; *is_rtl = 1; } else if (code < 0x870) { hbscript = HB_SCRIPT_SYRIAC; /* Syriac Supplement? */ *is_rtl = 1; } else if (code < 0x8a0) { hbscript = default_hbscript; /* Undefined area */ } else /* if (code < 0x900) */ { hbscript = HB_SCRIPT_ARABIC; *is_rtl = 1; } } else if (code < 0xd80) { if (code < 0x980) { hbscript = HB_SCRIPT_DEVANAGARI; } else if (code < 0xa00) { hbscript = HB_SCRIPT_BENGALI; } else if (code < 0xa80) { /* PUNJABI */ hbscript = HB_SCRIPT_GURMUKHI; } else if (code < 0xb00) { hbscript = HB_SCRIPT_GUJARATI; } else if (code < 0xb80) { hbscript = HB_SCRIPT_ORIYA; } else if (code < 0xc00) { hbscript = HB_SCRIPT_TAMIL; } else if (code < 0xc80) { hbscript = HB_SCRIPT_TELUGU; } else if (code < 0xd00) { hbscript = HB_SCRIPT_KANNADA; } else /* if (code < 0xd80) */ { hbscript = HB_SCRIPT_MALAYALAM; } } else if (0x10300 <= code && code < 0x10e80) { if (code < 0x10330) { hbscript = HB_SCRIPT_OLD_ITALIC; *is_rtl = 1; } else if (code < 0x10800) { hbscript = default_hbscript; } else if (code < 0x10840) { hbscript = HB_SCRIPT_CYPRIOT; *is_rtl = 1; } else if (code < 0x10860) { hbscript = HB_SCRIPT_IMPERIAL_ARAMAIC; *is_rtl = 1; } else if (code < 0x10880) { hbscript = default_hbscript; } else if (code < 0x108b0) { #if HB_VERSION_ATLEAST(0,9,30) hbscript = HB_SCRIPT_NABATAEAN; *is_rtl = 1; #else hbscript = default_hbscript; #endif } else if (code < 0x10900) { hbscript = default_hbscript; } else if (code < 0x10920) { hbscript = HB_SCRIPT_PHOENICIAN; *is_rtl = 1; } else if (code < 0x10940) { hbscript = HB_SCRIPT_LYDIAN; *is_rtl = 1; } else if (code < 0x10a00) { hbscript = default_hbscript; } else if (code < 0x10a60) { hbscript = HB_SCRIPT_KHAROSHTHI; *is_rtl = 1; } else if (code < 0x10b00) { hbscript = default_hbscript; } else if (code < 0x10b40) { hbscript = HB_SCRIPT_AVESTAN; *is_rtl = 1; } else if (code < 0x10b60) { hbscript = HB_SCRIPT_INSCRIPTIONAL_PARTHIAN; *is_rtl = 1; } else if (code < 0x10b80) { hbscript = HB_SCRIPT_INSCRIPTIONAL_PAHLAVI; *is_rtl = 1; } else if (code < 0x10bb0) { #if HB_VERSION_ATLEAST(0,9,30) hbscript = HB_SCRIPT_PSALTER_PAHLAVI; *is_rtl = 1; #else hbscript = default_hbscript; #endif } else if (code < 0x10c00) { hbscript = default_hbscript; } else if (code < 0x10c50) { hbscript = HB_SCRIPT_OLD_TURKIC; *is_rtl = 1; } else if (code < 0x10e60) { hbscript = default_hbscript; } else /* if (code < 0x10e80) */ { hbscript = HB_SCRIPT_ARABIC; *is_rtl = 1; } } else if (0x1e800 <= code && code < 0x1ef00) { if (code < 0x1e8f0) { #if HB_VERSION_ATLEAST(0,9,30) hbscript = HB_SCRIPT_MENDE_KIKAKUI; *is_rtl = 1; #else hbscript = default_hbscript; #endif } else if (code < 0x1e900) { hbscript = default_hbscript; } else if (code < 0x1e960) { #if HB_VERSION_ATLEAST(1,3,0) hbscript = HB_SCRIPT_ADLAM; *is_rtl = 1; #else hbscript = default_hbscript; #endif } else if (code < 0x1ee00) { hbscript = default_hbscript; } else /* if (code < 0x1ef00) */ { hbscript = HB_SCRIPT_ARABIC; *is_rtl = 1; } } else { hbscript = default_hbscript; } return hbscript; } #ifdef NO_DYNAMIC_LOAD_OTL static #endif u_int otl_convert_text_to_glyphs(void *hbfont, u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features, u_int fontsize) { if (src && cmapped) { if (cmapped != src) { memcpy(cmapped, src, sizeof(*src) * src_len); } return src_len; } else { u_int32_t code; hb_script_t hbscript; hb_script_t cur_hbscript; hb_script_t default_hbscript; int is_rtl; int is_cur_rtl; hb_feature_t *hbfeatures; u_int hbfeatures_num; u_int count; u_int num = 0; if (cmapped) { src = cmapped; } if (fontsize > 0) { u_int scale = fontsize << 6; /* fontsize x 64 */ #ifdef USE_WIN32GUI FT_Set_Pixel_Sizes(hb_ft_font_get_face(hbfont), fontsize, fontsize); #endif hb_font_set_scale(hbfont, scale, scale); } hbfeatures = get_hb_features(features, &hbfeatures_num); default_hbscript = HB_TAG(script[0] & ~0x20, /* Upper case */ script[1] | 0x20, /* Lower case */ script[2] | 0x20, /* Lower case */ script[3] | 0x20); /* Lower case */ cur_hbscript = get_hb_script(src[0], &is_cur_rtl, default_hbscript); for (count = 1; count < src_len; count++) { code = src[count]; hbscript = get_hb_script(code, &is_rtl, default_hbscript); if (hbscript != cur_hbscript) { u_int count2 = count; u_int n; if (is_cur_rtl) { while (1) { if (code <= 0x7f) { if (isalpha(code)) { break; } else { /* Regard neutral ascii characters in RTL context as RTL. */ } } else if (hbscript != cur_hbscript) { break; } count2++; if (code <= 0x7f) { /* Do not regard neutral ascii characters at the end of line as RTL. */ } else { count = count2; } if (count2 == src_len) { count2--; /* for count++ */ break; } code = src[count2]; hbscript = get_hb_script(code, &is_rtl, default_hbscript); } } n = convert_text_to_glyphs(hbfont, shaped, shaped_len, offsets, widths, cmapped, src, count, cur_hbscript, hbfeatures, hbfeatures_num); shaped += n; shaped_len -= n; offsets += n; widths += n; num += n; if (cmapped) { cmapped += count; } src += count; src_len -= count; count = count2 - count; cur_hbscript = hbscript; is_cur_rtl = is_rtl; } } num += convert_text_to_glyphs(hbfont, shaped, shaped_len, offsets, widths, cmapped, src, count, cur_hbscript, hbfeatures, hbfeatures_num); return num; } } mlterm-3.8.9/uitoolkit/libotl/otf.c010064400017600000144000000053531356600660700160140ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include #include /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_OTL static #endif void* otl_open(void *obj, u_int size) { OTF* otf; #if defined(USE_WIN32GUI) FT_Library ftlib; FT_Face face; if (FT_Init_FreeType(&ftlib) != 0) { free(obj); return NULL; } if (FT_New_Memory_Face(ftlib, obj, size, 0, &face) != 0) { otf = NULL; } else { if ((otf = OTF_open_ft_face(face))) { if (OTF_get_table(otf, "GSUB") != 0 || OTF_get_table(otf, "cmap") != 0) { OTF_close(otf); otf = NULL; } } FT_Done_Face(face); } free(obj); FT_Done_FreeType(ftlib); #else #if defined(USE_QUARTZ) if ((otf = OTF_open(obj))) #else if ((otf = OTF_open_ft_face(obj))) #endif { if (OTF_check_table(otf, "GSUB") != 0 || OTF_check_table(otf, "cmap") != 0) { OTF_close(otf); otf = NULL; } } #endif return otf; } #ifdef NO_DYNAMIC_LOAD_OTL static #endif void otl_close(void *otf) { OTF_close(otf); } #ifdef NO_DYNAMIC_LOAD_OTL static #endif u_int otl_convert_text_to_glyphs(void *otf, u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features, u_int fontsize) { static OTF_Glyph *glyphs; OTF_GlyphString otfstr; u_int count; otfstr.size = otfstr.used = src_len; /* Avoid bl_mem memory management */ #undef realloc if (!(otfstr.glyphs = realloc(glyphs, otfstr.size * sizeof(*otfstr.glyphs)))) { return 0; } #ifdef BL_DEBUG #define realloc(ptr, size) bl_mem_realloc(ptr, size, __FILE__, __LINE__, __FUNCTION__) #endif glyphs = otfstr.glyphs; memset(otfstr.glyphs, 0, otfstr.size * sizeof(*otfstr.glyphs)); if (src) { for (count = 0; count < src_len; count++) { otfstr.glyphs[count].c = src[count]; } OTF_drive_cmap(otf, &otfstr); if (cmapped) { for (count = 0; count < otfstr.used; count++) { cmapped[count] = otfstr.glyphs[count].glyph_id; } return otfstr.used; } else { #if 0 if (!offsets || !widths) { /* do nothing */ } else #endif { memset(offsets, 0, shaped_len * sizeof(*offsets)); memset(widths, 0, shaped_len * sizeof(*widths)); } } } else /* if(cmapped) */ { for (count = 0; count < src_len; count++) { otfstr.glyphs[count].glyph_id = cmapped[count]; } } OTF_drive_gsub(otf, &otfstr, script, NULL, features); for (count = 0; count < otfstr.used; count++) { shaped[count] = otfstr.glyphs[count].glyph_id; } return otfstr.used; } mlterm-3.8.9/uitoolkit/libotl/otl.h010064400017600000144000000041431356600660700160230ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __OTL_H__ #define __OTL_H__ #include #ifdef NO_DYNAMIC_LOAD_OTL #ifdef USE_HARFBUZZ #include "hb.c" #else #include "otf.c" #endif #else /* NO_DYNAMIC_LOAD_OTL */ #include #include #include #ifndef LIBDIR #define OTL_DIR "/usr/local/lib/mlterm/" #else #define OTL_DIR LIBDIR "/mlterm/" #endif #if defined(USE_WIN32GUI) #define OTL_LIB "otl-win32" #elif defined(USE_QUARTZ) #define OTL_LIB "otl-quartz" #else #define OTL_LIB "otl" #endif /* --- static variables --- */ static void *(*open_sym)(void *, u_int); static void (*close_sym)(void *); static u_int (*convert_sym)(void *, u_int32_t *, u_int, int8_t *, u_int8_t *, u_int32_t *, u_int32_t *, u_int, const char *, const char *, u_int); /* --- static functions --- */ static void *otl_open(void *obj, u_int size) { static int is_tried; if (!is_tried) { bl_dl_handle_t handle; is_tried = 1; if ((!(handle = bl_dl_open(OTL_DIR, OTL_LIB)) && !(handle = bl_dl_open("", OTL_LIB))) || !(open_sym = bl_dl_func_symbol(handle, "otl_open")) || !(close_sym = bl_dl_func_symbol(handle, "otl_close")) || !(convert_sym = bl_dl_func_symbol(handle, "otl_convert_text_to_glyphs"))) { bl_error_printf("libotl: Could not load.\n"); if (handle) { bl_dl_close(handle); } return NULL; } } else if (!open_sym) { return NULL; } return (*open_sym)(obj, size); } static void otl_close(void *otf) { (*close_sym)(otf); } static u_int otl_convert_text_to_glyphs(void *otf, u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features, u_int fontsize) { return (*convert_sym)(otf, shaped, shaped_len, offsets, widths, cmapped, src, src_len, script, features, fontsize); } #endif #endif /* __OTL_H__ */ mlterm-3.8.9/uitoolkit/sdl2004075500017600000144000000000001356600660700143555ustar kenusersmlterm-3.8.9/uitoolkit/sdl2/winrs.rs012075500017600000144000000000001356600660700210212../win32/winrs.rsustar kenusersmlterm-3.8.9/uitoolkit/sdl2/syswminfo.h010064400017600000144000000002131356600660700166340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ void syswminfo_init(void *window); int syswminfo_is_thread_safe(void); mlterm-3.8.9/uitoolkit/sdl2/ui.c012075500017600000144000000000001356600660700171432../win32/ui.custar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui.h010064400017600000144000000231571356600660700152270ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_H__ #define ___UI_H__ #include #ifdef USE_FREETYPE #include /* u_int32_t etc */ #endif #if 0 #define USE_BG_TEXTURE #endif typedef int KeyCode; /* Same as type of wparam */ typedef int KeySym; /* Same as type of wparam */ typedef unsigned long Atom; /* Same as definition in X11/X.h */ typedef uint32_t Time; typedef struct { int type; Time time; unsigned int state; KeySym ksym; unsigned int keycode; unsigned char *str; void *parser; } XKeyEvent; typedef struct { int type; Time time; int x; int y; unsigned int state; unsigned int button; } XButtonEvent; typedef struct { int type; Time time; int x; int y; unsigned int state; } XMotionEvent; typedef struct { int type; struct ui_window *target; } XSelectionRequestEvent; typedef union { int type; XKeyEvent xkey; XButtonEvent xbutton; XMotionEvent xmotion; XSelectionRequestEvent xselectionrequest; } XEvent; typedef struct { SDL_Window *window; SDL_Renderer *renderer; SDL_Texture *texture; unsigned char *fb; unsigned int bytes_per_pixel; unsigned int line_length; int lock_state; struct rgb_info { unsigned int r_limit; unsigned int g_limit; unsigned int b_limit; unsigned int r_offset; unsigned int g_offset; unsigned int b_offset; } rgbinfo; unsigned int width; unsigned int height; int damaged; int resizing; struct ui_display *parent; #ifdef USE_BG_TEXTURE SDL_Texture *bg_texture; #endif } Display; #define PIXEL_RED(pixel, rgbinfo) (((pixel) >> (rgbinfo).r_offset) << (rgbinfo).r_limit) #define PIXEL_BLUE(pixel, rgbinfo) (((pixel) >> (rgbinfo).b_offset) << (rgbinfo).b_limit) #define PIXEL_GREEN(pixel, rgbinfo) (((pixel) >> (rgbinfo).g_offset) << (rgbinfo).g_limit) #define RGB_TO_PIXEL(r, g, b, rgbinfo) \ ((((r) >> (rgbinfo).r_limit) << (rgbinfo).r_offset) | \ (((g) >> (rgbinfo).g_limit) << (rgbinfo).g_offset) | \ (((b) >> (rgbinfo).b_limit) << (rgbinfo).b_offset)) typedef int XIC; /* dummy */ typedef void *XID; /* dummy */ typedef void *Window; /* dummy */ typedef void *Drawable; /* dummy */ typedef struct { unsigned char *image; unsigned int width; unsigned int height; } * Pixmap; typedef unsigned char *PixmapMask; typedef int GC; typedef int Font; typedef int Cursor; typedef struct /* Same as definition in X11/X.h */ { int max_keypermod; KeyCode *modifiermap; } XModifierKeymap; typedef struct /* Same as definition in X11/X.h */ { unsigned char byte1; unsigned char byte2; } XChar2b; typedef struct _XFontStruct { char *file; #ifdef USE_FREETYPE int32_t format; /* XXX (fontsize|FONT_BOLD|FONT_ITALIC) on freetype. */ #endif int32_t num_glyphs; unsigned char *glyphs; int32_t glyph_width_bytes; unsigned char width; /* Width of full width characters or max width of half width characters. */ unsigned char width_full; unsigned char height; unsigned char ascent; #if 0 u_int16_t *glyph_indeces; #else unsigned short *glyph_indeces; #endif /* for pcf */ int16_t min_char_or_byte2; int16_t max_char_or_byte2; int16_t min_byte1; int16_t max_byte1; int32_t *glyph_offsets; #ifdef USE_FREETYPE /* for freetype */ void *face; u_int32_t num_indeces; u_int32_t glyph_size; int is_aa; #ifdef USE_FONTCONFIG struct _XFontStruct **compl_xfonts; #endif #endif unsigned int ref_count; } XFontStruct; typedef int XFontSet; /* dummy */ #define None 0L /* Same as definition in X11/X.h */ #define NoSymbol 0L /* Same as definition in X11/X.h */ #define CurrentTime 0L /* Same as definition in X11/X.h */ /* Same as definition in X11/X.h */ #define NoEventMask 0L #define KeyPressMask (1L << 0) #define KeyReleaseMask (1L << 1) #define ButtonPressMask (1L << 2) #define ButtonReleaseMask (1L << 3) #define EnterWindowMask (1L << 4) #define LeaveWindowMask (1L << 5) #define PointerMotionMask (1L << 6) #define PointerMotionHintMask (1L << 7) #define Button1MotionMask (1L << 8) #define Button2MotionMask (1L << 9) #define Button3MotionMask (1L << 10) #define Button4MotionMask (1L << 11) #define Button5MotionMask (1L << 12) #define ButtonMotionMask (1L << 13) #define KeymapStateMask (1L << 14) #define ExposureMask (1L << 15) #define VisibilityChangeMask (1L << 16) #define StructureNotifyMask (1L << 17) #define ResizeRedirectMask (1L << 18) #define SubstructureNotifyMask (1L << 19) #define SubstructureRedirectMask (1L << 20) #define FocusChangeMask (1L << 21) #define PropertyChangeMask (1L << 22) #define ColormapChangeMask (1L << 23) #define OwnerGrabButtonMask (1L << 24) #define ShiftMask (1 << 0) #define LockMask (1 << 1) #define ControlMask (1 << 2) #define Mod1Mask (1 << 3) #define Mod2Mask (1 << 4) #define Mod3Mask (1 << 5) #define Mod4Mask (1 << 6) #define Mod5Mask (1 << 7) #define Button1Mask (1 << 8) #define Button2Mask (1 << 9) #define Button3Mask (1 << 10) #define Button4Mask (1 << 11) #define Button5Mask (1 << 12) #define CommandMask (1 << 13) #define Button1 1 #define Button2 2 #define Button3 3 #define Button4 4 #define Button5 5 #define XK_Super_L 0xfffe #define XK_Super_R 0xfffd #define XK_Hyper_L 0xfffc #define XK_Hyper_R 0xfffb #define XK_BackSpace SDLK_BACKSPACE #define XK_Tab SDLK_TAB #define XK_Clear 0xfffa #define XK_Linefeed 0xfff9 #define XK_Return SDLK_RETURN #define XK_Shift_L SDLK_LSHIFT #define XK_Control_L SDLK_LCTRL #define XK_Alt_L SDLK_LALT #define XK_Shift_R SDLK_RSHIFT #define XK_Control_R SDLK_RCTRL #define XK_Alt_R SDLK_RALT #define XK_Meta_L 0xfff8 #define XK_Meta_R 0xfff7 #define XK_Pause SDLK_PAUSE #define XK_Shift_Lock 0xfff6 #define XK_Caps_Lock SDLK_CAPSLOCK #define XK_Escape SDLK_ESCAPE #define XK_Prior SDLK_PAGEUP #define XK_Next SDLK_PAGEDOWN #define XK_End SDLK_END #define XK_Home SDLK_HOME #define XK_Left SDLK_LEFT #define XK_Up SDLK_UP #define XK_Right SDLK_RIGHT #define XK_Down SDLK_DOWN #define XK_Select SDLK_SELECT #define XK_Print SDLK_PRINTSCREEN #define XK_Execute SDLK_EXECUTE #define XK_Insert SDLK_INSERT #define XK_Delete SDLK_DELETE #define XK_Help SDLK_HELP #define XK_F1 SDLK_F1 #define XK_F2 SDLK_F2 #define XK_F3 SDLK_F3 #define XK_F4 SDLK_F4 #define XK_F5 SDLK_F5 #define XK_F6 SDLK_F6 #define XK_F7 SDLK_F7 #define XK_F8 SDLK_F8 #define XK_F9 SDLK_F9 #define XK_F10 SDLK_F10 #define XK_F11 SDLK_F11 #define XK_F12 SDLK_F12 #define XK_F13 0xfff5 #define XK_F14 0xfff4 #define XK_F15 0xfff3 #define XK_F16 0xfff2 #define XK_F17 0xfff1 #define XK_F18 0xfff0 #define XK_F19 0xffef #define XK_F20 0xffee #define XK_F21 0xffed #define XK_F22 0xffec #define XK_F23 0xffeb #define XK_F24 0xffea #define XK_FMAX SDLK_F12 #define XK_Num_Lock SDLK_NUMLOCKCLEAR #define XK_Scroll_Lock SDLK_SCROLLLOCK #define XK_Find SDLK_FIND #define XK_Menu SDLK_MENU #define XK_Begin 0xffe9 #define XK_Muhenkan 0xffe8 #define XK_Henkan_Mode 0xffe7 #define XK_Zenkaku_Hankaku 0xffe6 #define XK_Hiragana_Katakana 0xffe5 #define XK_KP_Prior 0xffe4 #define XK_KP_Next 0xffe3 #define XK_KP_End 0xffe2 #define XK_KP_Home 0xffe1 #define XK_KP_Left 0xffe0 #define XK_KP_Up 0xffdf #define XK_KP_Right 0xffde #define XK_KP_Down 0xffdd #define XK_KP_Insert 0xffdc #define XK_KP_Delete 0xffdb #define XK_KP_F1 0xffda #define XK_KP_F2 0xffd9 #define XK_KP_F3 0xffd8 #define XK_KP_F4 0xffd7 #define XK_KP_Begin 0xffd6 #define XK_KP_Multiply SDLK_KP_MULTIPLY #define XK_KP_Add SDLK_KP_PLUS #define XK_KP_Separator 0xffd5 #define XK_KP_Subtract SDLK_KP_MINUS #define XK_KP_Decimal SDLK_KP_DECIMAL #define XK_KP_Divide SDLK_KP_DIVIDE #define XK_KP_0 SDLK_KP_0 #define XK_KP_1 SDLK_KP_1 #define XK_KP_2 SDLK_KP_2 #define XK_KP_3 SDLK_KP_3 #define XK_KP_4 SDLK_KP_4 #define XK_KP_5 SDLK_KP_5 #define XK_KP_6 SDLK_KP_6 #define XK_KP_7 SDLK_KP_7 #define XK_KP_8 SDLK_KP_8 #define XK_KP_9 SDLK_KP_9 #define IsKeypadKey(ksym) (0) /* XXX */ #define IsModifierKey(ksym) (0) #define XK_ISO_Left_Tab (0) /* XXX */ typedef struct { short x; short y; } XPoint; /* XXX dummy */ #define XKeysymToKeycode(disp, ks) (ks) #define XKeycodeToKeysym(disp, kc, i) (kc) #define XKeysymToString(ks) "" #define DefaultScreen(disp) (0) #define BlackPixel(disp, screen) (0xff000000 | RGB(0, 0, 0)) #define WhitePixel(disp, screen) (0xff000000 | RGB(0xff, 0xff, 0xff)) /* Same as definition in X11/cursorfont.h */ #define XC_xterm 152 #define XC_left_ptr 68 /* Same as definition in X11/Xutil.h */ #define NoValue 0x0000 #define XValue 0x0001 #define YValue 0x0002 #define WidthValue 0x0004 #define HeightValue 0x0008 #define AllValues 0x000F #define XNegative 0x0010 #define YNegative 0x0020 int XParseGeometry(char *str, int *x, int *y, unsigned int *width, unsigned int *height); KeySym XStringToKeysym(char *str); /* === Platform dependent options === */ #define UI_COLOR_HAS_RGB #define SUPPORT_TRUE_TRANSPARENT_BG #ifdef USE_FREETYPE #define TYPE_XCORE_SCALABLE #else #undef TYPE_XCORE_SCALABLE #endif #define MANAGE_SUB_WINDOWS_BY_MYSELF /* ui_im_{candidate|status}_screen.c, ui_window.c */ #undef MANAGE_ROOT_WINDOWS_BY_MYSELF #define INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS #undef SUPPORT_POINT_SIZE_FONT #undef XIM_SPOT_IS_LINE_TOP #undef USE_GC #undef CHANGEABLE_CURSOR #define PLUGIN_MODULE_SUFFIX "sdl2" #undef KEY_REPEAT_BY_MYSELF #define ROTATABLE_DISPLAY #undef PSEUDO_COLOR_DISPLAY #undef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE #undef SUPPORT_URGENT_BELL #undef FORCE_UNICODE #undef NEED_DISPLAY_SYNC_EVERY_TIME #define DRAW_SCREEN_IN_PIXELS #undef NO_DRAW_IMAGE_STRING /* libpthread is not linked to mlterm explicitly for now. */ #undef HAVE_PTHREAD #define COMPOSE_DECSP_FONT #ifdef USE_FREETYPE #define USE_REAL_VERTICAL_FONT #else #undef USE_REAL_VERTICAL_FONT #endif #define NO_DISPLAY_FD #undef FLICK_SCROLL #define UIWINDOW_SUPPORTS_PREEDITING #endif mlterm-3.8.9/uitoolkit/sdl2/ui_color.c012075500017600000144000000000001356600660700211642../fb/ui_color.custar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui_connect_dialog.c010064400017600000144000000003441356600660700202430ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #ifdef USE_WIN32API #include #include "../win32/ui_connect_dialog.c" #else #include "../fb/ui_connect_dialog.c" #endif mlterm-3.8.9/uitoolkit/sdl2/ui_decsp_font.c012075500017600000144000000000001356600660700232002../fb/ui_decsp_font.custar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui_decsp_font.h012075500017600000144000000000001356600660700232122../fb/ui_decsp_font.hustar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui_display.c010064400017600000144000001027241356600660700167450ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_display.h" #include /* memset/memcpy */ #include #include #include #include #include /* strdup/bl_compare_str */ #include /* BL_SWAP */ #include #include "../ui_window.h" #include "../ui_picture.h" #include "../ui_imagelib.h" #include "../ui_selection_encoding.h" #include "syswminfo.h" #ifndef USE_WIN32API #define MONITOR_PTY #include #include "../vtemu/vt_term_manager.h" #endif #define START_PRESENT_MSEC 4 #if 0 #define MEASURE_TIME #endif #if 0 #define __DEBUG #endif #define DECORATION_MARGIN 0 /* for decorataion */ /* --- static variables --- */ static u_int num_displays; static ui_display_t **displays; static int rotate_display; static Uint32 pty_event_type; static Uint32 vsync_interval_msec; static Uint32 next_vsync_msec; static u_char *cur_preedit_text; static SDL_threadID main_tid; #ifdef MONITOR_PTY static SDL_cond *pty_cond; #endif /* --- static functions --- */ static int dialog_cb(bl_dialog_style_t style, const char *msg) { if (syswminfo_is_thread_safe() || main_tid == SDL_GetThreadID(NULL)) { const SDL_MessageBoxButtonData buttons[] = { { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 0, "OK" }, { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 1, "Cancel" } }; const SDL_MessageBoxColorScheme color_scheme = { { /* SDL_MESSAGEBOX_COLOR_BACKGROUND */ { 255, 255, 255 }, /* SDL_MESSAGEBOX_COLOR_TEXT */ { 0, 0, 0 }, /* SDL_MESSAGEBOX_COLOR_BUTTON_BORDER */ { 0, 0, 0 }, /* SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND */ { 255, 255, 255 }, /* SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED */ { 0, 0, 0 } } }; SDL_MessageBoxData data = { SDL_MESSAGEBOX_INFORMATION, NULL, "Dialog", NULL, SDL_arraysize(buttons), buttons, &color_scheme, }; int buttonid; data.message = msg; if (style == BL_DIALOG_ALERT) { data.numbuttons = 1; } else if (style != BL_DIALOG_OKCANCEL) { return -1; } if (SDL_ShowMessageBox(&data, &buttonid) == 0) { if (buttonid == 0) { return 1; } else { return 0; } } } return -1; } static ui_window_t *search_focused_window(ui_window_t *win) { u_int count; ui_window_t *focused; /* * *parent* - *child* * ^^^^^^^ => Hit this window instead of the parent window. * - child * - child * (**: is_focused == 1) */ for (count = 0; count < win->num_children; count++) { if ((focused = search_focused_window(win->children[count]))) { return focused; } } if (win->is_focused) { return win; } return NULL; } static ui_window_t *search_inputtable_window(ui_window_t *candidate, ui_window_t *win) { u_int count; if (win->inputtable) { if (candidate == NULL || win->inputtable > candidate->inputtable) { candidate = win; } } for (count = 0; count < win->num_children; count++) { candidate = search_inputtable_window(candidate, win->children[count]); } return candidate; } static void update_ime_text(ui_window_t *uiwindow, const char *preedit_text) { if (!(uiwindow = search_focused_window(uiwindow)) || !uiwindow->inputtable) { return; } (*uiwindow->preedit)(uiwindow, preedit_text, cur_preedit_text); if (*preedit_text == '\0') { free(cur_preedit_text); cur_preedit_text = NULL; } else { free(cur_preedit_text); cur_preedit_text = strdup(preedit_text); } } /* * x and y are rotated values. */ static inline ui_window_t *get_window(ui_window_t *win, int x, int y) { u_int count; for (count = 0; count < win->num_children; count++) { ui_window_t *child; if ((child = win->children[count])->is_mapped) { if (child->x <= x && x < child->x + ACTUAL_WIDTH(child) && child->y <= y && y < child->y + ACTUAL_HEIGHT(child)) { return get_window(child, x - child->x, y - child->y); } } } return win; } static inline u_char *get_fb(Display *display, int x, int y) { return ((u_char*)display->fb) + (y + DECORATION_MARGIN) * display->line_length + x * display->bytes_per_pixel; } static u_int total_min_width(ui_window_t *win) { u_int count; u_int min_width; min_width = win->min_width + win->hmargin * 2; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped) { /* XXX */ min_width += total_min_width(win->children[count]); } } return min_width; } static u_int total_min_height(ui_window_t *win) { u_int count; u_int min_height; min_height = win->min_height + win->vmargin * 2; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped) { /* XXX */ min_height += total_min_height(win->children[count]); } } return min_height; } static u_int max_width_inc(ui_window_t *win) { u_int count; u_int width_inc; width_inc = win->width_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped) { u_int sub_inc; /* * XXX * we should calculate least common multiple of width_inc and sub_inc. */ if ((sub_inc = max_width_inc(win->children[count])) > width_inc) { width_inc = sub_inc; } } } return width_inc; } static u_int max_height_inc(ui_window_t *win) { u_int count; u_int height_inc; height_inc = win->height_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped) { u_int sub_inc; /* * XXX * we should calculate least common multiple of width_inc and sub_inc. */ if ((sub_inc = max_height_inc(win->children[count])) > height_inc) { height_inc = sub_inc; } } } return height_inc; } static int modify_resize(u_int old_width, u_int old_height, int32_t *new_width, int32_t *new_height, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc, int check_inc) { u_int diff; u_int orig_new_width = *new_width; u_int orig_new_height = *new_height; if (rotate_display) { BL_SWAP(unsigned int, min_width, min_height); BL_SWAP(unsigned int, width_inc, height_inc); } if (old_width < *new_width) { diff = ((*new_width - old_width) / width_inc) * width_inc; if (check_inc || diff < width_inc) { *new_width = old_width + diff; } } else if (*new_width < old_width) { diff = ((old_width - *new_width) / width_inc) * width_inc; if (!check_inc && diff >= width_inc) { diff = old_width - *new_width; } if (old_width < min_width + diff) { *new_width = min_width; } else { *new_width = old_width - diff; } } if (old_height < *new_height) { diff = ((*new_height - old_height) / height_inc) * height_inc; if (check_inc || diff < height_inc) { *new_height = old_height + diff; } } else if (*new_height < old_height) { diff = ((old_height - *new_height) / height_inc) * height_inc; if (!check_inc && diff >= height_inc) { diff = old_height - *new_height; } if (old_height < min_height + diff) { *new_height = min_height; } else { *new_height = old_height - diff; } } if (orig_new_width == *new_width && orig_new_height == *new_height) { return 0; } else { return 1; } } static void close_display(ui_display_t *disp) { u_int count; #ifdef __DEBUG bl_debug_printf("Closing ui_display_t\n"); #endif free(disp->name); for (count = 0; count < disp->num_roots; count++) { ui_window_unmap(disp->roots[count]); ui_window_final(disp->roots[count]); } free(disp->roots); #ifdef USE_BG_TEXTURE if (disp->display->bg_texture) { SDL_DestroyTexture(disp->display->bg_texture); } #endif SDL_DestroyTexture(disp->display->texture); SDL_DestroyWindow(disp->display->window); SDL_DestroyRenderer(disp->display->renderer); ui_picture_display_closed(disp->display); free(disp); } static int init_display(Display *display, char *app_name, int x, int y, int hint) { SDL_Rect rect; if (!display->window) { if (!(display->window = SDL_CreateWindow(app_name, (hint & XValue) ? x : SDL_WINDOWPOS_CENTERED, (hint & YValue) ? y : SDL_WINDOWPOS_CENTERED, display->width, display->height, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_INPUT_FOCUS))) { return 0; } if (!(display->renderer = SDL_CreateRenderer(display->window, -1, SDL_RENDERER_ACCELERATED #if 1 | SDL_RENDERER_PRESENTVSYNC #endif ))) { SDL_DestroyWindow(display->window); return 0; } if (vsync_interval_msec == 0) { int idx; SDL_DisplayMode mode; SDL_RendererInfo info; Uint32 count; idx = SDL_GetWindowDisplayIndex(display->window); if (SDL_GetCurrentDisplayMode(idx, &mode) == 0 && mode.refresh_rate > 0) { vsync_interval_msec = 1000 / mode.refresh_rate; } else { vsync_interval_msec = 16; } next_vsync_msec = SDL_GetTicks() + vsync_interval_msec; syswminfo_init(display->window); SDL_GetRendererInfo(display->renderer, &info); bl_msg_printf("SDL2 with %s\n", info.name); if (!(info.flags & SDL_RENDERER_ACCELERATED)) { bl_msg_printf("SDL2 doesn't use hardware acceleration.\n"); } for (count = 0; count < info.num_texture_formats; count++) { if (info.texture_formats[count] == SDL_PIXELFORMAT_ARGB8888) { goto next_step; } } bl_error_printf("ARGB8888 is not supported.\n"); } next_step: SDL_SetRenderDrawColor(display->renderer, 0xff, 0xff, 0xff, 0xff); } rect.x = 0; rect.y = 0; rect.w = display->width; rect.h = display->height; SDL_RenderSetViewport(display->renderer, &rect); if (display->texture) { SDL_DestroyTexture(display->texture); } display->texture = SDL_CreateTexture(display->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, display->width, display->height); #ifdef USE_BG_TEXTURE SDL_SetTextureBlendMode(display->texture, SDL_BLENDMODE_BLEND); #endif SDL_LockTexture(display->texture, NULL, &display->fb, &display->line_length); return 1; } #ifdef MONITOR_PTY static int monitor_ptys(void *p) { SDL_mutex *mutex; vt_term_t **terms; u_int num_terms; int ptyfd; int maxfd; fd_set read_fds; u_int count; SDL_Event ev; mutex = SDL_CreateMutex(); SDL_LockMutex(mutex); while (1) { while ((num_terms = vt_get_all_terms(&terms)) == 0) { if (num_displays == 0) { goto end; } SDL_Delay(100); } maxfd = -1; FD_ZERO(&read_fds); for (count = 0; count < num_terms; count++) { if ((ptyfd = vt_term_get_master_fd(terms[count])) >= 0) { FD_SET(ptyfd, &read_fds); if (ptyfd > maxfd) { maxfd = ptyfd; } } } if (maxfd >= 0) { select(maxfd + 1, &read_fds, NULL, NULL, NULL); SDL_zero(ev); ev.type = pty_event_type; SDL_PushEvent(&ev); SDL_CondWait(pty_cond, mutex); } else { SDL_Delay(100); } } #ifdef DEBUG bl_debug_printf("Finish monitoring pty.\n"); #endif end: SDL_DestroyMutex(mutex); return 0; } #endif static ui_display_t *get_display(Uint32 window_id) { u_int count; for (count = 0; count < num_displays; count++) { if (SDL_GetWindowID(displays[count]->display->window) == window_id) { return displays[count]; } } return displays[0]; } static void present_displays(void) { u_int count; for (count = 0; count < num_displays; count++) { Display *display = displays[count]->display; if (display->damaged) { #ifdef MEASURE_TIME Uint32 msec[5]; Uint32 old_next_vsync_msec = next_vsync_msec; msec[0] = SDL_GetTicks(); #endif SDL_UnlockTexture(display->texture); #ifdef MEASURE_TIME msec[1] = SDL_GetTicks(); #endif #ifdef USE_BG_TEXTURE if (display->bg_texture) { SDL_RenderCopy(display->renderer, display->bg_texture, NULL, NULL); } else { SDL_RenderClear(display->renderer); } #endif #if 1 SDL_RenderCopy(display->renderer, display->texture, NULL, NULL); #else SDL_RenderCopyEx(display->renderer, display->texture, NULL, NULL, 20.0, NULL, SDL_FLIP_NONE); #endif #ifdef MEASURE_TIME msec[2] = SDL_GetTicks(); #endif SDL_RenderPresent(display->renderer); next_vsync_msec = SDL_GetTicks() + vsync_interval_msec; #ifdef MEASURE_TIME msec[3] = SDL_GetTicks(); #endif SDL_LockTexture(display->texture, NULL, &display->fb, &display->line_length); #ifdef MEASURE_TIME msec[4] = SDL_GetTicks(); bl_msg_printf("%d: %d %d %d %d %d\n", old_next_vsync_msec, msec[0], msec[1], msec[2], msec[3], msec[4]); #endif display->damaged = 0; } } } static void receive_mouse_event(ui_display_t *disp, XButtonEvent *xev) { ui_window_t *win; if (rotate_display) { int tmp = xev->x; if (rotate_display > 0) { xev->x = xev->y; xev->y = disp->display->width - tmp - 1; } else { xev->x = disp->display->height - xev->y - 1; xev->y = tmp; } } win = get_window(disp->roots[0], xev->x, xev->y); xev->x -= win->x; xev->y -= win->y; ui_window_receive_event(win, xev); } static u_int get_mod_state(SDL_Keymod mod) { u_int state = 0; if (mod & KMOD_CTRL) { state |= ControlMask; } if (mod & KMOD_SHIFT) { state |= ShiftMask; } if (mod & KMOD_ALT) { state |= Mod1Mask; } if (mod & KMOD_GUI) { state |= CommandMask; } return state; } static void poll_event(void) { SDL_Event ev; XEvent xev; ui_display_t *disp; Uint32 spent_time = 0; Uint32 now = SDL_GetTicks(); Uint32 skipped_msec; #ifdef MONITOR_PTY static int processing_pty_event; if (processing_pty_event) { processing_pty_event = 0; SDL_CondSignal(pty_cond); } #endif while (1) { if (now > next_vsync_msec) { skipped_msec = now - next_vsync_msec; next_vsync_msec += (((skipped_msec + vsync_interval_msec - 1) / vsync_interval_msec) * vsync_interval_msec); } else { skipped_msec = 0; #if 0 if (now + vsync_interval_msec < next_vsync_msec) { /* SDL_GetTicks() is reset. */ next_vsync_msec = now; } #endif } if (next_vsync_msec - now > START_PRESENT_MSEC) { if (SDL_WaitEventTimeout(&ev, next_vsync_msec - now - START_PRESENT_MSEC)) { if (skipped_msec >= vsync_interval_msec) { present_displays(); } break; } if ((spent_time += (skipped_msec + next_vsync_msec - now - START_PRESENT_MSEC)) >= 100) { u_int count; for (count = 0; count < num_displays; count++) { ui_display_idling(displays[count]); } spent_time = 0; } } now = SDL_GetTicks(); /* avoid to fall into busy loop in case present_displays does nothing. */ next_vsync_msec += vsync_interval_msec; present_displays(); } switch(ev.type) { case SDL_QUIT: { u_int count; disp = get_display(ev.window.windowID); for (count = 0; count < disp->num_roots; count++) { if (disp->roots[count]->window_destroyed) { (*disp->roots[count]->window_destroyed)(disp->roots[count]); } } } break; case SDL_KEYDOWN: xev.xkey.type = KeyPress; xev.xkey.time = ev.key.timestamp; xev.xkey.ksym = ev.key.keysym.sym; xev.xkey.keycode = ev.key.keysym.scancode; xev.xkey.str = NULL; xev.xkey.parser = NULL; xev.xkey.state = get_mod_state(ev.key.keysym.mod); if (!cur_preedit_text && (xev.xkey.ksym < 0x20 || xev.xkey.ksym >= 0x7f || xev.xkey.state == ControlMask || xev.xkey.state == CommandMask)) { ui_window_receive_event(get_display(ev.key.windowID)->roots[0], &xev); } break; case SDL_TEXTINPUT: { ui_window_t *win = get_display(ev.text.windowID)->roots[0]; update_ime_text(win, ""); xev.xkey.type = KeyPress; xev.xkey.time = ev.text.timestamp; if (strlen(ev.text.text) == 1) { xev.xkey.ksym = ev.text.text[0]; xev.xkey.keycode = ev.text.text[0]; } else { xev.xkey.ksym = 0; xev.xkey.keycode = 0; } xev.xkey.str = ev.text.text; xev.xkey.parser = ui_get_selection_parser(1); xev.xkey.state = get_mod_state(SDL_GetModState()); ui_window_receive_event(win, &xev); } #ifdef DEBUG bl_debug_printf("SDL_TEXTINPUT event: %s(%x...)\n", ev.text.text, ev.text.text[0]); #endif break; case SDL_TEXTEDITING: if (strlen(ev.edit.text) > 0) { update_ime_text(get_display(ev.edit.windowID)->roots[0], ev.edit.text); } #ifdef DEBUG bl_debug_printf("SDL_TEXTEDITING event: %s(%x...)\n", ev.edit.text, ev.edit.text[0]); #endif break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: disp = get_display(ev.window.windowID); if (ev.button.type == SDL_MOUSEBUTTONDOWN) { xev.type = ButtonPress; } else { xev.type = ButtonRelease; } xev.xbutton.time = ev.button.timestamp; if (ev.button.button == SDL_BUTTON_LEFT) { xev.xbutton.button = 1; } else if (ev.button.button == SDL_BUTTON_MIDDLE) { xev.xbutton.button = 2; } else if (ev.button.button == SDL_BUTTON_RIGHT) { xev.xbutton.button = 3; } xev.xbutton.state = get_mod_state(SDL_GetModState()); xev.xbutton.x = ev.button.x; xev.xbutton.y = ev.button.y; receive_mouse_event(disp, &xev.xbutton); break; case SDL_MOUSEWHEEL: if (ev.wheel.y) { disp = get_display(ev.window.windowID); xev.xbutton.type = ButtonPress; xev.xbutton.time = ev.button.timestamp; SDL_GetMouseState(&xev.xbutton.x, &xev.xbutton.y); xev.xbutton.state = get_mod_state(SDL_GetModState()); if (ev.wheel.y > 0) { xev.xbutton.button = 4; } else { xev.xbutton.button = 5; } receive_mouse_event(disp, &xev.xbutton); } break; case SDL_MOUSEMOTION: disp = get_display(ev.window.windowID); xev.xmotion.type = MotionNotify; xev.xmotion.time = ev.motion.timestamp; xev.xmotion.state = 0; if (ev.motion.state & SDL_BUTTON_LMASK) { xev.xmotion.state |= Button1Mask; } if (ev.motion.state & SDL_BUTTON_MMASK) { xev.xmotion.state |= Button2Mask; } if (ev.motion.state & SDL_BUTTON_RMASK) { xev.xmotion.state |= Button3Mask; } xev.xmotion.x = ev.motion.x; xev.xmotion.y = ev.motion.y; receive_mouse_event(disp, &xev.xmotion); #if 0 /* defined(__HAIKU__) */ /* If mouse cursor moves, garbage is left on HaikuOS, so damaged = 1 to redraw screen. */ disp->display->damaged = 1; #endif break; case SDL_WINDOWEVENT: disp = get_display(ev.window.windowID); if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { u_int width = ev.window.data1; u_int height = ev.window.data2; #if 0 if (modify_resize(disp->display->width, disp->display->height, &width, &height, total_min_width(disp->roots[0]), total_min_height(disp->roots[0]), max_width_inc(disp->roots[0]), max_height_inc(disp->roots[0]), 1)) { SDL_SetWindowSize(disp->display->window, width, height); } else #endif if (width != disp->display->width || height != disp->display->height) { disp->display->width = width; disp->display->height = height; if (rotate_display) { disp->width = height; disp->height = width; } else { disp->width = width; disp->height = height; } init_display(disp->display, NULL, 0, 0, 0); disp->display->resizing = 0; ui_window_resize_with_margin(disp->roots[0], disp->width, disp->height, NOTIFY_TO_MYSELF); #if 1 /* This is because ui_window_resize_with_margin() redraws screen partially. */ ui_window_update_all(disp->roots[0]); #endif } } else if (ev.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) { ui_window_t *win; if ((win = search_inputtable_window(NULL, disp->roots[0]))) { ui_window_set_input_focus(win); } } else if (ev.window.event == SDL_WINDOWEVENT_FOCUS_LOST) { ui_window_t *win; if ((win = search_focused_window(disp->roots[0]))) { xev.type = FocusOut; ui_window_receive_event(win, &xev); } } else if (ev.window.event == SDL_WINDOWEVENT_EXPOSED) { get_display(ev.window.windowID)->display->damaged = 1; } break; case SDL_DROPFILE: { ui_window_t *win = get_display(ev.key.windowID)->roots[0]; if ((SDL_GetModState() & KMOD_SHIFT) && win->set_xdnd_config) { (*win->set_xdnd_config)(win, NULL, "scp", ev.drop.file); } else if (win->utf_selection_notified) { (*win->utf_selection_notified)(win, ev.drop.file, strlen(ev.drop.file)); } SDL_free(ev.drop.file); break; } default: if (ev.type == pty_event_type) { #ifdef MONITOR_PTY processing_pty_event = 1; #endif } break; } } /* --- global functions --- */ ui_display_t *ui_display_open(char *disp_name, u_int depth) { ui_display_t *disp; void *p; struct rgb_info rgbinfo = {0, 0, 0, 16, 8, 0}; if (!(disp = calloc(1, sizeof(ui_display_t) + sizeof(Display)))) { return NULL; } disp->display = disp + 1; if ((p = realloc(displays, sizeof(ui_display_t*) * (num_displays + 1))) == NULL) { free(disp); return NULL; } displays = p; displays[num_displays] = disp; if (num_displays == 0) { /* Callback should be set before bl_dialog() is called. */ bl_dialog_set_callback(dialog_cb); if (SDL_Init(SDL_INIT_VIDEO) < 0) { return NULL; } SDL_StartTextInput(); pty_event_type = SDL_RegisterEvents(1); main_tid = SDL_GetThreadID(NULL); SDL_EventState(SDL_DROPFILE, SDL_ENABLE); num_displays = 1; #ifdef MONITOR_PTY { SDL_Thread *thrd; pty_cond = SDL_CreateCond(); thrd = SDL_CreateThread(monitor_ptys, "pty_thread", NULL); SDL_DetachThread(thrd); } #endif } else { num_displays ++; } disp->name = strdup(disp_name); disp->display->rgbinfo = rgbinfo; disp->display->bytes_per_pixel = 4; disp->depth = 32; ui_picture_display_opened(disp->display); return disp; } void ui_display_close(ui_display_t *disp) { u_int count; for (count = 0; count < num_displays; count++) { if (displays[count] == disp) { close_display(disp); if (--num_displays == 0) { free(displays); displays = NULL; free(cur_preedit_text); cur_preedit_text = NULL; #ifdef MONITOR_PTY SDL_CondSignal(pty_cond); SDL_DestroyCond(pty_cond); #endif SDL_Quit(); } else { displays[count] = displays[num_displays]; } #ifdef DEBUG bl_debug_printf("sdl2 display connection closed.\n"); #endif return; } } } void ui_display_close_all(void) { while (num_displays > 0) { close_display(displays[0]); } } ui_display_t **ui_get_opened_displays(u_int *num) { poll_event(); *num = 0; return NULL; } int ui_display_fd(ui_display_t *disp) { return -1; } int ui_display_show_root(ui_display_t *disp, ui_window_t *root, int x, int y, int hint, char *app_name, Window parent_window) { void *p; if (disp->num_roots > 0) { /* XXX Input Method */ ui_display_t *parent = disp; disp = ui_display_open(disp->name, disp->depth); disp->display->parent = parent; } root->parent_window = parent_window; if ((p = realloc(disp->roots, sizeof(ui_window_t *) * (disp->num_roots + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } disp->roots = p; root->disp = disp; root->parent = NULL; root->gc = disp->gc; root->x = 0; /* XXX */ root->y = 0; /* XXX */ if (app_name) { root->app_name = app_name; } /* * root is added to disp->roots before ui_window_show() because * ui_display_get_group_leader() is called in ui_window_show(). */ disp->roots[disp->num_roots++] = root; disp->width = ACTUAL_WIDTH(root); disp->height = ACTUAL_HEIGHT(root); if (rotate_display) { disp->display->width = disp->height; disp->display->height = disp->width; } else { disp->display->width = disp->width; disp->display->height = disp->height; } if (!init_display(disp->display, root->app_name, x, y, hint)) { return 0; } ui_window_show(root, hint); return 1; } int ui_display_remove_root(ui_display_t *disp, ui_window_t *root) { u_int count; for (count = 0; count < disp->num_roots; count++) { if (disp->roots[count] == root) { /* Don't switching on or off screen in exiting. */ ui_window_unmap(root); ui_window_final(root); disp->num_roots--; if (count == disp->num_roots) { disp->roots[count] = NULL; if (disp->num_roots == 0 && disp->display->parent /* XXX input method alone */) { ui_display_close(disp); } } else { disp->roots[count] = disp->roots[disp->num_roots]; } return 1; } } return 0; } void ui_display_idling(ui_display_t *disp) { u_int count; for (count = 0; count < disp->num_roots; count++) { ui_window_idling(disp->roots[count]); } } int ui_display_receive_next_event(ui_display_t *disp) { return 0; } /* * Folloing functions called from ui_window.c */ int ui_display_own_selection(ui_display_t *disp, ui_window_t *win) { u_int count; if (disp->selection_owner) { ui_display_clear_selection(NULL, disp->selection_owner); } for (count = 0; count < num_displays; count++) { displays[count]->selection_owner = win; } (*win->utf_selection_requested)(win, NULL, 0); return 1; } int ui_display_clear_selection(ui_display_t *disp, /* NULL means all selection owner windows. */ ui_window_t *win) { u_int count; for (count = 0; count < num_displays; count++) { if (displays[count]->selection_owner == win) { displays[count]->selection_owner = NULL; } } if (win->selection_cleared) { (*win->selection_cleared)(win); } return 1; } XModifierKeymap *ui_display_get_modifier_mapping(ui_display_t *disp) { return disp->modmap.map; } void ui_display_update_modifier_mapping(ui_display_t *disp, u_int serial) {} XID ui_display_get_group_leader(ui_display_t *disp) { if (disp->num_roots > 0) { return disp->roots[0]->my_window; } else { return None; } } void ui_display_rotate(int rotate) { if (num_displays > 0) { bl_msg_printf("rotate_display option is not changeable.\n"); return; } rotate_display = rotate; } int ui_display_resize(ui_display_t *disp, u_int width, u_int height) { if (width != disp->width || height != disp->height) { if (rotate_display) { BL_SWAP(unsigned int, width, height); } disp->display->resizing = 1; SDL_SetWindowSize(disp->display->window, width, height); return 1; } else { return 0; } } int ui_display_move(ui_display_t *disp, int x, int y) { SDL_SetWindowPosition(disp->display->window, x, y); return 1; } u_long ui_display_get_pixel(ui_display_t *disp, int x, int y) { u_char *fb; u_long pixel; if (rotate_display) { int tmp; if (rotate_display > 0) { tmp = x; x = disp->height - y - 1; y = tmp; } else { tmp = x; x = y; y = disp->width - tmp - 1; } } fb = get_fb(disp->display, x, y); pixel = TOINT32(fb); return pixel; } void ui_display_put_image(ui_display_t *disp, int x, int y, u_char *image, size_t size, int need_fb_pixel) { Display *display = disp->display; if (rotate_display) { /* Display is rotated. */ u_char *fb; int tmp; int line_length; size_t count; tmp = x; if (rotate_display > 0) { x = disp->height - y - 1; y = tmp; line_length = display->line_length; } else { x = y; y = disp->width - tmp - 1; line_length = -display->line_length; } fb = get_fb(display, x, y); if (display->bytes_per_pixel == 2) { size /= 2; for (count = 0; count < size; count++) { *((u_int16_t*)fb) = ((u_int16_t*)image)[count]; fb += line_length; } } else /* if (display->bytes_per_pixel == 4) */ { size /= 4; for (count = 0; count < size; count++) { *((u_int32_t*)fb) = ((u_int32_t*)image)[count]; fb += line_length; } } } else { memcpy(get_fb(display, x, y), image, size); } display->damaged = 1; } void ui_display_copy_lines(ui_display_t *disp, int src_x, int src_y, int dst_x, int dst_y, u_int width, u_int height) { Display *display = disp->display; u_char *src; u_char *dst; u_int copy_len; u_int count; size_t line_length; if (rotate_display) { int tmp; if (rotate_display > 0) { tmp = src_x; src_x = disp->height - src_y - height; src_y = tmp; tmp = dst_x; dst_x = disp->height - dst_y - height; dst_y = tmp; } else { tmp = src_x; src_x = src_y; src_y = disp->width - tmp - width; tmp = dst_x; dst_x = dst_y; dst_y = disp->width - tmp - width; } tmp = height; height = width; width = tmp; } copy_len = width * display->bytes_per_pixel; line_length = display->line_length; if (src_y <= dst_y) { src = get_fb(display, src_x, src_y + height - 1); dst = get_fb(display, dst_x, dst_y + height - 1); if (src_y == dst_y) { for (count = 0; count < height; count++) { memmove(dst, src, copy_len); dst -= line_length; src -= line_length; } } else { for (count = 0; count < height; count++) { memcpy(dst, src, copy_len); dst -= line_length; src -= line_length; } } } else { src = get_fb(display, src_x, src_y); dst = get_fb(display, dst_x, dst_y); for (count = 0; count < height; count++) { memcpy(dst, src, copy_len); dst += line_length; src += line_length; } } display->damaged = 1; } void ui_display_request_text_selection(ui_display_t *disp) { if (SDL_HasClipboardText() && disp->roots[0]->utf_selection_notified) { char *text; if ((text = SDL_GetClipboardText())) { (*disp->roots[0]->utf_selection_notified)(disp->roots[0], text, strlen(text)); SDL_free(text); return; } } if (disp->selection_owner) { XSelectionRequestEvent ev; ev.type = 0; ev.target = disp->roots[0]; if (disp->selection_owner->utf_selection_requested) { /* utf_selection_requested() calls ui_display_send_text_selection() */ (*disp->selection_owner->utf_selection_requested)(disp->selection_owner, &ev, 0); } } } void ui_display_send_text_selection(ui_display_t *disp, XSelectionRequestEvent *ev, u_char *sel_data, size_t sel_len) { if (ev && ev->target->utf_selection_notified) { (*ev->target->utf_selection_notified)(ev->target, sel_data, sel_len); } else { char *text; if ((text = alloca(sel_len + 1))) { memcpy(text, sel_data, sel_len); text[sel_len] = '\0'; SDL_SetClipboardText(text); } } } void ui_display_logical_to_physical_coordinates(ui_display_t *disp, int *x, int *y) { int global_x; int global_y; if (rotate_display) { int tmp = *y; if (rotate_display > 0) { *y = *x; *x = disp->display->width - tmp - 1; } else { *y = disp->display->height - *x - 1; *x = tmp; } } SDL_GetWindowPosition(disp->display->window, &global_x, &global_y); *x += global_x; *y += global_y; } void ui_display_set_maximized(ui_display_t *disp, int flag) { if (flag) { SDL_MaximizeWindow(disp->display->window); } else { SDL_RestoreWindow(disp->display->window); } } void ui_display_set_title(ui_display_t *disp, const u_char *name) { SDL_SetWindowTitle(disp->display->window, name); } void ui_display_trigger_pty_read(void) { SDL_Event ev; SDL_zero(ev); ev.type = pty_event_type; SDL_PushEvent(&ev); } #ifdef USE_BG_TEXTURE void ui_display_set_bg_color(ui_display_t *disp, u_long bg) { SDL_SetRenderDrawColor(disp->display->renderer, (bg >> 16) & 0xff, (bg >> 8) & 0xff, bg & 0xff, (bg >> 24) & 0xff); } void ui_display_set_wall_picture(ui_display_t *disp, u_char *image, u_int width, u_int height) { Display *display = disp->display; if (display->bg_texture) { SDL_DestroyTexture(display->bg_texture); } if (image) { u_char *fb; u_int line_length; int y; display->bg_texture = SDL_CreateTexture(display->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height); SDL_SetTextureBlendMode(display->bg_texture, SDL_BLENDMODE_BLEND); SDL_LockTexture(display->bg_texture, NULL, &fb, &line_length); for (y = 0; y < height; y++) { memcpy(fb, image, width * 4); fb += line_length; image += (width * 4); } SDL_UnlockTexture(display->bg_texture); } else { display->bg_texture = NULL; } } #endif mlterm-3.8.9/uitoolkit/sdl2/ui_display.h010064400017600000144000000034061356600660700167470ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_DISPLAY_H__ #define ___UI_DISPLAY_H__ #include "../ui_display.h" #define CLKED 1 #define NLKED 2 #define SLKED 4 #define ALKED 8 #define KeyPress 2 /* Private in sdl2/ */ #define ButtonPress 4 /* Private in sdl2/ */ #define ButtonRelease 5 /* Private in sdl2/ */ #define MotionNotify 6 /* Private in sdl2/ */ #define FocusOut 10 /* Private in sdl2/ */ /* common functions for ui_window.c */ u_long ui_display_get_pixel(ui_display_t *disp, int x, int y); void ui_display_put_image(ui_display_t *disp, int x, int y, u_char *image, size_t size, int need_fb_pixel); void ui_display_copy_lines(ui_display_t *disp, int src_x, int src_y, int dst_x, int dst_y, u_int width, u_int height); /* common functions for ui_window.c (pseudo color) */ #define ui_display_fill_with(x, y, width, height, pixel) (0) #define ui_cmap_get_closest_color(closest, red, green, blue) (0) #define ui_cmap_get_pixel_rgb(red, green, blue, pixel) (0) /* platform specific functions for ui_window.c */ int ui_display_resize(ui_display_t *disp, u_int width, u_int height); int ui_display_move(ui_display_t *disp, int x, int y); void ui_display_request_text_selection(ui_display_t *disp); void ui_display_send_text_selection(ui_display_t *disp, XSelectionRequestEvent *ev, u_char *sel_data, size_t sel_len); void ui_display_set_title(ui_display_t *disp, const u_char *name); void ui_display_set_maximized(ui_display_t *disp, int flag); #ifdef USE_BG_TEXTURE void ui_display_set_bg_color(ui_display_t *disp, u_long bg); void ui_display_set_wall_picture(ui_display_t *disp, u_char *image, u_int width, u_int height); #endif #endif mlterm-3.8.9/uitoolkit/sdl2/ui_dnd.c012075500017600000144000000000001356600660700202422../fb/ui_dnd.custar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui_font.c012075500017600000144000000000001356600660700206442../fb/ui_font.custar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui_font.h012075500017600000144000000000001356600660700206562../fb/ui_font.hustar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui_gc.c012075500017600000144000000000001356600660700177122../fb/ui_gc.custar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui_imagelib.c012075500017600000144000000000001356600660700222522../fb/ui_imagelib.custar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui_selection_encoding.c012075500017600000144000000000001356600660700267652../xlib/ui_selection_encoding.custar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui_virtual_kbd.c012075500017600000144000000000001356600660700235442../fb/ui_virtual_kbd.custar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui_virtual_kbd.h012075500017600000144000000000001356600660700235562../fb/ui_virtual_kbd.hustar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui_window.c012075500017600000144000000000001356600660700215462../fb/ui_window.custar kenusersmlterm-3.8.9/uitoolkit/sdl2/ui_xic.c012075500017600000144000000000001356600660700202762../fb/ui_xic.custar kenusersmlterm-3.8.9/uitoolkit/sdl2/syswminfo.c010064400017600000144000000007211356600660700166330ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include static SDL_SYSWM_TYPE subsystem = SDL_SYSWM_UNKNOWN; void syswminfo_init(void *window) { SDL_SysWMinfo info; SDL_VERSION(&info.version); if (SDL_GetWindowWMInfo(window, &info)) { subsystem = info.subsystem; } } int syswminfo_is_thread_safe(void) { return (subsystem == SDL_SYSWM_WINDOWS || subsystem == SDL_SYSWM_X11 || subsystem == SDL_SYSWM_DIRECTFB); } mlterm-3.8.9/uitoolkit/console004075500017600000144000000000001356600660700151535ustar kenusersmlterm-3.8.9/uitoolkit/console/ui_xic.c012075500017600000144000000000001356600660700210742../fb/ui_xic.custar kenusersmlterm-3.8.9/uitoolkit/console/ui.h010064400017600000144000000352601356600660700160230ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_H__ #define ___UI_H__ #if defined(__linux__) #include #elif defined(__NetBSD__) || defined(__OpenBSD__) #include #endif #include typedef struct { FILE* fp; /* Actual width, while ui_display_t.width excludes virtual kbd area. */ unsigned int width; /* Actual height, while ui_display_t.height excludes virtual kbd area. */ unsigned int height; unsigned int col_width; unsigned int line_height; int key_state; int lock_state; struct ef_conv *conv; unsigned char buf[512]; unsigned int buf_len; int is_pressing; void *sixel_output; void *sixel_dither; int support_hmargin; } Display; typedef int XIC; /* dummy */ typedef void* XID; /* dummy */ typedef void* Window; /* dummy */ typedef void* Drawable; /* dummy */ typedef struct { unsigned char *image; unsigned int width; unsigned int height; } * Pixmap; typedef unsigned char* PixmapMask; typedef int GC; /* dummy */ typedef int Font; /* dummy */ typedef int Cursor; /* dummy */ typedef int KeyCode; typedef int KeySym; typedef struct /* Same as definition in X11/X.h */ { int max_keypermod; KeyCode *modifiermap; } XModifierKeymap; typedef struct /* Same as definition in X11/X.h */ { unsigned char byte1; unsigned char byte2; } XChar2b; typedef struct { int type; unsigned int state; KeySym ksym; unsigned int keycode; } XKeyEvent; typedef unsigned long Time; /* Same as definition in X11/X.h */ typedef unsigned long Atom; /* Same as definition in X11/X.h */ typedef struct { int type; Time time; int x; int y; unsigned int state; unsigned int button; } XButtonEvent; typedef struct { int type; Time time; int x; int y; unsigned int state; } XMotionEvent; typedef struct { int type; struct ui_window *target; } XSelectionRequestEvent; typedef union { int type; XKeyEvent xkey; XButtonEvent xbutton; XMotionEvent xmotion; XSelectionRequestEvent xselectionrequest; } XEvent; typedef struct { void *dummy; } XFontStruct; typedef int XFontSet; /* dummy */ #define None 0L /* Same as definition in X11/X.h */ #define NoSymbol 0L /* Same as definition in X11/X.h */ #define CurrentTime 0L /* Same as definition in X11/X.h */ /* Same as definition in X11/X.h */ #define NoEventMask 0L #define KeyPressMask (1L << 0) #define KeyReleaseMask (1L << 1) #define ButtonPressMask (1L << 2) #define ButtonReleaseMask (1L << 3) #define EnterWindowMask (1L << 4) #define LeaveWindowMask (1L << 5) #define PointerMotionMask (1L << 6) #define PointerMotionHintMask (1L << 7) #define Button1MotionMask (1L << 8) #define Button2MotionMask (1L << 9) #define Button3MotionMask (1L << 10) #define Button4MotionMask (1L << 11) #define Button5MotionMask (1L << 12) #define ButtonMotionMask (1L << 13) #define KeymapStateMask (1L << 14) #define ExposureMask (1L << 15) #define VisibilityChangeMask (1L << 16) #define StructureNotifyMask (1L << 17) #define ResizeRedirectMask (1L << 18) #define SubstructureNotifyMask (1L << 19) #define SubstructureRedirectMask (1L << 20) #define FocusChangeMask (1L << 21) #define PropertyChangeMask (1L << 22) #define ColormapChangeMask (1L << 23) #define OwnerGrabButtonMask (1L << 24) #define ShiftMask (1 << 0) #define LockMask (1 << 1) #define ControlMask (1 << 2) #define Mod1Mask (1 << 3) #define Mod2Mask (1 << 4) #define Mod3Mask (1 << 5) #define Mod4Mask (1 << 6) #define Mod5Mask (1 << 7) #define Button1Mask (1 << 8) #define Button2Mask (1 << 9) #define Button3Mask (1 << 10) #define Button4Mask (1 << 11) #define Button5Mask (1 << 12) #define Button1 1 #define Button2 2 #define Button3 3 #define Button4 4 #define Button5 5 /* Same as fb/ui.h (to use same inputmethod plugins from both mlterm-fb and * mlterm-con) */ #if defined(__NetBSD__) || defined(__OpenBSD__) #define XK_Super_L 0xfffe /* dummy */ #define XK_Super_R 0xfffd /* dummy */ #define XK_Hyper_L 0xfffc /* dummy */ #define XK_Hyper_R 0xfffb /* dummy */ #define XK_BackSpace 0x08 #define XK_Tab 0x09 #define XK_Clear KS_Clear #define XK_Linefeed KS_Linefeed #define XK_Return 0x0d #define XK_Shift_L KS_Shift_L #define XK_Control_L KS_Control_L #define XK_Alt_L KS_Alt_L #define XK_Shift_R KS_Shift_R #define XK_Control_R KS_Control_R #define XK_Alt_R KS_Alt_R #define XK_Meta_L KS_Meta_L #define XK_Meta_R KS_Meta_R #define XK_Pause KS_Pause #define XK_Shift_Lock KS_Shift_Lock #define XK_Caps_Lock KS_Caps_Lock #define XK_Escape KS_Escape #define XK_Prior KS_Prior #define XK_Next KS_Next #define XK_End KS_End #define XK_Home KS_Home #define XK_Left KS_Left #define XK_Up KS_Up #define XK_Right KS_Right #define XK_Down KS_Down #define XK_Select KS_Select #define XK_Print KS_Print_Screen #define XK_Execute KS_Execute #define XK_Insert KS_Insert #define XK_Delete KS_Delete #define XK_Help KS_Help #define XK_F1 KS_F1 #define XK_F2 KS_F2 #define XK_F3 KS_F3 #define XK_F4 KS_F4 #define XK_F5 KS_F5 #define XK_F6 KS_F6 #define XK_F7 KS_F7 #define XK_F8 KS_F8 #define XK_F9 KS_F9 #define XK_F10 KS_F10 #define XK_F11 KS_F11 #define XK_F12 KS_F12 #define XK_F13 KS_F13 #define XK_F14 KS_F14 #define XK_F15 KS_F15 #define XK_F16 KS_F16 #define XK_F17 KS_F17 #define XK_F18 KS_F18 #define XK_F19 KS_F19 #define XK_F20 KS_F20 #define XK_F21 0xfffa /* dummy */ #define XK_F22 0xfff9 /* dummy */ #define XK_F23 0xfff8 /* dummy */ #define XK_F24 0xfff7 /* dummy */ #define XK_FMAX KS_F20 #define XK_Num_Lock KS_Num_Lock #define XK_Scroll_Lock KS_Scroll_Lock #define XK_Find KS_Find #define XK_Menu KS_Menu #define XK_Begin 0xfff6 /* dummy */ #define XK_Muhenkan KS_Muhenkan #define XK_Henkan_Mode KS_Henkan_Mode #define XK_Zenkaku_Hankaku KS_Zenkaku_Hankaku #define XK_Hiragana_Katakana KS_Hiragana_Katakana #define XK_KP_Prior KS_KP_Prior #define XK_KP_Next KS_KP_Next #define XK_KP_End KS_KP_End #define XK_KP_Home KS_KP_Home #define XK_KP_Left KS_KP_Left #define XK_KP_Up KS_KP_Up #define XK_KP_Right KS_KP_Right #define XK_KP_Down KS_KP_Down #define XK_KP_Insert KS_KP_Insert #define XK_KP_Delete KS_KP_Delete #define XK_KP_F1 KS_KP_F1 #define XK_KP_F2 KS_KP_F2 #define XK_KP_F3 KS_KP_F3 #define XK_KP_F4 KS_KP_F4 #define XK_KP_Begin KS_KP_Begin #define XK_KP_Multiply KS_KP_Multiply #define XK_KP_Add KS_KP_Add #define XK_KP_Separator KS_KP_Separator #define XK_KP_Subtract KS_KP_Subtract #define XK_KP_Decimal KS_KP_Decimal #define XK_KP_Divide KS_KP_Divide #define XK_KP_0 KS_KP_0 #define XK_KP_1 KS_KP_1 #define XK_KP_2 KS_KP_2 #define XK_KP_3 KS_KP_3 #define XK_KP_4 KS_KP_4 #define XK_KP_5 KS_KP_5 #define XK_KP_6 KS_KP_6 #define XK_KP_7 KS_KP_7 #define XK_KP_8 KS_KP_8 #define XK_KP_9 KS_KP_9 #define IsKeypadKey(ksym) (0xf200 <= (ksym) && (ksym) < 0xf300) #define IsModifierKey(ksym) (KS_Shift_L <= (ksym) && (ksym) <= KS_Alt_R) #else /* if __FreeBSD__ || __linux__ || __darwin__ */ #ifndef __linux__ /* FreeBSD / MacOSX etc */ #define KEY_CLEAR 0xff /* dummy */ #define KEY_LINEFEED 0xfe /* dummy */ #define KEY_LEFTSHIFT 0x02 #define KEY_LEFTCTRL 0x09 #define KEY_LEFTALT 0x07 #define KEY_RIGHTSHIFT 0x03 #define KEY_RIGHTCTRL 0x80 #define KEY_RIGHTALT 0x81 #define KEY_LEFTMETA 0xfd /* dummy */ #define KEY_RIGHTMETA 0xfc /* dummy */ #define KEY_CAPSLOCK 0x04 #define KEY_PAGEUP 0x4d #define KEY_PAGEDOWN 0x55 #define KEY_END 0x53 #define KEY_HOME 0x4b #define KEY_LEFT 0x4f #define KEY_UP 0x4c #define KEY_RIGHT 0x51 #define KEY_DOWN 0x54 #define KEY_SELECT 0xfb /* dummy */ #define KEY_PRINT 0x0a #define KEY_INSERT 0x56 #define KEY_DELETE 0x57 #define KEY_HELP 0xfa /* dummy */ #define KEY_F1 0x1b #define KEY_F2 0x1c #define KEY_F3 0x1d #define KEY_F4 0x1e #define KEY_F5 0x1f #define KEY_F6 0x20 #define KEY_F7 0x21 #define KEY_F8 0x22 #define KEY_F9 0x23 #define KEY_F10 0x24 #define KEY_F11 0x25 #define KEY_F12 0x26 #define KEY_F13 0xf9 /* dummy */ #define KEY_F14 0xf8 /* dummy */ #define KEY_F15 0xf7 /* dummy */ #define KEY_F16 0xf6 /* dummy */ #define KEY_F17 0xf5 /* dummy */ #define KEY_F18 0xf4 /* dummy */ #define KEY_F19 0xf3 /* dummy */ #define KEY_F20 0xf2 /* dummy */ #define KEY_F21 0xf1 /* dummy */ #define KEY_F22 0xf0 /* dummy */ #define KEY_F23 0xef /* dummy */ #define KEY_F24 0xee /* dummy */ #define KEY_NUMLOCK 0x05 #define KEY_SCROLLLOCK 0x06 #define KEY_FIND 0xed /* dummy */ #define KEY_MENU 0xec /* dummy */ #define KEY_MUHENKAN 0xeb /* dummy */ #define KEY_HENKAN 0xea /* dummy */ #define KEY_ZENKAKUHANKAKU 0xe9 /* dummy */ #define KEY_KATAKANAHIRAGANA 0xe8 /* dummy */ #define KEY_KPASTERISK 0xe7 /* dummy */ #define KEY_KPPLUS (0x52 + 0x100) #define KEY_KPCOMMA 0xe6 /* dummy */ #define KEY_KPMINUS (0x4e + 0x100) #define KEY_KPDOT (0x7f + 0x100) #define KEY_KPSLASH 0xe5 /* dummy */ #define KEY_KP0 (0x56 + 0x100) #define KEY_KP1 (0x53 + 0x100) #define KEY_KP2 (0x54 + 0x100) #define KEY_KP3 (0x55 + 0x100) #define KEY_KP4 (0x4f + 0x100) #define KEY_KP5 (0x50 + 0x100) #define KEY_KP6 (0x51 + 0x100) #define KEY_KP7 (0x4b + 0x100) #define KEY_KP8 (0x4c + 0x100) #define KEY_KP9 (0x4d + 0x100) #endif /* FreeBSD */ #define XK_Super_L 0xfffe /* dummy */ #define XK_Super_R 0xfffd /* dummy */ #define XK_Hyper_L 0xfffc /* dummy */ #define XK_Hyper_R 0xfffb /* dummy */ #define XK_BackSpace 0x08 #define XK_Tab 0x09 #define XK_Clear (KEY_CLEAR + 0x100) #define XK_Linefeed (KEY_LINEFEED + 0x100) #define XK_Return 0x0d #define XK_Shift_L (KEY_LEFTSHIFT + 0x100) #define XK_Control_L (KEY_LEFTCTRL + 0x100) #define XK_Alt_L (KEY_LEFTALT + 0x100) #define XK_Shift_R (KEY_RIGHTSHIFT + 0x100) #define XK_Control_R (KEY_RIGHTCTRL + 0x100) #define XK_Alt_R (KEY_RIGHTALT + 0x100) #define XK_Meta_L (KEY_LEFTMETA + 0x100) #define XK_Meta_R (KEY_RIGHTMETA + 0x100) #define XK_Pause 0xfff1 /* dummy */ #define XK_Shift_Lock 0xfff0 /* dummy */ #define XK_Caps_Lock (KEY_CAPSLOCK + 0x100) #define XK_Escape 0x1b #define XK_Prior (KEY_PAGEUP + 0x100) #define XK_Next (KEY_PAGEDOWN + 0x100) #define XK_End (KEY_END + 0x100) #define XK_Home (KEY_HOME + 0x100) #define XK_Left (KEY_LEFT + 0x100) #define XK_Up (KEY_UP + 0x100) #define XK_Right (KEY_RIGHT + 0x100) #define XK_Down (KEY_DOWN + 0x100) #define XK_Select (KEY_SELECT + 0x100) #define XK_Print (KEY_PRINT + 0x100) #define XK_Execute 0xffef /* dummy */ #define XK_Insert (KEY_INSERT + 0x100) #define XK_Delete (KEY_DELETE + 0x100) #define XK_Help (KEY_HELP + 0x100) #define XK_F1 (KEY_F1 + 0x100) #define XK_F2 (KEY_F2 + 0x100) #define XK_F3 (KEY_F3 + 0x100) #define XK_F4 (KEY_F4 + 0x100) #define XK_F5 (KEY_F5 + 0x100) #define XK_F6 (KEY_F6 + 0x100) #define XK_F7 (KEY_F7 + 0x100) #define XK_F8 (KEY_F8 + 0x100) #define XK_F9 (KEY_F9 + 0x100) #define XK_F10 (KEY_F10 + 0x100) #define XK_F11 (KEY_F11 + 0x100) #define XK_F12 (KEY_F12 + 0x100) #define XK_F13 (KEY_F13 + 0x100) #define XK_F14 (KEY_F14 + 0x100) #define XK_F15 (KEY_F15 + 0x100) #define XK_F16 (KEY_F16 + 0x100) #define XK_F17 (KEY_F17 + 0x100) #define XK_F18 (KEY_F18 + 0x100) #define XK_F19 (KEY_F19 + 0x100) #define XK_F20 (KEY_F20 + 0x100) #define XK_F21 (KEY_F21 + 0x100) #define XK_F22 (KEY_F22 + 0x100) #define XK_F23 (KEY_F23 + 0x100) #define XK_F24 (KEY_F24 + 0x100) #ifdef __FreeBSD__ #define XK_FMAX XK_F12 #else #define XK_FMAX XK_F10 /* F11 or later is not sequential number. */ #endif #define XK_Num_Lock (KEY_NUMLOCK + 0x100) #define XK_Scroll_Lock (KEY_SCROLLLOCK + 0x100) #define XK_Find (KEY_FIND + 0x100) #define XK_Menu (KEY_MENU + 0x100) #define XK_Begin 0xffee /* dummy */ #define XK_Muhenkan (KEY_MUHENKAN + 0x100) #define XK_Henkan_Mode (KEY_HENKAN + 0x100) #define XK_Zenkaku_Hankaku (KEY_ZENKAKUHANKAKU + 0x100) #define XK_Hiragana_Katakana (KEY_KATAKANAHIRAGANA + 0x100) #define XK_KP_Prior (KEY_KP9 + 0x100) #define XK_KP_Next (KEY_KP3 + 0x100) #define XK_KP_End (KEY_KP1 + 0x100) #define XK_KP_Home (KEY_KP7 + 0x100) #define XK_KP_Left (KEY_KP4 + 0x100) #define XK_KP_Up (KEY_KP8 + 0x100) #define XK_KP_Right (KEY_KP6 + 0x100) #define XK_KP_Down (KEY_KP2 + 0x100) #define XK_KP_Insert (KEY_KP0 + 0x100) #define XK_KP_Delete (KEY_KPDOT + 0x100) #define XK_KP_F1 0xffed /* dummy */ #define XK_KP_F2 0xffec /* dummy */ #define XK_KP_F3 0xffeb /* dummy */ #define XK_KP_F4 0xffea /* dummy */ #define XK_KP_Begin (KEY_KP5 + 0x100) /* dummy */ #define XK_KP_Multiply (KEY_KPASTERISK + 0x100) #define XK_KP_Add (KEY_KPPLUS + 0x100) #define XK_KP_Separator (KEY_KPCOMMA + 0x100) #define XK_KP_Subtract (KEY_KPMINUS + 0x100) #define XK_KP_Decimal 0xffe9 /* dummy */ #define XK_KP_Divide (KEY_KPSLASH + 0x100) #define XK_KP_0 0xffe8 /* dummy */ #define XK_KP_1 0xffe7 /* dummy */ #define XK_KP_2 0xffe6 /* dummy */ #define XK_KP_3 0xffe5 /* dummy */ #define XK_KP_4 0xffe4 /* dummy */ #define XK_KP_5 0xffe3 /* dummy */ #define XK_KP_6 0xffe1 /* dummy */ #define XK_KP_7 0xffe0 /* dummy */ #define XK_KP_8 0xffdf /* dummy */ #define XK_KP_9 0xffde /* dummy */ #define IsKeypadKey(ksym) (1) #define IsModifierKey(ksym) (0) #endif /* FreeBSD/Linux/NetBSD */ #define XK_ISO_Left_Tab 0xff61 /* dummy */ /* Same as definition in X11/X.h */ typedef struct { short x; short y; } XPoint; /* XXX dummy */ #define XKeysymToKeycode(disp, ks) (ks) #define XKeycodeToKeysym(disp, kc, i) (kc) #define XKeysymToString(ks) "" #define DefaultScreen(disp) (0) #define BlackPixel(disp, screen) (0) #define WhitePixel(disp, screen) (-1) /* Same as definition in X11/cursorfont.h */ #define XC_xterm 152 #define XC_left_ptr 68 /* Same as definition in X11/Xutil.h */ #define NoValue 0x0000 #define XValue 0x0001 #define YValue 0x0002 #define WidthValue 0x0004 #define HeightValue 0x0008 #define AllValues 0x000F #define XNegative 0x0010 #define YNegative 0x0020 int XParseGeometry(char *str, int *x, int *y, unsigned int *width, unsigned int *height); KeySym XStringToKeysym(char *str); /* === Platform dependent options === */ #define UI_COLOR_HAS_RGB #undef SUPPORT_TRUE_TRANSPARENT_BG /* Actually, fonts aren't scalable, but define TYPE_XCORE_SCALABLE to avoid * double drawing. */ #define TYPE_XCORE_SCALABLE #define MANAGE_ROOT_WINDOWS_BY_MYSELF #define MANAGE_SUB_WINDOWS_BY_MYSELF /* See also console/ui_display.c where ui_picture_display_closed() is never * called. */ #define INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS #undef SUPPORT_POINT_SIZE_FONT #undef XIM_SPOT_IS_LINE_TOP #undef USE_GC #undef CHANGEABLE_CURSOR /* use same modules as those for framebuffer */ #define PLUGIN_MODULE_SUFFIX "fb" #undef KEY_REPEAT_BY_MYSELF #undef ROTATABLE_DISPLAY #undef PSEUDO_COLOR_DISPLAY #undef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE #undef SUPPORT_URGENT_BELL #undef FORCE_UNICODE #undef NEED_DISPLAY_SYNC_EVERY_TIME #undef DRAW_SCREEN_IN_PIXELS #undef NO_DRAW_IMAGE_STRING /* libpthread is not linked to mlterm explicitly for now. */ #undef HAVE_PTHREAD #undef COMPOSE_DECSP_FONT #undef USE_REAL_VERTICAL_FONT #undef NO_DISPLAY_FD #undef FLICK_SCROLL #undef UIWINDOW_SUPPORTS_PREEDITING #endif mlterm-3.8.9/uitoolkit/console/ui_color.c010064400017600000144000000055701356600660700172150ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_color.h" #include /* strcmp */ #include #include "ui_display.h" /* CMAP_SIZE, ui_cmap_get_closest_color */ /* --- global functions --- */ int ui_load_named_xcolor(ui_display_t *disp, ui_color_t *xcolor, char *name) { vt_color_t color; u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; if (vt_color_parse_rgb_name(&red, &green, &blue, &alpha, name)) { return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, alpha); } if ((color = vt_get_color(name)) != VT_UNKNOWN_COLOR && IS_VTSYS_BASE_COLOR(color)) { /* * 0 : 0x00, 0x00, 0x00 * 1 : 0xff, 0x00, 0x00 * 2 : 0x00, 0xff, 0x00 * 3 : 0xff, 0xff, 0x00 * 4 : 0x00, 0x00, 0xff * 5 : 0xff, 0x00, 0xff * 6 : 0x00, 0xff, 0xff * 7 : 0xe5, 0xe5, 0xe5 */ red = (color & 0x1) ? 0xff : 0; green = (color & 0x2) ? 0xff : 0; blue = (color & 0x4) ? 0xff : 0; } else { if (strcmp(name, "gray") == 0) { red = green = blue = 190; } else if (strcmp(name, "lightgray") == 0) { red = green = blue = 211; } else { return 0; } } return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, 0xff); } int ui_load_rgb_xcolor(ui_display_t *disp, ui_color_t *xcolor, u_int8_t red, u_int8_t green, u_int8_t blue, u_int8_t alpha) { xcolor->pixel = vt_get_closest_color(red, green, blue); /* XXX */ if (xcolor->pixel == 0x10) { xcolor->pixel = 0; } else if (xcolor->pixel == 0xe2) { xcolor->pixel = 0xb; } else if (xcolor->pixel == 0xc4) { xcolor->pixel = 0x9; } else if (xcolor->pixel == 0x2e) { xcolor->pixel = 0xa; } else if (xcolor->pixel == 0xc9) { xcolor->pixel = 0xd; } else if (xcolor->pixel == 0x33) { xcolor->pixel = 0xe; } else if (xcolor->pixel == 0xe7) { xcolor->pixel = 0xf; } vt_get_color_rgba(xcolor->pixel, &xcolor->red, &xcolor->green, &xcolor->blue, NULL); return 1; } void ui_unload_xcolor(ui_display_t *disp, ui_color_t *xcolor) {} void ui_get_xcolor_rgba(u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_int8_t *alpha /* can be NULL */, ui_color_t *xcolor) { *red = xcolor->red; *green = xcolor->green; *blue = xcolor->blue; if (alpha) { *alpha = xcolor->alpha; } } int ui_xcolor_fade(ui_display_t *disp, ui_color_t *xcolor, u_int fade_ratio) { u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; ui_get_xcolor_rgba(&red, &green, &blue, &alpha, xcolor); #if 0 bl_msg_printf("Fading R%d G%d B%d => ", red, green, blue); #endif red = (red * fade_ratio) / 100; green = (green * fade_ratio) / 100; blue = (blue * fade_ratio) / 100; ui_unload_xcolor(disp, xcolor); #if 0 bl_msg_printf("R%d G%d B%d\n", red, green, blue); #endif return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, alpha); } mlterm-3.8.9/uitoolkit/console/ui_connect_dialog.c012075500017600000144000000000001356600660700254462../fb/ui_connect_dialog.custar kenusersmlterm-3.8.9/uitoolkit/console/ui_display.c010064400017600000144000000716261356600660700175510ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_display.h" #include /* printf */ #include /* STDIN_FILENO */ #include /* fcntl */ #include /* ioctl */ #include /* memset/memcpy */ #include /* getenv */ #include #include #include /* time */ #include /* gettimeofday */ #include #include /* select */ #include /* HAVE_GETTIMEOFDAY */ #include #include /* bl_priv_change_e(u|g)id */ #include /* bl_getuid */ #include #include /* alloca */ #include #include #include #include #ifdef __linux__ #include #endif #ifdef USE_LIBSIXEL #include #endif #include "../ui_window.h" #include "../ui_picture.h" /* --- static variables --- */ static ui_display_t **displays; static u_int num_displays; static struct termios orig_tm; static vt_char_encoding_t encoding = VT_UTF8; static u_int default_col_width = 8; static u_int default_line_height = 16; #ifdef USE_LIBSIXEL static int dither_id = BUILTIN_XTERM256; static int check_xtcolreg; #endif /* --- static functions --- */ static void set_blocking(int fd, int block) { fcntl(fd, F_SETFL, block ? (fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK) : (fcntl(fd, F_GETFL, 0) | O_NONBLOCK)); } static int set_winsize(ui_display_t *disp, char *seq) { struct winsize ws; memset(&ws, 0, sizeof(ws)); if (seq) { int col; int row; int x; int y; if (sscanf(seq, "8;%d;%d;4;%d;%dt", &row, &col, &y, &x) != 4) { return 0; } ws.ws_col = col; ws.ws_row = row; disp->width = x; disp->height = y; } else { if (ioctl(fileno(disp->display->fp), TIOCGWINSZ, &ws) == 0) { disp->width = ws.ws_xpixel; disp->height = ws.ws_ypixel; } } if (ws.ws_col == 0) { bl_error_printf("winsize.ws_col is 0\n"); ws.ws_col = 80; } if (ws.ws_row == 0) { bl_error_printf("winsize.ws_row is 0\n"); ws.ws_row = 24; } if (disp->width == 0) { disp->width = ws.ws_col * default_col_width; disp->display->col_width = default_col_width; } else { disp->display->col_width = disp->width / ws.ws_col; disp->width = disp->display->col_width * ws.ws_col; } if (disp->height == 0) { disp->height = ws.ws_row * default_line_height; disp->display->line_height = default_line_height; } else { disp->display->line_height = disp->height / ws.ws_row; disp->height = disp->display->line_height * ws.ws_row; } bl_msg_printf("Screen is %dx%d (Cell %dx%d)\n", disp->width / disp->display->col_width, disp->height / disp->display->line_height, disp->display->col_width, disp->display->line_height); return 1; } /* XXX */ int ui_font_cache_unload_all(void); static void sig_winch(int sig) { u_int count; set_winsize(displays[0], NULL); /* XXX */ ui_font_cache_unload_all(); for (count = 0; count < displays[0]->num_roots; count++) { ui_window_resize_with_margin(displays[0]->roots[count], displays[0]->width, displays[0]->height, NOTIFY_TO_MYSELF); } signal(SIGWINCH, sig_winch); } static void init_console(int fd) { #ifdef USE_LIBSIXEL /* * The response is parsed in receive_stdin_event() or ui_display_output_picture(). * (To reflect it to wall picture, ui_display_output_picture() parses it.) */ write(fd, "\x1b[?1;1;0S", 9); check_xtcolreg = -1; #endif /* The response is parsed in receive_stdin_event(). */ write(fd, "\x1b[>c", 4); write(fd, "\x1b[?25l", 6); write(fd, "\x1b[>4;2m", 7); write(fd, "\x1b[?1002h\x1b[?1006h\x1b[?8452h", 24); } static ui_display_t *open_display_socket(int fd) { void *p; if (!(p = realloc(displays, sizeof(ui_display_t *) * (num_displays + 1)))) { return NULL; } displays = p; if (!(displays[num_displays] = calloc(1, sizeof(ui_display_t))) || !(displays[num_displays]->display = calloc(1, sizeof(Display)))) { free(displays[num_displays]); return NULL; } if (!(displays[num_displays]->display->fp = fdopen(fd, "w"))) { free(displays[num_displays]->display); free(displays[num_displays]); return NULL; } /* * Set the close-on-exec flag. * If this flag off, this fd remained open until the child process forked in * open_screen_intern()(vt_term_open_pty()) close it. */ bl_file_set_cloexec(fd); set_blocking(fd, 1); init_console(fd); displays[num_displays]->display->conv = vt_char_encoding_conv_new(encoding); vt_char_encoding_conv_set_use_loose_rule(displays[num_displays]->display->conv, encoding, 1); set_winsize(displays[num_displays], "8;24;80;4;384;640t"); return displays[num_displays++]; } static ui_display_t *open_display_console(void) { void *p; struct termios tio; int fd; if (num_displays > 0 || !isatty(STDIN_FILENO) || !(p = realloc(displays, sizeof(ui_display_t *)))) { return NULL; } displays = p; if (!(displays[0] = calloc(1, sizeof(ui_display_t))) || !(displays[0]->display = calloc(1, sizeof(Display)))) { free(displays[0]); return NULL; } tcgetattr(STDIN_FILENO, &orig_tm); if (!(displays[0]->display->fp = fopen(ttyname(STDIN_FILENO), "r+"))) { free(displays[0]->display); free(displays[0]); return NULL; } fd = fileno(displays[0]->display->fp); bl_file_set_cloexec(fd); close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); init_console(fd); tio = orig_tm; #ifdef IMAXBEL tio.c_iflag &= ~(IXON | IXOFF | ICRNL | INLCR | IGNCR | IMAXBEL | ISTRIP); #else /* IMAXBEL is not defined on HaikuOS */ tio.c_iflag &= ~(IXON | IXOFF | ICRNL | INLCR | IGNCR | ISTRIP); #endif tio.c_iflag |= IGNBRK; tio.c_oflag &= ~(OPOST | ONLCR | OCRNL | ONLRET); #ifdef ECHOPRT tio.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHOE | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | ECHOCTL | ISIG); #else /* ECHOPRT is not defined on cygwin. */ tio.c_lflag &= ~(IEXTEN | ICANON | ECHO | ECHOE | ECHONL | ECHOCTL | ECHOKE | ECHOCTL | ISIG); #endif tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; tcsetattr(fd, TCSANOW, &tio); displays[0]->display->conv = vt_char_encoding_conv_new(encoding); vt_char_encoding_conv_set_use_loose_rule(displays[0]->display->conv, encoding, 1); set_winsize(displays[0], NULL); signal(SIGWINCH, sig_winch); return displays[num_displays++]; } #ifdef __linux__ static int get_key_state(void) { int ret; char state; state = 6; ret = ioctl(STDIN_FILENO, TIOCLINUX, &state); if (ret == -1) { return 0; } else { /* ShiftMask and ControlMask is the same. */ return state | ((state & (1 << KG_ALT)) ? Mod1Mask : 0); } } #else #define get_key_state() (0) #endif static inline ui_window_t *get_window_intern(ui_window_t *win, int x, int y) { u_int count; for (count = 0; count < win->num_children; count++) { ui_window_t *child; if ((child = win->children[count])->is_mapped) { if (child->x <= x && x < child->x + ACTUAL_WIDTH(child) && child->y <= y && y < child->y + ACTUAL_HEIGHT(child)) { return get_window_intern(child, x - child->x, y - child->y); } } } return win; } /* * disp->roots[1] is ignored. */ static inline ui_window_t *get_window(ui_display_t *disp, int x, /* X in display */ int y /* Y in display */ ) { return get_window_intern(disp->roots[0], x, y); } /* XXX defined in console/ui_window.c */ void ui_window_clear_margin_area(ui_window_t *win); static void expose_window(ui_window_t *win, int x, int y, u_int width, u_int height) { if (x + width <= win->x || win->x + ACTUAL_WIDTH(win) < x || y + height <= win->y || win->y + ACTUAL_HEIGHT(win) < y) { return; } if (x < win->x + win->hmargin || y < win->y + win->vmargin || x - win->x + width > win->hmargin + win->width || y - win->y + height > win->vmargin + win->height) { ui_window_clear_margin_area(win); } if (win->window_exposed) { if (x < win->x + win->hmargin) { width -= (win->x + win->hmargin - x); x = 0; } else { x -= (win->x + win->hmargin); } if (y < win->y + win->vmargin) { height -= (win->y + win->vmargin - y); y = 0; } else { y -= (win->y + win->vmargin); } (*win->window_exposed)(win, x, y, width, height); } } static void expose_display(ui_display_t *disp, int x, int y, u_int width, u_int height) { u_int count; /* * XXX * ui_im_{status|candidate}_screen can exceed display width or height, * because ui_im_{status|candidate}_screen_new() shows screen at * non-adjusted position. */ if (x + width > disp->width) { width = disp->width - x; } if (y + height > disp->height) { height = disp->height - y; } expose_window(disp->roots[0], x, y, width, height); for (count = 0; count < disp->roots[0]->num_children; count++) { expose_window(disp->roots[0]->children[count], x, y, width, height); } } static int check_visibility_of_im_window(ui_display_t *disp) { static struct { int saved; int x; int y; u_int width; u_int height; } im_region; int redraw_im_win = 0; #ifdef DEBUG if (disp->num_roots > 2) { bl_debug_printf(BL_DEBUG_TAG" Multiple IM Windows (%d) are activated.\n", disp->num_roots - 1); } #endif if (IM_WINDOW_IS_ACTIVATED(disp)) { if (im_region.saved) { if (im_region.x == disp->roots[1]->x && im_region.y == disp->roots[1]->y && im_region.width == ACTUAL_WIDTH(disp->roots[1]) && im_region.height == ACTUAL_HEIGHT(disp->roots[1])) { return 0; } if (im_region.x < disp->roots[1]->x || im_region.y < disp->roots[1]->y || im_region.x + im_region.width > disp->roots[1]->x + ACTUAL_WIDTH(disp->roots[1]) || im_region.y + im_region.height > disp->roots[1]->y + ACTUAL_HEIGHT(disp->roots[1])) { expose_display(disp, im_region.x, im_region.y, im_region.width, im_region.height); redraw_im_win = 1; } } im_region.saved = 1; im_region.x = disp->roots[1]->x; im_region.y = disp->roots[1]->y; im_region.width = ACTUAL_WIDTH(disp->roots[1]); im_region.height = ACTUAL_HEIGHT(disp->roots[1]); } else { if (im_region.saved) { expose_display(disp, im_region.x, im_region.y, im_region.width, im_region.height); im_region.saved = 0; } } return redraw_im_win; } static void receive_event_for_multi_roots(ui_display_t *disp, XEvent *xev) { int redraw_im_win; if ((redraw_im_win = check_visibility_of_im_window(disp))) { /* Stop drawing input method window */ disp->roots[1]->is_mapped = 0; } ui_window_receive_event(disp->roots[0], xev); if (redraw_im_win && disp->num_roots == 2) { /* Restart drawing input method window */ disp->roots[1]->is_mapped = 1; } else if (!check_visibility_of_im_window(disp)) { return; } expose_window(disp->roots[1], disp->roots[1]->x, disp->roots[1]->y, ACTUAL_WIDTH(disp->roots[1]), ACTUAL_HEIGHT(disp->roots[1])); } static int receive_stdin(Display *display) { ssize_t len; if ((len = read(fileno(display->fp), display->buf + display->buf_len, sizeof(display->buf) - display->buf_len - 1)) > 0) { display->buf_len += len; display->buf[display->buf_len] = '\0'; return 1; } else { return 0; } } static u_char *skip_range(u_char *seq, int beg, int end) { while (beg <= *seq && *seq <= end) { seq++; } return seq; } static int parse(u_char **param, u_char **intermed, u_char **ft, u_char *seq) { *param = seq; if ((*intermed = skip_range(*param, 0x30, 0x3f)) == *param) { *param = NULL; } if ((*ft = skip_range(*intermed, 0x20, 0x2f)) == *intermed) { *intermed = NULL; } if (0x40 <= **ft && **ft <= 0x7e) { return 1; } else { return 0; } } static int parse_modify_other_keys(XKeyEvent *kev, const char *param, const char *format, int key_mod_order) { int key; int modcode; if (sscanf(param, format, &key, &modcode) == 2) { if (!key_mod_order) { int tmp; tmp = key; key = modcode; modcode = tmp; } kev->ksym = key; modcode--; if (modcode & 1) { kev->state |= ShiftMask; } if (modcode & (2 | 8)) { kev->state |= Mod1Mask; } if (modcode & 4) { kev->state |= ControlMask; } return 1; } else { return 0; } } #ifdef USE_LIBSIXEL static void parse_xtcolreg(ui_display_t *disp, u_char *param) { int pi; int pa; int pv; if (sscanf(param, "%d;%d;%dS", &pi, &pa, &pv) == 3) { check_xtcolreg = 1; if (pv == 16) { ui_display_set_sixel_colors(disp, "16"); } } } #endif /* Same as fb/ui_display */ static int receive_stdin_event(ui_display_t *disp) { u_char *p; if (!receive_stdin(disp->display)) { u_int count; for (count = disp->num_roots; count > 0; count--) { if (disp->roots[count - 1]->window_destroyed) { (*disp->roots[count - 1]->window_destroyed)(disp->roots[count - 1]); } } return 0; } p = disp->display->buf; while (p - disp->display->buf < disp->display->buf_len) { XKeyEvent kev; u_char *param; u_char *intermed; u_char *ft; kev.type = KeyPress; kev.state = get_key_state(); kev.ksym = 0; kev.keycode = 0; if (*p == '\x1b' && p[1] == '\x0') { fd_set fds; struct timeval tv; FD_ZERO(&fds); FD_SET(fileno(disp->display->fp), &fds); tv.tv_usec = 50000; /* 0.05 sec */ tv.tv_sec = 0; if (select(fileno(disp->display->fp) + 1, &fds, NULL, NULL, &tv) == 1) { receive_stdin(disp->display); } } if (*p == '\x1b' && (p[1] == '[' || p[1] == 'O')) { if (!parse(¶m, &intermed, &ft, p + 2)) { set_blocking(fileno(disp->display->fp), 0); if (!receive_stdin(disp->display)) { break; } continue; } if (p[1] == '[') { p = ft + 1; if (*ft == '~') { if (!param || intermed) { continue; } else if (!parse_modify_other_keys(&kev, param, "27;%d;%d~", 0)) { switch (atoi(param)) { case 2: kev.ksym = XK_Insert; break; case 3: kev.ksym = XK_Delete; break; case 5: kev.ksym = XK_Prior; break; case 6: kev.ksym = XK_Next; break; case 7: kev.ksym = XK_Home; break; case 8: kev.ksym = XK_End; break; case 17: kev.ksym = XK_F6; break; case 18: kev.ksym = XK_F7; break; case 19: kev.ksym = XK_F8; break; case 20: kev.ksym = XK_F9; break; case 21: kev.ksym = XK_F10; break; case 23: kev.ksym = XK_F11; break; case 24: kev.ksym = XK_F12; break; default: continue; } } } else if (*ft == 'M' || *ft == 'm') { XButtonEvent bev; int state; #ifdef HAVE_GETTIMEOFDAY struct timeval tv; #endif ui_window_t *win; if (*ft == 'M') { if (disp->display->is_pressing) { bev.type = MotionNotify; } else { bev.type = ButtonPress; disp->display->is_pressing = 1; } if (!param) { state = *(p++) - 0x20; bev.x = *(p++) - 0x20; bev.y = *(p++) - 0x20; goto make_event; } } else { bev.type = ButtonRelease; disp->display->is_pressing = 0; } *ft = '\0'; if (!param || sscanf(param, "<%d;%d;%d", &state, &bev.x, &bev.y) != 3) { continue; } make_event: bev.button = (state & 0x2) + 1; if (bev.type == MotionNotify) { bev.state = Button1Mask << (bev.button - 1); } else { bev.state = 0; } bev.x--; bev.x *= disp->display->col_width; bev.y--; bev.y *= disp->display->line_height; win = get_window(disp, bev.x, bev.y); bev.x -= win->x; bev.y -= win->y; #ifdef HAVE_GETTIMEOFDAY gettimeofday(&tv, NULL); bev.time = tv.tv_sec * 1000 + tv.tv_usec / 1000; #else bev.time = time(NULL) * 1000; #endif set_blocking(fileno(disp->display->fp), 1); ui_window_receive_event(win, &bev); set_blocking(fileno(disp->display->fp), 0); continue; } else if (param && set_winsize(disp, param)) { u_int count; /* XXX */ ui_font_cache_unload_all(); for (count = 0; count < disp->num_roots; count++) { ui_window_resize_with_margin(disp->roots[count], disp->width, disp->height, NOTIFY_TO_MYSELF); } continue; } else if (param && *ft == 'u') { if (!parse_modify_other_keys(&kev, param, "%d;%du", 1)) { continue; } } else if (param && /* (*param == '>' || *param == '?') && */ *ft == 'c') { int pp; int pv; int pc; /* * iTerm2 2.0.0.20141103: CSI>0;95;c * MacOSX Terminal 2.1.2: CSI?1;2c * mlterm: CSI>24;279;0c */ if (sscanf(param + 1, "%d;%d;%dc", &pp, &pv, &pc) >= 2 && (pp >= 41 /* VT420 or later */ || /* * xterm 279 or later supports DECSLRM/DECLRMM * but mlterm 3.7.1 or before which supports it * responses 277. */ pv >= 277)) { disp->display->support_hmargin = 1; } else { bl_msg_printf("Slow scrolling on splitted screens\n"); disp->display->support_hmargin = 0; } continue; } #ifdef USE_LIBSIXEL else if (param && *param == '?' && *ft == 'S') { parse_xtcolreg(disp, param + 1); continue; } #endif else if ('P' <= *ft && *ft <= 'S') { kev.ksym = XK_F1 + (*ft - 'P'); } #ifdef __FreeBSD__ else if ('Y' <= *ft && *ft <= 'Z') { kev.ksym = XK_F1 + (*ft - 'Y'); kev.state = ShiftMask; } else if ('a' <= *ft && *ft <= 'j') { kev.ksym = XK_F3 + (*ft - 'a'); kev.state = ShiftMask; } else if ('k' <= *ft && *ft <= 'v') { kev.ksym = XK_F1 + (*ft - 'k'); kev.state = ControlMask; } else if ('w' <= *ft && *ft <= 'z') { kev.ksym = XK_F1 + (*ft - 'w'); kev.state = ControlMask | ShiftMask; } else if (*ft == '@') { kev.ksym = XK_F5; kev.state = ControlMask | ShiftMask; } else if ('[' <= *ft && *ft <= '\`') { kev.ksym = XK_F6 + (*ft - '['); kev.state = ControlMask | ShiftMask; } else if (*ft == '{') { kev.ksym = XK_F12; kev.state = ControlMask | ShiftMask; } #endif else { switch (*ft) { case 'A': kev.ksym = XK_Up; break; case 'B': kev.ksym = XK_Down; break; case 'C': kev.ksym = XK_Right; break; case 'D': kev.ksym = XK_Left; break; case 'F': kev.ksym = XK_End; break; case 'H': kev.ksym = XK_Home; break; default: continue; } } if (param) { u_char *tmp; if ((tmp = strchr(param, ';'))) { param = tmp + 1; } } } else /* if( p[1] == 'O') */ { p = ft + 1; switch (*ft) { case 'P': kev.ksym = XK_F1; break; case 'Q': kev.ksym = XK_F2; break; case 'R': kev.ksym = XK_F3; break; case 'S': kev.ksym = XK_F4; break; default: continue; } } if (param && '1' <= *param && *param <= '9') { int state; state = atoi(param) - 1; if (state & 0x1) { kev.state |= ShiftMask; } if (state & 0x2) { kev.state |= Mod1Mask; } if (state & 0x4) { kev.state |= ControlMask; } } } else { kev.ksym = *(p++); /* XXX */ if (kev.ksym == 0x7f && orig_tm.c_cc[VERASE] == 0x7f) { /* Convert to BackSpace */ kev.ksym = 0x08; } if ((u_int)kev.ksym <= 0x1f) { if (kev.ksym == '\0') { /* CTL+' ' instead of CTL+@ */ kev.ksym = ' '; } else if (0x01 <= kev.ksym && kev.ksym <= 0x1a) { /* Lower case alphabets instead of upper ones. */ kev.ksym = kev.ksym + 0x60; } else { kev.ksym = kev.ksym + 0x40; } kev.state = ControlMask; } else if ('A' <= kev.ksym && kev.ksym <= 'Z') { kev.state = ShiftMask; } } set_blocking(fileno(disp->display->fp), 1); receive_event_for_multi_roots(disp, &kev); set_blocking(fileno(disp->display->fp), 0); } if ((disp->display->buf_len = disp->display->buf + disp->display->buf_len - p) > 0) { memcpy(disp->display->buf, p, disp->display->buf_len + 1); } set_blocking(fileno(disp->display->fp), 1); return 1; } /* --- global functions --- */ ui_display_t *ui_display_open(char *disp_name, u_int depth) { ui_display_t *disp; if (disp_name && strncmp(disp_name, "client:", 7) == 0) { disp = open_display_socket(atoi(disp_name + 7)); } else if (!displays) { disp = open_display_console(); } else { return displays[0]; } if (disp) { if (!(disp->name = getenv("DISPLAY"))) { disp->name = ":0.0"; } } return disp; } void ui_display_close(ui_display_t *disp) { u_int count; /* inline pictures are alive until vt_term_t is destroyed. */ #if 0 ui_picture_display_closed(disp->display); #endif if (isatty(fileno(disp->display->fp))) { tcsetattr(fileno(disp->display->fp), TCSAFLUSH, &orig_tm); signal(SIGWINCH, SIG_IGN); } write(fileno(disp->display->fp), "\x1b[?25h", 6); write(fileno(disp->display->fp), "\x1b[>4;0m", 7); write(fileno(disp->display->fp), "\x1b[?1002l\x1b[?1006l\x1b[?8452l", 24); fclose(disp->display->fp); (*disp->display->conv->destroy)(disp->display->conv); for (count = 0; count < num_displays; count++) { if (displays[count] == disp) { memcpy(displays + count, displays + count + 1, sizeof(ui_display_t *) * (num_displays - count - 1)); num_displays--; break; } } } void ui_display_close_all(void) { u_int count; for (count = num_displays; count > 0; count--) { ui_display_close(displays[count - 1]); } free(displays); displays = NULL; } ui_display_t **ui_get_opened_displays(u_int *num) { *num = num_displays; return displays; } int ui_display_fd(ui_display_t *disp) { return fileno(disp->display->fp); } int ui_display_show_root(ui_display_t *disp, ui_window_t *root, int x, int y, int hint, char *app_name, Window parent_window /* Ignored */ ) { void *p; if ((p = realloc(disp->roots, sizeof(ui_window_t *) * (disp->num_roots + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } disp->roots = p; root->disp = disp; root->parent = NULL; root->parent_window = disp->my_window; root->gc = disp->gc; root->x = x; root->y = y; if (app_name) { root->app_name = app_name; } disp->roots[disp->num_roots++] = root; /* Cursor is drawn internally by calling ui_display_put_image(). */ if (!ui_window_show(root, hint)) { return 0; } return 1; } int ui_display_remove_root(ui_display_t *disp, ui_window_t *root) { u_int count; for (count = 0; count < disp->num_roots; count++) { if (disp->roots[count] == root) { /* XXX ui_window_unmap resizes all windows internally. */ #if 0 ui_window_unmap(root); #endif ui_window_final(root); disp->num_roots--; if (count == disp->num_roots) { disp->roots[count] = NULL; } else { disp->roots[count] = disp->roots[disp->num_roots]; } return 1; } } return 0; } void ui_display_idling(ui_display_t *disp) { u_int count; for (count = 0; count < disp->num_roots; count++) { ui_window_idling(disp->roots[count]); } } int ui_display_receive_next_event(ui_display_t *disp) { return receive_stdin_event(disp); } /* * Folloing functions called from ui_window.c */ int ui_display_own_selection(ui_display_t *disp, ui_window_t *win) { if (disp->selection_owner) { ui_display_clear_selection(NULL, NULL); } disp->selection_owner = win; return 1; } int ui_display_clear_selection(ui_display_t *disp, /* NULL means all selection owner windows. */ ui_window_t *win) { if (disp == NULL) { u_int count; for (count = 0; count < num_displays; count++) { ui_display_clear_selection(displays[count], displays[count]->selection_owner); } return 1; } if (disp->selection_owner == NULL || disp->selection_owner != win) { return 0; } if (disp->selection_owner->selection_cleared) { (*disp->selection_owner->selection_cleared)(disp->selection_owner); } disp->selection_owner = NULL; return 1; } XModifierKeymap *ui_display_get_modifier_mapping(ui_display_t *disp) { return disp->modmap.map; } void ui_display_update_modifier_mapping(ui_display_t *disp, u_int serial) { /* dummy */ } XID ui_display_get_group_leader(ui_display_t *disp) { return None; } /* XXX for input method window */ void ui_display_reset_input_method_window(void) { #if 0 if (IM_WINDOW_IS_ACTIVATED(displays[0])) #endif { check_visibility_of_im_window(displays[0]); ui_window_clear_margin_area(displays[0]->roots[1]); } } void ui_display_set_char_encoding(ui_display_t *disp, vt_char_encoding_t e) { encoding = e; if (disp) { (*disp->display->conv->destroy)(disp->display->conv); disp->display->conv = vt_char_encoding_conv_new(encoding); vt_char_encoding_conv_set_use_loose_rule(disp->display->conv, encoding, 1); } } void ui_display_set_default_cell_size(u_int width, u_int height) { default_col_width = width; default_line_height = height; } #ifdef USE_LIBSIXEL void ui_display_set_sixel_colors(ui_display_t *disp, const char *colors) { int old_dither_id = dither_id; if (strcmp(colors, "16") == 0) { dither_id = BUILTIN_XTERM16; } else if (strcmp(colors, "full") == 0) { dither_id = -1; } else { dither_id = BUILTIN_XTERM256; } if (disp) { if (disp->display->sixel_dither) { if (old_dither_id == dither_id) { return; } sixel_dither_destroy(disp->display->sixel_dither); } if (dither_id == -1) { disp->display->sixel_dither = sixel_dither_create(-1); } else { disp->display->sixel_dither = sixel_dither_get(dither_id); } /* See modify_pixmap() (which reorder ARGB bytes by RGBA) in ui_imagelib.c */ sixel_dither_set_pixelformat(disp->display->sixel_dither, PIXELFORMAT_RGBA8888); } } static int callback(char *data, int size, void *out) { return fwrite(data, 1, size, out); } void ui_display_output_picture(ui_display_t *disp, u_char *picture, u_int width, u_int height) { if (!disp->display->sixel_output) { disp->display->sixel_output = sixel_output_create(callback, disp->display->fp); } if (check_xtcolreg == -1) { /* * Don't call receive_stdin_event() which may have called this function itself. * (receive_stdin_event() -> set_winsize() -> ui_display_output_picture(). */ if (disp->display->buf_len > 0 || receive_stdin(disp->display)) { char *p; for (p = disp->display->buf; (p = strchr(p, '\x1b')); p ++) { if (p[1] == '[' && p[2] == '?' && strchr(p, 'S')) { parse_xtcolreg(disp, p + 3); break; } } } } if (!disp->display->sixel_dither) { if (dither_id == -1) { disp->display->sixel_dither = sixel_dither_create(-1); } else { disp->display->sixel_dither = sixel_dither_get(dither_id); } } sixel_dither_set_pixelformat(disp->display->sixel_dither, PIXELFORMAT_RGBA8888); sixel_encode(picture, width, height, 4, disp->display->sixel_dither, disp->display->sixel_output); } #endif mlterm-3.8.9/uitoolkit/console/ui_display.h010064400017600000144000000013661356600660700175500ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_DISPLAY_H__ #define ___UI_DISPLAY_H__ #include "../ui_display.h" #ifdef __FreeBSD__ #include /* NLKED */ #else #define CLKED 1 #define NLKED 2 #define SLKED 4 #define ALKED 8 #endif #define KeyPress 2 /* Private in fb/ */ #define ButtonPress 4 /* Private in fb/ */ #define ButtonRelease 5 /* Private in fb/ */ #define MotionNotify 6 /* Private in fb/ */ #define IM_WINDOW_IS_ACTIVATED(disp) ((disp)->num_roots > 1 && (disp)->roots[1]->is_mapped) #ifdef USE_LIBSIXEL void ui_display_output_picture(ui_display_t *disp, u_char *picture, u_int width, u_int height); #else #define ui_display_output_picture(disp, picture, width, height) (0) #endif #endif mlterm-3.8.9/uitoolkit/console/ui_dnd.c012075500017600000144000000000001356600660700210402../fb/ui_dnd.custar kenusersmlterm-3.8.9/uitoolkit/console/ui_font.c010064400017600000144000000131501356600660700170360ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_font.h" #include #include /* open */ #include /* close */ #include /* mmap */ #include /* memcmp */ #include /* fstat */ #include /* utime */ #include /* WORDS_BIGENDIAN */ #include #include #include /* strdup */ #include /* bl_basename */ #include /* bl_get_user_rc_path */ #include /* TOINT32 */ #include #ifdef __ANDROID__ #include #endif #include "ui_display.h" #define DIVIDE_ROUNDINGUP(a, b) (((int)((a)*10 + (b)*10 - 1)) / ((int)((b)*10))) #if 0 #define __DEBUG #endif /* --- global functions --- */ void ui_compose_dec_special_font(void) { /* Do nothing for now in console. */ } ui_font_t *ui_font_new(Display *display, vt_font_t id, int size_attr, ui_type_engine_t type_engine, ui_font_present_t font_present, const char *fontname, u_int fontsize, u_int col_width, int use_medium_for_bold, u_int letter_space /* Ignored for now. */ ) { ui_font_t *font; u_int cols; if (type_engine != TYPE_XCORE || !(font = calloc(1, sizeof(ui_font_t)))) { return NULL; } if (!(font->xfont = calloc(1, sizeof(XFontStruct)))) { free(font); return NULL; } font->display = display; font->xfont = NULL; font->id = id; if (font->id & FONT_FULLWIDTH) { cols = 2; } else { cols = 1; } if (font_present & FONT_VAR_WIDTH) { /* * If you use fixed-width fonts whose width is differnet from * each other. */ font->is_var_col_width = 1; } if (font_present & FONT_VERTICAL) { font->is_vertical = 1; } if (use_medium_for_bold) { font->double_draw_gap = 1; } font->width = font->display->col_width * cols; font->height = font->display->line_height; font->ascent = 0; /* x_off is *not* divided by 2 => see draw_string() in ui_window.c */ if (col_width == 0) { /* standard(usascii) font */ if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ font->x_off = font->width /* / 2 */; font->width *= 2; } /* letter_space and line_space are ignored. */ #if 0 if (letter_space > 0) { font->width += letter_space; font->x_off += (letter_space /* / 2 */); } #endif } else { /* not a standard(usascii) font */ /* * XXX hack * forcibly conforming non standard font width to standard font width. */ if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ if (font->width != col_width) { bl_msg_printf( "Font(id %x) width(%d) is not matched with " "standard width(%d).\n", font->id, font->width, col_width); /* is_var_col_width is always false if is_vertical is true. */ #if 0 if (!font->is_var_col_width) #endif { if (font->width < col_width) { font->x_off = (col_width - font->width) /* / 2 */; } font->width = col_width; } } } else { if (font->width != col_width * cols) { bl_msg_printf( "Font(id %x) width(%d) is not matched with " "standard width(%d).\n", font->id, font->width, col_width * cols); if (!font->is_var_col_width) { if (font->width < col_width * cols) { font->x_off = (col_width * cols - font->width) /* / 2 */; } font->width = col_width * cols; } } } } font->size_attr = size_attr; /* * checking if font width/height/ascent member is sane. */ if (font->width == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " font width is 0.\n"); #endif /* XXX this may be inaccurate. */ font->width = DIVIDE_ROUNDINGUP(fontsize * cols, 2); } if (font->height == 0) { /* XXX this may be inaccurate. */ font->height = fontsize; } #ifdef DEBUG ui_font_dump(font); #endif return font; } void ui_font_destroy(ui_font_t *font) { free(font); } u_int ui_calculate_char_width(ui_font_t *font, u_int32_t ch, ef_charset_t cs, int *draw_alone) { if (draw_alone) { *draw_alone = 0; } return font->width; } /* Return written size */ size_t ui_convert_ucs4_to_utf16(u_char *dst, /* 4 bytes. Big endian. */ u_int32_t src) { if (src < 0x10000) { dst[0] = (src >> 8) & 0xff; dst[1] = src & 0xff; return 2; } else if (src < 0x110000) { /* surrogate pair */ u_char c; src -= 0x10000; c = (u_char)(src / (0x100 * 0x400)); src -= (c * 0x100 * 0x400); dst[0] = c + 0xd8; c = (u_char)(src / 0x400); src -= (c * 0x400); dst[1] = c; c = (u_char)(src / 0x100); src -= (c * 0x100); dst[2] = c + 0xdc; dst[3] = (u_char)src; return 4; } return 0; } #ifdef DEBUG void ui_font_dump(ui_font_t *font) { bl_msg_printf("Font id %x: XFont %p (width %d, height %d, ascent %d, x_off %d)", font->id, font->xfont, font->width, font->height, font->ascent, font->x_off); if (font->is_proportional) { bl_msg_printf(" (proportional)"); } if (font->is_var_col_width) { bl_msg_printf(" (var col width)"); } if (font->is_vertical) { bl_msg_printf(" (vertical)"); } if (font->double_draw_gap) { bl_msg_printf(" (double drawing)"); } bl_msg_printf("\n"); } #endif mlterm-3.8.9/uitoolkit/console/ui_font.h012075500017600000144000000000001356600660700214542../fb/ui_font.hustar kenusersmlterm-3.8.9/uitoolkit/console/ui_gc.c012075500017600000144000000000001356600660700205102../fb/ui_gc.custar kenusersmlterm-3.8.9/uitoolkit/console/ui_imagelib.c010064400017600000144000000245531356600660700176520ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef NO_IMAGE #include "../ui_imagelib.h" #include /* sprintf */ #include /* write , STDIN_FILENO */ #ifdef DLOPEN_LIBM #include /* dynamically loading pow */ #else #include /* pow */ #endif #include #include #include /* BL_LIBEXECDIR */ #include "ui_display.h" /* ui_cmap_get_closest_color */ /* Trailing "/" is appended in value_table_refresh(). */ #ifndef LIBMDIR #define LIBMDIR "/lib" #endif #if 1 #define BUILTIN_SIXEL #endif /* --- static functions --- */ static void value_table_refresh(u_char *value_table, /* 256 bytes */ ui_picture_modifier_t *mod) { int i, tmp; double real_gamma, real_brightness, real_contrast; static double (*pow_func)(double, double); real_gamma = (double)(mod->gamma) / 100; real_contrast = (double)(mod->contrast) / 100; real_brightness = (double)(mod->brightness) / 100; if (!pow_func) { #ifdef DLOPEN_LIBM bl_dl_handle_t handle; if ((!(handle = bl_dl_open(LIBMDIR "/", "m")) && !(handle = bl_dl_open("", "m"))) || !(pow_func = bl_dl_func_symbol(handle, "pow"))) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to load pow in libm.so\n"); #endif if (handle) { bl_dl_close(handle); } /* * gamma, contrast and brightness options are ignored. * (alpha option still survives.) */ for (i = 0; i < 256; i++) { value_table[i] = i; } return; } bl_dl_close_at_exit(handle); #else /* DLOPEN_LIBM */ pow_func = pow; #endif /* DLOPEN_LIBM */ } for (i = 0; i < 256; i++) { tmp = real_contrast * (255 * (*pow_func)(((double)i + 0.5) / 255, real_gamma) - 128) + 128 * real_brightness; if (tmp >= 255) { break; } else if (tmp < 0) { value_table[i] = 0; } else { value_table[i] = tmp; } } for (; i < 256; i++) { value_table[i] = 255; } } static void modify_pixmap(Display *display, Pixmap pixmap, ui_picture_modifier_t *pic_mod, u_int depth) { u_char *value_table; u_int32_t *src; u_char *dst; u_int num_pixels; u_int count; u_char r, g, b, a; u_long pixel; if (!ui_picture_modifier_is_normal(pic_mod) && (value_table = alloca(256))) { value_table_refresh(value_table, pic_mod); } else { value_table = NULL; } src = dst = pixmap->image; num_pixels = pixmap->width * pixmap->height; for (count = 0; count < num_pixels; count++) { pixel = *(src++); a = (pixel >> 24) & 0xff; r = (pixel >> 16) & 0xff; g = (pixel >> 8) & 0xff; b = pixel & 0xff; if (value_table) { r = (value_table[r] * (255 - pic_mod->alpha) + pic_mod->blend_red * pic_mod->alpha) / 255; g = (value_table[g] * (255 - pic_mod->alpha) + pic_mod->blend_green * pic_mod->alpha) / 255; b = (value_table[b] * (255 - pic_mod->alpha) + pic_mod->blend_blue * pic_mod->alpha) / 255; } dst[0] = r; dst[1] = g; dst[2] = b; dst[3] = a; dst += 4; } } #ifdef BUILTIN_SIXEL #include #include #include /* SSIZE_MAX */ /* * This function resizes the sixel image to the specified size and shrink * pixmap->image. * It frees pixmap->image in failure. * Call resize_sixel() after load_sixel_from_file() because it returns at least * 1024*1024 pixels memory even if the actual image size is less than 1024*1024. */ static int resize_sixel(Pixmap pixmap, u_int width, u_int height, u_int bytes_per_pixel) { void *p; size_t line_len; size_t old_line_len; size_t image_len; size_t old_image_len; u_char *dst; u_char *src; int y; u_int min_height; p = NULL; if ((width == 0 || width == pixmap->width) && (height == 0 || height == pixmap->height)) { goto end; } if (width > SSIZE_MAX / bytes_per_pixel / height) { goto error; } old_line_len = pixmap->width * bytes_per_pixel; line_len = width * bytes_per_pixel; image_len = line_len * height; old_image_len = old_line_len * pixmap->height; if (image_len > old_image_len) { if (!(p = realloc(pixmap->image, image_len))) { goto error; } pixmap->image = p; } /* Tiling */ min_height = BL_MIN(height, pixmap->height); if (width > pixmap->width) { size_t surplus; u_int num_copy; u_int count; u_char *dst_next; y = min_height - 1; src = pixmap->image + old_line_len * y; dst = pixmap->image + line_len * y; surplus = line_len % old_line_len; num_copy = line_len / old_line_len - 1; for (; y >= 0; y--) { dst_next = memmove(dst, src, old_line_len); for (count = num_copy; count > 0; count--) { memcpy((dst_next += old_line_len), dst, old_line_len); } memcpy(dst_next + old_line_len, dst, surplus); dst -= line_len; src -= old_line_len; } } else if (width < pixmap->width) { src = pixmap->image + old_line_len; dst = pixmap->image + line_len; for (y = 1; y < min_height; y++) { memmove(dst, src, old_line_len); dst += line_len; src += old_line_len; } } if (height > pixmap->height) { y = pixmap->height; src = pixmap->image; dst = src + line_len * y; for (; y < height; y++) { memcpy(dst, src, line_len); dst += line_len; src += line_len; } } bl_msg_printf("Resize sixel from %dx%d to %dx%d\n", pixmap->width, pixmap->height, width, height); pixmap->width = width; pixmap->height = height; end: /* Always realloate pixmap->image according to its width, height and * bytes_per_pixel. */ if (!p && (p = realloc(pixmap->image, pixmap->width * pixmap->height * bytes_per_pixel))) { pixmap->image = p; } return 1; error: free(pixmap->image); return 0; } #define CARD_HEAD_SIZE 0 #include "../../common/c_sixel.c" #endif /* BUILTIN_SIXEL */ static int load_file(Display *display, char *path, u_int width, u_int height, int keep_aspect, ui_picture_modifier_t *pic_mod, u_int depth, Pixmap *pixmap, PixmapMask *mask) { pid_t pid; int fds[2]; ssize_t size; u_int32_t tmp; if (!path || !*path) { return 0; } #ifdef BUILTIN_SIXEL if (strcasecmp(path + strlen(path) - 4, ".six") == 0 && /* For old machines and Android (not to use mlimgloader) */ #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__ANDROID__) width == 0 && height == 0 && #endif (*pixmap = calloc(1, sizeof(**pixmap)))) { if (((*pixmap)->image = load_sixel_from_file(path, &(*pixmap)->width, &(*pixmap)->height)) && /* resize_sixel() frees pixmap->image in failure. */ resize_sixel(*pixmap, width, height, 4)) { goto loaded; } else { free(*pixmap); } } #endif #ifdef __ANDROID__ if (!(*pixmap = calloc(1, sizeof(**pixmap)))) { return 0; } (*pixmap)->width = width; (*pixmap)->height = height; if (!((*pixmap)->image = ui_display_get_bitmap(path, &(*pixmap)->width, &(*pixmap)->height))) { free(*pixmap); return 0; } #else if (pipe(fds) == -1) { return 0; } pid = fork(); if (pid == -1) { close(fds[0]); close(fds[1]); return 0; } if (pid == 0) { /* child process */ char *args[8]; char width_str[DIGIT_STR_LEN(u_int) + 1]; char height_str[DIGIT_STR_LEN(u_int) + 1]; args[0] = BL_LIBEXECDIR("mlterm") "/mlimgloader"; args[1] = "0"; sprintf(width_str, "%u", width); args[2] = width_str; sprintf(height_str, "%u", height); args[3] = height_str; args[4] = path; args[5] = "stdout"; if (keep_aspect) { args[6] = "-a"; args[7] = NULL; } else { args[6] = NULL; } close(fds[0]); if (dup2(fds[1], STDOUT_FILENO) != -1) { execv(args[0], args); } bl_msg_printf("Failed to exec %s.\n", args[0]); exit(1); } close(fds[1]); if (!(*pixmap = calloc(1, sizeof(**pixmap)))) { goto error; } if (read(fds[0], &tmp, sizeof(u_int32_t)) != sizeof(u_int32_t)) { goto error; } size = ((*pixmap)->width = tmp) * sizeof(u_int32_t); if (read(fds[0], &tmp, sizeof(u_int32_t)) != sizeof(u_int32_t)) { goto error; } size *= ((*pixmap)->height = tmp); if (!((*pixmap)->image = malloc(size))) { goto error; } else { u_char *p; ssize_t n_rd; p = (*pixmap)->image; while ((n_rd = read(fds[0], p, size)) > 0) { p += n_rd; size -= n_rd; } if (size > 0) { goto error; } } close(fds[0]); #endif loaded: if (mask) { *mask = None; } modify_pixmap(display, *pixmap, pic_mod, depth); #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " %s(w %d h %d) is loaded%s.\n", path, (*pixmap)->width, (*pixmap)->height, (mask && *mask) ? " (has mask)" : ""); #endif return 1; error: #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to load %s\n", path); #endif if (*pixmap) { free((*pixmap)->image); free(*pixmap); } close(fds[0]); return 0; } /* --- global functions --- */ void ui_imagelib_display_opened(Display *display) {} void ui_imagelib_display_closed(Display *display) {} Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, ui_picture_modifier_t *pic_mod) { Pixmap pixmap; if (!load_file(win->disp->display, path, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), 0, pic_mod, win->disp->depth, &pixmap, NULL)) { pixmap = None; } return pixmap; } int ui_imagelib_root_pixmap_available(Display *display) { return 0; } Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modifier_t *pic_mod) { return None; } int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) { if (cardinal) { return 0; } if (!load_file(disp->display, path, *width, *height, keep_aspect, NULL, disp->depth, pixmap, mask)) { return 0; } if (*width == 0 || *height == 0 || keep_aspect) { *width = (*pixmap)->width; *height = (*pixmap)->height; } return 1; } void ui_destroy_image(Display *display, Pixmap pixmap) { free(pixmap->image); free(pixmap); } void ui_destroy_mask(Display *display, PixmapMask mask /* can be NULL */) { if (mask) { free(mask); } } #endif /* NO_IMAGE */ mlterm-3.8.9/uitoolkit/console/ui_selection_encoding.c012075500017600000144000000000001356600660700275632../xlib/ui_selection_encoding.custar kenusersmlterm-3.8.9/uitoolkit/console/ui_window.c010064400017600000144000001214051356600660700174020ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_window.h" #include #include #include #include #include /* bl_usleep */ #include #include #include #include #include "ui_display.h" #include "ui_font.h" #define MAX_CLICK 3 /* max is triple click */ /* win->width is not multiples of (win)->width_inc in framebuffer. */ #define RIGHT_MARGIN(win) \ ((win)->width_inc ? ((win)->width - (win)->min_width) % (win)->width_inc : 0) #define BOTTOM_MARGIN(win) \ ((win)->height_inc ? ((win)->height - (win)->min_height) % (win)->height_inc : 0) #ifdef USE_GRF static ui_color_t black = {TP_COLOR, 0, 0, 0, 0}; #endif #define ParentRelative (1L) #define DummyPixmap (2L) #define COL_WIDTH (win->disp->display->col_width) #define LINE_HEIGHT (win->disp->display->line_height) /* XXX Check if win is input method window or not. */ #define IS_IM_WINDOW(win) ((win)->disp->num_roots >= 2 && (win) == (win)->disp->roots[1]) /* --- static variables --- */ static int click_interval = 250; /* millisecond, same as xterm. */ static ef_parser_t *cp_parser; static ef_parser_t *utf16_parser; /* --- static functions --- */ static int scroll_region(ui_window_t *win, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y) { int top; int top_c; int bottom; int bottom_c; int left; int left_c; int right; int right_c; if (!win->is_mapped || !ui_window_is_scrollable(win)) { return 0; } if (src_y < dst_y) { top = src_y; bottom = dst_y + height; } else { top = dst_y; bottom = src_y + height; } top_c = (top + win->y) / LINE_HEIGHT; bottom_c = (bottom + win->y) / LINE_HEIGHT; if (src_x < dst_x) { left = src_x; right = dst_x + width; } else { left = dst_x; right = src_x + width; } left_c = (left + win->x) / COL_WIDTH; right_c = (right + win->x) / COL_WIDTH; fprintf(win->disp->display->fp, "\x1b[%d;%dr", top_c + 1, bottom_c); fprintf(win->disp->display->fp, "\x1b[?69h\x1b[%d;%ds", left_c + 1, right_c); /* XXX for mlterm-3.7.1 or before */ #if 1 fprintf(win->disp->display->fp, "\x1b[%d;%dH", top_c + 1, left_c + 1); #endif if (src_y < dst_y) { fprintf(win->disp->display->fp, "\x1b[%dT", (dst_y - src_y) / LINE_HEIGHT); } else if (src_y > dst_y) { fprintf(win->disp->display->fp, "\x1b[%dS", (src_y - dst_y) / LINE_HEIGHT); } if (src_x < dst_x) { int len = (dst_x - src_x) / COL_WIDTH; for (; top_c < bottom_c; top_c++) { fprintf(win->disp->display->fp, "\x1b[%d;%dH\x1b[%d@", top_c + 1, left_c + 1, len); } } else if (src_x > dst_x) { int len = (src_x - dst_x) / COL_WIDTH; for (; top_c < bottom_c; top_c++) { fprintf(win->disp->display->fp, "\x1b[%d;%dH\x1b[%dP", top_c + 1, left_c + 1, len); } } fprintf(win->disp->display->fp, "\x1b[r\x1b[?69l"); return 1; } static void set_attr(FILE *fp, vt_font_t font, u_int fg_pixel, u_int bg_pixel, int line_style, int size_attr) { static int size_attr_set; if (fg_pixel < 0x8) { fprintf(fp, "\x1b[%dm", fg_pixel + 30); } else if (fg_pixel < 0x10) { fprintf(fp, "\x1b[%dm", (fg_pixel & ~VT_BOLD_COLOR_MASK) + 90); } else { fprintf(fp, "\x1b[38;5;%dm", fg_pixel); } if (bg_pixel < 0x8) { fprintf(fp, "\x1b[%dm", bg_pixel + 40); } else if (bg_pixel < 0x10) { fprintf(fp, "\x1b[%dm", (bg_pixel & ~VT_BOLD_COLOR_MASK) + 100); } else { fprintf(fp, "\x1b[48;5;%dm", bg_pixel); } if (line_style & LS_UNDERLINE_SINGLE) { fwrite("\x1b[4m", 1, 4, fp); } else if (line_style & LS_UNDERLINE_DOUBLE) { fwrite("\x1b[21m", 1, 5, fp); } if (line_style & LS_CROSSED_OUT) { fwrite("\x1b[9m", 1, 4, fp); } if (line_style & LS_OVERLINE) { fwrite("\x1b[53m", 1, 5, fp); } if (font & FONT_BOLD) { fwrite("\x1b[1m", 1, 4, fp); } if (font & FONT_ITALIC) { fwrite("\x1b[3m", 1, 4, fp); } if (size_attr == 0) { if (size_attr_set) { fwrite("\x1b#5", 1, 3, fp); } } else { size_attr_set = 1; if (size_attr == DOUBLE_WIDTH) { fwrite("\x1b#6", 1, 3, fp); } else if (size_attr == DOUBLE_HEIGHT_TOP) { fwrite("\x1b#3", 1, 3, fp); } else /* if (size_attr == DOUBLE_HEIGHT_BOTTOM) */ { fwrite("\x1b#4", 1, 3, fp); } } } static void draw_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, /* must be NULL if wall_picture_bg is 1 */ int x, int y, u_char *str, /* 'len * ch_len' bytes */ u_int len, u_int ch_len, int line_style) { u_char *str2; if (!win->is_mapped) { return; } if ((ch_len != 1 || str[0] >= 0x80) && (str2 = alloca(len * UTF_MAX_SIZE))) { ef_parser_t *parser; ef_charset_t cs; if ((cs = FONT_CS(font->id)) == ISO10646_UCS4_1) { if (!utf16_parser) { utf16_parser = ef_utf16_parser_new(); } parser = utf16_parser; (*parser->init)(parser); (*parser->set_str)(parser, str, len * ch_len); } else { if (!cp_parser) { cp_parser = ef_codepoint_parser_new(); } parser = cp_parser; (*parser->init)(parser); /* 3rd argument of parser->set_str is len(16bit) + cs(16bit) */ (*parser->set_str)(parser, str, (len * ch_len) | (cs << 16)); } (*win->disp->display->conv->init)(win->disp->display->conv); if ((len = (*win->disp->display->conv->convert)(win->disp->display->conv, str2, len *UTF_MAX_SIZE, parser)) > 0) { str = str2; } } else { /* * XXX * Padding white space by font->x_off is processed only if ch_len == 1 for now. * font->x_off is calculated by the right-justified in ui_font.c. */ if (font->x_off >= font->width / 2) { if ((str2 = alloca(len * 2))) { u_int count; for (count = 0; count < len; count++) { str2[count * 2] = str[count]; str2[count * 2 + 1] = ' '; } len *= 2; str = str2; } } len *= ch_len; } fprintf(win->disp->display->fp, "\x1b[%d;%dH", (win->y + win->vmargin + y) / LINE_HEIGHT + 1 + (font->size_attr == DOUBLE_HEIGHT_BOTTOM ? 1 : 0), (win->x + win->hmargin + x) / COL_WIDTH + 1); set_attr(win->disp->display->fp, font->id, fg_color->pixel, bg_color->pixel, line_style, font->size_attr); fwrite(str, 1, len, win->disp->display->fp); fwrite("\x1b[m", 1, 3, win->disp->display->fp); fflush(win->disp->display->fp); } #ifdef USE_LIBSIXEL static int copy_area(ui_window_t *win, Pixmap src, int src_x, /* can be minus */ int src_y, /* can be minus */ u_int width, u_int height, int dst_x, /* can be minus */ int dst_y, /* can be minus */ int accept_margin /* x/y can be minus and over width/height */ ) { int hmargin; int vmargin; int right_margin; int bottom_margin; u_char *picture; if (!win->is_mapped) { return 0; } #if 0 if (accept_margin) #endif { hmargin = win->hmargin; vmargin = win->vmargin; right_margin = bottom_margin = 0; } #if 0 else { hmargin = vmargin = 0; right_margin = RIGHT_MARGIN(win); bottom_margin = BOTTOM_MARGIN(win); } #endif if (width == 0 || height == 0) { /* This can happen in setting a wall paper. */ return 0; } if (dst_x >= (int)win->width + hmargin - right_margin || dst_y >= (int)win->height + vmargin - bottom_margin) { return 0; } if (dst_x + width > win->width + hmargin - right_margin) { width = win->width + hmargin - right_margin - dst_x; } if (dst_y + height > win->height + vmargin - bottom_margin) { height = win->height + vmargin - bottom_margin - dst_y; } picture = src->image + src->width * 4 * (vmargin + src_y) + 4 * (hmargin + src_x); if (width < src->width) { u_char *clip; u_char *p; size_t line_len; line_len = width * 4; if ((p = clip = calloc(line_len, height))) { u_int count; for (count = 0; count < height; count++) { memcpy(p, picture, line_len); p += line_len; picture += (src->width * 4); } picture = clip; } } fprintf(win->disp->display->fp, "\x1b[%d;%dH", (win->y + win->vmargin + dst_y) / LINE_HEIGHT + 1, (win->x + win->hmargin + dst_x) / COL_WIDTH + 1); ui_display_output_picture(win->disp, picture, width, height); fflush(win->disp->display->fp); if (width < src->width) { free(picture); } return 1; } #else #define copy_area(win, src, src_x, src_y, width, height, dst_x, dst_y, accept_margin) (0) #endif static void clear_margin_area(ui_window_t *win) { u_int right_margin; u_int bottom_margin; right_margin = RIGHT_MARGIN(win); bottom_margin = BOTTOM_MARGIN(win); if (win->hmargin | win->vmargin | right_margin | bottom_margin) { ui_window_clear(win, -(win->hmargin), -(win->vmargin), win->hmargin, ACTUAL_HEIGHT(win)); ui_window_clear(win, 0, -(win->vmargin), win->width, win->vmargin); ui_window_clear(win, win->width - right_margin, -(win->vmargin), win->hmargin + right_margin, ACTUAL_HEIGHT(win)); ui_window_clear(win, 0, win->height - bottom_margin, win->width, win->vmargin + bottom_margin); } /* XXX */ if (win->num_children == 2 && ACTUAL_HEIGHT(win->children[0]) == ACTUAL_HEIGHT(win->children[1])) { if (win->children[0]->x + ACTUAL_WIDTH(win->children[0]) <= win->children[1]->x) { ui_window_clear(win, win->children[0]->x + ACTUAL_WIDTH(win->children[0]), 0, win->children[1]->x - win->children[0]->x - ACTUAL_WIDTH(win->children[0]), win->height); } else if (win->children[0]->x >= win->children[1]->x + ACTUAL_WIDTH(win->children[1])) { ui_window_clear(win, win->children[1]->x + ACTUAL_WIDTH(win->children[1]), 0, win->children[0]->x - win->children[1]->x - ACTUAL_WIDTH(win->children[1]), win->height); } } } static int fix_rl_boundary(ui_window_t *win, int boundary_start, int *boundary_end) { int margin; margin = RIGHT_MARGIN(win); if (boundary_start > win->width - margin) { return 0; } if (*boundary_end > win->width - margin) { *boundary_end = win->width - margin; } return 1; } static void reset_input_focus(ui_window_t *win) { u_int count; if (win->inputtable) { win->inputtable = -1; } else { win->inputtable = 0; } if (win->is_focused) { win->is_focused = 0; if (win->window_unfocused) { (*win->window_unfocused)(win); } } for (count = 0; count < win->num_children; count++) { reset_input_focus(win->children[count]); } } #if 0 static int check_child_window_area(ui_window_t *win) { if (win->num_children > 0) { u_int count; u_int sum; for (sum = 0, count = 1; count < win->num_children; count++) { sum += (ACTUAL_WIDTH(win->children[count]) * ACTUAL_HEIGHT(win->children[count])); } if (sum < win->disp->width * win->disp->height * 0.9) { return 0; } } return 1; } #endif /* --- global functions --- */ int ui_window_init(ui_window_t *win, u_int width, u_int height, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc, u_int hmargin, u_int vmargin, int create_gc, int inputtable) { memset(win, 0, sizeof(ui_window_t)); /* If wall picture is set, scrollable will be 0. */ win->is_scrollable = 1; win->is_focused = 1; win->inputtable = inputtable; win->is_mapped = 1; win->create_gc = create_gc; win->width = width; win->height = height; win->min_width = min_width; win->min_height = min_height; win->width_inc = width_inc; win->height_inc = height_inc; win->sizehint_flag = SIZEHINT_WIDTH|SIZEHINT_HEIGHT; win->hmargin = 0 /* hmargin */; win->vmargin = 0 /* vmargin */; win->prev_clicked_button = -1; win->app_name = "mlterm"; /* Can be changed in ui_display_show_root(). */ return 1; } void ui_window_final(ui_window_t *win) { u_int count; for (count = 0; count < win->num_children; count++) { ui_window_final(win->children[count]); } free(win->children); ui_display_clear_selection(win->disp, win); if (win->window_finalized) { (*win->window_finalized)(win); } } void ui_window_set_type_engine(ui_window_t *win, ui_type_engine_t type_engine) {} void ui_window_add_event_mask(ui_window_t *win, long event_mask) { win->event_mask |= event_mask; } void ui_window_remove_event_mask(ui_window_t *win, long event_mask) { win->event_mask &= ~event_mask; } void ui_window_ungrab_pointer(ui_window_t *win) {} int ui_window_set_wall_picture(ui_window_t *win, Pixmap pic, int do_expose) { u_int count; win->wall_picture = pic; win->is_scrollable = 0; if (do_expose) { clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } #if 0 else { ui_window_clear_all(win); } #endif } for (count = 0; count < win->num_children; count++) { ui_window_set_wall_picture(win->children[count], ParentRelative, do_expose); } return 1; } int ui_window_unset_wall_picture(ui_window_t *win, int do_expose) { u_int count; win->wall_picture = None; win->is_scrollable = 1; if (do_expose) { clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } #if 0 else { ui_window_clear_all(win); } #endif } for (count = 0; count < win->num_children; count++) { ui_window_unset_wall_picture(win->children[count], do_expose); } return 1; } int ui_window_set_transparent( ui_window_t *win, /* Transparency is applied to all children recursively */ ui_picture_modifier_ptr_t pic_mod) { return 0; } int ui_window_unset_transparent(ui_window_t *win) { return 0; } void ui_window_set_cursor(ui_window_t *win, u_int cursor_shape) { win->cursor_shape = cursor_shape; } int ui_window_set_fg_color(ui_window_t *win, ui_color_t *fg_color) { if (win->fg_color.pixel == fg_color->pixel) { return 0; } win->fg_color = *fg_color; return 1; } int ui_window_set_bg_color(ui_window_t *win, ui_color_t *bg_color) { if (win->bg_color.pixel == bg_color->pixel) { return 0; } win->bg_color = *bg_color; clear_margin_area(win); return 1; } int ui_window_add_child(ui_window_t *win, ui_window_t *child, int x, int y, int map) { void *p; if (win->parent) { /* Can't add a grand child window. */ return 0; } if ((p = realloc(win->children, sizeof(*win->children) * (win->num_children + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } win->children = p; child->parent = win; child->x = x + win->hmargin; child->y = y + win->vmargin; if ((child->is_mapped = map) && win->is_focused && child->inputtable) { child->is_focused = 1; } else { child->is_focused = 0; if (child->inputtable > 0) { child->inputtable = -1; } } win->children[win->num_children++] = child; return 1; } int ui_window_remove_child(ui_window_t *win, ui_window_t *child) { u_int count; for (count = 0; count < win->num_children; count++) { if (win->children[count] == child) { child->parent = NULL; win->children[count] = win->children[--win->num_children]; return 1; } } return 0; } ui_window_t *ui_get_root_window(ui_window_t *win) { while (win->parent != NULL) { win = win->parent; } return win; } GC ui_window_get_fg_gc(ui_window_t *win) { return None; } GC ui_window_get_bg_gc(ui_window_t *win) { return None; } int ui_window_show(ui_window_t *win, int hint /* If win->parent(_window) is None, specify XValue|YValue to localte window at win->x/win->y. */ ) { u_int count; if (win->my_window) { /* already shown */ return 0; } if (win->parent) { win->disp = win->parent->disp; win->parent_window = win->parent->my_window; win->gc = win->parent->gc; } win->my_window = win; /* Note that ui_connect_dialog.c uses this. */ if (win->parent && !win->parent->is_transparent && win->parent->wall_picture) { ui_window_set_wall_picture(win, ParentRelative, 0); } /* * This should be called after Window Manager settings, because * ui_set_{window|icon}_name() can be called in win->window_realized(). */ if (win->window_realized) { int is_mapped; /* * Don't show anything until ui_window_resize_with_margin() is called * at the end of this function. */ is_mapped = win->is_mapped; win->is_mapped = 0; /* XXX ui_window_set_wall_picture() depends on this. */ (*win->window_realized)(win); win->is_mapped = is_mapped; } /* * showing child windows. */ for (count = 0; count < win->num_children; count++) { ui_window_show(win->children[count], 0); } if (!win->parent && win->x == 0 && win->y == 0) { ui_window_resize_with_margin(win, win->disp->width, win->disp->height, NOTIFY_TO_MYSELF); } return 1; } void ui_window_map(ui_window_t *win) { if (!win->is_mapped) { win->is_mapped = 1; (*win->window_exposed)(win, 0, 0, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); clear_margin_area(win); } } void ui_window_unmap(ui_window_t *win) { win->is_mapped = 0; } int ui_window_resize(ui_window_t *win, u_int width, /* excluding margin */ u_int height, /* excluding margin */ ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */ ) { if ((flag & NOTIFY_TO_PARENT) && !IS_IM_WINDOW(win)) { if (win->parent) { win = win->parent; } /* * XXX * If Font size, screen_{width|height}_ratio or vertical_mode is changed * and ui_window_resize( NOTIFY_TO_PARENT) is called, ignore this call and * resize windows with display size. */ win->width = 0; return ui_window_resize_with_margin(win, win->disp->width, win->disp->height, NOTIFY_TO_MYSELF); } if (width + win->hmargin * 2 > win->disp->width) { width = win->disp->width - win->hmargin * 2; } if (height + win->vmargin * 2 > win->disp->height) { height = win->disp->height - win->vmargin * 2; } if (win->width == width && win->height == height) { return 0; } win->width = width; win->height = height; if (flag & NOTIFY_TO_MYSELF) { if (win->window_resized) { (*win->window_resized)(win); } /* * clear_margin_area() must be called after win->window_resized * because wall_picture can be resized to fit to the new window * size in win->window_resized. * * Don't clear_margin_area() if flag == 0 because ui_window_resize() * is called before ui_window_move() in ui_im_*_screen.c and could * cause segfault. */ clear_margin_area(win); } return 1; } /* * !! Notice !! * This function is not recommended. * Use ui_window_resize if at all possible. */ int ui_window_resize_with_margin(ui_window_t *win, u_int width, u_int height, ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */ ) { return ui_window_resize(win, width - win->hmargin * 2, height - win->vmargin * 2, flag); } void ui_window_set_maximize_flag(ui_window_t *win, ui_maximize_flag_t flag) {} void ui_window_set_normal_hints(ui_window_t *win, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc) {} void ui_window_set_override_redirect(ui_window_t *win, int flag) {} int ui_window_set_borderless_flag(ui_window_t *win, int flag) { return 0; } int ui_window_move(ui_window_t *win, int x, int y) { if (win->parent) { x += win->parent->hmargin; y += win->parent->vmargin; } if (win->x == x && win->y == y) { return 0; } win->x = x; win->y = y; if (/* ! check_child_window_area( ui_get_root_window( win)) || */ win->x + ACTUAL_WIDTH(win) > win->disp->width || win->y + ACTUAL_HEIGHT(win) > win->disp->height) { /* * XXX Hack * (Expect the caller to call ui_window_resize() immediately after this.) */ return 1; } /* * XXX * Check if win is input method window or not, because ui_window_move() * can fall into the following infinite loop on framebuffer. * 1) ui_im_stat_screen::draw_screen() -> * ui_window_move() -> * ui_im_stat_screen::window_exposed() -> * ui_im_stat_screen::draw_screen() * 2) ui_im_candidate_screen::draw_screen() -> * ui_im_candidate_screen::resize() -> * ui_window_move() -> * ui_im_candidate_screen::window_exposed() -> * ui_im_candidate_screen::draw_screen() */ if (!IS_IM_WINDOW(win)) { clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } #if 0 else { ui_window_clear_all(win); } #endif /* XXX */ if (win->parent) { clear_margin_area(win->parent); } } return 1; } void ui_window_clear(ui_window_t *win, int x, int y, u_int width, u_int height) { if (!win->wall_picture) { ui_window_fill_with(win, &win->bg_color, x, y, width, height); } else { Pixmap pic; int src_x; int src_y; if (win->wall_picture == ParentRelative) { src_x = x + win->x; src_y = y + win->y; pic = win->parent->wall_picture; } else { pic = win->wall_picture; src_x = x; src_y = y; } copy_area(win, pic, src_x, src_y, width, height, x, y, 1); } } void ui_window_clear_all(ui_window_t *win) { ui_window_clear(win, 0, 0, win->width, win->height); } void ui_window_fill(ui_window_t *win, int x, int y, u_int width, u_int height) { ui_window_fill_with(win, &win->fg_color, x, y, width, height); } void ui_window_fill_with(ui_window_t *win, ui_color_t *color, int x, int y, u_int width, u_int height) { u_int h; int fill_to_end; if (!win->is_mapped) { return; } if (height < LINE_HEIGHT || width < COL_WIDTH) { return; } if (!IS_IM_WINDOW(win) && (!win->parent || win->x + ACTUAL_WIDTH(win) >= win->parent->width) && x + width >= win->width) { fill_to_end = 1; } else { fill_to_end = 0; } x += (win->x + win->hmargin); y += (win->y + win->vmargin); if (color->pixel < 0x8) { fprintf(win->disp->display->fp, "\x1b[%dm", color->pixel + 40); } else if (color->pixel < 0x10) { fprintf(win->disp->display->fp, "\x1b[%dm", (color->pixel & ~VT_BOLD_COLOR_MASK) + 100); } else { fprintf(win->disp->display->fp, "\x1b[48;5;%dm", color->pixel); } #if 1 for (h = 0; h < height; h += LINE_HEIGHT) { fprintf(win->disp->display->fp, "\x1b[%d;%dH", (y + h) / LINE_HEIGHT + 1, x / COL_WIDTH + 1); if (fill_to_end) { fwrite("\x1b[K", 1, 3, win->disp->display->fp); } else { u_int w; for (w = 0; w < width; w += COL_WIDTH) { fwrite(" ", 1, 1, win->disp->display->fp); } } } #else fprintf(win->disp->display->fp, "\x1b[%d;%d;%d;%d$z", y / LINE_HEIGHT + 1, x / COL_WIDTH + 1, (y + height) / LINE_HEIGHT, (x + width) / COL_WIDTH); #endif fwrite("\x1b[m", 1, 3, win->disp->display->fp); fflush(win->disp->display->fp); } void ui_window_blank(ui_window_t *win) { ui_window_fill_with(win, &win->fg_color, 0, 0, win->width - RIGHT_MARGIN(win), win->height - BOTTOM_MARGIN(win)); } void ui_window_update(ui_window_t *win, int flag) { if (!win->is_mapped) { return; } if (win->update_window) { (*win->update_window)(win, flag); } } void ui_window_update_all(ui_window_t *win) { u_int count; if (!win->is_mapped) { return; } if (!win->parent) { ui_display_reset_cmap(); } clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } for (count = 0; count < win->num_children; count++) { ui_window_update_all(win->children[count]); } } void ui_window_idling(ui_window_t *win) { u_int count; for (count = 0; count < win->num_children; count++) { ui_window_idling(win->children[count]); } #ifdef __DEBUG if (win->button_is_pressing) { bl_debug_printf(BL_DEBUG_TAG " button is pressing...\n"); } #endif if (win->button_is_pressing && win->button_press_continued) { (*win->button_press_continued)(win, &win->prev_button_press_event); } else if (win->idling) { (*win->idling)(win); } } /* * Return value: 0 => different window. * 1 => finished processing. */ int ui_window_receive_event(ui_window_t *win, XEvent *event) { #if 0 u_int count; for (count = 0; count < win->num_children; count++) { if (ui_window_receive_event(win->children[count], event)) { return 1; } } #endif if (event->type == KeyPress) { if (win->key_pressed) { (*win->key_pressed)(win, &event->xkey); } } else if (event->type == MotionNotify) { if (win->button_is_pressing) { if (win->button_motion) { event->xmotion.x -= win->hmargin; event->xmotion.y -= win->vmargin; (*win->button_motion)(win, &event->xmotion); } /* following button motion ... */ win->prev_button_press_event.x = event->xmotion.x; win->prev_button_press_event.y = event->xmotion.y; win->prev_button_press_event.time = event->xmotion.time; } else if ((win->event_mask & PointerMotionMask) && win->pointer_motion) { event->xmotion.x -= win->hmargin; event->xmotion.y -= win->vmargin; (*win->pointer_motion)(win, &event->xmotion); } } else if (event->type == ButtonRelease) { if (win->button_released) { event->xbutton.x -= win->hmargin; event->xbutton.y -= win->vmargin; (*win->button_released)(win, &event->xbutton); } win->button_is_pressing = 0; } else if (event->type == ButtonPress) { if (win->button_pressed) { event->xbutton.x -= win->hmargin; event->xbutton.y -= win->vmargin; /* XXX If button is released outside screen, ButtonRelease event might not happen. */ if (win->button_is_pressing) { if (win->button_released) { XButtonEvent ev = event->xbutton; ev.type = ButtonRelease; (*win->button_released)(win, &ev); } win->button_is_pressing = 0; } if (win->click_num == MAX_CLICK) { win->click_num = 0; } if (win->prev_clicked_time + click_interval >= event->xbutton.time && event->xbutton.button == win->prev_clicked_button) { win->click_num++; win->prev_clicked_time = event->xbutton.time; } else { win->click_num = 1; win->prev_clicked_time = event->xbutton.time; win->prev_clicked_button = event->xbutton.button; } (*win->button_pressed)(win, &event->xbutton, win->click_num); } if (event->xbutton.button <= Button3) { /* button_is_pressing flag is on except wheel mouse (Button4/Button5). */ win->button_is_pressing = 1; win->prev_button_press_event = event->xbutton; } if (!win->is_focused && win->inputtable && event->xbutton.button == Button1 && !event->xbutton.state) { ui_window_set_input_focus(win); } } return 1; } size_t ui_window_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { u_char ch; if (seq_len == 0) { return 0; } *parser = NULL; ch = event->ksym; if ((*keysym = event->ksym) >= 0x100) { switch (*keysym) { case XK_KP_Multiply: ch = '*'; break; case XK_KP_Add: ch = '+'; break; case XK_KP_Separator: ch = ','; break; case XK_KP_Subtract: ch = '-'; break; case XK_KP_Divide: ch = '/'; break; default: if (win->disp->display->lock_state & NLKED) { switch (*keysym) { case XK_KP_Insert: ch = '0'; break; case XK_KP_End: ch = '1'; break; case XK_KP_Down: ch = '2'; break; case XK_KP_Next: ch = '3'; break; case XK_KP_Left: ch = '4'; break; case XK_KP_Begin: ch = '5'; break; case XK_KP_Right: ch = '6'; break; case XK_KP_Home: ch = '7'; break; case XK_KP_Up: ch = '8'; break; case XK_KP_Prior: ch = '9'; break; case XK_KP_Delete: ch = '.'; break; default: return 0; } *keysym = ch; } else { return 0; } } } else if (*keysym == XK_Tab && (event->state & ShiftMask)) { *keysym = XK_ISO_Left_Tab; return 0; } /* * Control + '@'(0x40) ... '_'(0x5f) -> 0x00 ... 0x1f * * Not "<= '_'" but "<= 'z'" because Control + 'a' is not * distinguished from Control + 'A'. */ if ((event->state & ControlMask) && (ch == ' ' || ('@' <= ch && ch <= 'z'))) { seq[0] = (ch & 0x1f); if (seq[0] == XK_BackSpace || seq[0] == XK_Tab || seq[0] == XK_Return) { *keysym = seq[0]; event->state &= ~ControlMask; } } else { seq[0] = ch; } return 1; } /* * Scroll functions. * The caller side should clear the scrolled area. */ int ui_window_scroll_upward(ui_window_t *win, u_int height) { return ui_window_scroll_upward_region(win, 0, win->height, height); } int ui_window_is_scrollable(ui_window_t *win) { /* XXX If input method module is activated, don't scroll window. */ if (win->is_scrollable && (win->disp->display->support_hmargin || win->disp->width == ACTUAL_WIDTH(win)) && !IM_WINDOW_IS_ACTIVATED(win->disp)) { return 1; } else { return 0; } } int ui_window_scroll_upward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height) { if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d in window((h) %d (w) %d)\n", boundary_start, boundary_end, height, win->height, win->width); #endif return 0; } return scroll_region(win, 0, boundary_start + height, /* src */ win->width, boundary_end - boundary_start - height, /* size */ 0, boundary_start); /* dst */ } int ui_window_scroll_downward(ui_window_t *win, u_int height) { return ui_window_scroll_downward_region(win, 0, win->height, height); } int ui_window_scroll_downward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height) { if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d\n", boundary_start, boundary_end, height); #endif return 0; } return scroll_region(win, 0, boundary_start, win->width, boundary_end - boundary_start - height, 0, boundary_start + height); } int ui_window_scroll_leftward(ui_window_t *win, u_int width) { return ui_window_scroll_leftward_region(win, 0, win->width, width); } int ui_window_scroll_leftward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width) { if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width || !fix_rl_boundary(win, boundary_start, &boundary_end)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d in window((h) %d (w) %d)\n", boundary_start, boundary_end, width, win->height, win->width); #endif return 0; } scroll_region(win, boundary_start + width, 0, /* src */ boundary_end - boundary_start - width, win->height, /* size */ boundary_start, 0); /* dst */ return 1; } int ui_window_scroll_rightward(ui_window_t *win, u_int width) { return ui_window_scroll_rightward_region(win, 0, win->width, width); } int ui_window_scroll_rightward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width) { if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width || !fix_rl_boundary(win, boundary_start, &boundary_end)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d\n", boundary_start, boundary_end, width); #endif return 0; } scroll_region(win, boundary_start, 0, boundary_end - boundary_start - width, win->height, boundary_start + width, 0); return 1; } int ui_window_copy_area(ui_window_t *win, Pixmap src, PixmapMask mask, int src_x, /* >= 0 */ int src_y, /* >= 0 */ u_int width, u_int height, int dst_x, /* >= 0 */ int dst_y /* >= 0 */ ) { return copy_area(win, src, src_x, src_y, width, height, dst_x, dst_y, 0); } void ui_window_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height) {} void ui_window_unset_clip(ui_window_t *win) {} void ui_window_console_draw_decsp_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, u_char *str, u_int len, int line_style) { if (!win->is_mapped) { return; } fprintf(win->disp->display->fp, "\x1b[%d;%dH", (win->y + win->vmargin + y) / LINE_HEIGHT + 1 + (font->size_attr == DOUBLE_HEIGHT_BOTTOM ? 1 : 0), (win->x + win->hmargin + x) / COL_WIDTH + 1); set_attr(win->disp->display->fp, font->id, fg_color->pixel, bg_color->pixel, line_style, font->size_attr); fwrite("\x1b(0", 1, 3, win->disp->display->fp); fwrite(str, 1, len, win->disp->display->fp); fwrite("\x1b(B\x1b[m", 1, 6, win->disp->display->fp); fflush(win->disp->display->fp); } void ui_window_console_draw_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, u_char *str, u_int len, int line_style) { draw_string(win, font, fg_color, bg_color, x, y, str, len, 1, line_style); } void ui_window_console_draw_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, XChar2b *str, u_int len, int line_style) { draw_string(win, font, fg_color, bg_color, x, y, str, len, 2, line_style); } void ui_window_draw_rect_frame(ui_window_t *win, int x1, int y1, int x2, int y2) { ui_window_fill_with(win, &win->fg_color, x1, y1, x2 - x1 + 1, 1); ui_window_fill_with(win, &win->fg_color, x1, y1, 1, y2 - y1 + 1); ui_window_fill_with(win, &win->fg_color, x1, y2, x2 - x1 + 1, 1); ui_window_fill_with(win, &win->fg_color, x2, y1, 1, y2 - y1 + 1); } void ui_set_use_clipboard_selection(int use_it) {} int ui_is_using_clipboard_selection(void) { return 0; } int ui_window_set_selection_owner(ui_window_t *win, Time time) { if (ui_window_is_selection_owner(win)) { /* Already owner */ return 1; } return ui_display_own_selection(win->disp, win); } int ui_window_xct_selection_request(ui_window_t *win, Time time) { u_int count; u_int num_displays; ui_display_t **displays = ui_get_opened_displays(&num_displays); for (count = 0; count < num_displays; count++) { if (displays[count]->selection_owner) { ui_window_t *owner = displays[count]->selection_owner; if (owner->xct_selection_requested) { XSelectionRequestEvent ev; ev.type = 0; ev.target = win; (*owner->xct_selection_requested)(owner, &ev, 0); } break; } } return 1; } int ui_window_utf_selection_request(ui_window_t *win, Time time) { u_int count; u_int num_displays; ui_display_t **displays = ui_get_opened_displays(&num_displays); for (count = 0; count < num_displays; count++) { if (displays[count]->selection_owner) { ui_window_t *owner = displays[count]->selection_owner; if (owner->utf_selection_requested) { XSelectionRequestEvent ev; ev.type = 1; ev.target = win; (*owner->utf_selection_requested)(owner, &ev, 0); } break; } } return 1; } void ui_window_send_picture_selection(ui_window_t *win, Pixmap pixmap, u_int width, u_int height) {} void ui_window_send_text_selection(ui_window_t *win, XSelectionRequestEvent *req_ev, u_char *sel_data, size_t sel_len, Atom sel_type) { if (req_ev) { if (req_ev->type == 1) { if (req_ev->target->utf_selection_notified) { (*req_ev->target->utf_selection_notified)(req_ev->target, sel_data, sel_len); } } else { if (req_ev->target->xct_selection_notified) { (*req_ev->target->xct_selection_notified)(req_ev->target, sel_data, sel_len); } } } } void ui_set_window_name(ui_window_t *win, u_char *name) { vt_char_encoding_t encoding; ef_parser_t *parser; if (name == NULL) { name = win->app_name; } /* See parse_title() in vt_parser.c */ if ((encoding = vt_get_char_encoding("auto")) == VT_UTF8) { fwrite("\x1b[>2t\x1b]2;", 1, 9, win->disp->display->fp); fwrite(name, 1, strlen(name), win->disp->display->fp); fwrite("\x07\x1b[>2T", 1, 6, win->disp->display->fp); } else if ((parser = vt_char_encoding_parser_new(encoding))) { u_char buf[64]; size_t len; (*win->disp->display->conv->init)(win->disp->display->conv); (*parser->init)(parser); (*parser->set_str)(parser, name, strlen(name)); fwrite("\x1b]2;", 1, 4, win->disp->display->fp); while ((len = (*win->disp->display->conv->convert)(win->disp->display->conv, buf, sizeof(buf), parser)) > 0) { fwrite(buf, 1, len, win->disp->display->fp); } fwrite("\x07", 1, 1, win->disp->display->fp); (*parser->destroy)(parser); } } void ui_set_icon_name(ui_window_t *win, u_char *name) { vt_char_encoding_t encoding; ef_parser_t *parser; if (name == NULL) { name = win->app_name; } if ((encoding = vt_get_char_encoding("auto")) == VT_UTF8) { fwrite("\x1b[>2t\x1b]1;", 1, 9, win->disp->display->fp); fwrite(name, 1, strlen(name), win->disp->display->fp); fwrite("\x07\x1b[>2T", 1, 6, win->disp->display->fp); } else if ((parser = vt_char_encoding_parser_new(encoding))) { u_char buf[64]; size_t len; (*win->disp->display->conv->init)(win->disp->display->conv); (*parser->init)(parser); (*parser->set_str)(parser, name, strlen(name)); fwrite("\x1b]1;", 1, 4, win->disp->display->fp); while ((len = (*win->disp->display->conv->convert)(win->disp->display->conv, buf, sizeof(buf), parser)) > 0) { fwrite(buf, 1, len, win->disp->display->fp); } fwrite("\x07", 1, 1, win->disp->display->fp); (*parser->destroy)(parser); } } void ui_window_set_icon(ui_window_t *win, ui_icon_picture_ptr_t icon) {} void ui_window_remove_icon(ui_window_t *win) {} void ui_window_reset_group(ui_window_t *win) {} void ui_set_click_interval(int interval) { click_interval = interval; } int ui_get_click_interval(void) { return click_interval; } u_int ui_window_get_mod_ignore_mask(ui_window_t *win, KeySym *keysyms) { return ~0; } u_int ui_window_get_mod_meta_mask(ui_window_t *win, char *mod_key) { return ModMask; } void ui_window_bell(ui_window_t *win, ui_bel_mode_t mode) { if (mode & BEL_VISUAL) { ui_window_blank(win); bl_usleep(100000); /* 100 mili sec */ (*win->window_exposed)(win, 0, 0, win->width, win->height); } if (mode & BEL_SOUND) { fwrite("\x07", 1, 1, win->disp->display->fp); } } void ui_window_translate_coordinates(ui_window_t *win, int x, int y, int *global_x, int *global_y) { *global_x = x + win->x; *global_y = y + win->y; } void ui_window_set_input_focus(ui_window_t *win) { reset_input_focus(ui_get_root_window(win)); win->inputtable = win->is_focused = 1; if (win->window_focused) { (*win->window_focused)(win); } } /* for ui_display.c */ void ui_window_clear_margin_area(ui_window_t *win) { clear_margin_area(win); } mlterm-3.8.9/uitoolkit/console/ui.c012075500017600000144000000000001356600660700177412../win32/ui.custar kenusersmlterm-3.8.9/uitoolkit/beos004075500017600000144000000000001356600660700144415ustar kenusersmlterm-3.8.9/uitoolkit/beos/ui_xic.c010064400017600000144000000046751356600660700161550ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_xic.h" #include #include #include /* malloc */ /* --- global functions --- */ int ui_xic_activate(ui_window_t *win, char *xim_name, char *xim_locale) { if (win->xic) { /* already activated */ return 0; } if ((win->xic = malloc(sizeof(ui_xic_t))) == NULL) { return 0; } if ((win->xic->parser = vt_char_encoding_parser_new(VT_UTF8)) == NULL) { free(win->xic); win->xic = NULL; return 0; } ui_xic_font_set_changed(win); return 1; } int ui_xic_deactivate(ui_window_t *win) { if (win->xic == NULL) { /* already deactivated */ return 0; } (*win->xic->parser->destroy)(win->xic->parser); free(win->xic); win->xic = NULL; return 1; } char *ui_xic_get_xim_name(ui_window_t *win) { return ""; } char *ui_xic_get_default_xim_name(void) { return ""; } int ui_xic_fg_color_changed(ui_window_t *win) { return 0; } int ui_xic_bg_color_changed(ui_window_t *win) { return 0; } int ui_xic_font_set_changed(ui_window_t *win) { return 0; } int ui_xic_resized(ui_window_t *win) { return 0; } int ui_xic_set_spot(ui_window_t *win) { return 0; } size_t ui_xic_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { *keysym = event->keysym; if (event->utf8 == NULL) { *parser = NULL; return 0; } else { size_t len = strlen(event->utf8); if (len == 0 && (event->state & ControlMask)) { *seq = '\0'; len = 1; *parser = NULL; } else if (len <= seq_len) { memcpy(seq, event->utf8, seq_len); *parser = win->xic->parser; } return len; } } size_t ui_xic_get_utf8_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { return 0; } int ui_xic_filter_event(ui_window_t *win, /* Should be root window. */ XEvent *event) { return 0; } int ui_xic_set_focus(ui_window_t *win) { return 1; } int ui_xic_unset_focus(ui_window_t *win) { return 1; } int ui_xic_is_active(ui_window_t *win) { return 0; } int ui_xic_switch_mode(ui_window_t *win) { return 0; } #if 0 /* * ui_xim.c <-> ui_xic.c communication functions * Not necessary in fb. */ int ui_xim_activated(ui_window_t *win) { return 1; } int ui_xim_destroyed(ui_window_t *win) { return 1; } #endif mlterm-3.8.9/uitoolkit/beos/beos.h010064400017600000144000000057261356600660700156300ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __BEOS_H__ #define __BEOS_H__ #include #ifdef __UI_WINDOW_H__ /* for BView */ void view_alloc(ui_window_t *uiwindow, int x, int y, u_int width, u_int height); void view_dealloc(void *view); void view_update(void *view, int force_expose); void view_set_clip(void *view, int x, int y, u_int width, u_int height); void view_unset_clip(void *view); void view_draw_string(void *view, ui_font_t *font, ui_color_t *fg_color, int x, int y, char *str, size_t len); void view_draw_string16(void *view, ui_font_t *font, ui_color_t *fg_color, int x, int y, XChar2b *str, size_t len); void view_fill_with(void *view, ui_color_t *color, int x, int y, u_int width, u_int height); void view_draw_rect_frame(void *view, ui_color_t *color, int x1, int y1, int x2, int y2); void view_copy_area(void *view, Pixmap src, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y); void view_scroll(void *view, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y); void view_bg_color_changed(void *view); void view_visual_bell(void *view); void view_set_input_focus(void *view); void view_resize(void *view, u_int width, u_int height); void view_move(void *view, int x, int y); void view_set_hidden(void *view, int flag); void view_reset_uiwindow(ui_window_t *uiwindow); /* for BWindow */ void window_alloc(ui_window_t *root, int x, int y, u_int width, u_int height, int popup); void window_show(void *window); void window_dealloc(void *window); void window_move(void *window, int x, int y); void window_resize(void *window, int width, int height); void window_get_position(void *window, int *x, int *y); void window_set_title(void *window, const char *title); void *window_get_orphan(void *window, int idx); /* for BApplication */ void app_urgent_bell(int on); /* for Clipboard */ void beos_clipboard_set(const u_char *utf8, size_t len); int beos_clipboard_get(u_char **utf8, size_t *len); void beos_beep(void); #endif /* __UI_WINDOW_H__ */ void *beos_create_font(const char *font_family, float size, int is_italic, int is_bold); char *beos_get_font_path(void *bfont); void beos_release_font(void *bfont); void beos_font_get_metrics(void *bfont, u_int *width, u_int *height, u_int *ascent); u_int beos_font_get_advance(void *bfont, int size_attr, u_int16_t *utf16, u_int len, u_int32_t glyph); void *beos_create_image(const void *data, u_int len, u_int width, u_int height); void beos_destroy_image(void *bitmap); void *beos_load_image(const char *path, u_int *width, u_int *height); void *beos_resize_image(void *bitmap, u_int width, u_int height); u_char *beos_get_bits(void *bitmap); /* Utility */ char *beos_dialog_password(const char *msg); int beos_dialog_okcancel(const char *msg); int beos_dialog_alert(const char *msg); void beos_lock(void); void beos_unlock(void); #endif mlterm-3.8.9/uitoolkit/beos/ui.c012075500017600000144000000000001356600660700172272../win32/ui.custar kenusersmlterm-3.8.9/uitoolkit/beos/ui.h010064400017600000144000000246021356600660700153070ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_H__ #define ___UI_H__ #ifndef _INTERFACE_DEFS_H /* InterfaceDefs.h */ enum { B_BACKSPACE = 0x08, B_RETURN = 0x0a, B_ENTER = 0x0a, B_SPACE = 0x20, B_TAB = 0x09, B_ESCAPE = 0x1b, B_SUBSTITUTE = 0x1a, B_LEFT_ARROW = 0x1c, B_RIGHT_ARROW = 0x1d, B_UP_ARROW = 0x1e, B_DOWN_ARROW = 0x1f, B_INSERT = 0x05, B_DELETE = 0x7f, B_HOME = 0x01, B_END = 0x04, B_PAGE_UP = 0x0b, B_PAGE_DOWN = 0x0c, B_FUNCTION_KEY = 0x10, /* for Japanese and Korean keyboards */ B_KATAKANA_HIRAGANA = 0xf2, B_HANKAKU_ZENKAKU = 0xf3, B_HANGUL = 0xf0, B_HANGUL_HANJA = 0xf1 }; enum { B_F1_KEY = 0x02, B_F2_KEY = 0x03, B_F3_KEY = 0x04, B_F4_KEY = 0x05, B_F5_KEY = 0x06, B_F6_KEY = 0x07, B_F7_KEY = 0x08, B_F8_KEY = 0x09, B_F9_KEY = 0x0a, B_F10_KEY = 0x0b, B_F11_KEY = 0x0c, B_F12_KEY = 0x0d, B_PRINT_KEY = 0x0e, B_SCROLL_KEY = 0x0f, B_PAUSE_KEY = 0x10 }; enum { B_SHIFT_KEY = 0x00000001, B_COMMAND_KEY = 0x00000002, B_CONTROL_KEY = 0x00000004, B_CAPS_LOCK = 0x00000008, B_SCROLL_LOCK = 0x00000010, B_NUM_LOCK = 0x00000020, B_OPTION_KEY = 0x00000040, B_MENU_KEY = 0x00000080, B_LEFT_SHIFT_KEY = 0x00000100, B_RIGHT_SHIFT_KEY = 0x00000200, B_LEFT_COMMAND_KEY = 0x00000400, B_RIGHT_COMMAND_KEY = 0x00000800, B_LEFT_CONTROL_KEY = 0x00001000, B_RIGHT_CONTROL_KEY = 0x00002000, B_LEFT_OPTION_KEY = 0x00004000, B_RIGHT_OPTION_KEY = 0x00008000 }; #endif typedef struct { int fd; } Display; typedef int XIC; typedef int XID; typedef void *Window; /* BView/BWindow */ typedef void *Drawable; typedef void *Pixmap; /* BBitmap */ typedef void *PixmapMask; typedef int GC; typedef void *Font; /* BFont */ typedef int Cursor; typedef int KeyCode; typedef int KeySym; typedef struct /* Same as definition in X11/X.h */ { int max_keypermod; KeyCode *modifiermap; } XModifierKeymap; typedef struct /* Same as definition in X11/X.h */ { unsigned char byte1; unsigned char byte2; } XChar2b; #define UI_FOCUS_IN 1 #define UI_FOCUS_OUT 2 #define UI_BUTTON_PRESS 3 #define UI_BUTTON_RELEASE 4 #define UI_BUTTON_MOTION 5 #define UI_KEY_PRESS 6 #define UI_EXPOSE 7 #define UI_SELECTION_REQUESTED 8 #define UI_CLOSE_WINDOW 9 #define UI_KEY_FOCUS_IN 10 #define UI_SELECTION_NOTIFIED 11 #define UI_POINTER_MOTION 12 #define UI_RESIZE 13 typedef struct { int type; } XEvent; typedef struct { int type; unsigned int state; KeySym keysym; const char *utf8; } XKeyEvent; typedef unsigned long Time; /* Same as definition in X11/X.h */ typedef unsigned long Atom; /* Same as definition in X11/X.h */ typedef struct { int type; int time; int x; int y; unsigned int state; unsigned int button; int click_count; } XButtonEvent; typedef struct { int type; int time; int x; int y; unsigned int state; } XMotionEvent; typedef struct { int type; int x; int y; unsigned int width; unsigned int height; int force_expose; } XExposeEvent; typedef struct { int type; void *sender; } XSelectionRequestEvent; typedef struct { int type; char *data; unsigned int len; } XSelectionNotifyEvent; typedef struct { Font fid; } XFontStruct; typedef int XFontSet; /* dummy */ #define None 0L /* Same as definition in X11/X.h */ #define NoSymbol 0L /* Same as definition in X11/X.h */ #define CurrentTime 0L /* Same as definition in X11/X.h */ /* Same as definition in X11/X.h */ #define NoEventMask 0L #define KeyPressMask (1L << 0) #define KeyReleaseMask (1L << 1) #define ButtonPressMask (1L << 2) #define ButtonReleaseMask (1L << 3) #define EnterWindowMask (1L << 4) #define LeaveWindowMask (1L << 5) #define PointerMotionMask (1L << 6) #define PointerMotionHintMask (1L << 7) #define Button1MotionMask (1L << 8) #define Button2MotionMask (1L << 9) #define Button3MotionMask (1L << 10) #define Button4MotionMask (1L << 11) #define Button5MotionMask (1L << 12) #define ButtonMotionMask (1L << 13) #define KeymapStateMask (1L << 14) #define ExposureMask (1L << 15) #define VisibilityChangeMask (1L << 16) #define StructureNotifyMask (1L << 17) #define ResizeRedirectMask (1L << 18) #define SubstructureNotifyMask (1L << 19) #define SubstructureRedirectMask (1L << 20) #define FocusChangeMask (1L << 21) #define PropertyChangeMask (1L << 22) #define ColormapChangeMask (1L << 23) #define OwnerGrabButtonMask (1L << 24) #define ShiftMask B_SHIFT_KEY #define LockMask 0 #define ControlMask B_CONTROL_KEY #define Mod1Mask B_MENU_KEY #define Mod2Mask 0 #define Mod3Mask 0 #define Mod4Mask 0 #define Mod5Mask 0 #define CommandMask B_COMMAND_KEY #define Button1Mask 0 #define Button2Mask 0 #define Button3Mask 0 #define Button4Mask 0 #define Button5Mask 0 #define Button1 1 #define Button2 2 #define Button3 3 #define Button4 4 #define Button5 5 #define XK_Super_L 0xfffe /* dummy */ #define XK_Super_R 0xfffd /* dummy */ #define XK_Hyper_L 0xfffc /* dummy */ #define XK_Hyper_R 0xfffb /* dummy */ #define XK_BackSpace B_BACKSPACE #define XK_Tab B_TAB #define XK_Clear 0xfffa /* dummy */ #define XK_Linefeed 0xfff9 /* dummy */ #define XK_Return B_RETURN #define XK_Shift_L 0xfff8 /* dummy */ #define XK_Control_L 0xfff7 /* dummy */ #define XK_Alt_L 0xfff6 /* dummy */ #define XK_Shift_R 0xfff5 /* dummy */ #define XK_Control_R 0xfff4 /* dummy */ #define XK_Alt_R 0xfff3 /* dummy */ #define XK_Meta_L 0xfff2 /* dummy */ #define XK_Meta_R 0xfff1 /* dummy */ #define XK_Pause (B_PAUSE_KEY | 0xf000) #define XK_Shift_Lock 0xfff0 /* dummy */ #define XK_Caps_Lock 0xffef /* dummy */ #define XK_Escape B_ESCAPE #define XK_Prior (B_PAGE_UP | 0xe000) #define XK_Next (B_PAGE_DOWN | 0xe000) #define XK_End (B_END | 0xe000) #define XK_Home (B_HOME | 0xe000) #define XK_Left (B_LEFT_ARROW | 0xe000) #define XK_Up (B_UP_ARROW | 0xe000) #define XK_Right (B_RIGHT_ARROW | 0xe000) #define XK_Down (B_DOWN_ARROW | 0xe000) #define XK_Select 0xffee /* dummy */ #define XK_Print (B_PRINT_KEY | 0xf000) #define XK_Execute 0xffed /* dummy */ #define XK_Insert (B_INSERT | 0xe000) #define XK_Delete (B_DELETE | 0xe000) #define XK_Help 0xffec /* dummy */ #define XK_F1 (B_F1_KEY | 0xf000) #define XK_F2 (B_F2_KEY | 0xf000) #define XK_F3 (B_F3_KEY | 0xf000) #define XK_F4 (B_F4_KEY | 0xf000) #define XK_F5 (B_F5_KEY | 0xf000) #define XK_F6 (B_F6_KEY | 0xf000) #define XK_F7 (B_F7_KEY | 0xf000) #define XK_F8 (B_F8_KEY | 0xf000) #define XK_F9 (B_F9_KEY | 0xf000) #define XK_F10 (B_F10_KEY | 0xf000) #define XK_F11 (B_F11_KEY | 0xf000) #define XK_F12 (B_F12_KEY | 0xf000) #define XK_F13 0xffeb /* dummy */ #define XK_F14 0xffea /* dummy */ #define XK_F15 0xffe9 /* dummy */ #define XK_F16 0xffe8 /* dummy */ #define XK_F17 0xffe7 /* dummy */ #define XK_F18 0xffe6 /* dummy */ #define XK_F19 0xffe5 /* dummy */ #define XK_F20 0xffe4 /* dummy */ #define XK_F21 0xffe3 /* dummy */ #define XK_F22 0xffe2 /* dummy */ #define XK_F23 0xffe1 /* dummy */ #define XK_F24 0xffe0 /* dummy */ #define XK_FMAX XK_F12 #define XK_Num_Lock 0xffdf /* dummy */ #define XK_Scroll_Lock 0xffde /* dummy */ #define XK_Find 0xffdd /* dummy */ #define XK_Menu 0xffdc /* dummy */ #define XK_Begin 0xffdb /* dummy */ #define XK_Muhenkan 0xffda /* dummy */ #define XK_Henkan_Mode B_KATAKANA_HIRAGANA #define XK_Zenkaku_Hankaku B_HANKAKU_ZENKAKU #define XK_KP_Prior 0xffd9 /* dummy */ #define XK_KP_Next 0xffd8 /* dummy */ #define XK_KP_End 0xffd7 /* dummy */ #define XK_KP_Home 0xffd6 /* dummy */ #define XK_KP_Left 0xffd5 /* dummy */ #define XK_KP_Up 0xffd4 /* dummy */ #define XK_KP_Right 0xffd3 /* dummy */ #define XK_KP_Down 0xffd2 /* dummy */ #define XK_KP_Insert 0xffd1 /* dummy */ #define XK_KP_Delete 0xffd0 /* dummy */ #define XK_KP_F1 0xffcf /* dummy */ #define XK_KP_F2 0xffce /* dummy */ #define XK_KP_F3 0xffcd /* dummy */ #define XK_KP_F4 0xffcc /* dummy */ #define XK_KP_Begin 0xffcb /* dummy */ #define XK_KP_Multiply 0xffca /* dummy */ #define XK_KP_Add 0xffc9 /* dummy */ #define XK_KP_Separator 0xffc8 /* dummy */ #define XK_KP_Subtract 0xffc7 /* dummy */ #define XK_KP_Decimal 0xffc6 /* dummy */ #define XK_KP_Divide 0xffc5 /* dummy */ #define XK_KP_0 0xffc4 /* dummy */ #define XK_KP_1 0xffc3 /* dummy */ #define XK_KP_2 0xffc2 /* dummy */ #define XK_KP_3 0xffc1 /* dummy */ #define XK_KP_4 0xffc0 /* dummy */ #define XK_KP_5 0xffbf /* dummy */ #define XK_KP_6 0xffbe /* dummy */ #define XK_KP_7 0xffbd /* dummy */ #define XK_KP_8 0xffbc /* dummy */ #define XK_KP_9 0xffbb /* dummy */ #define IsKeypadKey(ksym) (0) #define IsModifierKey(ksym) (0) #define XK_ISO_Left_Tab 0xffba /* dummy */ /* XPoint(short x, short y) in Xlib. POINT(float x, float y) in win32. */ typedef struct { short x; short y; } XPoint; /* XXX dummy */ #define XKeysymToKeycode(disp, ks) (ks) #define XKeycodeToKeysym(disp, kc, i) (kc) #define XKeysymToString(ks) "" #define DefaultScreen(disp) (0) #define BlackPixel(disp, screen) (0xff000000) #define WhitePixel(disp, screen) (0xffffffff) /* Same as definition in X11/cursorfont.h */ #define XC_xterm 152 #define XC_left_ptr 68 /* Same as definition in X11/Xutil.h */ #define NoValue 0x0000 #define XValue 0x0001 #define YValue 0x0002 #define WidthValue 0x0004 #define HeightValue 0x0008 #define AllValues 0x000F #define XNegative 0x0010 #define YNegative 0x0020 int XParseGeometry(char *str, int *x, int *y, unsigned int *width, unsigned int *height); KeySym XStringToKeysym(char *str); /* === Platform dependent options === */ #undef UI_COLOR_HAS_RGB #undef SUPPORT_TRUE_TRANSPARENT_BG #define TYPE_XCORE_SCALABLE #undef MANAGE_ROOT_WINDOWS_BY_MYSELF #undef MANAGE_SUB_WINDOWS_BY_MYSELF #undef INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS #define SUPPORT_POINT_SIZE_FONT #define XIM_SPOT_IS_LINE_TOP #undef USE_GC #undef CHANGEABLE_CURSOR #undef PLUGIN_MODULE_SUFFIX #undef KEY_REPEAT_BY_MYSELF #undef ROTATABLE_DISPLAY #undef PSEUDO_COLOR_DISPLAY #undef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE #define SUPPORT_URGENT_BELL #define FORCE_UNICODE #undef NEED_DISPLAY_SYNC_EVERY_TIME #undef DRAW_SCREEN_IN_PIXELS #define NO_DRAW_IMAGE_STRING /* libpthread is not linked to mlterm explicitly for now. */ #undef HAVE_PTHREAD #undef COMPOSE_DECSP_FONT #undef USE_REAL_VERTICAL_FONT #undef NO_DISPLAY_FD #undef FLICK_SCROLL #define UIWINDOW_SUPPORTS_PREEDITING #endif mlterm-3.8.9/uitoolkit/beos/ui_color.c012075500017600000144000000000001356600660700222072../quartz/ui_color.custar kenusersmlterm-3.8.9/uitoolkit/beos/ui_connect_dialog.c010064400017600000144000000023241356600660700203270ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ /* Note that protocols except ssh aren't supported if USE_LIBSSH2 is defined. */ #ifdef USE_LIBSSH2 #include "../ui_connect_dialog.h" #include #include /* strdup */ #include /* alloca */ #include "beos.h" /* --- global functions --- */ int ui_connect_dialog(char **uri, /* Should be free'ed by those who call this. */ char **pass, /* Same as uri. If pass is not input, "" is set. */ char **exec_cmd, /* Same as uri. If exec_cmd is not input, NULL is set. */ char **privkey, /* in/out */ int *x11_fwd, /* in/out */ char *display_name, Window parent_window, char *def_server /* (@)(:)(:). */) { char *msg; if (!(*uri = strdup(def_server))) { return 0; } if ((msg = alloca(19 + strlen(*uri) + 1))) { char *p; sprintf(msg, "Enter password for %s", *uri); if ((p = beos_dialog_password(msg))) { *pass = p; *exec_cmd = NULL; return 1; } } free(*uri); *uri = NULL; return 0; } #endif mlterm-3.8.9/uitoolkit/beos/ui_display.c010064400017600000144000000107541356600660700170320ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_display.h" #include /* NULL */ #include /* getenv */ #include /* USE_WIN32API */ #include #include #include #include #include "ui.h" #include "../ui_window.h" #include "../ui_picture.h" #include "beos.h" #define DISP_IS_INITED (_disp.display) #if 0 #define __DEBUG #endif /* --- static variables --- */ static ui_display_t _disp; /* Singleton */ static Display _display; static ui_display_t *opened_disp = &_disp; /* --- static functions --- */ static int dialog_cb(bl_dialog_style_t style, const char *msg) { if (style == BL_DIALOG_OKCANCEL) { return beos_dialog_okcancel(msg); } else if (style == BL_DIALOG_ALERT) { return beos_dialog_alert(msg); } else { return -1; } } /* --- global functions --- */ ui_display_t *ui_display_open(char *disp_name, /* Ignored */ u_int depth /* Ignored */ ) { if (DISP_IS_INITED) { /* Already opened. */ return &_disp; } /* Callback should be set before bl_dialog() is called. */ bl_dialog_set_callback(dialog_cb); /* _disp.width and _disp.height are set in viewDidMoveToWindow */ _disp.depth = 32; if (!(_disp.name = getenv("DISPLAY"))) { _disp.name = ":0.0"; } /* _disp is initialized successfully. */ _display.fd = -1; _disp.display = &_display; return &_disp; } void ui_display_close(ui_display_t *disp) { if (disp == &_disp) { ui_display_close_all(); } } void ui_display_close_all(void) { u_int count; if (!DISP_IS_INITED) { return; } ui_picture_display_closed(_disp.display); ui_gc_destroy(_disp.gc); for (count = 0; count < _disp.num_roots; count++) { ui_window_unmap(_disp.roots[count]); ui_window_final(_disp.roots[count]); } free(_disp.roots); _disp.display = NULL; } ui_display_t **ui_get_opened_displays(u_int *num) { #if 0 if (!DISP_IS_INITED) { *num = 0; return NULL; } *num = 1; return &opened_disp; #else *num = 0; return NULL; #endif } int ui_display_fd(ui_display_t *disp) { return disp->display->fd; } int ui_display_show_root(ui_display_t *disp, ui_window_t *root, int x, int y, int hint, char *app_name, Window parent_window /* Ignored */ ) { void *p; if ((p = realloc(disp->roots, sizeof(ui_window_t*) * (disp->num_roots + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } disp->roots = p; root->disp = disp; root->parent = NULL; root->parent_window = disp->my_window; root->gc = disp->gc; root->x = x; root->y = y; if (app_name) { root->app_name = app_name; } disp->roots[disp->num_roots++] = root; return ui_window_show(root, hint); } int ui_display_remove_root(ui_display_t *disp, ui_window_t *root) { u_int count; for (count = 0; count < disp->num_roots; count++) { if (disp->roots[count] == root) { disp->num_roots--; if (count == disp->num_roots) { disp->roots[count] = NULL; } else { disp->roots[count] = disp->roots[disp->num_roots]; } ui_window_unmap(root); ui_window_final(root); return 1; } } return 0; } void ui_display_idling(ui_display_t *disp) { u_int count; for (count = 0; count < _disp.num_roots; count++) { ui_window_idling(_disp.roots[count]); } } int ui_display_receive_next_event(ui_display_t *disp) { return 1; } /* * Folloing functions called from ui_window.c */ int ui_display_own_selection(ui_display_t *disp, ui_window_t *win) { if (disp->selection_owner) { ui_display_clear_selection(disp, disp->selection_owner); } disp->selection_owner = win; return 1; } int ui_display_clear_selection(ui_display_t *disp, ui_window_t *win) { if (disp->selection_owner == NULL || disp->selection_owner != win) { return 0; } if (disp->selection_owner->selection_cleared) { (*disp->selection_owner->selection_cleared)(disp->selection_owner); } disp->selection_owner = NULL; return 1; } XModifierKeymap *ui_display_get_modifier_mapping(ui_display_t *disp) { return disp->modmap.map; } void ui_display_update_modifier_mapping(ui_display_t *disp, u_int serial) { /* dummy */ } Cursor ui_display_get_cursor(ui_display_t *disp, u_int shape) { return None; } XID ui_display_get_group_leader(ui_display_t *disp) { return None; } mlterm-3.8.9/uitoolkit/beos/ui_display.h010064400017600000144000000003331356600660700170270ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_DISPLAY_H__ #define ___UI_DISPLAY_H__ #include "../ui_display.h" Cursor ui_display_get_cursor(ui_display_t *disp, u_int shape); #endif mlterm-3.8.9/uitoolkit/beos/ui_dnd.c012075500017600000144000000000001356600660700212652../quartz/ui_dnd.custar kenusersmlterm-3.8.9/uitoolkit/beos/ui_font.c010064400017600000144000000263201356600660700163270ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_font.h" #include #include /* memset/strncasecmp */ #include #include /* alloca */ #include /* bl_str_to_int */ #include #include #include /* ui_convert_to_xft_ucs4 */ #ifdef USE_OT_LAYOUT #include #endif #define DEFAULT_FONT "Noto Mono" #include "beos.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static int use_point_size; /* --- static functions --- */ static int parse_font_name( char **font_family, double *font_size, /* if size is not specified in font_name, not changed. */ int *is_bold, /* if bold is not specified in font_name, not changed. */ int *is_italic, /* if italic is not specified in font_name, not changed. */ u_int *percent, /* if percent is not specified in font_name , not changed. */ char *font_name /* modified by this function. */ ) { char *p; size_t len; /* * Format. * [Family]( [WEIGHT] [SLANT] [SIZE]:[Percentage]) */ *font_family = font_name; if ((p = strrchr(font_name, ':'))) { /* Parsing ":[Percentage]" */ if (bl_str_to_uint(percent, p + 1)) { *p = '\0'; } #ifdef DEBUG else { bl_warn_printf(BL_DEBUG_TAG " Percentage(%s) is illegal.\n", p + 1); } #endif } /* * Parsing "[Family] [WEIGHT] [SLANT] [SIZE]". * Following is the same as ui_font.c:parse_xft_font_name() * except FW_* and is_italic. */ #if 0 bl_debug_printf("Parsing %s for [Family] [Weight] [Slant]\n", *font_family); #endif p = bl_str_chop_spaces(*font_family); len = strlen(p); while (len > 0) { size_t step = 0; if (*p == ' ') { char *orig_p; orig_p = p; do { p++; len--; } while (*p == ' '); if (len == 0) { *orig_p = '\0'; break; } else { int count; /* * XXX * "medium" is necessary because GTK font selection dialog (mlconfig) * returns "Osaka medium" */ char *styles[] = { "italic", "bold", "medium", "oblique", "light", "semi-bold", "heavy", "semi-condensed", }; for (count = 0; count < sizeof(styles) / sizeof(styles[0]); count++) { size_t len_v; len_v = strlen(styles[count]); /* XXX strncasecmp is not portable? */ if (len >= len_v && strncasecmp(p, styles[count], len_v) == 0) { /* [WEIGHT] [SLANT] */ *orig_p = '\0'; step = len_v; if (count <= 1) { if (count == 0) { *is_italic = 1; } else { *is_bold = 1; } } goto next_char; } } if (*p != '0' || /* In case of "DevLys 010" font family. */ *(p + 1) == '\0') /* "MS Gothic 0" => "MS Gothic" + "0" */ { char *end; double size; size = strtod(p, &end); if (*end == '\0') { /* p has no more parameters. */ *orig_p = '\0'; if (size > 0) { *font_size = size; } break; } } step = 1; } } else { step = 1; } next_char: p += step; len -= step; } return 1; } /* --- global functions --- */ void ui_compose_dec_special_font(void) { /* Do nothing for now in quartz. */ } ui_font_t *ui_font_new(Display *display, vt_font_t id, int size_attr, ui_type_engine_t type_engine, ui_font_present_t font_present, const char *fontname, u_int fontsize, u_int col_width, int use_medium_for_bold, u_int letter_space /* Ignored for now. */ ) { ui_font_t *font; char *font_family; u_int percent; u_int cols; int is_italic = 0; int is_bold = 0; if (type_engine != TYPE_XCORE || (font = calloc(1, sizeof(ui_font_t) + sizeof(XFontStruct))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc() failed.\n"); #endif return NULL; } font->xfont = font + 1; font->display = display; font->id = id; if (font->id & FONT_FULLWIDTH) { cols = 2; } else { cols = 1; } if (IS_ISCII(FONT_CS(font->id)) || FONT_CS(font->id) == ISO10646_UCS4_1_V) { /* * For exampe, 'W' width and 'l' width of OR-TTSarala font for ISCII_ORIYA * are the same by chance, though it is actually a proportional font. */ font->is_var_col_width = font->is_proportional = 1; } else if (font_present & FONT_VAR_WIDTH) { font->is_var_col_width = 1; } if (font_present & FONT_VERTICAL) { font->is_vertical = 1; } font_family = NULL; percent = 0; if (fontname) { char *p; double fontsize_d = 0; if ((p = alloca(strlen(fontname) + 1)) == NULL) { free(font); return NULL; } parse_font_name(&font_family, &fontsize_d, &is_bold, &is_italic, &percent, strcpy(p, fontname)); if (fontsize_d > 0.0) { fontsize = fontsize_d; } } else { /* Default font */ font_family = DEFAULT_FONT; } if (font->id & FONT_BOLD) { is_bold = 1; } if (font->id & FONT_ITALIC) { is_italic = 1; } if (size_attr >= DOUBLE_HEIGHT_TOP) { fontsize *= 2; col_width *= 2; } load_bfont: while (!(font->xfont->fid = beos_create_font(font_family, fontsize, is_italic, is_bold))) { bl_warn_printf("%s font is not found.\n", font_family); if (col_width == 0 && strcmp(font_family, DEFAULT_FONT) != 0) { /* * standard(usascii) font * Fall back to default font. */ font_family = DEFAULT_FONT; } else { free(font); return NULL; } } { u_int width; u_int height; u_int ascent; beos_font_get_metrics(font->xfont->fid, &width, &height, &ascent); font->width = width; font->height = height; font->ascent = ascent; } font->x_off = 0; if (col_width == 0) { /* standard(usascii) font */ if (percent > 0) { u_int ch_width; if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ ch_width = font->width * percent / 50; } else { ch_width = font->width * percent / 100; } if (ch_width != font->width) { if (ch_width > font->width) { font->x_off += (ch_width - font->width) / 2; } font->width = ch_width; font->is_proportional = 1; } } else if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ font->is_proportional = 1; font->width *= 2; font->x_off += (font->width / 4); } if (!font->is_var_col_width && letter_space > 0) { font->is_proportional = 1; font->width += letter_space; font->x_off += (letter_space / 2); } } else { /* not a standard(usascii) font */ font->width *= cols; if (font->is_vertical) { if (font->width != col_width) { font->is_proportional = 1; if (/* !font->is_var_col_width && */ font->width < col_width) { font->x_off = (col_width - font->width) / 2; } font->width = col_width; } } else { if (font->width != col_width * cols) { if (is_bold && font->double_draw_gap == 0) { /* Retry */ is_bold = 0; font->double_draw_gap = 1; beos_release_font(font->xfont->fid); goto load_bfont; } font->is_proportional = 1; if (!font->is_var_col_width && font->width < col_width * cols) { font->x_off = (col_width * 2 - font->width) / 2; } font->width = col_width * cols; } } } font->decsp_font = NULL; if (size_attr == DOUBLE_WIDTH) { font->width *= 2; font->x_off += (font->width / 4); font->is_proportional = 1; font->is_var_col_width = 0; font->size_attr = size_attr; } #ifdef DEBUG ui_font_dump(font); #endif return font; } void ui_font_destroy(ui_font_t *font) { #ifdef USE_OT_LAYOUT if (font->ot_font) { otl_close(font->ot_font); } #endif beos_release_font(font->xfont->fid); free(font); } #ifdef USE_OT_LAYOUT int ui_font_has_ot_layout_table(ui_font_t *font) { if (!font->ot_font) { #ifdef USE_HARFBUZZ if (font->ot_font_not_found) { return 0; } font->ot_font = otl_open(font->xfont->fid, 0); #else char *path; if (font->ot_font_not_found || !(path = beos_get_font_path(font->xfont->fid))) { return 0; } font->ot_font = otl_open(path, 0); free(path); #endif if (!font->ot_font) { font->ot_font_not_found = 1; return 0; } } return 1; } u_int ui_convert_text_to_glyphs(ui_font_t *font, u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features) { return otl_convert_text_to_glyphs(font->ot_font, shaped, shaped_len, offsets, widths, cmapped, src, src_len, script, features, font->xfont->size * (font->size_attr >= DOUBLE_WIDTH ? 2 : 1)); } #endif /* USE_OT_LAYOUT */ u_int ui_calculate_char_width(ui_font_t *font, u_int32_t ch, ef_charset_t cs, int *draw_alone) { if (draw_alone) { *draw_alone = 0; } if (font->is_proportional) { if (font->is_var_col_width) { #ifdef USE_OT_LAYOUT if (font->use_ot_layout /* && font->ot_font */) { return beos_font_get_advance(font->xfont->fid, font->size_attr, NULL, 0, ch); } else #endif { u_int16_t utf16[2]; u_int len; if ((len = ui_convert_ucs4_to_utf16(utf16, ch) / 2) > 0) { return beos_font_get_advance(font->xfont->fid, font->size_attr, utf16, len, 0); } else { return 0; } } } if (draw_alone) { *draw_alone = 1; } } return font->width; } void ui_font_use_point_size(int use) { use_point_size = use; } /* Return written size */ size_t ui_convert_ucs4_to_utf16(u_char *dst, /* 4 bytes. Little endian. */ u_int32_t src) { if (src < 0x10000) { dst[1] = (src >> 8) & 0xff; dst[0] = src & 0xff; return 2; } else if (src < 0x110000) { /* surrogate pair */ u_char c; src -= 0x10000; c = (u_char)(src / (0x100 * 0x400)); src -= (c * 0x100 * 0x400); dst[1] = c + 0xd8; c = (u_char)(src / 0x400); src -= (c * 0x400); dst[0] = c; c = (u_char)(src / 0x100); src -= (c * 0x100); dst[3] = c + 0xdc; dst[2] = (u_char)src; return 4; } return 0; } #ifdef DEBUG void ui_font_dump(ui_font_t *font) { bl_msg_printf(" id %x: Font %p width %d height %d ascent %d", font->id, font->xfont->fid, font->width, font->height, font->ascent); if (font->is_proportional) { bl_msg_printf(" (proportional)"); } bl_msg_printf("\n"); } #endif mlterm-3.8.9/uitoolkit/beos/ui_gc.c012075500017600000144000000000001356600660700177762../fb/ui_gc.custar kenusersmlterm-3.8.9/uitoolkit/beos/ui_imagelib.c010064400017600000144000000143651356600660700171400ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef NO_IMAGE #include "../ui_imagelib.h" #include /* sprintf */ #include /* pow */ #include /* DIGIT_STR_LEN */ #include #include #include /* bl_get_user_rc_path */ #include "beos.h" #if 1 #define BUILTIN_SIXEL #endif /* --- static functions --- */ #define CARD_HEAD_SIZE 0 #include "../../common/c_sixel.c" #include "../../common/c_regis.c" #include "../../common/c_animgif.c" static void value_table_refresh(u_char *value_table, /* 256 bytes */ ui_picture_modifier_t *mod) { int i, tmp; double real_gamma, real_brightness, real_contrast; real_gamma = (double)(mod->gamma) / 100; real_contrast = (double)(mod->contrast) / 100; real_brightness = (double)(mod->brightness) / 100; for (i = 0; i < 256; i++) { tmp = real_contrast * (255 * pow(((double)i + 0.5) / 255, real_gamma) - 128) + 128 * real_brightness; if (tmp >= 255) { break; } else if (tmp < 0) { value_table[i] = 0; } else { value_table[i] = tmp; } } for (; i < 256; i++) { value_table[i] = 255; } } static void adjust_pixmap(u_char *image, u_int width, u_int height, ui_picture_modifier_t *pic_mod) { u_char *value_table; u_int y; u_int x; u_char r, g, b, a; u_int32_t pixel; if (!ui_picture_modifier_is_normal(pic_mod) && (value_table = alloca(256))) { value_table_refresh(value_table, pic_mod); } else { return; } for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixel = *(((u_int32_t *)image) + (y * width + x)); a = (pixel >> 24) & 0xff; r = (pixel >> 16) & 0xff; g = (pixel >> 8) & 0xff; b = pixel & 0xff; r = (value_table[r] * (255 - pic_mod->alpha) + pic_mod->blend_red * pic_mod->alpha) / 255; g = (value_table[g] * (255 - pic_mod->alpha) + pic_mod->blend_green * pic_mod->alpha) / 255; b = (value_table[b] * (255 - pic_mod->alpha) + pic_mod->blend_blue * pic_mod->alpha) / 255; pixel = (a << 24) | (r << 16) | (g << 8) | b; *(((u_int32_t *)image) + (y * width + x)) = pixel; } } } static void adjust_pixmap2(u_char *image, u_int width, u_int height, ui_picture_modifier_t *pic_mod) { u_char *value_table; u_int y; u_int x; u_char r, g, b; if (!ui_picture_modifier_is_normal(pic_mod) && (value_table = alloca(256))) { value_table_refresh(value_table, pic_mod); } else { return; } for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { r = image[0]; g = image[1]; b = image[2]; image[0] = (value_table[r] * (255 - pic_mod->alpha) + pic_mod->blend_red * pic_mod->alpha) / 255; image[1] = (value_table[g] * (255 - pic_mod->alpha) + pic_mod->blend_green * pic_mod->alpha) / 255; image[2] = (value_table[b] * (255 - pic_mod->alpha) + pic_mod->blend_blue * pic_mod->alpha) / 255; image += 4; } } } static int check_has_alpha(u_char *image, u_int width, u_int height) { u_int x; u_int y; u_char *p = image + 3; for (y = 0; y < height; y++) { for (x = 0; x < width; x++, p += 4) { if (*p != 0xff) { return 1; } } } return 0; } static int load_file(char *path, /* must be UTF-8 */ u_int *width, u_int *height, ui_picture_modifier_t *pic_mod, Pixmap *pixmap, PixmapMask *mask) { char *suffix; u_char *image; suffix = path + strlen(path) - 4; #ifdef BUILTIN_SIXEL if (strcasecmp(suffix, ".six") == 0 && *width == 0 && *height == 0 && (image = load_sixel_from_file(path, width, height))) { adjust_pixmap(image, *width, *height, pic_mod); *pixmap = beos_create_image(image, (*width) * (*height) * 4, *width, *height); } else #endif { if (strcmp(suffix, ".gif") == 0) { char *dir; if (!strstr(path, "mlterm/anim") && /* is animation gif */ (dir = bl_get_user_rc_path("mlterm/"))) { split_animation_gif(path, dir, hash_path(path)); free(dir); } } else if (strcasecmp(suffix, ".rgs") == 0) { convert_regis_to_bmp(path); } /* XXX pic_mod is ignored */ if (!(*pixmap = beos_load_image(path, width, height))) { return 0; } if (!ui_picture_modifier_is_normal(pic_mod)) { Pixmap new_pixmap; image = beos_get_bits(*pixmap); adjust_pixmap2(image, *width, *height, pic_mod); new_pixmap = beos_create_image(image, (*width) * (*height) * 4, *width, *height); beos_destroy_image(*pixmap); *pixmap = new_pixmap; } } if (mask) { *mask = None; } return 1; } /* --- global functions --- */ void ui_imagelib_display_opened(Display *display) {} void ui_imagelib_display_closed(Display *display) {} Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, ui_picture_modifier_t *pic_mod) { Pixmap pixmap; u_int width = 0; u_int height = 0; if (!load_file(path, &width, &height, pic_mod, &pixmap, NULL)) { return None; } if (ACTUAL_WIDTH(win) != width || ACTUAL_HEIGHT(win) != height) { pixmap = beos_resize_image(pixmap, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); } return pixmap; } int ui_imagelib_root_pixmap_available(Display *display) { return 0; } Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modifier_t *pic_mod) { return None; } int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) { u_int pix_width = 0; u_int pix_height = 0; if (cardinal) { return 0; } if (!load_file(path, &pix_width, &pix_height, NULL, pixmap, mask)) { return 0; } if ((*width > 0 && pix_width != *width) || (*height > 0 && pix_height != *height)) { *pixmap = beos_resize_image(*pixmap, *width, *height); } else { *width = pix_width; *height = pix_height; } return 1; } void ui_destroy_image(Display *display, Pixmap pixmap) { beos_destroy_image(pixmap); } void ui_destroy_mask(Display *display, PixmapMask mask /* can be NULL */) {} #endif /* NO_IMAGE */ mlterm-3.8.9/uitoolkit/beos/ui_selection_encoding.c012075500017600000144000000000001356600660700270512../xlib/ui_selection_encoding.custar kenusersmlterm-3.8.9/uitoolkit/beos/ui_window.c010064400017600000144000001026271356600660700166750ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_window.h" #include /* abs */ #include /* memset/memcpy */ #include #include /* realloc/free */ #include "../ui_xic.h" #include "../ui_picture.h" #include "../ui_imagelib.h" #ifndef DISABLE_XDND #include "../ui_dnd.h" #endif #include "ui_display.h" /* ui_display_get_cursor */ #include "beos.h" /* win->width is not multiples of (win)->width_inc if window is maximized. */ #define RIGHT_MARGIN(win) \ ((win)->width_inc ? ((win)->width - (win)->min_width) % (win)->width_inc : 0) #define BOTTOM_MARGIN(win) \ ((win)->height_inc ? ((win)->height - (win)->min_height) % (win)->height_inc : 0) #define ParentRelative (1L) #define IS_UILAYOUT(win) ((win)->child_window_resized) #define IS_IM_WINDOW(win) ((win)->window_resized == NULL) #if 0 #define DEBUG_SCROLLABLE #endif #if 0 #define __DEBUG #endif /* --- static variables --- */ static int click_interval = 250; /* millisecond, same as xterm. */ static int use_urgent_bell; /* --- static functions --- */ static void urgent_bell(ui_window_t *win, int on) { if (use_urgent_bell && (!win->is_focused || !on)) { win = ui_get_root_window(win); app_urgent_bell(on); } } static void notify_focus_in_to_children(ui_window_t *win) { u_int count; if (!win->is_focused) { if (win->inputtable > 0 || win->parent == NULL) /* check_scrollable checks root->is_focused */ { win->is_focused = 1; } if (win->inputtable > 0) { ui_xic_set_focus(win); if (win->window_focused) { (*win->window_focused)(win); } } } for (count = 0; count < win->num_children; count++) { notify_focus_in_to_children(win->children[count]); } } static void notify_focus_out_to_children(ui_window_t *win) { u_int count; if (win->is_focused) { win->is_focused = 0; ui_xic_unset_focus(win); if (win->window_unfocused) { (*win->window_unfocused)(win); } } for (count = 0; count < win->num_children; count++) { notify_focus_out_to_children(win->children[count]); } } static void notify_move_to_children(ui_window_t *win) { int count; for (count = 0; count < win->num_children; count++) { notify_move_to_children(win->children[count]); } } static u_int max_width_inc(ui_window_t *win) { u_int count; u_int width_inc; width_inc = win->width_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_WIDTH)) { u_int sub_inc; /* * XXX * we should calculate least common multiple of width_inc and sub_inc. */ if ((sub_inc = max_width_inc(win->children[count])) > width_inc) { width_inc = sub_inc; } } } return width_inc; } static u_int max_height_inc(ui_window_t *win) { u_int count; u_int height_inc; height_inc = win->height_inc; for (count = 0; count < win->num_children; count++) { if (win->children[count]->is_mapped && (win->children[count]->sizehint_flag & SIZEHINT_HEIGHT)) { u_int sub_inc; /* * XXX * we should calculate least common multiple of width_inc and sub_inc. */ if ((sub_inc = max_height_inc(win->children[count])) > height_inc) { height_inc = sub_inc; } } } return height_inc; } static void reset_input_focus(ui_window_t *win) { u_int count; if (win->inputtable) { win->inputtable = -1; } else { win->inputtable = 0; } for (count = 0; count < win->num_children; count++) { reset_input_focus(win->children[count]); } } static void clear_margin_area(ui_window_t *win) { void *view; u_int right_margin; u_int bottom_margin; u_int win_width; u_int win_height; if (win->parent) { view = win->my_window; } else if (!(view = window_get_orphan(win->my_window, 0))) { return; } right_margin = RIGHT_MARGIN(win); bottom_margin = BOTTOM_MARGIN(win); win_width = win->width - right_margin; win_height = win->height - bottom_margin; if (win->wall_picture) { Pixmap pic; int src_x; int src_y; if (win->wall_picture == ParentRelative) { pic = win->parent->wall_picture; src_x = win->x; src_y = win->y; } else { pic = win->wall_picture; src_x = src_y = 0; } if (win->hmargin > 0 || right_margin > 0) { view_copy_area(view, pic, src_x, src_y, win->hmargin, ACTUAL_HEIGHT(win), 0, 0); view_copy_area(view, pic, src_x + win_width + win->hmargin, src_y, win->hmargin + right_margin, ACTUAL_HEIGHT(win), win_width + win->hmargin, 0); } if (win->vmargin > 0 || bottom_margin > 0) { view_copy_area(view, pic, src_x + win->hmargin, src_y, win_width, win->vmargin, win->hmargin, 0); view_copy_area(view, pic, src_x + win->hmargin, src_y + win_height + win->vmargin, win_width, win->vmargin + bottom_margin, win->hmargin, win_height + win->vmargin); } } else { if (win->hmargin > 0 || right_margin > 0) { view_fill_with(view, &win->bg_color, 0, 0, win->hmargin, ACTUAL_HEIGHT(win)); view_fill_with(view, &win->bg_color, win_width + win->hmargin, 0, ACTUAL_WIDTH(win) - win_width - win->hmargin, ACTUAL_HEIGHT(win)); } if (win->vmargin > 0 || bottom_margin > 0) { view_fill_with(view, &win->bg_color, win->hmargin, 0, win_width, win->vmargin); view_fill_with(view, &win->bg_color, win->hmargin, win_height + win->vmargin, win_width, ACTUAL_HEIGHT(win) - win_height - win->vmargin); } } } static void clear_margin_area_all(ui_window_t *win) { u_int count; clear_margin_area(win); for (count = 0; count < win->num_children; count++) { clear_margin_area_all(win->children[count]); } } static void expose(ui_window_t *win, XExposeEvent *event) { int clear_margin; if (event->force_expose) { event->x = win->hmargin; event->y = win->vmargin; event->width = win->width; event->height = win->height; clear_margin = 1; } else if (win->update_window_flag) { if (win->update_window) { (*win->update_window)(win, win->update_window_flag); } return; } else { clear_margin = 0; if (event->x < win->hmargin) { event->width -= (win->hmargin - event->x); event->x = win->hmargin; clear_margin = 1; } if (event->y < win->vmargin) { event->height -= (win->vmargin - event->y); event->y = win->vmargin; clear_margin = 1; } if (!clear_margin && (event->x + event->width > win->hmargin + win->width || event->y + event->height > win->vmargin + win->height)) { clear_margin = 1; } } if (clear_margin) { clear_margin_area(win); } if (win->window_exposed) { (*win->window_exposed)(win, event->x - win->hmargin, event->y - win->vmargin, event->width, event->height); } } /* --- global functions --- */ int ui_window_init(ui_window_t *win, u_int width, u_int height, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc, u_int hmargin, u_int vmargin, int create_gc, /* ignored */ int inputtable) { memset(win, 0, sizeof(ui_window_t)); win->fg_color.pixel = 0xff000000; win->bg_color.pixel = 0xffffffff; win->is_scrollable = 0; win->is_focused = 0; win->inputtable = inputtable; /* This flag will map window automatically in ui_window_show(). */ win->is_mapped = 1; win->create_gc = create_gc; win->width = width; win->height = height; win->min_width = min_width; win->min_height = min_height; win->width_inc = width_inc; win->height_inc = height_inc; win->sizehint_flag = SIZEHINT_WIDTH|SIZEHINT_HEIGHT; win->hmargin = hmargin; win->vmargin = vmargin; win->prev_clicked_button = -1; win->app_name = "mlterm"; return 1; } void ui_window_final(ui_window_t *win) { u_int count; Window my_window; int is_window; #ifdef __DEBUG bl_debug_printf("[deleting child windows]\n"); ui_window_dump_children(win); #endif for (count = 0; count < win->num_children; count++) { ui_window_final(win->children[count]); } my_window = win->my_window; if (win->my_window) { /* * win->parent may be NULL because this function is called * from ui_layout after ui_window_remove_child(), * not only win->parent but also IS_UILAYOUT(win) is necessary. */ if (!win->parent && (IS_UILAYOUT(win) || IS_IM_WINDOW(win))) { is_window = 1; } else { is_window = -1; } win->my_window = None; } else { is_window = 0; } free(win->children); win->num_children = 0; ui_display_clear_selection(win->disp, win); ui_xic_deactivate(win); if (win->window_finalized) { (*win->window_finalized)(win); } if (is_window == 1) { window_dealloc(my_window); /* Not reach. */ } else if (is_window == -1) { view_dealloc(my_window); } } void ui_window_set_type_engine(ui_window_t *win, ui_type_engine_t type_engine) {} void ui_window_add_event_mask(ui_window_t *win, long event_mask) { if (event_mask & PointerMotionMask) { win->event_mask = PointerMotionMask; } } void ui_window_remove_event_mask(ui_window_t *win, long event_mask) { if (event_mask & PointerMotionMask) { win->event_mask = 0; } } void ui_window_ungrab_pointer(ui_window_t *win) {} int ui_window_set_wall_picture(ui_window_t *win, Pixmap pic, int do_expose) { u_int count; win->wall_picture = pic; #if 1 if (win->my_window != None && do_expose) { if (win->parent) { view_update(win->my_window, 1); } else { void *view; if ((view = window_get_orphan(win->my_window, 0))) { view_update(view, 1); } } } #endif for (count = 0; count < win->num_children; count++) { ui_window_set_wall_picture(win->children[count], ParentRelative, do_expose); } return 1; } int ui_window_unset_wall_picture(ui_window_t *win, int do_expose) { u_int count; win->wall_picture = None; if (win->my_window != None) { #if 0 InvalidateRect(win->my_window, NULL, FALSE); #endif } for (count = 0; count < win->num_children; count++) { ui_window_unset_wall_picture(win->children[count], do_expose); } return 1; } int ui_window_set_transparent(ui_window_t *win, ui_picture_modifier_t *pic_mod) { return 0; } int ui_window_unset_transparent(ui_window_t *win) { return 0; } void ui_window_set_cursor(ui_window_t *win, u_int cursor_shape) { win->cursor_shape = cursor_shape; } int ui_window_set_fg_color(ui_window_t *win, ui_color_t *fg_color) { if (win->fg_color.pixel == fg_color->pixel) { return 0; } win->fg_color = *fg_color; return 1; } int ui_window_set_bg_color(ui_window_t *win, ui_color_t *bg_color) { if (win->bg_color.pixel == bg_color->pixel) { return 0; } win->bg_color = *bg_color; if (win->my_window && win->parent) { view_bg_color_changed(win->my_window); ui_window_update_all(win); } return 1; } int ui_window_add_child(ui_window_t *win, ui_window_t *child, int x, int y, int map) { void *p; if ((p = realloc(win->children, sizeof(*win->children) * (win->num_children + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } win->children = p; child->parent = win; child->x = x + win->hmargin; child->y = y + win->vmargin; if (!(child->is_mapped = map) && child->inputtable > 0) { child->inputtable = -1; } win->children[win->num_children++] = child; return 1; } int ui_window_remove_child(ui_window_t *win, ui_window_t *child) { u_int count; for (count = 0; count < win->num_children; count++) { if (win->children[count] == child) { child->parent = NULL; win->children[count] = win->children[--win->num_children]; return 1; } } return 0; } GC ui_window_get_fg_gc(ui_window_t *win) { return None; } GC ui_window_get_bg_gc(ui_window_t *win) { return None; } ui_window_t *ui_get_root_window(ui_window_t *win) { while (win->parent != NULL) { win = win->parent; } return win; } int ui_window_show(ui_window_t *win, int hint /* If win->parent(_window) is None, specify XValue|YValue to localte window at win->x/win->y. */ ) { u_int count; if (win->my_window) { /* already shown */ return 0; } #ifndef USE_BEOS if (hint & XNegative) { win->x += (win->disp->width - ACTUAL_WIDTH(win)); } if (hint & YNegative) { win->y += (win->disp->height - ACTUAL_HEIGHT(win)); } #endif if (win->parent) { win->disp = win->parent->disp; win->parent_window = win->parent->my_window; win->gc = win->parent->gc; view_alloc(win, win->x, win->y, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); } else { window_alloc(win, win->x, win->y, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), IS_IM_WINDOW(win)); } #ifndef DISABLE_XDND /* DragAcceptFiles( win->my_window , TRUE) ; */ #endif if (win->parent && !win->parent->is_transparent && win->parent->wall_picture) { ui_window_set_wall_picture(win, ParentRelative, 0); } /* * This should be called after Window Manager settings, because * ui_set_{window|icon}_name() can be called in win->window_realized(). */ if (win->window_realized) { (*win->window_realized)(win); } /* * showing child windows. */ for (count = 0; count < win->num_children; count++) { ui_window_show(win->children[count], 0); } if (!win->parent) { window_show(win->my_window); } /* * really visualized. */ if (win->is_mapped) { if (win->inputtable > 0) { reset_input_focus(ui_get_root_window(win)); win->inputtable = 1; } } if (win->is_transparent) { ui_window_set_transparent(win, win->pic_mod); } return 1; } void ui_window_map(ui_window_t *win) { if (win->is_mapped) { return; } if (win->parent) { view_set_hidden(win->my_window, 0); } win->is_mapped = 1; } void ui_window_unmap(ui_window_t *win) { if (!win->is_mapped) { return; } if (win->parent) { view_set_hidden(win->my_window, 1); #if 0 /* Scrollbar position is corrupt without this. */ ui_window_move(win, -1, -1); #endif } win->is_mapped = 0; } int ui_window_resize(ui_window_t *win, u_int width, /* excluding margin */ u_int height, /* excluding margin */ ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */ ) { if (win->width == width && win->height == height) { return 0; } /* Max width of each window is screen width. */ if ((flag & LIMIT_RESIZE) && win->disp->width < width) { win->width = win->disp->width - win->hmargin * 2; } else { win->width = width; } /* Max.height of each window is screen height. */ if ((flag & LIMIT_RESIZE) && win->disp->height < height) { win->height = win->disp->height - win->vmargin * 2; } else { win->height = height; } if (win->parent) { view_resize(win->my_window, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); if ((flag & NOTIFY_TO_PARENT) && win->parent->child_window_resized) { (*win->parent->child_window_resized)(win->parent, win); } } else { /* * win->parent may be NULL because this function is called * from ui_layout after ui_window_remove_child(), * not only win->parent but also IS_UILAYOUT(win) is necessary. */ if (IS_UILAYOUT(win) || IS_IM_WINDOW(win)) { window_resize(win->my_window, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); } } if ((flag & NOTIFY_TO_MYSELF) && win->window_resized) { (*win->window_resized)(win); win->update_window_flag = 0; /* force redraw */ } return 1; } /* * !! Notice !! * This function is not recommended. * Use ui_window_resize if at all possible. */ int ui_window_resize_with_margin(ui_window_t *win, u_int width, u_int height, ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */ ) { return ui_window_resize(win, width - win->hmargin * 2, height - win->vmargin * 2, flag); } void ui_window_set_maximize_flag(ui_window_t *win, ui_maximize_flag_t flag) { if (flag) { u_int w; u_int h; int x; int y; win = ui_get_root_window(win); window_get_position(win->my_window, &x, &y); if (flag & MAXIMIZE_HORIZONTAL) { w = win->disp->width; x = 0; } else { w = win->width; } if (flag & MAXIMIZE_VERTICAL) { h = win->disp->height; y = 0; } else { h = win->height; } window_resize(win->my_window, w, h); window_move(win->my_window, x, y); /* Same processing as ui_window_resize() */ if (win->window_resized) { (*win->window_resized)(win); win->update_window_flag = 0; /* force redraw */ } } else { /* XXX MAXIMIZE_RESTORE is not supported for now. */ } } void ui_window_set_normal_hints(ui_window_t *win, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc) { win->min_width = min_width; win->min_height = min_height; win->width_inc = width_inc; win->height_inc = height_inc; } void ui_window_set_override_redirect(ui_window_t *win, int flag) {} int ui_window_set_borderless_flag(ui_window_t *win, int flag) { return 0; } int ui_window_move(ui_window_t *win, int x, int y) { if (win->parent) { x += win->parent->hmargin; y += win->parent->vmargin; } if (win->x == x && win->y == y) { return 0; } win->x = x; win->y = y; if (win->parent) { view_move(win->my_window, x, y); } else { window_move(win->my_window, x, y); } return 1; } /* * This function can be used in context except window_exposed and update_window * events. */ void ui_window_clear(ui_window_t *win, int x, int y, u_int width, u_int height) { void *view; #ifdef AUTO_CLEAR_MARGIN if (x + width >= win->width) { /* Clearing margin area */ width += win->hmargin; } if (x > 0) #endif { x += win->hmargin; } #ifdef AUTO_CLEAR_MARGIN else { /* Clearing margin area */ width += win->hmargin; } if (y + height >= win->height) { /* Clearing margin area */ height += win->vmargin; } if (y > 0) #endif { y += win->vmargin; } #ifdef AUTO_CLEAR_MARGIN else { /* Clearing margin area */ height += win->vmargin; } #endif if (win->parent) { view = win->my_window; } else if (!(view = window_get_orphan(win->my_window, 0))) { return; } if (win->wall_picture) { Pixmap pic; int src_x; int src_y; if (win->wall_picture == ParentRelative) { pic = win->parent->wall_picture; src_x = win->x; src_y = win->y; } else { pic = win->wall_picture; src_x = src_y = 0; } view_copy_area(view, pic, src_x + x, src_y + y, width, height, x, y); } else { view_fill_with(view, &win->bg_color, x, y, width, height); } } void ui_window_clear_all(ui_window_t *win) { ui_window_clear(win, 0, 0, win->width, win->height); } void ui_window_fill(ui_window_t *win, int x, int y, u_int width, u_int height) { ui_window_fill_with(win, &win->fg_color, x, y, width, height); } void ui_window_fill_with(ui_window_t *win, ui_color_t *color, int x, int y, u_int width, u_int height) { void *view; if (win->parent) { view = win->my_window; } else if (!(view = window_get_orphan(win->my_window, 0))) { return; } view_fill_with(view, color, x + win->hmargin, y + win->vmargin, width, height); } /* * This function can be used in context except window_exposed and update_window * events. */ void ui_window_blank(ui_window_t *win) {} #if 0 /* * XXX * at the present time , not used and not maintained. */ void ui_window_fill_all_with(ui_window_t *win, ui_color_t *color) {} #endif void ui_window_update(ui_window_t *win, int flag) { void *view; if (win->parent) { view = win->my_window; } /* * ui_screen which is removed and becomes an orphan is resized by * ui_window_resize() in ui_layout_remove_child(), then ui_window_update() * is called. * In this case win->parent is NULL but win->my_window is not MLWindow* but * MLView*, so window_get_orphan(win->my_window) fails. * 'if ((!IS_UILAYOUT(win) && !IS_IM_WINDOW(win)))' avoids the failure. */ else if ((!IS_UILAYOUT(win) && !IS_IM_WINDOW(win)) || !(view = window_get_orphan(win->my_window, 0))) { return; } win->update_window_flag |= flag; view_update(view, 0); } void ui_window_update_all(ui_window_t *win) { void *view; u_int count; if (win->parent) { view = win->my_window; } else if (!(view = window_get_orphan(win->my_window, 0))) { return; } view_update(view, 1); for (count = 0; count < win->num_children; count++) { ui_window_update_all(win->children[count]); } } void ui_window_idling(ui_window_t *win) { u_int count; for (count = 0; count < win->num_children; count++) { ui_window_idling(win->children[count]); } #ifdef __DEBUG if (win->button_is_pressing) { bl_debug_printf(BL_DEBUG_TAG " button is pressing...\n"); } #endif if (win->button_is_pressing && win->button_press_continued) { (*win->button_press_continued)(win, &win->prev_button_press_event); } else if (win->idling) { (*win->idling)(win); } } /* * Return value: 0 => different window. * 1 => finished processing. * -1 => continuing default processing. */ int ui_window_receive_event(ui_window_t *win, XEvent *event) { switch (event->type) { case UI_KEY_FOCUS_IN: reset_input_focus(ui_get_root_window(win)); win->inputtable = 1; win = ui_get_root_window(win); notify_focus_out_to_children(win); /* Fall through */ case UI_FOCUS_IN: urgent_bell(win, 0); notify_focus_in_to_children(win); break; case UI_FOCUS_OUT: notify_focus_out_to_children(win); break; case UI_BUTTON_PRESS: if (win->button_pressed) { XButtonEvent *bev; bev = (XButtonEvent*)event; bev->x -= win->hmargin; bev->y -= win->vmargin; (*win->button_pressed)(win, bev, bev->click_count); win->button_is_pressing = 1; win->prev_button_press_event = *bev; } break; case UI_BUTTON_RELEASE: if (win->button_released) { XButtonEvent *bev; bev = (XButtonEvent*)event; bev->x -= win->hmargin; bev->y -= win->vmargin; (*win->button_released)(win, bev); win->button_is_pressing = 0; } break; case UI_BUTTON_MOTION: if (win->button_motion) { XMotionEvent *mev; mev = (XMotionEvent*)event; mev->x -= win->hmargin; mev->y -= win->vmargin; (*win->button_motion)(win, mev); /* following button motion ... */ win->prev_button_press_event.x = mev->x; win->prev_button_press_event.y = mev->y; win->prev_button_press_event.time = mev->time; } break; case UI_POINTER_MOTION: if (win->pointer_motion) { XMotionEvent *mev; mev = (XMotionEvent*)event; mev->x -= win->hmargin; mev->y -= win->vmargin; (*win->pointer_motion)(win, mev); } break; case UI_KEY_PRESS: if (win->key_pressed) { (*win->key_pressed)(win, (XKeyEvent*)event); } break; case UI_EXPOSE: expose(win, (XExposeEvent*)event); break; case UI_SELECTION_REQUESTED: if (win->utf_selection_requested) { (*win->utf_selection_requested)(win, (XSelectionRequestEvent*)event, 0); } break; case UI_SELECTION_NOTIFIED: if (win->utf_selection_notified) { (*win->utf_selection_notified)(win, ((XSelectionNotifyEvent*)event)->data, ((XSelectionNotifyEvent*)event)->len); } break; case UI_CLOSE_WINDOW: /* root window */ if (win->window_destroyed) { (*win->window_destroyed)(win); } break; case UI_RESIZE: if (win->window_resized) { (*win->window_resized)(win); } clear_margin_area_all(win); break; } return 1; } size_t ui_window_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { return ui_xic_get_str(win, seq, seq_len, parser, keysym, event); } /* * Scroll functions. * The caller side should clear the scrolled area. */ int ui_window_scroll_upward(ui_window_t *win, u_int height) { return ui_window_scroll_upward_region(win, 0, win->height, height); } int ui_window_scroll_upward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d in window((h) %d (w) %d)\n", boundary_start, boundary_end, height, win->height, win->width); #endif return 0; } if (win->parent) { view_scroll(win->my_window, win->hmargin, win->vmargin + boundary_start + height, /* src */ win->width, boundary_end - boundary_start - height, /* size */ win->hmargin, win->vmargin + boundary_start); /* dst */ } return 1; } int ui_window_scroll_downward(ui_window_t *win, u_int height) { return ui_window_scroll_downward_region(win, 0, win->height, height); } int ui_window_scroll_downward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d\n", boundary_start, boundary_end, height); #endif return 0; } if (win->parent) { view_scroll(win->my_window, win->hmargin, win->vmargin + boundary_start, /* src */ win->width, boundary_end - boundary_start - height, /* size */ win->hmargin, win->vmargin + boundary_start + height); /* dst */ } return 1; } int ui_window_scroll_leftward(ui_window_t *win, u_int width) { return ui_window_scroll_leftward_region(win, 0, win->width, width); } int ui_window_scroll_leftward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d in window((h) %d (w) %d)\n", boundary_start, boundary_end, width, win->height, win->width); #endif return 0; } if (win->parent) { view_scroll(win->my_window, win->hmargin + boundary_start + width, win->vmargin, /* src */ boundary_end - boundary_start - width, win->height, /* size */ win->hmargin + boundary_start, win->vmargin); /* dst */ } return 1; } int ui_window_scroll_rightward(ui_window_t *win, u_int width) { return ui_window_scroll_rightward_region(win, 0, win->width, width); } int ui_window_scroll_rightward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width) { if (!win->is_scrollable) { return 0; } if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d\n", boundary_start, boundary_end, width); #endif return 0; } if (win->parent) { view_scroll(win->my_window, win->hmargin + boundary_start, win->vmargin, /* src */ boundary_end - boundary_start - width, win->height, /* size */ win->hmargin + boundary_start + width, win->vmargin); /* dst */ } return 1; } int ui_window_copy_area(ui_window_t *win, Pixmap src, PixmapMask mask, int src_x, /* >= 0 */ int src_y, /* >= 0 */ u_int width, u_int height, int dst_x, /* >= 0 */ int dst_y /* >= 0 */ ) { if (dst_x >= win->width || dst_y >= win->height) { return 0; } if (dst_x + width > win->width) { width = win->width - dst_x; } if (dst_y + height > win->height) { height = win->height - dst_y; } if (win->parent) { view_copy_area(win->my_window, src, src_x, src_y, width, height, dst_x + win->hmargin, dst_y + win->vmargin); } return 1; } void ui_window_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height) { if (win->parent) { view_set_clip(win->my_window, x + win->hmargin, y + win->vmargin, width, height); } } void ui_window_unset_clip(ui_window_t *win) { if (win->parent) { view_unset_clip(win->my_window); } } void ui_window_draw_decsp_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int len) { ui_window_draw_string(win, font, fg_color, x, y, str, len); } void ui_window_draw_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int len) { void *view; if (win->parent) { view = win->my_window; } else if (!(view = window_get_orphan(win->my_window, 0))) { return; } view_draw_string(view, font, fg_color, x + win->hmargin, y + win->vmargin, str, len); } void ui_window_draw_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, XChar2b *str, u_int len) { void *view; if (win->parent) { view = win->my_window; } else if (!(view = window_get_orphan(win->my_window, 0))) { return; } view_draw_string16(view, font, fg_color, x + win->hmargin, y + win->vmargin, str, len); } void ui_window_draw_rect_frame(ui_window_t *win, int x1, int y1, int x2, int y2) { if (win->parent) { view_draw_rect_frame(win->my_window, &win->fg_color, x1 + win->hmargin, y1 + win->vmargin, x2 + win->hmargin, y2 + win->vmargin); } } void ui_set_use_clipboard_selection(int use_it) {} int ui_is_using_clipboard_selection(void) { return 0; } int ui_window_set_selection_owner(ui_window_t *win, Time time) { if (ui_window_is_selection_owner(win)) { /* Already owner */ return 1; } #if 0 bl_debug_printf(BL_DEBUG_TAG " ui_window_set_selection_owner.\n"); #endif if (win->utf_selection_requested) { (*win->utf_selection_requested)(win, NULL, 0); } return 1; } int ui_window_xct_selection_request(ui_window_t *win, Time time) { return 0; } int ui_window_utf_selection_request(ui_window_t *win, Time time) { if (win->utf_selection_notified) { u_char *str; size_t len; if (beos_clipboard_get(&str, &len)) { (*win->utf_selection_notified)(win, str, len); return 1; } } return 0; } void ui_window_send_picture_selection(ui_window_t *win, Pixmap pixmap, u_int width, u_int height) {} void ui_window_send_text_selection(ui_window_t *win, XSelectionRequestEvent *req_ev, u_char *sel_data, size_t sel_len, Atom sel_type) { beos_clipboard_set(sel_data, sel_len); } void ui_set_window_name(ui_window_t *win, u_char *name) { ui_window_t *root = ui_get_root_window(win); if (name == NULL) { name = root->app_name; } /* name is utf8 (see vt_parser.c) */ window_set_title(root->my_window, name); } void ui_set_icon_name(ui_window_t *win, u_char *name) {} void ui_window_set_icon(ui_window_t *win, ui_icon_picture_t *icon) {} void ui_window_remove_icon(ui_window_t *win) {} void ui_window_reset_group(ui_window_t *win) {} void ui_set_click_interval(int interval) { click_interval = interval; } int ui_get_click_interval(void) { return click_interval; } u_int ui_window_get_mod_ignore_mask(ui_window_t *win, KeySym *keysyms) { return ~0; } u_int ui_window_get_mod_meta_mask(ui_window_t *win, char *mod_key) { return ModMask; } void ui_set_use_urgent_bell(int use) { use_urgent_bell = use; } void ui_window_bell(ui_window_t *win, ui_bel_mode_t mode) { urgent_bell(win, 1); if (mode & BEL_VISUAL) { if (win->parent) { view_visual_bell(win->my_window); } } if (mode & BEL_SOUND) { beos_beep(); } } void ui_window_translate_coordinates(ui_window_t *win, int x, int y, int *global_x, int *global_y) { win = ui_get_root_window(win); window_get_position(win->my_window, global_x, global_y); *global_x += x; *global_y += y; } void ui_window_set_input_focus(ui_window_t *win) { reset_input_focus(ui_get_root_window(win)); win->inputtable = 1; if (win->parent) { view_set_input_focus(win->my_window); } } #ifdef DEBUG void ui_window_dump_children(ui_window_t *win) { u_int count; bl_msg_printf("%p(%li) => ", win, win->my_window); for (count = 0; count < win->num_children; count++) { bl_msg_printf("%p(%li) ", win->children[count], win->children[count]->my_window); } bl_msg_printf("\n"); for (count = 0; count < win->num_children; count++) { ui_window_dump_children(win->children[count]); } } #endif mlterm-3.8.9/uitoolkit/beos/ui_window.h010064400017600000144000000002211356600660700166650ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_window.h" int ui_window_clear_margin_area(ui_window_t *win); mlterm-3.8.9/uitoolkit/beos/beos.cpp010064400017600000144000000762141356600660700161630ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern "C" { #include "ui_window.h" #include "beos.h" #include "../ui_screen.h" #include "../ui_selection_encoding.h" #include /* strdup */ #include #include /* usleep/bl_getuid/bl_getgid */ #include /* bl_file_set_cloexec */ #include #include #include } #define IS_UISCREEN(win) ((win)->xim_listener) class MLWindow : public BWindow { public: MLWindow(BRect frame, const char *title, window_type type, uint32 flags); virtual void WindowActivated(bool active); virtual void FrameResized(float width, float height); virtual void Quit(); ui_window_t *uiwindow; }; class MLView : public BView { private: int32 buttons; const BFont *cur_font; public: MLView(BRect frame, const char *name, uint32 resizemode, uint32 flags); virtual void Draw(BRect updaterect); virtual void KeyDown(const char *bytes, int32 numBytes); virtual void MouseDown(BPoint where); virtual void MouseMoved(BPoint where, uint32 code, const BMessage *dragMessage); virtual void MouseUp(BPoint where); virtual void SetFont(const BFont *font, uint32 mask = B_FONT_ALL); virtual void MessageReceived(BMessage *msg); ui_window_t *uiwindow; BMessenger *messenger; }; class ConnectDialog : public BWindow { private: int button; public: ConnectDialog(); bool Go(); void ConnectDialog::Position(BWindow *parent); virtual void MessageReceived(BMessage *message); BTextControl *text; }; enum { MSG_OK = 'ok', MSG_CANCEL = 'can' }; static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; /* --- static variables --- */ static ef_parser_t *utf16_parser; /* --- static functions --- */ static void set_input_focus(MLView *view) { view->MakeFocus(true); XEvent ev; ev.type = UI_KEY_FOCUS_IN; ui_window_receive_event(view->uiwindow, &ev); } static void update_ime_text(ui_window_t *uiwindow, const char *preedit_text) { (*uiwindow->preedit)(uiwindow, preedit_text, NULL); } static void draw_screen(ui_window_t *uiwindow, BRect update, int force_expose) { XExposeEvent ev; ev.type = UI_EXPOSE; ev.x = update.left; ev.y = update.top; ev.width = update.right - update.left + 1.0; ev.height = update.bottom - update.top + 1.0; ev.force_expose = force_expose; ui_window_receive_event(uiwindow, (XEvent *)&ev); uiwindow->update_window_flag = 0; } static void window_lock(MLWindow *window) { #ifdef __DEBUG bl_debug_printf("Locking %p(%s)\n", uiwindow, uiwindow->parent ? "child" : "root"); #endif #ifdef DEBUG if (!window->IsLocked()) { bl_debug_printf(BL_DEBUG_TAG " Looper is not locked\n"); beos_lock(); } else #endif { window->UnlockLooper(); beos_lock(); window->LockLooper(); } #ifdef __DEBUG bl_debug_printf("Done\n"); #endif } static void view_lock(MLView *view) { #ifdef __DEBUG bl_debug_printf("Locking %p(%s)\n", uiwindow, uiwindow->parent ? "child" : "root"); #endif #ifdef DEBUG if (!view->Window()->IsLocked()) { bl_debug_printf(BL_DEBUG_TAG " Looper is not locked\n"); beos_lock(); } else #endif { view->UnlockLooper(); beos_lock(); view->LockLooper(); } #ifdef __DEBUG bl_debug_printf("Done\n"); #endif } /* --- class methods --- */ /* Lock is unnecessary because no mlterm function is called. */ MLWindow::MLWindow(BRect frame, const char *title, window_type type, uint32 flags) : BWindow(frame, title, type, flags) { frame.OffsetTo(0, 0); } void MLWindow::WindowActivated(bool active) { if (!uiwindow) { /* WindowActivated() can be called by BWindow::Quit() in window_dealloc() */ return; } XEvent ev; if (active) { ev.type = UI_FOCUS_IN; } else { ev.type = UI_FOCUS_OUT; } window_lock(this); ui_window_receive_event(ui_get_root_window(uiwindow), &ev); beos_unlock(); } /* * I don't know why but the value of 'width' or 'height' is 'right - left' or * 'bottom - top'. */ void MLWindow::FrameResized(float width, float height) { window_lock(this); /* MLWindow::ResizeTo() causes FrameResized() event. */ if (uiwindow->width != ((u_int)width) + 1 - uiwindow->hmargin * 2 || uiwindow->height != ((u_int)height) + 1 - uiwindow->vmargin * 2) { uiwindow->width = width + 1 - uiwindow->hmargin * 2; uiwindow->height = height + 1 - uiwindow->vmargin * 2; XEvent ev; ev.type = UI_RESIZE; ui_window_receive_event(uiwindow, &ev); } beos_unlock(); } void MLWindow::Quit() { if (uiwindow) { if (uiwindow->disp->num_roots == 1) { be_app->PostMessage(B_QUIT_REQUESTED); } XEvent ev; ev.type = UI_CLOSE_WINDOW; window_lock(this); ui_window_receive_event(uiwindow, &ev); /* * Not reach. * window_destroyed() => ui_window_final() => window_dealloc() => * MLWindow::Quit() => BWindow::Quit() */ } else { /* Called from window_dealloc() */ beos_unlock(); BWindow::Quit(); /* Not reach. This thread exits in BWindow::Quit(). */ } } /* Lock is unnecessary because no mlterm function is called. */ MLView::MLView(BRect frame, const char *title, uint32 resizemode, uint32 flags) : BView(frame, title, resizemode, flags) { SetViewColor(255, 255, 255); SetHighColor(0, 0, 0); SetLowColor(0, 0, 0); SetFontSize(14); SetDrawingMode(B_OP_OVER); cur_font = NULL; buttons = 0; messenger = NULL; /* uiwindow is initialized in view_alloc() or window_alloc(). */ #if 0 uiwindow = NULL; #endif } void MLView::Draw(BRect update) { if (!uiwindow || (IS_UISCREEN(uiwindow) && !((ui_screen_t *)uiwindow)->term)) { /* It has been already removed from ui_layout or term has been detached. */ return; } view_lock(this); draw_screen(uiwindow, update, 0); beos_unlock(); } void MLView::KeyDown(const char *bytes, int32 numBytes) { if (!uiwindow || (IS_UISCREEN(uiwindow) && !((ui_screen_t *)uiwindow)->term)) { /* It has been already removed from ui_layout or term has been detached. */ return; } view_lock(this); int32 modifiers; Window()->CurrentMessage()->FindInt32((const char*)"modifiers", &modifiers); XKeyEvent kev; kev.type = UI_KEY_PRESS; kev.state = modifiers & (ShiftMask|ControlMask|Mod1Mask|CommandMask); if (numBytes == 1) { if (bytes[0] == B_FUNCTION_KEY) { int32 key; Window()->CurrentMessage()->FindInt32((const char*)"key", &key); kev.keysym = (key | 0xf000); kev.utf8 = NULL; } else { kev.keysym = *bytes; switch(kev.keysym) { case B_LEFT_ARROW: /* 0x61 (raw key - jp106) */ case B_RIGHT_ARROW: /* 0x63 */ case B_UP_ARROW: /* 0x57 */ case B_DOWN_ARROW: /* 0x62 */ case B_INSERT: /* 0x1f */ case B_DELETE: /* 0x34 */ case B_HOME: /* 0x20 */ case B_END: /* 0x35 */ case B_PAGE_UP: /* 0x21 */ case B_PAGE_DOWN: /* 0x36 */ if (kev.state & ControlMask) { int32 key; Window()->CurrentMessage()->FindInt32((const char*)"key", &key); /* raw key */ if (key <= 0x1e || (0x22 <= key && key <= 0x33) || (0x37 <= key && key <= 0x56) || (0x58 <= key && key <= 0x60) || 0x64 <= key) { kev.utf8 = bytes; break; } } kev.keysym |= 0xe000; kev.utf8 = NULL; break; case B_KATAKANA_HIRAGANA: case B_HANKAKU_ZENKAKU: case B_HANGUL: case B_HANGUL_HANJA: kev.utf8 = NULL; break; default: kev.utf8 = bytes; break; } } } else { kev.keysym = 0; kev.utf8 = bytes; } ui_window_receive_event(uiwindow, (XEvent *)&kev); beos_unlock(); } void MLView::MouseDown(BPoint where) { if (!uiwindow || (IS_UISCREEN(uiwindow) && !((ui_screen_t *)uiwindow)->term)) { /* It has been already removed from ui_layout or term has been detached. */ return; } view_lock(this); if (!IsFocus()) { set_input_focus(this); } int32 clicks; int64 when; /* microsec */ int32 modifiers; Window()->CurrentMessage()->FindInt32((const char*)"buttons", &this->buttons); Window()->CurrentMessage()->FindInt32((const char*)"clicks", &clicks); Window()->CurrentMessage()->FindInt64((const char*)"when", &when); Window()->CurrentMessage()->FindInt32((const char*)"modifiers", &modifiers); XButtonEvent bev; bev.type = UI_BUTTON_PRESS; bev.time = when / 1000; /* msec */ bev.x = where.x; bev.y = where.y; bev.state = modifiers & (ShiftMask|ControlMask|Mod1Mask|CommandMask); bev.click_count = clicks; if (buttons == 0) { bev.button = 0; } else { if (buttons & B_PRIMARY_MOUSE_BUTTON) { bev.button = 1; } else if (buttons & B_SECONDARY_MOUSE_BUTTON) { bev.button = 3; } else /* if (buttons & B_TERTIARY_MOUSE_BUTTON) */ { bev.button = 2; } } ui_window_receive_event(uiwindow, (XEvent *)&bev); beos_unlock(); } void MLView::MouseMoved(BPoint where, uint32 code, const BMessage *dragMessage) { if (dragMessage || !uiwindow || (IS_UISCREEN(uiwindow) && !((ui_screen_t *)uiwindow)->term)) { /* It has been already removed from ui_layout or term has been detached. */ return; } view_lock(this); int32 buttons; int64 when; /* microsec */ int32 modifiers; Window()->CurrentMessage()->FindInt32((const char*)"buttons", &buttons); Window()->CurrentMessage()->FindInt64((const char*)"when", &when); Window()->CurrentMessage()->FindInt32((const char*)"modifiers", &modifiers); XMotionEvent mev; mev.time = when / 1000; /* msec */ mev.x = where.x; mev.y = where.y; mev.state = modifiers & (ShiftMask|ControlMask|Mod1Mask|CommandMask); if (buttons == 0) { mev.type = UI_POINTER_MOTION; } else { if (buttons & B_PRIMARY_MOUSE_BUTTON) { mev.state |= Button1Mask; } if (buttons & B_SECONDARY_MOUSE_BUTTON) { mev.state |= Button3Mask; } if (buttons & B_TERTIARY_MOUSE_BUTTON) { mev.state |= Button2Mask; } mev.type = UI_BUTTON_MOTION; } ui_window_receive_event(uiwindow, (XEvent *)&mev); beos_unlock(); } void MLView::MouseUp(BPoint where) { if (!uiwindow || (IS_UISCREEN(uiwindow) && !((ui_screen_t *)uiwindow)->term)) { /* It has been already removed from ui_layout or term has been detached. */ return; } view_lock(this); int32 clicks; int64 when; /* microsec */ Window()->CurrentMessage()->FindInt32((const char*)"clicks", &clicks); Window()->CurrentMessage()->FindInt64((const char*)"when", &when); XButtonEvent bev; bev.type = UI_BUTTON_RELEASE; bev.time = when / 1000; /* msec */ bev.x = where.x; bev.y = where.y; bev.state = 0; if (buttons == 0) { bev.button = 0; } else { if (buttons & B_PRIMARY_MOUSE_BUTTON) { bev.button = 1; } else if (buttons & B_SECONDARY_MOUSE_BUTTON) { bev.button = 3; } else /* if (buttons & B_TERTIARY_MOUSE_BUTTON) */ { bev.button = 2; } } this->buttons = 0; ui_window_receive_event(uiwindow, (XEvent *)&bev); beos_unlock(); } /* * SetFont() doesn't check if the specified font is different from the current font, * while SetHighColor() checks if the specified RGB is different from the current RGB. * (https://github.com/haiku/haiku/blob/master/src/kits/interface/View.cpp) */ void MLView::SetFont(const BFont *font, uint32 mask) { if (cur_font != font) { cur_font = font; BView::SetFont(font, mask); } } void MLView::MessageReceived(BMessage *message) { if (message->what == B_SIMPLE_DATA) { int32 count = 0; entry_ref ref; while (message->FindRef("refs", count++, &ref) == B_OK) { BPath path(&ref); XSelectionNotifyEvent ev; ev.type = UI_SELECTION_NOTIFIED; ev.data = (char*)path.Path(); ev.len = strlen(ev.data); view_lock(this); ui_window_receive_event(uiwindow, (XEvent*)&ev); beos_unlock(); } } else if (message->what == B_INPUT_METHOD_EVENT) { if (IS_UISCREEN(uiwindow) && !((ui_screen_t *)uiwindow)->term) { /* It has been already removed from ui_layout or term has been detached. */ return; } view_lock(this); int32 opcode; /* * If a focused view is changed from a view where you are inputting with * ime to another in splitted screen, following check enclosed by * #if 1 ... #endif is necessary. */ if (message->FindInt32("be:opcode", &opcode) == B_OK) { if (opcode == B_INPUT_METHOD_STARTED) { BMessenger m; if (message->FindMessenger("be:reply_to", &m) == B_OK) { if (messenger) { delete messenger; } messenger = new BMessenger(m); } } else if (opcode == B_INPUT_METHOD_STOPPED) { if (messenger) { delete messenger; messenger = NULL; } } else if (opcode == B_INPUT_METHOD_CHANGED) { const char *str; if (message->FindString("be:string", &str) != B_OK || *str == '\0') { update_ime_text(uiwindow, ""); goto end; } bool confirmed; if (message->FindBool("be:confirmed", &confirmed) == B_OK && confirmed) { update_ime_text(uiwindow, ""); XKeyEvent kev; kev.type = UI_KEY_PRESS; kev.state = 0; kev.keysym = 0; kev.utf8 = str; ui_window_receive_event(uiwindow, (XEvent *)&kev); } else { int32 start; int32 end; #if 0 int32 count = 0; while (message->FindInt32("be:clause_start", count, &start) == B_OK && message->FindInt32("be:clause_end", count, &end) == B_OK) { bl_debug_printf("Clause %d: %d-%d\n", count, start, end); count++; } #endif message->FindInt32("be:selection", 1, &end); if (end > 0) { message->FindInt32("be:selection", 0, &start); char str2[strlen(str) + 10]; char *p = str2; memcpy(p, str, start); strcpy((p += start), "\x1b[7m"); int32 len = end - start; strncpy((p += 4), str + start, len); strcpy((p += len), "\x1b[27m"); strcpy((p += 5), str + end); update_ime_text(uiwindow, str2); } else { update_ime_text(uiwindow, str); } } } else if (opcode == B_INPUT_METHOD_LOCATION_REQUEST && messenger) { int x; int y; if (!uiwindow->xim_listener || !(*uiwindow->xim_listener->get_spot)(uiwindow->xim_listener->self, &x, &y)) { x = y = 0; } BMessage message(B_INPUT_METHOD_EVENT); message.AddInt32("be:opcode", B_INPUT_METHOD_LOCATION_REQUEST); BPoint where((float)x, (float)y); ConvertToScreen(&where); float height = ui_line_height((ui_screen_t*)uiwindow); message.AddPoint("be:location_reply", where); message.AddFloat("be:height_reply", height); messenger->SendMessage(&message); } } end: beos_unlock(); } else if (message->what == B_MOUSE_WHEEL_CHANGED) { int64 when; /* microsec */ float y; XButtonEvent bev; message->FindFloat("be:wheel_delta_y", &y); message->FindInt64("be:when", &when); bev.type = UI_BUTTON_PRESS; bev.time = when / 1000; /* msec */ bev.x = 0; bev.y = 0; bev.state = 0; bev.click_count = 1; if (y < 0) { bev.button = 4; } else { bev.button = 5; } view_lock(this); ui_window_receive_event(uiwindow, (XEvent *)&bev); beos_unlock(); } } /* --- global functions --- */ void view_alloc(ui_window_t *uiwindow, int x, int y, u_int width, u_int height) { uint32 flags = B_WILL_DRAW; if (uiwindow->key_pressed) { flags |= B_INPUT_METHOD_AWARE; } MLView *view = new MLView(BRect(x, y, x + width - 1, y + height - 1), "mlterm", B_FOLLOW_NONE, flags); MLWindow *win = (MLWindow*)uiwindow->parent->my_window; if (win->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { delete view; return; } view->uiwindow = uiwindow; win->AddChild(view); uiwindow->my_window = (void*)view; if (uiwindow->inputtable) { view->MakeFocus(true); } win->UnlockLooper(); } void view_dealloc(/* BView */ void *view) { BWindow *win = ((BView*)view)->Window(); if (win->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } win->RemoveChild((BView*)view); ((MLView*)view)->uiwindow = None; delete (BView*)view; win->UnlockLooper(); } void view_update(/* BView */ void *view, int force_expose) { ui_window_t *uiwindow = ((MLView*)view)->uiwindow; int x; int y; if (!uiwindow->xim_listener || !(*uiwindow->xim_listener->get_spot)(uiwindow->xim_listener->self, &x, &y)) { x = y = 0; } x += (uiwindow->hmargin); y += (uiwindow->vmargin); draw_screen(uiwindow, BRect(x, y, x, y), force_expose); } void view_set_clip(/* BView */ void *view, int x, int y, u_int width, u_int height) { if (((BView*)view)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } BRegion *region = new BRegion(BRect(x, y, x + width - 1, y + height - 1)); ((BView*)view)->ConstrainClippingRegion(region); ((BView*)view)->UnlockLooper(); } void view_unset_clip(/* BView */ void *view) { if (((BView*)view)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } ((BView*)view)->ConstrainClippingRegion(NULL); ((BView*)view)->UnlockLooper(); } void view_draw_string(/* BView */ void *view, ui_font_t *font, ui_color_t *fg_color, int x, int y, char *str, size_t len) { if (((BView*)view)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } u_int32_t pixel = fg_color->pixel; ((BView*)view)->SetHighColor((pixel >> 16) & 0xff, (pixel >> 8) & 0xff, pixel & 0xff, (pixel >> 24) & 0xff); ((BView*)view)->SetFont((BFont*)font->xfont->fid); ((BView*)view)->MovePenTo(x, y); ((BView*)view)->DrawString(str, len); if (font->double_draw_gap) { ((BView*)view)->MovePenTo(x + font->double_draw_gap, y); ((BView*)view)->DrawString(str, len); } ((BView*)view)->UnlockLooper(); } void view_draw_string16(/* BView */ void *view, ui_font_t *font, ui_color_t *fg_color, int x, int y, XChar2b *str, size_t len) { if (!utf16_parser) { utf16_parser = ef_utf16le_parser_new(); /* XXX leaked */ } ef_conv_t *utf8_conv = ui_get_selection_conv(1); char str2[len * UTF_MAX_SIZE]; (*utf16_parser->init)(utf16_parser); (*utf16_parser->set_str)(utf16_parser, (u_char*)str, len * 2); (*utf8_conv->init)(utf8_conv); len = (*utf8_conv->convert)(utf8_conv, (u_char*)str2, len * UTF_MAX_SIZE, utf16_parser); /* LockLooper() is called in view_draw_string() */ view_draw_string(view, font, fg_color, x, y, str2, len); } void view_fill_with(/* BView */ void *view, ui_color_t *color, int x, int y, u_int width /* > 0 */, u_int height /* > 0 */) { if (((BView*)view)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } u_long pixel = color->pixel; ((BView*)view)->SetLowColor((pixel >> 16) & 0xff, (pixel >> 8) & 0xff, pixel & 0xff, (pixel >> 24) & 0xff); ((BView*)view)->FillRect(BRect(x, y, x + width - 1, y + height - 1), B_SOLID_LOW); ((BView*)view)->UnlockLooper(); } void view_draw_rect_frame(/* BView */ void *view, ui_color_t *color, int x1, int y1, int x2, int y2) { u_long pixel = color->pixel; rgb_color rgb; rgb.red = (pixel >> 16) & 0xff; rgb.green = (pixel >> 8) & 0xff; rgb.blue = pixel & 0xff; rgb.alpha = (pixel >> 24) & 0xff; if (((BView*)view)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } ((BView*)view)->BeginLineArray(4); ((BView*)view)->AddLine(BPoint(x1, y1), BPoint(x1, y2), rgb); ((BView*)view)->AddLine(BPoint(x1, y2), BPoint(x2, y2), rgb); ((BView*)view)->AddLine(BPoint(x2, y1), BPoint(x2, y2), rgb); ((BView*)view)->AddLine(BPoint(x1, y1), BPoint(x2, y1), rgb); ((BView*)view)->EndLineArray(); ((BView*)view)->UnlockLooper(); } void view_copy_area(/* BView */ void *view, Pixmap src, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y) { if (((BView*)view)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } ((BView*)view)->DrawBitmap((BBitmap*)src, BRect(src_x, src_y, src_x + width - 1, src_y + height - 1), BRect(dst_x, dst_y, dst_x + width - 1, dst_y + height - 1)); ((BView*)view)->UnlockLooper(); } void view_scroll(/* BView */ void *view, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y) { #if 0 if (((BView*)view)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } ((BView*)view)->CopyBits(BRect(src_x, src_y, src_x + width - 1, src_y + height - 1), BRect(dst_x, dst_y, dst_x + width - 1, dst_y + height - 1)); ((BView*)view)->UnlockLooper(); #endif } void view_bg_color_changed(/* BView */ void *view) { } void view_visual_bell(/* BView */ void *view) { if (((BView*)view)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } u_long pixel = ((MLView*)view)->uiwindow->fg_color.pixel; ((BView*)view)->SetLowColor((pixel >> 16) & 0xff, (pixel >> 8) & 0xff, pixel & 0xff, (pixel >> 24) & 0xff); ui_window_t *win = ((MLView*)view)->uiwindow; ((BView*)view)->FillRect(BRect(0, 0, ACTUAL_WIDTH(win) - 1, ACTUAL_HEIGHT(win) - 1), B_SOLID_LOW); ((BView*)view)->UnlockLooper(); usleep(100000); /* 100 msec */ draw_screen(((MLView*)view)->uiwindow, BRect(0, 0, ACTUAL_WIDTH(win) - 1, ACTUAL_HEIGHT(win) - 1), 1); } void view_set_input_focus(/* BView */ void *view) { if (((BView*)view)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } set_input_focus((MLView*)view); ((BView*)view)->UnlockLooper(); } void view_resize(/* BView */ void *view, u_int width, u_int height) { if (((BView*)view)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } ((BView*)view)->ResizeTo((float)width - 1.0, (float)height - 1.0); ((BView*)view)->UnlockLooper(); } void view_move(/* BView */ void *view, int x, int y) { if (((BView*)view)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } ((BView*)view)->MoveTo((float)x, (float)y); ((BView*)view)->UnlockLooper(); } void view_set_hidden(/* BView */ void *view, int flag) { } void view_reset_uiwindow(ui_window_t *uiwindow) { ((MLView*)uiwindow->my_window)->uiwindow = uiwindow; } void window_alloc(ui_window_t *root, int x, int y, u_int width, u_int height, int popup) { MLWindow *window; if (popup) { window = new MLWindow(BRect(x, y, x + width - 1, y + height - 1), "", B_BORDERED_WINDOW, B_NOT_RESIZABLE|B_NOT_CLOSABLE|B_NOT_ZOOMABLE|B_NOT_MINIMIZABLE| B_NOT_MOVABLE|B_AVOID_FOCUS|B_NOT_ANCHORED_ON_ACTIVATE); MLView *view = new MLView(BRect(0, 0, width - 1, height - 1), "IM", B_FOLLOW_NONE, B_WILL_DRAW); view->uiwindow = root; window->AddChild(view); } else { #if 1 /* XXX */ static int count = 0; BRect r = BScreen(window).Frame(); int x = ((r.right - width) / 8) * count + 50; int y = ((r.bottom - height) / 8) * count + 50; if (++count == 8) { count = 0; } #endif window = new MLWindow(BRect(x, y, x + width - 1, y + height - 1), "mlterm", B_DOCUMENT_WINDOW, 0); if (root->disp->width == 0) { BScreen *screen = new BScreen(window); BRect rect = screen->Frame(); root->disp->width = rect.right + 1; root->disp->height = rect.bottom + 1; delete screen; } } window->uiwindow = root; root->my_window = (void*)window; } void window_show(void *window) { if (((BWindow*)window)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } ((BWindow*)window)->Show(); ((BWindow*)window)->UnlockLooper(); } void window_dealloc(/* BWindow */ void *window) { if (((BWindow*)window)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } ((MLWindow*)window)->uiwindow = None; ((BWindow*)window)->Quit(); /* Not reach. This thread exits in BWindow::Quit(). */ } void window_move(/* BWindow */ void *window, int x, int y) { if (((BWindow*)window)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } ((BWindow*)window)->MoveTo((float)x, (float)y); ((BWindow*)window)->UnlockLooper(); } void window_resize(/* BWindow */ void *window, int width, int height) { if (((BWindow*)window)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } ((BWindow*)window)->ResizeTo((float)width - 1.0, (float)height - 1.0); BView *view; if ((view = (BView*)window_get_orphan(window, 0))) { ((BView*)view)->ResizeTo((float)width - 1.0, (float)height - 1.0); } ((BWindow*)window)->UnlockLooper(); } void window_get_position(/* BWindow */ void *window, int *x, int *y) { BRect rect = ((BWindow*)window)->Frame(); *x = rect.left; *y = rect.top; } void window_set_title(/* BWindow */ void *window, const char *title /* utf8 */) { if (((BWindow*)window)->LockLooperWithTimeout(B_INFINITE_TIMEOUT) != B_OK) { return; } ((BWindow*)window)->SetTitle(title); ((BWindow*)window)->UnlockLooper(); } void *window_get_orphan(void *window, int idx) { if (((MLWindow*)window)->uiwindow->num_children == 0) { void *child = ((BWindow*)window)->ChildAt(idx); return child; } else { return NULL; } } void app_urgent_bell(int on) { } void *beos_create_font(const char *font_family, float size, int is_italic, int is_bold) { BFont *bfont = new BFont(); bfont->SetFamilyAndStyle(font_family, is_bold ? "Bold" : "Regular"); bfont->SetSpacing(B_FIXED_SPACING); bfont->SetSize(size); if (is_italic) { bfont->SetShear(100.0); } return bfont; } #ifdef USE_OT_LAYOUT char *beos_get_font_path(void *bfont) { return NULL; } #endif /* USE_OT_LAYOUT */ void beos_release_font(void *bfont) { delete (BFont*)bfont; } void beos_font_get_metrics(void *bfont, u_int *width, u_int *height, u_int *ascent) { const char *strs[] = { "M" }; int32 lens[] = { 1 }; float widths[1]; ((BFont*)bfont)->GetStringWidths(strs, lens, 1, widths); *width = widths[0] + 0.5; font_height height_info; ((BFont*)bfont)->GetHeight(&height_info); *height = (height_info.ascent + height_info.descent + height_info.leading) + 0.5; *ascent = (height_info.ascent + 0.5); } u_int beos_font_get_advance(void *bfont, int size_attr, unichar *utf16, u_int len, u_int32_t glyph) { if (!utf16_parser) { /* XXX leaked */ utf16_parser = ef_utf16le_parser_new(); } ef_conv_t *utf8_conv = ui_get_selection_conv(1); char utf8[len * UTF_MAX_SIZE]; (*utf16_parser->init)(utf16_parser); (*utf16_parser->set_str)(utf16_parser, (u_char*)utf16, len * 2); (*utf8_conv->init)(utf8_conv); len = (*utf8_conv->convert)(utf8_conv, (u_char*)utf8, len * UTF_MAX_SIZE, utf16_parser); const char *strs[] = { utf8 }; int32 lens[] = { len }; float widths[1]; ((BFont*)bfont)->GetStringWidths(strs, lens, 1, widths); return (u_int)(widths[0] + 0.5); } void beos_clipboard_set(const u_char *utf8, size_t len) { if (be_clipboard->Lock()) { be_clipboard->Clear(); BMessage *clip = be_clipboard->Data(); clip->AddData("text/plain", B_MIME_TYPE, utf8, len); be_clipboard->Commit(); be_clipboard->Unlock(); } } int beos_clipboard_get(u_char **str, size_t *len) { if (be_clipboard->Lock()) { BMessage *clip = be_clipboard->Data(); clip->FindData("text/plain", B_MIME_TYPE, (const void **)str, (ssize_t*)len); be_clipboard->Unlock(); return 1; } else { return 0; } } void beos_beep(void) { beep(); } void *beos_create_image(const void *data, u_int len, u_int width, u_int height) { BBitmap *bitmap; if ((bitmap = new BBitmap(BRect(0, 0, width - 1, height - 1), 0, B_RGBA32))) { bitmap->SetBits(data, len, 0, B_RGBA32); } return bitmap; } void beos_destroy_image(void *bitmap) { delete (BBitmap*)bitmap; } void *beos_load_image(const char *path, u_int *width, u_int *height) { BBitmap *bitmap; if ((bitmap = BTranslationUtils::GetBitmap(path))) { BRect rect = bitmap->Bounds(); *width = rect.right + 1; *height = rect.bottom + 1; } return bitmap; } void *beos_resize_image(void *bitmap, u_int width, u_int height) { BRect rect(0, 0, width - 1, height - 1); BBitmap *new_bitmap = new BBitmap(rect, B_RGBA32, true); BView *view = new BView(rect, "", B_FOLLOW_ALL_SIDES, 0); new_bitmap->AddChild(view); new_bitmap->Lock(); view->DrawBitmap((BBitmap*)bitmap, ((BBitmap*)bitmap)->Bounds(), rect); new_bitmap->Unlock(); new_bitmap->RemoveChild(view); delete view; delete (BBitmap*)bitmap; return new_bitmap; } u_char *beos_get_bits(void *bitmap) { return (u_char*)((BBitmap*)bitmap)->Bits(); } ConnectDialog::ConnectDialog() : BWindow(BRect(0, 0, 200, 100), "Password", B_MODAL_WINDOW, B_NOT_RESIZABLE|B_NOT_CLOSABLE|B_NOT_ZOOMABLE|B_NOT_MINIMIZABLE|B_NOT_MOVABLE, 0) { BButton *ok = new BButton(BRect(0, 0, 100, 100), "OkButton", "OK", new BMessage(MSG_OK)); BButton *cancel = new BButton(BRect(0, 0, 100, 100), "CancelButton", "Cancel", new BMessage(MSG_CANCEL)); text = new BTextControl("", "Password", "", NULL); text->TextView()->HideTyping(true); BLayoutBuilder::Group<>(this, B_VERTICAL) .Add(text) .AddGroup(B_HORIZONTAL) .AddGlue() .Add(ok) .Add(cancel) .End() .SetInsets(B_USE_DEFAULT_SPACING); SetDefaultButton(ok); button = -1; text->MakeFocus(); } bool ConnectDialog::Go() { Show(); while (button == -1) { usleep(1000); } return (button == 0); } void ConnectDialog::Position(BWindow *parent) { BRect rect = (parent ? parent->Frame() : BScreen(this).Frame()); MoveTo((rect.right + rect.left) / 2 - 100, (rect.bottom + rect.top) / 2 - 50); } void ConnectDialog::MessageReceived(BMessage *message) { switch(message->what) { case MSG_OK: button = 0; break; case MSG_CANCEL: button = 1; break; default: return; } PostMessage(B_QUIT_REQUESTED); } char *beos_dialog_password(const char *msg) { ConnectDialog *dialog = new ConnectDialog(); dialog->Position(dynamic_cast(BLooper::LooperForThread(find_thread(NULL)))); if (dialog->Go()) { return strdup(dialog->text->Text()); } else { return NULL; } } int beos_dialog_okcancel(const char *msg) { BAlert *alert = new BAlert("Dialog", msg, "OK", "Cencel"); if (alert->Go() == 0) { return 1; } else { return 0; } } int beos_dialog_alert(const char *msg) { BAlert *alert = new BAlert("Alert", msg, "OK"); alert->Go(); return 1; } void beos_lock(void) { pthread_mutex_lock(&mutex); } void beos_unlock(void) { pthread_mutex_unlock(&mutex); } mlterm-3.8.9/uitoolkit/fb004075500017600000144000000000001356600660700141005ustar kenusersmlterm-3.8.9/uitoolkit/fb/ui_virtual_kbd.c010064400017600000144000000270751356600660700173360ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_virtual_kbd.h" #include #include "../ui_imagelib.h" #ifndef XDATADIR #define KBD_DIR "/usr/local/share/mlterm/kbd" #else #define KBD_DIR XDATADIR "/mlterm/kbd" #endif /* --- static variables --- */ static ui_window_t *kbd_win; static struct kbd_key { int16_t left; int16_t right; u_int16_t ksym; u_int16_t shift_ksym; u_int keycode; } kbd_keys[] = { {1, 35, XK_Escape, XK_Escape, 1}, {37, 71, XK_F1, XK_F1, 59}, {73, 107, XK_F2, XK_F2, 60}, {109, 143, XK_F3, XK_F3, 61}, {145, 179, XK_F4, XK_F4, 62}, {181, 215, XK_F5, XK_F5, 63}, {217, 251, XK_F6, XK_F6, 64}, {253, 287, XK_F7, XK_F7, 65}, {289, 323, XK_F8, XK_F8, 66}, {325, 359, XK_F9, XK_F9, 67}, {361, 395, XK_F10, XK_F10, 68}, {397, 431, XK_F11, XK_F11, 87}, {433, 467, XK_F11, XK_F12, 88}, {589, 623, 0, 0, 0}, {1, 35, '`', '~', 41}, {37, 71, '1', '!', 2}, {73, 107, '2', '@', 3}, {109, 143, '3', '#', 4}, {145, 179, '4', '$', 5}, {181, 215, '5', '%', 6}, {217, 251, '6', '^', 7}, {253, 287, '7', '&', 8}, {289, 323, '8', '*', 9}, {325, 359, '9', '(', 10}, {361, 395, '0', ')', 11}, {397, 431, '-', '_', 12}, {433, 467, '=', '+', 13}, {469, 515, XK_BackSpace, XK_BackSpace, 14}, {517, 551, XK_Insert, XK_Insert, 110}, {553, 587, XK_Home, XK_Home, 102}, {589, 623, XK_Prior, XK_Prior, 104}, {1, 47, XK_Tab, XK_Tab, 15}, {49, 83, 'q', 'Q', 16}, {85, 119, 'w', 'W', 17}, {121, 155, 'e', 'E', 18}, {157, 191, 'r', 'R', 19}, {193, 227, 't', 'T', 20}, {229, 263, 'y', 'Y', 21}, {265, 299, 'u', 'U', 22}, {301, 335, 'i', 'I', 23}, {337, 371, 'o', 'O', 24}, {373, 407, 'p', 'P', 25}, {409, 443, '[', '{', 26}, {445, 479, ']', '}', 27}, {481, 515, '\\', '|', 43}, {517, 551, XK_Delete, XK_Delete, 111}, {553, 587, XK_End, XK_End, 107}, {589, 623, XK_Next, XK_Next, 109}, {1, 59, XK_Caps_Lock, XK_Caps_Lock, 58}, {61, 95, 'a', 'A', 30}, {97, 131, 's', 'S', 31}, {133, 167, 'd', 'D', 32}, {169, 203, 'f', 'F', 33}, {205, 239, 'g', 'G', 34}, {241, 275, 'h', 'H', 35}, {277, 311, 'j', 'J', 36}, {313, 347, 'k', 'K', 37}, {349, 383, 'l', 'L', 38}, {385, 419, ';', ':', 39}, {421, 455, '\'', '\"', 40}, {457, 515, XK_Return, XK_Return, 28}, {1, 71, XK_Shift_L, XK_Shift_L, 42}, {73, 107, 'z', 'Z', 44}, {109, 143, 'x', 'X', 45}, {145, 179, 'c', 'C', 46}, {181, 215, 'v', 'V', 47}, {217, 251, 'b', 'B', 48}, {253, 287, 'n', 'N', 49}, {289, 323, 'm', 'M', 50}, {325, 359, ',', '<', 51}, {361, 395, '.', '>', 52}, {397, 431, '/', '?', 53}, {433, 515, XK_Shift_R, XK_Shift_R, 54}, {553, 587, XK_Up, XK_Up, 103}, {1, 71, XK_Control_L, XK_Control_L, 29}, {73, 143, XK_Alt_L, XK_Alt_L, 56}, {145, 359, ' ', ' ', 57}, {361, 431, XK_Alt_R, XK_Alt_R, 100}, {433, 515, XK_Control_R, XK_Control_R, 97}, {517, 551, XK_Left, XK_Left, 105}, {553, 587, XK_Down, XK_Down, 108}, {589, 623, XK_Right, XK_Right, 106}, }; static struct kbd_key_group { int16_t top; int16_t bottom; u_int16_t num_keys; struct kbd_key *keys; } kbd_key_groups[] = { {1, 35, 14, kbd_keys}, {37, 71, 17, kbd_keys + 14}, {73, 107, 17, kbd_keys + 31}, {109, 143, 13, kbd_keys + 48}, {145, 179, 13, kbd_keys + 61}, {181, 215, 8, kbd_keys + 74}, }; static Pixmap normal_pixmap; static Pixmap pressed_pixmap; static int is_pressed; static int16_t pressed_top; static int16_t pressed_left; static u_int16_t pressed_width; static u_int16_t pressed_height; static int x_off; static int state; static int lock_state; /* --- static functions --- */ static int update_state(u_int ksym) { if (ksym == XK_Alt_L || ksym == XK_Alt_R) { if (state & Mod1Mask) { state &= ~Mod1Mask; return -1; } else { state |= Mod1Mask; return 1; } } else if (ksym == XK_Control_L || ksym == XK_Control_R) { if (state & ControlMask) { state &= ~ControlMask; return -1; } else { state |= ControlMask; return 1; } } else if (ksym == XK_Shift_L || ksym == XK_Shift_R) { if (state & ShiftMask) { state &= ~ShiftMask; return (lock_state & CLKED) ? 1 : -1; } else { state |= ShiftMask; return (lock_state & CLKED) ? -1 : 1; } } else if (ksym == XK_Caps_Lock) { state ^= ShiftMask; if (lock_state & CLKED) { lock_state &= ~CLKED; return -1; } else { lock_state |= CLKED; return 1; } } else { return 0; } } static void window_exposed(ui_window_t *win, int x, int y, u_int width, u_int height) { if (x < x_off) { ui_window_clear(win, x, y, width, height); if (width <= x_off - x) { return; } width -= (x_off - x); x = x_off; } if (x + width > x_off + normal_pixmap->width) { ui_window_clear(win, x_off + normal_pixmap->width, y, x_off + 1, height); if (x >= x_off + normal_pixmap->width) { return; } width = x_off + normal_pixmap->width - x; } ui_window_copy_area(win, normal_pixmap, None, x - x_off, y, width, height, x, y); } static int start_virtual_kbd(ui_display_t *disp) { u_int width; u_int height; if (normal_pixmap /* && pressed_pixmap */) { width = normal_pixmap->width; height = normal_pixmap->height; } else { width = 0; height = 0; if (!ui_imagelib_load_file(disp, KBD_DIR "/pressed_kbd.six", NULL, &pressed_pixmap, NULL, &width, &height, 0)) { /* * Note that pressed_pixmap can be non-NULL even if * ui_imagelib_load_file() fails. */ pressed_pixmap = NULL; return 0; } width = 0; height = 0; if (!ui_imagelib_load_file(disp, KBD_DIR "/kbd.six", NULL, &normal_pixmap, NULL, &width, &height, 0)) { /* * Note that normal_pixmap can be non-NULL even if * ui_imagelib_load_file() fails. */ normal_pixmap = NULL; goto error; } #if 1 if (disp->depth == 1) { /* XXX */ Pixmap tmp; tmp = normal_pixmap; normal_pixmap = pressed_pixmap; pressed_pixmap = tmp; } #endif /* * It is assumed that the width and height of kbd.png are the same * as those of pressed_kbg.png */ } if (width > disp->width) { width = disp->width; } if (height > disp->height / 2) { height = disp->height / 2; } if (!(kbd_win = malloc(sizeof(ui_window_t)))) { goto error; } ui_window_init(kbd_win, disp->width, height, disp->width, height, disp->width, height, 0, 0, 0, 0); kbd_win->window_exposed = window_exposed; kbd_win->disp = disp; kbd_win->x = 0; kbd_win->y = disp->height - height; ui_window_show(kbd_win, 0); ui_window_clear_all(kbd_win); x_off = (disp->width - width) / 2; ui_window_copy_area(kbd_win, normal_pixmap, None, 0, 0, width, height, x_off, 0); if (disp->num_roots > 0) { ui_window_resize_with_margin(disp->roots[0], disp->width, disp->height - height, NOTIFY_TO_MYSELF); } return 1; error: if (normal_pixmap) { ui_destroy_image(disp->display, normal_pixmap); normal_pixmap = NULL; } if (pressed_pixmap) { ui_destroy_image(disp->display, pressed_pixmap); pressed_pixmap = NULL; } return 0; } /* --- global functions --- */ int ui_virtual_kbd_hide(void) { if (!kbd_win) { return 0; } #if 0 ui_destroy_image(kbd_win->disp->display, normal_pixmap); normal_pixmap = NULL; ui_destroy_image(kbd_win->disp->display, pressed_pixmap); pressed_pixmap = NULL; #endif if (kbd_win->disp->num_roots > 0) { ui_window_resize_with_margin(kbd_win->disp->roots[0], kbd_win->disp->width, kbd_win->disp->height, NOTIFY_TO_MYSELF); } ui_window_final(kbd_win); kbd_win = NULL; return 1; } /* * Return value * 0: is not virtual kbd event. * 1: is virtual kbd event. * -1: is inside the virtual kbd area but not virtual kbd event. */ int ui_is_virtual_kbd_event(ui_display_t *disp, XButtonEvent *bev) { while (!kbd_win) { static int click_num; if (bev->type == ButtonPress) { if (bev->x + bev->y + 20 >= disp->width + disp->height) { if (click_num == 0) { click_num = 1; } else /* if( click_num == 1) */ { click_num = 0; if (start_virtual_kbd(disp)) { break; } } } else { click_num = 0; } } return 0; } if (bev->y < kbd_win->y) { return 0; } if (kbd_win->disp->num_roots > 0 && kbd_win->disp->roots[0]->y + kbd_win->disp->roots[0]->height > kbd_win->y) { /* disp->roots[0] seems to be resized. */ ui_virtual_kbd_hide(); return 0; } if (bev->type == ButtonRelease || bev->type == ButtonPress) { return 1; } else { is_pressed = 0; return -1; } } /* * Call this function after checking if ui_is_virtual_kbd_event() returns 1. * Return value * 1: keytop image is redrawn and kev is set. * 2: keytop image is redrawn but kev is not set. * 0: keytop image is not redrawn and kev is not set. */ int ui_virtual_kbd_read(XKeyEvent *kev, XButtonEvent *bev) { int x; int y; if (bev->type == ButtonRelease) { if (is_pressed) { ui_window_copy_area(kbd_win, normal_pixmap, None, pressed_left, pressed_top, pressed_width, pressed_height, pressed_left + x_off, pressed_top); is_pressed = 0; return 2; } } else /* if( bev->type == ButtonPress) */ { struct kbd_key_group *key_group; u_int count; y = bev->y - kbd_win->y; x = bev->x - x_off; for (count = 0, key_group = kbd_key_groups; count < sizeof(kbd_key_groups) / sizeof(kbd_key_groups[0]); count++, key_group++) { if (y < key_group->top) { break; } if (y <= key_group->bottom) { u_int count2; for (count2 = 0; count2 < key_group->num_keys; count2++) { if (x < key_group->keys[count2].left) { break; } if (x <= key_group->keys[count2].right) { Pixmap pixmap; int ret; if (key_group->keys[count2].ksym == 0) { /* [X] button */ return ui_virtual_kbd_hide(); } if ((ret = update_state(key_group->keys[count2].ksym)) < 0) { pixmap = normal_pixmap; } else { pixmap = pressed_pixmap; } pressed_top = key_group->top; pressed_height = key_group->bottom - pressed_top + 1; pressed_left = key_group->keys[count2].left; pressed_width = key_group->keys[count2].right - pressed_left + 1; ui_window_copy_area(kbd_win, pixmap, None, pressed_left, pressed_top, pressed_width, pressed_height, pressed_left + x_off, pressed_top); if (ret == 0) { is_pressed = 1; kev->type = KeyPress; kev->state = state; kev->ksym = (state & ShiftMask) ? key_group->keys[count2].shift_ksym : key_group->keys[count2].ksym; kev->keycode = key_group->keys[count2].keycode; return 1; } else { return 2; } } } } } } is_pressed = 0; return 0; } ui_window_t *ui_is_virtual_kbd_area(int y) { if (kbd_win && y > kbd_win->y) { return kbd_win; } else { return NULL; } } mlterm-3.8.9/uitoolkit/fb/ui_window.c010064400017600000144000002032351356600660700163310ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_window.h" #include #include #include #include /* bl_usleep */ #include #ifdef USE_WAYLAND #include #endif #include "ui_display.h" #include "ui_font.h" #define MAX_CLICK 3 /* max is triple click */ /* win->width is not multiples of (win)->width_inc in framebuffer. */ #define RIGHT_MARGIN(win) \ ((win)->width_inc ? ((win)->width - (win)->min_width) % (win)->width_inc : 0) #define BOTTOM_MARGIN(win) \ ((win)->height_inc ? ((win)->height - (win)->min_height) % (win)->height_inc : 0) #ifdef USE_GRF static ui_color_t black = {TP_COLOR, 0, 0, 0, 0}; #endif #define ParentRelative (1L) #define DummyPixmap (2L) /* XXX Check if win is input method window or not. */ #define IS_IM_WINDOW(win) ((win)->disp->num_roots >= 2 && (win) == (win)->disp->roots[1]) /* --- static variables --- */ static int click_interval = 250; /* millisecond, same as xterm. */ /* --- static functions --- */ static int scroll_region(ui_window_t *win, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y) { if (!win->is_mapped || !ui_window_is_scrollable(win)) { return 0; } ui_display_copy_lines(win->disp, src_x + win->x + win->hmargin, src_y + win->y + win->vmargin, dst_x + win->x + win->hmargin, dst_y + win->y + win->vmargin, width, height); return 1; } /* * copy_pixel() is called more than twice, so if it is implemented as a function * it may be uninlined in compiling. * dst should be aligned. */ #define copy_pixel(dst, pixel, bpp) \ switch (bpp) { \ case 1: \ *(dst) = pixel; \ break; \ case 2: \ *((u_int16_t *)(dst)) = (pixel); \ break; \ /* case 4: */ \ default: \ *((u_int32_t *)(dst)) = (pixel); \ } static inline u_int16_t *memset16(u_int16_t *dst, u_int16_t i, u_int len) { u_int count; for (count = 0; count < len; count++) { dst[count] = i; } return dst; } static inline u_int32_t *memset32(u_int32_t *dst, u_int32_t i, u_int len) { u_int count; for (count = 0; count < len; count++) { dst[count] = i; } return dst; } #ifdef USE_FREETYPE #define BLEND(fg, bg, alpha) ((bg) + ((fg) - (bg)) * (alpha) / 255) static int copy_blended_pixel(Display *display, u_char *dst, u_char **bitmap, u_long fg, u_long bg, u_int bpp) { int a1 = *((*bitmap)++); int a2 = *((*bitmap)++); int a3 = *((*bitmap)++); if (a1 + a2 + a3 > 0) { int r1; int g1; int b1; int r2; int g2; int b2; u_long pixel; r1 = PIXEL_RED(fg, display->rgbinfo) & 0xff; g1 = PIXEL_GREEN(fg, display->rgbinfo) & 0xff; b1 = PIXEL_BLUE(fg, display->rgbinfo) & 0xff; r2 = PIXEL_RED(bg, display->rgbinfo) & 0xff; g2 = PIXEL_GREEN(bg, display->rgbinfo) & 0xff; b2 = PIXEL_BLUE(bg, display->rgbinfo) & 0xff; pixel = #ifndef MANAGE_ROOT_WINDOWS_BY_MYSELF /* * f: fg color * b: bg color * w: other windows or desktop wall picture below mlterm window. * 0.6, 0.4: a1, a2, a3 * 1.0, 0.0: alpha of fg_color * 0.8, 0.2: alpha of bg color * * Correct: 0.6*(1.0*f + 0.0*w) + 0.4*(0.8*b + 0.2*w) = 0.6*f + 0.32*b + 0.08*w * Lazy : (0.6*f + 0.4*b)*(1.0*0.6+0.8*0.4) + w*(1.0-(1.0*0.6+0.8*0.4)) * ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ * = 0.552*f + 0.368*b + 0.08*w */ BLEND((fg >> 24), (bg >> 24), (a1 + a2 + a3) / 3) << 24 | #endif RGB_TO_PIXEL(BLEND(r1, r2, a1), BLEND(g1, g2, a2), BLEND(b1, b2, a3), display->rgbinfo); copy_pixel(dst, pixel, bpp); return 1; } else { return 0; } } #endif /* * If the width and height of drawn characters is not over the window should be checked * before calling ui_window_draw_*string(). */ static void draw_string_intern(ui_window_t *win, XFontStruct *xfont, u_int font_height, u_int font_ascent, u_int font_width, int font_x_off, int double_draw_gap, int is_proportional, int is_var_col_width, u_int32_t fg_pixel, u_int32_t bg_pixel, int x, /* win->x and win->hmargin are added. */ int y, int y_off, u_char **bitmaps, u_int len, u_char *picture, size_t picture_line_len, int src_bg_is_set, int bpp) { size_t size; u_char *src; u_char *p; u_int count; int orig_x; int orig_y_off; /* * If font_width is larger than xfont->width_full, memory access must be limited * to the latter one. (Don't excess xfont->glyph_width_bytes) */ u_int max_glyph_width = xfont->width_full; u_char *bitmap_line; u_long pixel; if (max_glyph_width + font_x_off > font_width) { max_glyph_width = font_width - font_x_off; } /* (len + 1) is for decreasing the number of calling alloca() below. */ #ifdef USE_FREETYPE if (xfont->is_aa && is_proportional) { /* width_full == glyph_width_bytes / 3 */ u_int width = (len + 1) * (font_width > xfont->width_full ? font_width : xfont->width_full); if (x + width > win->width + win->hmargin + win->x) { width = win->width + win->hmargin + win->x - x; } size = width * bpp; /* This is true only if USE_SDL2 and USE_BG_TEXTURE. (see ui_draw_str.c) */ if (src_bg_is_set && picture) { picture = NULL; picture_line_len = 0; src_bg_is_set = 0; } #if defined(DEBUG) && defined(USE_SDL2) && !defined(USE_BG_TEXTURE) { static int output_msg; if (!output_msg) { bl_debug_printf("mlterm is built without USE_BG_TEXTURE, " "so screen is corrupt with -otl option.\n"); output_msg = 1; } } #endif } else #endif { size = (len + 1) * font_width * bpp; } #if defined(USE_SDL2) && defined(USE_BG_TEXTURE) if (bg_pixel == win->bg_color.pixel || !src_bg_is_set) { bg_pixel = 0x0; src_bg_is_set = 1; } #endif if (!(src = alloca(size))) { return; } #if 1 /* Optimization for most cases */ if (src_bg_is_set && !double_draw_gap #ifdef USE_FREETYPE && !xfont->face #endif ) { int x_off; u_int end_gap = font_width - font_x_off - max_glyph_width; u_int y_off_bytes = y_off * xfont->glyph_width_bytes; switch (bpp) { case 1: for (; y_off < font_height; y_off++, y_off_bytes += xfont->glyph_width_bytes) { p = (picture ? memcpy(src, (picture += picture_line_len), size) : memset(src, bg_pixel, size)); for (count = 0; count < len; count++) { if (!ui_get_bitmap_line(xfont, bitmaps[count], y_off_bytes, bitmap_line)) { p += font_width; } else { p += font_x_off; for (x_off = 0; x_off < max_glyph_width; x_off++, p++) { if (ui_get_bitmap_cell(bitmap_line, x_off)) { *p = fg_pixel; } } p += end_gap; } } ui_display_put_image(win->disp, x, y + y_off, src, p - src, 0); } return; case 2: for (; y_off < font_height; y_off++, y_off_bytes += xfont->glyph_width_bytes) { p = (picture ? memcpy(src, (picture += picture_line_len), size) : memset16(src, bg_pixel, size / 2)); for (count = 0; count < len; count++) { if (!ui_get_bitmap_line(xfont, bitmaps[count], y_off_bytes, bitmap_line)) { p += (font_width * 2); } else { p += (font_x_off * 2); for (x_off = 0; x_off < max_glyph_width; x_off++, p += 2) { if (ui_get_bitmap_cell(bitmap_line, x_off)) { *((u_int16_t *)p) = fg_pixel; } } p += (end_gap * 2); } } ui_display_put_image(win->disp, x, y + y_off, src, p - src, 0); } return; /* case 4: */ default: for (; y_off < font_height; y_off++, y_off_bytes += xfont->glyph_width_bytes) { p = (picture ? memcpy(src, (picture += picture_line_len), size) : memset32(src, bg_pixel, size / 4)); for (count = 0; count < len; count++) { if (!ui_get_bitmap_line(xfont, bitmaps[count], y_off_bytes, bitmap_line)) { p += (font_width * 4); } else { p += (font_x_off * 4); for (x_off = 0; x_off < max_glyph_width; x_off++, p += 4) { if (ui_get_bitmap_cell(bitmap_line, x_off)) { *((u_int32_t *)p) = fg_pixel; } } p += (end_gap * 4); } } ui_display_put_image(win->disp, x, y + y_off, src, p - src, 0); } return; } } #endif orig_x = x; orig_y_off = y_off; for (; y_off < font_height; y_off++) { #if defined(USE_FREETYPE) int prev_crowded_out = 0; #endif if (src_bg_is_set) { if (picture) { memcpy(src, (picture += picture_line_len), size); } else { switch (bpp) { case 1: memset(src, bg_pixel, size); break; case 2: memset16(src, bg_pixel, size / 2); break; /* case 4: */ default: memset32(src, bg_pixel, size / 4); break; } } } p = src; #if defined(USE_FREETYPE) if (xfont->is_aa) { if (is_proportional) { /* * Bitmap format * 1 byte 1 byte 1 byte 1 byte 1 byte 1 byte * [advance] [retreat] [glyph width] [R alpha] [G alpha] [B alpha] ... */ for (count = 0; count < len; count++) { /* * src_bg_is_set is always false if is_proportional is true. * This is because the edge of a glyph which is forced out from a cell * can be redrawn incorrectly even if is_var_col_width is false. * (see #ifdef USE_FRAMEBUFFER #ifdef USE_FREETYPE * #endif #endif in xcore_draw_str() in ui_draw_str.c) */ int x_off; if (!bitmaps[count]) { if (src_bg_is_set /* && !picture */) { p += (font_width * bpp); } else { for (x_off = 0; x_off < font_width; x_off++, p += bpp) { pixel = ui_display_get_pixel(win->disp, x + x_off, y + y_off); copy_pixel(p, pixel, bpp); } } x += font_width; } else { int retreat; int width; width = bitmaps[count][2]; bitmap_line = bitmaps[count] + 3 /* header */ + y_off * width * 3; if ((retreat = bitmaps[count][1]) > 0) { u_int filled; if ((filled = (p - src) / bpp) < retreat) { while (x >= retreat) { int x_off2; x_off = -retreat; if (y_off == orig_y_off) { u_char *new_src; if (retreat - filled > font_width) { /* See (len + 1) above */ size_t new_size = size + (retreat - filled - font_width) * bpp; if (!(new_src = alloca(new_size))) { break; } memcpy(new_src, src, p - src); p = new_src + (p - src); src = new_src; size = new_size; } orig_x -= (retreat - filled); } else { x += (retreat - filled); } memmove(src + (retreat - filled) * bpp, src, p - src); /* * Don't use bg_pixel even if src_bg_is_set and !picture, because retreated * pixels can be uncleared by overwriting glyphs afterwards. */ for (x_off2 = 0, p = src; x_off2 < retreat - filled; x_off2++, p += bpp) { pixel = ui_display_get_pixel(win->disp, x + x_off + x_off2, y + y_off); copy_pixel(p, pixel, bpp); } p = src; goto end_of_retreat; } /* Give up retreating before 'filled'. */ bitmap_line += (retreat - filled); x_off = -filled; p = src; } else { x_off = -retreat; p -= (retreat * bpp); } } else { x_off = 0; } end_of_retreat: width -= retreat; if (is_var_col_width) { int advance = bitmaps[count][0]; if (src_bg_is_set /* && !picture */) { for (; x_off < width; x_off++, p += bpp) { if (copy_blended_pixel(win->disp->display, p, &bitmap_line, fg_pixel, bg_pixel, bpp)) { /* do nothing */ } else if (x_off >= prev_crowded_out) { copy_pixel(p, bg_pixel, bpp); } } for (; x_off < advance; x_off++, p += bpp) { if (x_off >= prev_crowded_out) { copy_pixel(p, bg_pixel, bpp); } } } else { for (; x_off < width; x_off++, p += bpp) { u_long bg = ui_display_get_pixel(win->disp, x + x_off, y + y_off); if (copy_blended_pixel(win->disp->display, p, &bitmap_line, fg_pixel, bg, bpp)) { /* do nothing */ } else if (x_off >= prev_crowded_out) { copy_pixel(p, bg, bpp); } } for (; x_off < advance; x_off++, p += bpp) { if (x_off >= prev_crowded_out) { pixel = ui_display_get_pixel(win->disp, x + x_off, y + y_off); copy_pixel(p, pixel, bpp); } } } if (count + 1 < len) { if (prev_crowded_out > advance) { prev_crowded_out -= advance; } else { prev_crowded_out = 0; } if (advance > 0 && x_off != advance) { p += ((advance - x_off) * bpp); if (x_off > advance && prev_crowded_out < x_off - advance) { prev_crowded_out = x_off - advance; } } x += advance; } else { prev_crowded_out = 0; } } else { /* is_var_col_width is false */ int padding = font_x_off; width += font_x_off; if (width > (len - count) * font_width) { width = (len - count) * font_width; } else if (width + font_x_off < font_width) { int add = (font_width - width - font_x_off) / 2; width += add; padding += add; } if (padding > 0) { if ((!src_bg_is_set /* || picture */) && padding + x_off > 0) { int copy_and_skip = padding; if (x_off < 0) { /* x_off < 0 has been already copied from ui_display_get_pixel(). */ copy_and_skip += (x_off); p += (-x_off * bpp); x_off = 0; } for (; copy_and_skip > 0; copy_and_skip--, x_off++, p += bpp) { if (x_off >= prev_crowded_out) { pixel = ui_display_get_pixel(win->disp, x + x_off, y + y_off); copy_pixel(p, pixel, bpp); } } } else { /* x_off < 0 has been already copied from ui_display_get_pixel(). */ p += (padding * bpp); x_off += padding; } } if (src_bg_is_set /* && !picture */) { for (; x_off < width; x_off++, p += bpp) { if (copy_blended_pixel(win->disp->display, p, &bitmap_line, fg_pixel, bg_pixel, bpp)) { /* do nothing */ } else if (x_off >= prev_crowded_out) { copy_pixel(p, bg_pixel, bpp); } } for (; x_off < font_width; x_off++, p += bpp) { copy_pixel(p, bg_pixel, bpp); } } else { for (; x_off < width; x_off++, p += bpp) { u_long bg = ui_display_get_pixel(win->disp, x + x_off, y + y_off); if (copy_blended_pixel(win->disp->display, p, &bitmap_line, fg_pixel, bg, bpp)) { /* do nothing */ } else if (x_off >= prev_crowded_out) { copy_pixel(p, bg, bpp); } } for (; x_off < font_width; x_off++, p += bpp) { pixel = ui_display_get_pixel(win->disp, x + x_off, y + y_off); copy_pixel(p, pixel, bpp); } } /* If count == len - 1, width <= font_width is always true. */ if (width <= font_width) { prev_crowded_out = 0; } else { prev_crowded_out = width - font_width; p -= (prev_crowded_out * bpp); } x += font_width; } } } } else { u_int y_off_bytes = y_off * xfont->glyph_width_bytes; /* is_proportional is false */ for (count = 0; count < len; count++, x += font_width) { int x_off; if (!bitmaps[count]) { if (src_bg_is_set) { p += (font_width * bpp); } else { for (x_off = 0; x_off < font_width; x_off++, p += bpp) { pixel = ui_display_get_pixel(win->disp, x + x_off, y + y_off); copy_pixel(p, pixel, bpp); } } } else { u_int glyph_end = font_x_off + max_glyph_width; bitmap_line = bitmaps[count] + y_off_bytes; if (src_bg_is_set) { if (picture) { for (x_off = 0; ; x_off++, p += bpp) { if (font_x_off <= x_off && x_off < glyph_end) { u_long bg = (bpp == 2) ? *((u_int16_t *)p) : *((u_int32_t *)p); copy_blended_pixel(win->disp->display, p, &bitmap_line, fg_pixel, bg, bpp); } else if (font_width <= x_off) { break; } } } else { for (x_off = 0; ; x_off++, p += bpp) { if (font_x_off <= x_off && x_off < glyph_end) { copy_blended_pixel(win->disp->display, p, &bitmap_line, fg_pixel, bg_pixel, bpp); } else if (font_width <= x_off) { break; } } } } else { for (x_off = 0; ; x_off++, p += bpp) { if (font_x_off <= x_off && x_off < glyph_end) { u_long bg = ui_display_get_pixel(win->disp, x + x_off, y + y_off); if (copy_blended_pixel(win->disp->display, p, &bitmap_line, fg_pixel, bg, bpp)) { continue; } } else if (font_width <= x_off) { break; } pixel = ui_display_get_pixel(win->disp, x + x_off, y + y_off); copy_pixel(p, pixel, bpp); } } } } } } else #endif { u_int y_off_bytes = y_off * xfont->glyph_width_bytes; for (count = 0; count < len; count++, x += font_width) { int x_off; if (!ui_get_bitmap_line(xfont, bitmaps[count], y_off_bytes, bitmap_line)) { if (src_bg_is_set) { p += (font_width * bpp); } else { for (x_off = 0; x_off < font_width; x_off++, p += bpp) { pixel = ui_display_get_pixel(win->disp, x + x_off, y + y_off); copy_pixel(p, pixel, bpp); } } } else { int force_fg = 0; u_int glyph_end = font_x_off + max_glyph_width; for (x_off = 0; ; x_off++, p += bpp) { if (font_x_off <= x_off && x_off < glyph_end && ui_get_bitmap_cell(bitmap_line, x_off - font_x_off)) { pixel = fg_pixel; force_fg = double_draw_gap; } else if (font_width <= x_off) { break; } else { if (force_fg) { pixel = fg_pixel; force_fg = 0; } else if (src_bg_is_set) { continue; } else { pixel = ui_display_get_pixel(win->disp, x + x_off, y + y_off); } } copy_pixel(p, pixel, bpp); } } } } ui_display_put_image(win->disp, (x = orig_x), y + y_off, src, p - src, !src_bg_is_set); } } static void draw_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, /* must be NULL if wall_picture_bg is 1 */ int x, int y, u_char *str, /* 'len * ch_len' bytes */ u_int len, u_int ch_len, int wall_picture_bg) { u_int bpp; XFontStruct *xfont; u_char **bitmaps; u_int font_height; u_int font_ascent; int y_off; u_char *picture; size_t picture_line_len; u_int count; int src_bg_is_set; u_int clip_bottom; int use_ot_layout; int x_off; if (!win->is_mapped) { return; } if (!(bitmaps = alloca((len * sizeof(*bitmaps))))) { return; } bpp = win->disp->display->bytes_per_pixel; xfont = font->xfont; #ifdef USE_OT_LAYOUT use_ot_layout = (font->use_ot_layout /* && font->ot_font */); #else use_ot_layout = 0; #endif /* * Check if font->height or font->ascent excesses the display height, * because font->height doesn't necessarily equals to the height of the *US-ASCII font. * * XXX * On the other hand, font->width is always the same (or exactly double) for *now. */ font_ascent = font->ascent; font_height = font->height; if (win->clip_height == 0) { clip_bottom = win->height; } else { clip_bottom = win->clip_y + win->clip_height; } if (y >= clip_bottom + font_ascent) { return; } else if (y + font_height - font_ascent > clip_bottom) { font_height -= (y + font_height - font_ascent - clip_bottom + 1); if (font_height < font_ascent) { /* XXX I don't know why but without -1 causes line gap */ y -= (font_ascent - font_height - 1); font_ascent = font_height; } } if (y + font_height - font_ascent < win->clip_y) { return; } else if (y < win->clip_y + font_ascent) { y_off = win->clip_y + font_ascent - y; } else { y_off = 0; } /* Following check is done by the caller of this function. */ #if 0 /* * Check if font->width * len excesses the display height * because full width fonts can be used for characters which console * applications regard as half width. */ if (x + font->width * len > win->width) { len = (win->width - x) / font->width; } #endif x += (win->hmargin + win->x); y = y + (win->vmargin + win->y) - font_ascent; if (wall_picture_bg) { /* bg_color is always NULL */ Pixmap pic; int pic_x; int pic_y; if (win->wall_picture == ParentRelative) { pic = win->parent->wall_picture; pic_x = x; pic_y = y; } else { pic = win->wall_picture; pic_x = x - win->x; pic_y = y - win->y; } picture_line_len = pic->width * bpp; picture = pic->image + (pic_y + y_off) * picture_line_len + /* - picture_line_len is for picture += picture_line_len below. */ pic_x * bpp - picture_line_len; src_bg_is_set = 1; } else { picture = NULL; if (bg_color) { src_bg_is_set = 1; } else { src_bg_is_set = 0; } } x_off = font->x_off; if (ch_len == 1) { for (count = 0; count < len; count++) { bitmaps[count] = ui_get_bitmap(xfont, str + count, 1, use_ot_layout, NULL); } } else /* if(ch_len == 2) */ { XFontStruct *compl_xfont; #if defined(USE_FREETYPE) if (xfont->face && !IS_ISO10646_UCS4(font->id)) { u_char *str_p = str; ef_char_t non_ucs; ef_char_t ucs4; non_ucs.size = 2; non_ucs.cs = FONT_CS(font->id); non_ucs.property = 0; for (count = 0; count < len; count++, str_p += 2) { memcpy(non_ucs.ch, str_p, 2); if (!ef_map_to_ucs4(&ucs4, &non_ucs)) { continue; } if (ucs4.ch[0] == '\0' && ucs4.ch[1] == '\0') { memcpy(str_p, ucs4.ch + 2, 2); } #if 0 else { memcpy(str_p, ucs4.ch, 4); ch_len = 4; } #endif } } #endif for (count = 0; count < len;) { if (0xd8 <= str[0] && str[0] <= 0xdb) { if (use_ot_layout || count >= --len) { break; } if (0xdc <= str[2] && str[2] <= 0xdf) { /* surrogate pair */ ef_int_to_bytes(str, 4, (str[0] - 0xd8) * 0x100 * 0x400 + str[1] * 0x400 + (str[2] - 0xdc) * 0x100 + str[3] + 0x10000); ch_len = 4; } else { /* illegal, ignored. */ len--; count--; str += 4; continue; } } compl_xfont = NULL; bitmaps[count] = ui_get_bitmap(font->xfont, str, ch_len, use_ot_layout, &compl_xfont); if (compl_xfont && xfont != compl_xfont) { u_int w; if (count > 0) { draw_string_intern(win, xfont, font_height, font_ascent, font->width, x_off, font->double_draw_gap, font->is_proportional, font->is_var_col_width, fg_color->pixel, bg_color ? bg_color->pixel : 0, x, y, y_off, bitmaps, count, picture, picture_line_len, src_bg_is_set, bpp); x += (font->width * count); bitmaps[0] = bitmaps[count]; len -= count; count = 0; } else { count++; } xfont = compl_xfont; /* see ui_font.c */ if (font->id & FONT_FULLWIDTH) { w = xfont->width_full; } else { w = xfont->width; } if (w >= font->width) { x_off = 0; } else { x_off = (font->width - w) / 2; } } else { count++; } str += ch_len; ch_len = 2; } } draw_string_intern(win, xfont, font_height, font_ascent, font->width, x_off, font->double_draw_gap, font->is_proportional, font->is_var_col_width, fg_color->pixel, bg_color ? bg_color->pixel : 0, x, y, y_off, bitmaps, len, picture, picture_line_len, src_bg_is_set, bpp); } static int copy_area(ui_window_t *win, Pixmap src, PixmapMask mask, int src_x, /* can be minus */ int src_y, /* can be minus */ u_int width, u_int height, int dst_x, /* can be minus */ int dst_y, /* can be minus */ int accept_margin /* x/y can be minus and over width/height */ ) { int hmargin; int vmargin; int right_margin; int bottom_margin; int y_off; u_int bpp; u_char *picture; size_t src_width_size; if (!win->is_mapped) { return 0; } if (accept_margin) { hmargin = win->hmargin; vmargin = win->vmargin; right_margin = bottom_margin = 0; } else { hmargin = vmargin = 0; right_margin = RIGHT_MARGIN(win); bottom_margin = BOTTOM_MARGIN(win); } if (dst_x >= (int)win->width + hmargin || dst_y >= (int)win->height + vmargin) { return 0; } if (dst_x + width > win->width + hmargin - right_margin) { width = win->width + hmargin - right_margin - dst_x; } if (dst_y + height > win->height + vmargin - bottom_margin) { height = win->height + vmargin - bottom_margin - dst_y; } bpp = win->disp->display->bytes_per_pixel; src_width_size = src->width * bpp; picture = src->image + src_width_size * (vmargin + src_y) + bpp * (hmargin + src_x); if (mask) { mask += ((vmargin + src_y) * src->width + hmargin + src_x); for (y_off = 0; y_off < height; y_off++) { int x_off; u_int w; w = 0; for (x_off = 0; x_off < width; x_off++) { if (mask[x_off]) { w++; if (x_off + 1 == width) { /* for x_off - w */ x_off++; } else { continue; } } else if (w == 0) { continue; } ui_display_put_image(win->disp, win->x + win->hmargin + dst_x + x_off - w, win->y + win->vmargin + dst_y + y_off, picture + bpp * (x_off - w), w * bpp, 0); w = 0; } mask += src->width; picture += src_width_size; } } else { size_t size; size = width * bpp; for (y_off = 0; y_off < height; y_off++) { ui_display_put_image(win->disp, win->x + win->hmargin + dst_x, win->y + win->vmargin + dst_y + y_off, picture, size, 0); picture += src_width_size; } } return 1; } static void clear_margin_area(ui_window_t *win) { u_int right_margin; u_int bottom_margin; right_margin = RIGHT_MARGIN(win); bottom_margin = BOTTOM_MARGIN(win); if (win->hmargin | win->vmargin | right_margin | bottom_margin) { ui_window_clear(win, -(win->hmargin), -(win->vmargin), win->hmargin, ACTUAL_HEIGHT(win)); ui_window_clear(win, 0, -(win->vmargin), win->width, win->vmargin); ui_window_clear(win, win->width - right_margin, -(win->vmargin), win->hmargin + right_margin, ACTUAL_HEIGHT(win)); ui_window_clear(win, 0, win->height - bottom_margin, win->width, win->vmargin + bottom_margin); } /* XXX */ if (win->num_children == 2 && ACTUAL_HEIGHT(win->children[0]) == ACTUAL_HEIGHT(win->children[1])) { if (win->children[0]->x + ACTUAL_WIDTH(win->children[0]) <= win->children[1]->x) { ui_window_clear(win, win->children[0]->x + ACTUAL_WIDTH(win->children[0]), 0, win->children[1]->x - win->children[0]->x - ACTUAL_WIDTH(win->children[0]), win->height); } else if (win->children[0]->x >= win->children[1]->x + ACTUAL_WIDTH(win->children[1])) { ui_window_clear(win, win->children[1]->x + ACTUAL_WIDTH(win->children[1]), 0, win->children[0]->x - win->children[1]->x - ACTUAL_WIDTH(win->children[1]), win->height); } } } static int fix_rl_boundary(ui_window_t *win, int boundary_start, int *boundary_end) { int margin; margin = RIGHT_MARGIN(win); if (boundary_start > win->width - margin) { return 0; } if (*boundary_end > win->width - margin) { *boundary_end = win->width - margin; } return 1; } static void reset_input_focus(ui_window_t *win) { u_int count; #ifndef MANAGE_ROOT_WINDOWS_BY_MYSELF /* * Switching input method engines invokes unfocus and focus. In this case, * it is necessary to search a window which was focused most recently. */ if (win->inputtable > 0) { win->inputtable = -1; } else if (win->inputtable < 0) { if (win->inputtable > -10) { win->inputtable --; } } #else if (win->inputtable) { win->inputtable = -1; } #endif else { win->inputtable = 0; } if (win->is_focused) { win->is_focused = 0; if (win->window_unfocused) { (*win->window_unfocused)(win); } } for (count = 0; count < win->num_children; count++) { reset_input_focus(win->children[count]); } } #ifdef USE_WAYLAND static void check_update_window(ui_window_t *win, int x /* parent */, int y /* parent */) { u_int count; x += win->x; y += win->y; if ((win->parent || win->num_children == 0) && /* XXX ui_layout_t is not updated. */ (ui_display_get_pixel(win->disp, x + ACTUAL_WIDTH(win) / 2, y + ACTUAL_HEIGHT(win) / 2) == 0 || ui_display_get_pixel(win->disp, x + ACTUAL_WIDTH(win) - 1, y + ACTUAL_HEIGHT(win) - 1) == 0)) { /* This window doesn't seem to have been drawn correctly yet after ui_display_resize(). */ ui_window_update_all(win); } for (count = 0; count < win->num_children; count++) { check_update_window(win->children[count], x, y); } } #endif #if 0 static int check_child_window_area(ui_window_t *win) { if (win->num_children > 0) { u_int count; u_int sum; for (sum = 0, count = 1; count < win->num_children; count++) { sum += (ACTUAL_WIDTH(win->children[count]) * ACTUAL_HEIGHT(win->children[count])); } if (sum < win->disp->width * win->disp->height * 0.9) { return 0; } } return 1; } #endif static void convert_to_decsp_font_index(u_char *str, u_int len) { while (len != 0) { if (*str == 0x5f) { *str = 0x7f; } else if (0x5f < *str && *str < 0x7f) { (*str) -= 0x5f; } len--; str++; } } /* --- global functions --- */ int ui_window_init(ui_window_t *win, u_int width, u_int height, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc, u_int hmargin, u_int vmargin, int create_gc, int inputtable) { memset(win, 0, sizeof(ui_window_t)); /* If wall picture is set, scrollable will be 0. */ win->is_scrollable = 1; #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF win->is_focused = 1; #endif win->inputtable = inputtable; win->is_mapped = 1; win->create_gc = create_gc; win->width = width; win->height = height; win->min_width = min_width; win->min_height = min_height; win->width_inc = width_inc; win->height_inc = height_inc; win->sizehint_flag = SIZEHINT_WIDTH|SIZEHINT_HEIGHT; win->hmargin = hmargin; win->vmargin = vmargin; win->prev_clicked_button = -1; win->app_name = "mlterm"; /* Can be changed in ui_display_show_root(). */ return 1; } void ui_window_final(ui_window_t *win) { u_int count; for (count = 0; count < win->num_children; count++) { ui_window_final(win->children[count]); } free(win->children); ui_display_clear_selection(win->disp, win); if (win->window_finalized) { (*win->window_finalized)(win); } } void ui_window_set_type_engine(ui_window_t *win, ui_type_engine_t type_engine) {} void ui_window_add_event_mask(ui_window_t *win, long event_mask) { win->event_mask |= event_mask; } void ui_window_remove_event_mask(ui_window_t *win, long event_mask) { win->event_mask &= ~event_mask; } void ui_window_ungrab_pointer(ui_window_t *win) {} int ui_window_set_wall_picture(ui_window_t *win, Pixmap pic, int do_expose) { #if defined(USE_SDL2) && defined(USE_BG_TEXTURE) ui_display_set_wall_picture(win->disp, pic->image, pic->width, pic->height); return 0; /* to free pic memory */ #else u_int count; #ifdef USE_GRF int ret; if ((ret = x68k_tvram_set_wall_picture(pic->image, pic->width, pic->height))) { win->wall_picture = DummyPixmap; /* dummy */ /* Don't set is_scrollable = 0. */ /* If ret == 2, text vram was initialized just now. */ if (ret == 2) { clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } } return 0; /* to free pic memory. */ } #endif win->wall_picture = pic; win->is_scrollable = 0; if (do_expose) { clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } #if 0 else { ui_window_clear_all(win); } #endif } for (count = 0; count < win->num_children; count++) { ui_window_set_wall_picture(win->children[count], ParentRelative, do_expose); } return 1; #endif } int ui_window_unset_wall_picture(ui_window_t *win, int do_expose) { u_int count; #ifdef USE_GRF x68k_tvram_set_wall_picture(NULL, 0, 0); #endif #if defined(USE_SDL2) && defined(USE_BG_TEXTURE) ui_display_set_wall_picture(win->disp, NULL, 0, 0); #endif win->wall_picture = None; win->is_scrollable = 1; if (do_expose) { clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } #if 0 else { ui_window_clear_all(win); } #endif } for (count = 0; count < win->num_children; count++) { ui_window_unset_wall_picture(win->children[count], do_expose); } return 1; } int ui_window_set_transparent( ui_window_t *win, /* Transparency is applied to all children recursively */ ui_picture_modifier_ptr_t pic_mod) { return 0; } int ui_window_unset_transparent(ui_window_t *win) { return 0; } void ui_window_set_cursor(ui_window_t *win, u_int cursor_shape) { win->cursor_shape = cursor_shape; } int ui_window_set_fg_color(ui_window_t *win, ui_color_t *fg_color) { if (win->fg_color.pixel == fg_color->pixel) { return 0; } win->fg_color = *fg_color; return 1; } int ui_window_set_bg_color(ui_window_t *win, ui_color_t *bg_color) { if (win->bg_color.pixel == bg_color->pixel) { return 0; } #if defined(USE_SDL2) && defined(USE_BG_TEXTURE) ui_display_set_bg_color(win->disp, bg_color->pixel); #endif win->bg_color = *bg_color; clear_margin_area(win); return 1; } int ui_window_add_child(ui_window_t *win, ui_window_t *child, int x, int y, int map) { void *p; if (win->parent) { /* Can't add a grand child window. */ return 0; } if ((p = realloc(win->children, sizeof(*win->children) * (win->num_children + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } win->children = p; child->parent = win; child->x = x + win->hmargin; child->y = y + win->vmargin; #ifndef MANAGE_ROOT_WINDOWS_BY_MYSELF /* * The default value of is_focused is 0 on wayland, while 1 on framebuffer. * (see ui_window_init()) */ if (!(child->is_mapped = map) && child->inputtable > 0) { child->inputtable = -1; } #else if ((child->is_mapped = map) && win->is_focused && child->inputtable) { child->is_focused = 1; } else { child->is_focused = 0; if (child->inputtable > 0) { child->inputtable = -1; } } #endif win->children[win->num_children++] = child; return 1; } int ui_window_remove_child(ui_window_t *win, ui_window_t *child) { u_int count; for (count = 0; count < win->num_children; count++) { if (win->children[count] == child) { child->parent = NULL; win->children[count] = win->children[--win->num_children]; return 1; } } return 0; } ui_window_t *ui_get_root_window(ui_window_t *win) { while (win->parent != NULL) { win = win->parent; } return win; } GC ui_window_get_fg_gc(ui_window_t *win) { return None; } GC ui_window_get_bg_gc(ui_window_t *win) { return None; } int ui_window_show(ui_window_t *win, int hint /* If win->parent(_window) is None, specify XValue|YValue to localte window at win->x/win->y. */ ) { u_int count; if (win->my_window) { /* already shown */ return 0; } if (win->parent) { win->disp = win->parent->disp; win->parent_window = win->parent->my_window; win->gc = win->parent->gc; } win->my_window = win; /* Note that ui_connect_dialog.c uses this. */ if (win->parent && !win->parent->is_transparent && win->parent->wall_picture) { ui_window_set_wall_picture(win, ParentRelative, 0); } /* * This should be called after Window Manager settings, because * ui_set_{window|icon}_name() can be called in win->window_realized(). */ if (win->window_realized) { int is_mapped; /* * Don't show anything until ui_window_resize_with_margin() is called * at the end of this function. */ is_mapped = win->is_mapped; win->is_mapped = 0; /* XXX ui_window_set_wall_picture() depends on this. */ (*win->window_realized)(win); win->is_mapped = is_mapped; } /* * showing child windows. */ for (count = 0; count < win->num_children; count++) { ui_window_show(win->children[count], 0); } #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF if (!win->parent && win->x == 0 && win->y == 0) { ui_window_resize_with_margin(win, win->disp->width, win->disp->height, NOTIFY_TO_MYSELF); } #else /* win->window_realized() which was executed with is_mapped == 0 doesn't draw anything. */ ui_window_update_all(win); #endif return 1; } void ui_window_map(ui_window_t *win) { if (!win->is_mapped) { win->is_mapped = 1; clear_margin_area(win); (*win->window_exposed)(win, 0, 0, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)); } } void ui_window_unmap(ui_window_t *win) { win->is_mapped = 0; } int ui_window_resize(ui_window_t *win, u_int width, /* excluding margin */ u_int height, /* excluding margin */ ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */ ) { #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF if ((flag & NOTIFY_TO_PARENT) && /* XXX Check if win is input method window or not. */ !IS_IM_WINDOW(win)) { if (win->parent) { win = win->parent; } /* * XXX * If Font size, screen_{width|height}_ratio or vertical_mode is changed * and ui_window_resize( NOTIFY_TO_PARENT) is called, ignore this call and * resize windows with display size. */ win->width = 0; return ui_window_resize_with_margin(win, win->disp->width, win->disp->height, NOTIFY_TO_MYSELF); } if (width + win->hmargin * 2 > win->disp->width) { width = win->disp->width - win->hmargin * 2; } if (height + win->vmargin * 2 > win->disp->height) { height = win->disp->height - win->vmargin * 2; } #endif if (win->width == width && win->height == height) { return 0; } #ifndef MANAGE_ROOT_WINDOWS_BY_MYSELF if (win->parent == NULL) { ui_display_resize(win->disp, width + win->hmargin * 2, height + win->vmargin * 2); #ifdef USE_SDL2 if (win->disp->display->resizing) { return 1; } #endif } else if (flag & NOTIFY_TO_PARENT) { return ui_window_resize(win->parent, win->parent->width + width - win->width , win->parent->height + height - win->height, NOTIFY_TO_MYSELF); } #endif win->width = width; win->height = height; if (flag & NOTIFY_TO_MYSELF) { if (win->window_resized) { (*win->window_resized)(win); } /* * clear_margin_area() must be called after win->window_resized * because wall_picture can be resized to fit to the new window * size in win->window_resized. * * Don't clear_margin_area() if flag == 0 because ui_window_resize() * is called before ui_window_move() in ui_im_*_screen.c and could * cause segfault. */ clear_margin_area(win); } #ifdef USE_WAYLAND /* * ui_display_resize() clears screen. * (win is always root here.) */ check_update_window(win, 0, 0); #endif return 1; } /* * !! Notice !! * This function is not recommended. * Use ui_window_resize if at all possible. */ int ui_window_resize_with_margin(ui_window_t *win, u_int width, u_int height, ui_resize_flag_t flag /* NOTIFY_TO_PARENT , NOTIFY_TO_MYSELF */ ) { return ui_window_resize(win, width - win->hmargin * 2, height - win->vmargin * 2, flag); } void ui_window_set_maximize_flag(ui_window_t *win, ui_maximize_flag_t flag) { #ifndef MANAGE_ROOT_WINDOWS_BY_MYSELF if (flag == MAXIMIZE_FULL) { ui_display_set_maximized(win->disp, 1); } else if (flag == MAXIMIZE_RESTORE) { ui_display_set_maximized(win->disp, 0); } #endif } void ui_window_set_normal_hints(ui_window_t *win, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc) { win->min_width = min_width; win->min_height = min_height; win->width_inc = width_inc; win->height_inc = height_inc; } void ui_window_set_override_redirect(ui_window_t *win, int flag) {} int ui_window_set_borderless_flag(ui_window_t *win, int flag) { return 0; } int ui_window_move(ui_window_t *win, int x, int y) { if (win->parent) { x += win->parent->hmargin; y += win->parent->vmargin; } #ifndef MANAGE_ROOT_WINDOWS_BY_MYSELF else { /* * Don't do "win->x = x; win->y = y;" here. * ui_window_xxx(..., x, y) functions add win->x and win->y to x and y arguments, * but it causes unexpected result because MANAGE_ROOT_WINDOWS_BY_MYSELF means that * win->x and win->y of root windows are always 0. */ return ui_display_move(win->disp, x, y); } #endif if (win->x == x && win->y == y) { return 0; } win->x = x; win->y = y; if (/* ! check_child_window_area( ui_get_root_window( win)) || */ win->x + ACTUAL_WIDTH(win) > win->disp->width || win->y + ACTUAL_HEIGHT(win) > win->disp->height) { /* * XXX Hack * (Expect the caller to call ui_window_resize() immediately after this.) */ return 1; } /* * XXX * Check if win is input method window or not, because ui_window_move() * can fall into the following infinite loop on framebuffer. * 1) ui_im_stat_screen::draw_screen() -> * ui_window_move() -> * ui_im_stat_screen::window_exposed() -> * ui_im_stat_screen::draw_screen() * 2) ui_im_candidate_screen::draw_screen() -> * ui_im_candidate_screen::resize() -> * ui_window_move() -> * ui_im_candidate_screen::window_exposed() -> * ui_im_candidate_screen::draw_screen() */ if (!IS_IM_WINDOW(win)) { clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } #if 0 else { ui_window_clear_all(win); } #endif /* XXX */ if (win->parent) { clear_margin_area(win->parent); } } return 1; } void ui_window_clear(ui_window_t *win, int x, int y, u_int width, u_int height) { #ifdef USE_GRF if (x68k_tvram_is_enabled()) { ui_window_fill_with(win, &black, x, y, width, height); } else #endif if (!win->wall_picture) { ui_window_fill_with(win, &win->bg_color, x, y, width, height); } else { Pixmap pic; int src_x; int src_y; if (win->wall_picture == ParentRelative) { src_x = x + win->x; src_y = y + win->y; pic = win->parent->wall_picture; } else { pic = win->wall_picture; src_x = x; src_y = y; } copy_area(win, pic, None, src_x, src_y, width, height, x, y, 1); } } void ui_window_clear_all(ui_window_t *win) { ui_window_clear(win, 0, 0, win->width, win->height); } void ui_window_fill(ui_window_t *win, int x, int y, u_int width, u_int height) { ui_window_fill_with(win, &win->fg_color, x, y, width, height); } void ui_window_fill_with(ui_window_t *win, ui_color_t *color, int x, int y, u_int width, u_int height) { u_char *src; size_t size; int y_off; u_int bpp; u_long pixel; if (!win->is_mapped) { return; } #if defined(USE_SDL2) && defined(USE_BG_TEXTURE) if (color->pixel == win->bg_color.pixel) { pixel = 0; } else #endif { pixel = color->pixel; } x += (win->x + win->hmargin); y += (win->y + win->vmargin); if ((bpp = win->disp->display->bytes_per_pixel) == 1) { ui_display_fill_with(x, y, width, height, (u_int8_t)pixel); } else { if (!(src = alloca((size = width * bpp)))) { return; } for (y_off = 0; y_off < height; y_off++) { u_char *p = src; int x_off; if (bpp == 2) { for (x_off = 0; x_off < width; x_off++) { *((u_int16_t *)p) = pixel; p += 2; } } else /* if (bpp == 4) */ { for (x_off = 0; x_off < width; x_off++) { *((u_int32_t *)p) = pixel; p += 4; } } ui_display_put_image(win->disp, x, y + y_off, src, size, 0); } } } void ui_window_blank(ui_window_t *win) { ui_window_fill_with(win, &win->fg_color, 0, 0, win->width - RIGHT_MARGIN(win), win->height - BOTTOM_MARGIN(win)); } void ui_window_update(ui_window_t *win, int flag) { if (!win->is_mapped) { return; } if (win->update_window) { (*win->update_window)(win, flag); } } void ui_window_update_all(ui_window_t *win) { u_int count; if (!win->is_mapped) { return; } if (!win->parent) { ui_display_reset_cmap(); } clear_margin_area(win); if (win->window_exposed) { (*win->window_exposed)(win, 0, 0, win->width, win->height); } for (count = 0; count < win->num_children; count++) { ui_window_update_all(win->children[count]); } } void ui_window_idling(ui_window_t *win) { u_int count; for (count = 0; count < win->num_children; count++) { ui_window_idling(win->children[count]); } #ifdef __DEBUG if (win->button_is_pressing) { bl_debug_printf(BL_DEBUG_TAG " button is pressing...\n"); } #endif if (win->button_is_pressing && win->button_press_continued) { (*win->button_press_continued)(win, &win->prev_button_press_event); } else if (win->idling) { (*win->idling)(win); } } /* * Return value: 0 => different window. * 1 => finished processing. */ int ui_window_receive_event(ui_window_t *win, XEvent *event) { #if 0 u_int count; for (count = 0; count < win->num_children; count++) { if (ui_window_receive_event(win->children[count], event)) { return 1; } } #endif if (event->type == KeyPress) { if (win->key_pressed) { (*win->key_pressed)(win, &event->xkey); } } else if (event->type == MotionNotify) { if (win->button_is_pressing) { if (win->button_motion) { event->xmotion.x -= win->hmargin; event->xmotion.y -= win->vmargin; (*win->button_motion)(win, &event->xmotion); } /* following button motion ... */ win->prev_button_press_event.x = event->xmotion.x; win->prev_button_press_event.y = event->xmotion.y; win->prev_button_press_event.time = event->xmotion.time; } else if ((win->event_mask & PointerMotionMask) && win->pointer_motion) { event->xmotion.x -= win->hmargin; event->xmotion.y -= win->vmargin; (*win->pointer_motion)(win, &event->xmotion); } } else if (event->type == ButtonRelease) { if (win->button_released) { event->xbutton.x -= win->hmargin; event->xbutton.y -= win->vmargin; (*win->button_released)(win, &event->xbutton); } win->button_is_pressing = 0; } else if (event->type == ButtonPress) { if (win->button_pressed) { event->xbutton.x -= win->hmargin; event->xbutton.y -= win->vmargin; /* XXX If button is released outside screen, ButtonRelease event might not happen. */ if (win->button_is_pressing) { if (win->button_released) { XButtonEvent ev = event->xbutton; ev.type = ButtonRelease; (*win->button_released)(win, &ev); } win->button_is_pressing = 0; } if (win->click_num == MAX_CLICK) { win->click_num = 0; } if (win->prev_clicked_time + click_interval >= event->xbutton.time && event->xbutton.button == win->prev_clicked_button) { win->click_num++; win->prev_clicked_time = event->xbutton.time; } else { win->click_num = 1; win->prev_clicked_time = event->xbutton.time; win->prev_clicked_button = event->xbutton.button; } (*win->button_pressed)(win, &event->xbutton, win->click_num); } if (event->xbutton.button <= Button3) { /* button_is_pressing flag is on except wheel mouse (Button4/Button5). */ win->button_is_pressing = 1; win->prev_button_press_event = event->xbutton; } if (!win->is_focused && win->inputtable && event->xbutton.button == Button1 && !event->xbutton.state) { ui_window_set_input_focus(win); } } #ifndef MANAGE_ROOT_WINDOWS_BY_MYSELF else if (event->type == FocusOut) { reset_input_focus(win); } #endif return 1; } size_t ui_window_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { u_char ch; if (seq_len == 0) { return 0; } *parser = NULL; #ifdef USE_WAYLAND *keysym = event->ksym; { char buf[7]; /* UTF_MAX_SIZE + 1 */ size_t len = ui_display_get_utf8(buf, event->ksym); if (len > 2) { if (seq_len >= len) { static ef_parser_t *utf8_parser; if (utf8_parser == NULL) { utf8_parser = ef_utf8_parser_new(); /* XXX leaked */ } *parser = utf8_parser; memcpy(seq, buf, len); } return len; } else if (len == 0) { return 0; } else { ch = buf[0]; } } #else #ifdef USE_SDL2 if (event->str) { size_t len = strlen(event->str); if (len <= seq_len) { strncpy(seq, event->str, len); *parser = event->parser; *keysym = event->ksym; } return len; } #endif ch = event->ksym; #ifdef __ANDROID__ if (ch == 0) { return ui_display_get_str(seq, seq_len); } #endif if ((*keysym = event->ksym) >= 0x100) { switch (*keysym) { case XK_KP_Multiply: ch = '*'; break; case XK_KP_Add: ch = '+'; break; case XK_KP_Separator: ch = ','; break; case XK_KP_Subtract: ch = '-'; break; case XK_KP_Divide: ch = '/'; break; default: if (win->disp->display->lock_state & NLKED) { switch (*keysym) { case XK_KP_Insert: ch = '0'; break; case XK_KP_End: ch = '1'; break; case XK_KP_Down: ch = '2'; break; case XK_KP_Next: ch = '3'; break; case XK_KP_Left: ch = '4'; break; case XK_KP_Begin: ch = '5'; break; case XK_KP_Right: ch = '6'; break; case XK_KP_Home: ch = '7'; break; case XK_KP_Up: ch = '8'; break; case XK_KP_Prior: ch = '9'; break; case XK_KP_Delete: ch = '.'; break; default: return 0; } *keysym = ch; } else { return 0; } } } else if (*keysym == XK_Tab && (event->state & ShiftMask)) { *keysym = XK_ISO_Left_Tab; return 0; } #endif /* * Control + '@'(0x40) ... '_'(0x5f) -> 0x00 ... 0x1f * * Not "<= '_'" but "<= 'z'" because Control + 'a' is not * distinguished from Control + 'A'. */ if ((event->state & ControlMask) && (ch == ' ' || ('@' <= ch && ch <= 'z'))) { seq[0] = (ch & 0x1f); } else { seq[0] = ch; } return 1; } /* * Scroll functions. * The caller side should clear the scrolled area. */ int ui_window_scroll_upward(ui_window_t *win, u_int height) { return ui_window_scroll_upward_region(win, 0, win->height, height); } #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF int ui_window_is_scrollable(ui_window_t *win) { /* XXX If input method module is activated, don't scroll window. */ if (win->is_scrollable && !IM_WINDOW_IS_ACTIVATED(win->disp)) { return 1; } else { return 0; } } #endif int ui_window_scroll_upward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height) { if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d in window((h) %d (w) %d)\n", boundary_start, boundary_end, height, win->height, win->width); #endif return 0; } return scroll_region(win, 0, boundary_start + height, /* src */ win->width, boundary_end - boundary_start - height, /* size */ 0, boundary_start); /* dst */ } int ui_window_scroll_downward(ui_window_t *win, u_int height) { return ui_window_scroll_downward_region(win, 0, win->height, height); } int ui_window_scroll_downward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height) { if (boundary_start < 0 || boundary_end > win->height || boundary_end <= boundary_start + height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d height %d\n", boundary_start, boundary_end, height); #endif return 0; } return scroll_region(win, 0, boundary_start, win->width, boundary_end - boundary_start - height, 0, boundary_start + height); } int ui_window_scroll_leftward(ui_window_t *win, u_int width) { return ui_window_scroll_leftward_region(win, 0, win->width, width); } int ui_window_scroll_leftward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width) { if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width || !fix_rl_boundary(win, boundary_start, &boundary_end)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d in window((h) %d (w) %d)\n", boundary_start, boundary_end, width, win->height, win->width); #endif return 0; } scroll_region(win, boundary_start + width, 0, /* src */ boundary_end - boundary_start - width, win->height, /* size */ boundary_start, 0); /* dst */ return 1; } int ui_window_scroll_rightward(ui_window_t *win, u_int width) { return ui_window_scroll_rightward_region(win, 0, win->width, width); } int ui_window_scroll_rightward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width) { if (boundary_start < 0 || boundary_end > win->width || boundary_end <= boundary_start + width || !fix_rl_boundary(win, boundary_start, &boundary_end)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " boundary start %d end %d width %d\n", boundary_start, boundary_end, width); #endif return 0; } scroll_region(win, boundary_start, 0, boundary_end - boundary_start - width, win->height, boundary_start + width, 0); return 1; } int ui_window_copy_area(ui_window_t *win, Pixmap src, PixmapMask mask, int src_x, /* >= 0 */ int src_y, /* >= 0 */ u_int width, u_int height, int dst_x, /* >= 0 */ int dst_y /* >= 0 */ ) { return copy_area(win, src, mask, src_x, src_y, width, height, dst_x, dst_y, 0); } void ui_window_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height) { win->clip_y = y; win->clip_height = height; } void ui_window_unset_clip(ui_window_t *win) { win->clip_y = win->clip_height = 0; } void ui_window_draw_decsp_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int len) { convert_to_decsp_font_index(str, len); ui_window_draw_string(win, font, fg_color, x, y, str, len); } void ui_window_draw_decsp_image_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, /* NULL => use wall_picture for bg */ int x, int y, u_char *str, u_int len) { convert_to_decsp_font_index(str, len); ui_window_draw_image_string(win, font, fg_color, bg_color, x, y, str, len); } void ui_window_draw_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int len) { draw_string(win, font, fg_color, NULL, x, y, str, len, 1, 0); } void ui_window_draw_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, XChar2b *str, u_int len) { draw_string(win, font, fg_color, NULL, x, y, str, len, 2, 0); } void ui_window_draw_image_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, /* NULL => use wall_picture for bg */ int x, int y, u_char *str, u_int len) { #ifdef USE_GRF if (bg_color == NULL && x68k_tvram_is_enabled()) { bg_color = &black; } #endif draw_string(win, font, fg_color, bg_color, x, y, str, len, 1, bg_color == NULL); } void ui_window_draw_image_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, /* NULL => use wall_picture for bg */ int x, int y, XChar2b *str, u_int len) { #ifdef USE_GRF if (bg_color == NULL && x68k_tvram_is_enabled()) { bg_color = &black; } #endif draw_string(win, font, fg_color, bg_color, x, y, str, len, 2, bg_color == NULL); } void ui_window_draw_rect_frame(ui_window_t *win, int x1, int y1, int x2, int y2) { ui_window_fill_with(win, &win->fg_color, x1, y1, x2 - x1 + 1, 1); ui_window_fill_with(win, &win->fg_color, x1, y1, 1, y2 - y1 + 1); ui_window_fill_with(win, &win->fg_color, x1, y2, x2 - x1 + 1, 1); ui_window_fill_with(win, &win->fg_color, x2, y1, 1, y2 - y1 + 1); } void ui_set_use_clipboard_selection(int use_it) {} int ui_is_using_clipboard_selection(void) { return 0; } int ui_window_set_selection_owner(ui_window_t *win, Time time) { #ifndef USE_SDL2 if (ui_window_is_selection_owner(win)) { /* Already owner */ } else #endif { ui_display_own_selection(win->disp, win); } #ifdef __ANDROID__ if (win->utf_selection_requested) { (*win->utf_selection_requested)(win, NULL, 0); } #endif return 1; } int ui_window_xct_selection_request(ui_window_t *win, Time time) { #if defined(__ANDROID__) || defined(USE_WAYLAND) return 0; #else if (win->disp->selection_owner && win->disp->selection_owner->xct_selection_requested) { XSelectionRequestEvent ev; ev.type = 0; ev.target = win; (*win->disp->selection_owner->xct_selection_requested)(win->disp->selection_owner, &ev, 0); } return 1; #endif } int ui_window_utf_selection_request(ui_window_t *win, Time time) { #if defined(__ANDROID__) ui_display_request_text_selection(); #elif defined(USE_WAYLAND) || defined(USE_SDL2) ui_display_request_text_selection(win->disp); #else if (win->disp->selection_owner && win->disp->selection_owner->utf_selection_requested) { XSelectionRequestEvent ev; ev.type = 1; ev.target = win; (*win->disp->selection_owner->utf_selection_requested)(win->disp->selection_owner, &ev, 0); } #endif return 1; } void ui_window_send_picture_selection(ui_window_t *win, Pixmap pixmap, u_int width, u_int height) {} void ui_window_send_text_selection(ui_window_t *win, XSelectionRequestEvent *req_ev, u_char *sel_data, size_t sel_len, Atom sel_type) { #if defined(__ANDROID__) ui_display_send_text_selection(sel_data, sel_len); #elif defined(USE_WAYLAND) || defined(USE_SDL2) ui_display_send_text_selection(win->disp, req_ev, sel_data, sel_len); #else if (req_ev) { if (req_ev->type == 1) { if (req_ev->target->utf_selection_notified) { (*req_ev->target->utf_selection_notified)(req_ev->target, sel_data, sel_len); } } else { if (req_ev->target->xct_selection_notified) { (*req_ev->target->xct_selection_notified)(req_ev->target, sel_data, sel_len); } } } #endif } void ui_set_window_name(ui_window_t *win, u_char *name) { #ifndef MANAGE_ROOT_WINDOWS_BY_MYSELF if (name == NULL) { name = win->app_name; } ui_display_set_title(win->disp, name); #endif } void ui_set_icon_name(ui_window_t *win, u_char *name) {} void ui_window_set_icon(ui_window_t *win, ui_icon_picture_ptr_t icon) {} void ui_window_remove_icon(ui_window_t *win) {} void ui_window_reset_group(ui_window_t *win) {} void ui_set_click_interval(int interval) { click_interval = interval; } int ui_get_click_interval(void) { return click_interval; } u_int ui_window_get_mod_ignore_mask(ui_window_t *win, KeySym *keysyms) { return ~0; } u_int ui_window_get_mod_meta_mask(ui_window_t *win, char *mod_key) { return ModMask; } void ui_window_bell(ui_window_t *win, ui_bel_mode_t mode) { if (mode & BEL_VISUAL) { ui_window_blank(win); bl_usleep(100000); /* 100 mili sec */ (*win->window_exposed)(win, 0, 0, win->width, win->height); } } void ui_window_translate_coordinates(ui_window_t *win, int x, int y, int *global_x, int *global_y) { *global_x = x + win->x; *global_y = y + win->y; #if defined(ROTATABLE_DISPLAY) && !defined(MANAGE_ROOT_WINDOWS_BY_MYSELF) /* USE_WAYLAND|USE_SDL2 */ ui_display_logical_to_physical_coordinates(win->disp, global_x, global_y); #endif } void ui_window_set_input_focus(ui_window_t *win) { if (win->inputtable > 0 && win->is_focused) { return; } reset_input_focus(ui_get_root_window(win)); win->inputtable = win->is_focused = 1; if (win->window_focused) { (*win->window_focused)(win); } } /* for ui_display.c */ void ui_window_clear_margin_area(ui_window_t *win) { clear_margin_area(win); } mlterm-3.8.9/uitoolkit/fb/ui_xic.c010064400017600000144000000030251356600660700156000ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_xic.h" /* --- global functions --- */ int ui_xic_activate(ui_window_t *win, char *xim_name, char *xim_locale) { return 1; } int ui_xic_deactivate(ui_window_t *win) { return 1; } char *ui_xic_get_xim_name(ui_window_t *win) { return ""; } char *ui_xic_get_default_xim_name(void) { return ""; } int ui_xic_fg_color_changed(ui_window_t *win) { return 0; } int ui_xic_bg_color_changed(ui_window_t *win) { return 0; } int ui_xic_font_set_changed(ui_window_t *win) { return 0; } int ui_xic_resized(ui_window_t *win) { return 0; } int ui_xic_set_spot(ui_window_t *win) { return 0; } size_t ui_xic_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { return 0; } size_t ui_xic_get_utf8_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event) { return 0; } int ui_xic_filter_event(ui_window_t *win, /* Should be root window. */ XEvent *event) { return 0; } int ui_xic_set_focus(ui_window_t *win) { return 1; } int ui_xic_unset_focus(ui_window_t *win) { return 1; } int ui_xic_is_active(ui_window_t *win) { return 0; } int ui_xic_switch_mode(ui_window_t *win) { return 0; } #if 0 /* * ui_xim.c <-> ui_xic.c communication functions * Not necessary in fb. */ int ui_xim_activated(ui_window_t *win) { return 1; } int ui_xim_destroyed(ui_window_t *win) { return 1; } #endif mlterm-3.8.9/uitoolkit/fb/ui.c012075500017600000144000000000001356600660700166662../win32/ui.custar kenusersmlterm-3.8.9/uitoolkit/fb/ui.h010064400017600000144000000430501356600660700147440ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_H__ #define ___UI_H__ #if defined(__linux__) #include #include #include /* XXX */ #elif defined(__FreeBSD__) #include #if __FreeBSD_version >= 410000 #include #else #include #endif #elif defined(__NetBSD__) || defined(__OpenBSD__) #include #include #include #endif #if defined(__FreeBSD__) typedef video_color_palette_t fb_cmap_t; #elif defined(__NetBSD__) || defined(__OpenBSD__) #define FBIOGETCMAP WSDISPLAYIO_GETCMAP #define FBIOPUTCMAP WSDISPLAYIO_PUTCMAP typedef struct wsdisplay_cmap fb_cmap_t; #else typedef struct fb_cmap fb_cmap_t; #endif /* SIXEL_SHAREPALETTE in c_sixel.c reduces the role of COLOR_CACHE_MINIMUM. */ #define COLOR_CACHE_MINIMUM typedef struct { int fd; int fb_fd; unsigned char *fb; unsigned char *fb_base; size_t smem_len; unsigned int line_length; unsigned int xoffset; unsigned int yoffset; unsigned int bytes_per_pixel; /* public */ unsigned int pixels_per_byte; /* public */ /* Actual width, while ui_display_t.width excludes virtual kbd area. */ unsigned int width; /* Actual height, while ui_display_t.height excludes virtual kbd area. */ unsigned int height; struct rgb_info { unsigned int r_limit; unsigned int g_limit; unsigned int b_limit; unsigned int r_offset; unsigned int g_offset; unsigned int b_offset; } rgbinfo; fb_cmap_t *cmap; fb_cmap_t *cmap_orig; struct { #ifndef COLOR_CACHE_MINIMUM u_int8_t pixels[16384]; /* 2^14 */ u_int32_t flags[512]; /* 2^14/8/4 */ #else /* * Closest color is searched by 14 bits. * R(1)G(1)B(1): segment(3bits) * R(3)G(3)B(2): offset(11bits) */ u_int8_t pixels[2048]; /* 2^11 */ u_int8_t segments[2048]; /* 2^11 */ #endif } * color_cache; int key_state; int lock_state; /* For 1, 2 or 4 bpp */ unsigned char *back_fb; int shift_0; int mask; size_t plane_offset[8]; } Display; #define PIXEL_RED(pixel, rgbinfo) (((pixel) >> (rgbinfo).r_offset) << (rgbinfo).r_limit) #define PIXEL_BLUE(pixel, rgbinfo) (((pixel) >> (rgbinfo).b_offset) << (rgbinfo).b_limit) #define PIXEL_GREEN(pixel, rgbinfo) (((pixel) >> (rgbinfo).g_offset) << (rgbinfo).g_limit) #define RGB_TO_PIXEL(r, g, b, rgbinfo) \ ((((r) >> (rgbinfo).r_limit) << (rgbinfo).r_offset) | \ (((g) >> (rgbinfo).g_limit) << (rgbinfo).g_offset) | \ (((b) >> (rgbinfo).b_limit) << (rgbinfo).b_offset)) typedef int XIC; /* dummy */ typedef void *XID; /* dummy */ typedef void *Window; /* dummy */ typedef void *Drawable; /* dummy */ typedef struct { unsigned char *image; unsigned int width; unsigned int height; } * Pixmap; typedef unsigned char* PixmapMask; typedef int GC; /* dummy */ typedef int Font; /* dummy */ typedef int Cursor; /* dummy */ typedef int KeyCode; typedef int KeySym; typedef struct /* Same as definition in X11/X.h */ { int max_keypermod; KeyCode *modifiermap; } XModifierKeymap; typedef struct /* Same as definition in X11/X.h */ { unsigned char byte1; unsigned char byte2; } XChar2b; typedef struct { int type; unsigned int state; KeySym ksym; unsigned int keycode; } XKeyEvent; typedef unsigned long Time; /* Same as definition in X11/X.h */ typedef unsigned long Atom; /* Same as definition in X11/X.h */ typedef struct { int type; Time time; int x; int y; unsigned int state; unsigned int button; } XButtonEvent; typedef struct { int type; Time time; int x; int y; unsigned int state; } XMotionEvent; typedef struct { int type; struct ui_window *target; } XSelectionRequestEvent; typedef union { int type; XKeyEvent xkey; XButtonEvent xbutton; XMotionEvent xmotion; XSelectionRequestEvent xselectionrequest; } XEvent; typedef struct _XFontStruct { char *file; int32_t format; /* XXX (fontsize|FONT_BOLD|FONT_ITALIC|FONT_ROTATED) on freetype. */ int32_t num_glyphs; unsigned char *glyphs; int32_t glyph_width_bytes; unsigned char width; /* Width of full width characters or max width of half width characters. */ unsigned char width_full; unsigned char height; unsigned char ascent; u_int16_t *glyph_indeces; /* for pcf */ int16_t min_char_or_byte2; int16_t max_char_or_byte2; int16_t min_byte1; int16_t max_byte1; int32_t *glyph_offsets; #ifdef USE_FREETYPE /* for freetype */ void *face; u_int32_t num_indeces; u_int32_t glyph_size; int is_aa; #ifdef USE_FONTCONFIG struct _XFontStruct **compl_xfonts; #endif #endif unsigned int ref_count; } XFontStruct; typedef int XFontSet; /* dummy */ #define None 0L /* Same as definition in X11/X.h */ #define NoSymbol 0L /* Same as definition in X11/X.h */ #define CurrentTime 0L /* Same as definition in X11/X.h */ /* Same as definition in X11/X.h */ #define NoEventMask 0L #define KeyPressMask (1L << 0) #define KeyReleaseMask (1L << 1) #define ButtonPressMask (1L << 2) #define ButtonReleaseMask (1L << 3) #define EnterWindowMask (1L << 4) #define LeaveWindowMask (1L << 5) #define PointerMotionMask (1L << 6) #define PointerMotionHintMask (1L << 7) #define Button1MotionMask (1L << 8) #define Button2MotionMask (1L << 9) #define Button3MotionMask (1L << 10) #define Button4MotionMask (1L << 11) #define Button5MotionMask (1L << 12) #define ButtonMotionMask (1L << 13) #define KeymapStateMask (1L << 14) #define ExposureMask (1L << 15) #define VisibilityChangeMask (1L << 16) #define StructureNotifyMask (1L << 17) #define ResizeRedirectMask (1L << 18) #define SubstructureNotifyMask (1L << 19) #define SubstructureRedirectMask (1L << 20) #define FocusChangeMask (1L << 21) #define PropertyChangeMask (1L << 22) #define ColormapChangeMask (1L << 23) #define OwnerGrabButtonMask (1L << 24) #define ShiftMask (1 << 0) #define LockMask (1 << 1) #define ControlMask (1 << 2) #define Mod1Mask (1 << 3) #define Mod2Mask (1 << 4) #define Mod3Mask (1 << 5) #define Mod4Mask (1 << 6) #define Mod5Mask (1 << 7) #define Button1Mask (1 << 8) #define Button2Mask (1 << 9) #define Button3Mask (1 << 10) #define Button4Mask (1 << 11) #define Button5Mask (1 << 12) #define Button1 1 #define Button2 2 #define Button3 3 #define Button4 4 #define Button5 5 #if defined(__NetBSD__) || defined(__OpenBSD__) #define XK_Super_L 0xfffe /* dummy */ #define XK_Super_R 0xfffd /* dummy */ #define XK_Hyper_L 0xfffc /* dummy */ #define XK_Hyper_R 0xfffb /* dummy */ #define XK_BackSpace 0x08 #define XK_Tab 0x09 #define XK_Clear KS_Clear #define XK_Linefeed KS_Linefeed #define XK_Return 0x0d #define XK_Shift_L KS_Shift_L #define XK_Control_L KS_Control_L #define XK_Alt_L KS_Alt_L #define XK_Shift_R KS_Shift_R #define XK_Control_R KS_Control_R #define XK_Alt_R KS_Alt_R #define XK_Meta_L KS_Meta_L #define XK_Meta_R KS_Meta_R #define XK_Pause KS_Pause #define XK_Shift_Lock KS_Shift_Lock #define XK_Caps_Lock KS_Caps_Lock #define XK_Escape KS_Escape #define XK_Prior KS_Prior #define XK_Next KS_Next #define XK_End KS_End #define XK_Home KS_Home #define XK_Left KS_Left #define XK_Up KS_Up #define XK_Right KS_Right #define XK_Down KS_Down #define XK_Select KS_Select #define XK_Print KS_Print_Screen #define XK_Execute KS_Execute #define XK_Insert KS_Insert #define XK_Delete KS_Delete #define XK_Help KS_Help #define XK_F1 KS_F1 #define XK_F2 KS_F2 #define XK_F3 KS_F3 #define XK_F4 KS_F4 #define XK_F5 KS_F5 #define XK_F6 KS_F6 #define XK_F7 KS_F7 #define XK_F8 KS_F8 #define XK_F9 KS_F9 #define XK_F10 KS_F10 #define XK_F11 KS_F11 #define XK_F12 KS_F12 #define XK_F13 KS_F13 #define XK_F14 KS_F14 #define XK_F15 KS_F15 #define XK_F16 KS_F16 #define XK_F17 KS_F17 #define XK_F18 KS_F18 #define XK_F19 KS_F19 #define XK_F20 KS_F20 #define XK_F21 0xfffa /* dummy */ #define XK_F22 0xfff9 /* dummy */ #define XK_F23 0xfff8 /* dummy */ #define XK_F24 0xfff7 /* dummy */ #define XK_FMAX KS_F20 #define XK_Num_Lock KS_Num_Lock #define XK_Scroll_Lock KS_Scroll_Lock #define XK_Find KS_Find #define XK_Menu KS_Menu #define XK_Begin 0xfff6 /* dummy */ #define XK_Muhenkan KS_Muhenkan #define XK_Henkan_Mode KS_Henkan_Mode #define XK_Zenkaku_Hankaku KS_Zenkaku_Hankaku #define XK_Hiragana_Katakana KS_Hiragana_Katakana #define XK_KP_Prior KS_KP_Prior #define XK_KP_Next KS_KP_Next #define XK_KP_End KS_KP_End #define XK_KP_Home KS_KP_Home #define XK_KP_Left KS_KP_Left #define XK_KP_Up KS_KP_Up #define XK_KP_Right KS_KP_Right #define XK_KP_Down KS_KP_Down #define XK_KP_Insert KS_KP_Insert #define XK_KP_Delete KS_KP_Delete #define XK_KP_F1 KS_KP_F1 #define XK_KP_F2 KS_KP_F2 #define XK_KP_F3 KS_KP_F3 #define XK_KP_F4 KS_KP_F4 #define XK_KP_Begin KS_KP_Begin #define XK_KP_Multiply KS_KP_Multiply #define XK_KP_Add KS_KP_Add #define XK_KP_Separator KS_KP_Separator #define XK_KP_Subtract KS_KP_Subtract #define XK_KP_Decimal KS_KP_Decimal #define XK_KP_Divide KS_KP_Divide #define XK_KP_0 KS_KP_0 #define XK_KP_1 KS_KP_1 #define XK_KP_2 KS_KP_2 #define XK_KP_3 KS_KP_3 #define XK_KP_4 KS_KP_4 #define XK_KP_5 KS_KP_5 #define XK_KP_6 KS_KP_6 #define XK_KP_7 KS_KP_7 #define XK_KP_8 KS_KP_8 #define XK_KP_9 KS_KP_9 #define IsKeypadKey(ksym) (0xf200 <= (ksym) && (ksym) < 0xf300) #define IsModifierKey(ksym) (KS_Shift_L <= (ksym) && (ksym) <= KS_Alt_R) #else /* if __FreeBSD__ || __linux__ */ #ifndef __linux__ /* FreeBSD */ #define KEY_CLEAR 0xff /* dummy */ #define KEY_LINEFEED 0xfe /* dummy */ #define KEY_LEFTSHIFT 0x02 #define KEY_LEFTCTRL 0x09 #define KEY_LEFTALT 0x07 #define KEY_RIGHTSHIFT 0x03 #define KEY_RIGHTCTRL 0x80 #define KEY_RIGHTALT 0x81 #define KEY_LEFTMETA 0xfd /* dummy */ #define KEY_RIGHTMETA 0xfc /* dummy */ #define KEY_CAPSLOCK 0x04 #define KEY_PAGEUP 0x4d #define KEY_PAGEDOWN 0x55 #define KEY_END 0x53 #define KEY_HOME 0x4b #define KEY_LEFT 0x4f #define KEY_UP 0x4c #define KEY_RIGHT 0x51 #define KEY_DOWN 0x54 #define KEY_SELECT 0xfb /* dummy */ #define KEY_PRINT 0x0a #define KEY_INSERT 0x56 #define KEY_DELETE 0x57 #define KEY_HELP 0xfa /* dummy */ #define KEY_F1 0x1b #define KEY_F2 0x1c #define KEY_F3 0x1d #define KEY_F4 0x1e #define KEY_F5 0x1f #define KEY_F6 0x20 #define KEY_F7 0x21 #define KEY_F8 0x22 #define KEY_F9 0x23 #define KEY_F10 0x24 #define KEY_F11 0x25 #define KEY_F12 0x26 #define KEY_F13 0xf9 /* dummy */ #define KEY_F14 0xf8 /* dummy */ #define KEY_F15 0xf7 /* dummy */ #define KEY_F16 0xf6 /* dummy */ #define KEY_F17 0xf5 /* dummy */ #define KEY_F18 0xf4 /* dummy */ #define KEY_F19 0xf3 /* dummy */ #define KEY_F20 0xf2 /* dummy */ #define KEY_F21 0xf1 /* dummy */ #define KEY_F22 0xf0 /* dummy */ #define KEY_F23 0xef /* dummy */ #define KEY_F24 0xee /* dummy */ #define KEY_NUMLOCK 0x05 #define KEY_SCROLLLOCK 0x06 #define KEY_FIND 0xed /* dummy */ #define KEY_MENU 0xec /* dummy */ #define KEY_MUHENKAN 0xeb /* dummy */ #define KEY_HENKAN 0xea /* dummy */ #define KEY_ZENKAKUHANKAKU 0xe9 /* dummy */ #define KEY_KATAKANAHIRAGANA 0xe8 /* dummy */ #define KEY_KPASTERISK 0xe7 /* dummy */ #define KEY_KPPLUS (0x52 + 0x100) #define KEY_KPCOMMA 0xe6 /* dummy */ #define KEY_KPMINUS (0x4e + 0x100) #define KEY_KPDOT (0x7f + 0x100) #define KEY_KPSLASH 0xe5 /* dummy */ #define KEY_KP0 (0x56 + 0x100) #define KEY_KP1 (0x53 + 0x100) #define KEY_KP2 (0x54 + 0x100) #define KEY_KP3 (0x55 + 0x100) #define KEY_KP4 (0x4f + 0x100) #define KEY_KP5 (0x50 + 0x100) #define KEY_KP6 (0x51 + 0x100) #define KEY_KP7 (0x4b + 0x100) #define KEY_KP8 (0x4c + 0x100) #define KEY_KP9 (0x4d + 0x100) #endif /* FreeBSD */ #define XK_Super_L 0xfffe /* dummy */ #define XK_Super_R 0xfffd /* dummy */ #define XK_Hyper_L 0xfffc /* dummy */ #define XK_Hyper_R 0xfffb /* dummy */ #define XK_BackSpace 0x08 #define XK_Tab 0x09 #define XK_Clear (KEY_CLEAR + 0x100) #define XK_Linefeed (KEY_LINEFEED + 0x100) #define XK_Return 0x0d #define XK_Shift_L (KEY_LEFTSHIFT + 0x100) #define XK_Control_L (KEY_LEFTCTRL + 0x100) #define XK_Alt_L (KEY_LEFTALT + 0x100) #define XK_Shift_R (KEY_RIGHTSHIFT + 0x100) #define XK_Control_R (KEY_RIGHTCTRL + 0x100) #define XK_Alt_R (KEY_RIGHTALT + 0x100) #define XK_Meta_L (KEY_LEFTMETA + 0x100) #define XK_Meta_R (KEY_RIGHTMETA + 0x100) #define XK_Pause 0xfff1 /* dummy */ #define XK_Shift_Lock 0xfff0 /* dummy */ #define XK_Caps_Lock (KEY_CAPSLOCK + 0x100) #define XK_Escape 0x1b #define XK_Prior (KEY_PAGEUP + 0x100) #define XK_Next (KEY_PAGEDOWN + 0x100) #define XK_End (KEY_END + 0x100) #define XK_Home (KEY_HOME + 0x100) #define XK_Left (KEY_LEFT + 0x100) #define XK_Up (KEY_UP + 0x100) #define XK_Right (KEY_RIGHT + 0x100) #define XK_Down (KEY_DOWN + 0x100) #define XK_Select (KEY_SELECT + 0x100) #define XK_Print (KEY_PRINT + 0x100) #define XK_Execute 0xffef /* dummy */ #define XK_Insert (KEY_INSERT + 0x100) #define XK_Delete (KEY_DELETE + 0x100) #define XK_Help (KEY_HELP + 0x100) #define XK_F1 (KEY_F1 + 0x100) #define XK_F2 (KEY_F2 + 0x100) #define XK_F3 (KEY_F3 + 0x100) #define XK_F4 (KEY_F4 + 0x100) #define XK_F5 (KEY_F5 + 0x100) #define XK_F6 (KEY_F6 + 0x100) #define XK_F7 (KEY_F7 + 0x100) #define XK_F8 (KEY_F8 + 0x100) #define XK_F9 (KEY_F9 + 0x100) #define XK_F10 (KEY_F10 + 0x100) #define XK_F11 (KEY_F11 + 0x100) #define XK_F12 (KEY_F12 + 0x100) #define XK_F13 (KEY_F13 + 0x100) #define XK_F14 (KEY_F14 + 0x100) #define XK_F15 (KEY_F15 + 0x100) #define XK_F16 (KEY_F16 + 0x100) #define XK_F17 (KEY_F17 + 0x100) #define XK_F18 (KEY_F18 + 0x100) #define XK_F19 (KEY_F19 + 0x100) #define XK_F20 (KEY_F20 + 0x100) #define XK_F21 (KEY_F21 + 0x100) #define XK_F22 (KEY_F22 + 0x100) #define XK_F23 (KEY_F23 + 0x100) #define XK_F24 (KEY_F24 + 0x100) #ifdef __FreeBSD__ #define XK_FMAX XK_F12 #else #define XK_FMAX XK_F10 /* F11 or later is not sequential number. */ #endif #define XK_Num_Lock (KEY_NUMLOCK + 0x100) #define XK_Scroll_Lock (KEY_SCROLLLOCK + 0x100) #define XK_Find (KEY_FIND + 0x100) #define XK_Menu (KEY_MENU + 0x100) #define XK_Begin 0xffee /* dummy */ #define XK_Muhenkan (KEY_MUHENKAN + 0x100) #define XK_Henkan_Mode (KEY_HENKAN + 0x100) #define XK_Zenkaku_Hankaku (KEY_ZENKAKUHANKAKU + 0x100) #define XK_Hiragana_Katakana (KEY_KATAKANAHIRAGANA + 0x100) #define XK_KP_Prior (KEY_KP9 + 0x100) #define XK_KP_Next (KEY_KP3 + 0x100) #define XK_KP_End (KEY_KP1 + 0x100) #define XK_KP_Home (KEY_KP7 + 0x100) #define XK_KP_Left (KEY_KP4 + 0x100) #define XK_KP_Up (KEY_KP8 + 0x100) #define XK_KP_Right (KEY_KP6 + 0x100) #define XK_KP_Down (KEY_KP2 + 0x100) #define XK_KP_Insert (KEY_KP0 + 0x100) #define XK_KP_Delete (KEY_KPDOT + 0x100) #define XK_KP_F1 0xffed /* dummy */ #define XK_KP_F2 0xffec /* dummy */ #define XK_KP_F3 0xffeb /* dummy */ #define XK_KP_F4 0xffea /* dummy */ #define XK_KP_Begin (KEY_KP5 + 0x100) /* dummy */ #define XK_KP_Multiply (KEY_KPASTERISK + 0x100) #define XK_KP_Add (KEY_KPPLUS + 0x100) #define XK_KP_Separator (KEY_KPCOMMA + 0x100) #define XK_KP_Subtract (KEY_KPMINUS + 0x100) #define XK_KP_Decimal 0xffe9 /* dummy */ #define XK_KP_Divide (KEY_KPSLASH + 0x100) #define XK_KP_0 0xffe8 /* dummy */ #define XK_KP_1 0xffe7 /* dummy */ #define XK_KP_2 0xffe6 /* dummy */ #define XK_KP_3 0xffe5 /* dummy */ #define XK_KP_4 0xffe4 /* dummy */ #define XK_KP_5 0xffe3 /* dummy */ #define XK_KP_6 0xffe1 /* dummy */ #define XK_KP_7 0xffe0 /* dummy */ #define XK_KP_8 0xffdf /* dummy */ #define XK_KP_9 0xffde /* dummy */ #define IsKeypadKey(ksym) (1) #define IsModifierKey(ksym) (0) #endif /* FreeBSD/Linux/NetBSD */ #define XK_ISO_Left_Tab 0xffa3 /* dummy */ /* Same as definition in X11/X.h */ typedef struct { short x; short y; } XPoint; /* XXX dummy */ #define XKeysymToKeycode(disp, ks) (ks) #define XKeycodeToKeysym(disp, kc, i) (kc) #define XKeysymToString(ks) "" #define DefaultScreen(disp) (0) #define BlackPixel(disp, screen) (0) #define WhitePixel(disp, screen) (-1) /* Same as definition in X11/cursorfont.h */ #define XC_xterm 152 #define XC_left_ptr 68 /* Same as definition in X11/Xutil.h */ #define NoValue 0x0000 #define XValue 0x0001 #define YValue 0x0002 #define WidthValue 0x0004 #define HeightValue 0x0008 #define AllValues 0x000F #define XNegative 0x0010 #define YNegative 0x0020 int XParseGeometry(char *str, int *x, int *y, unsigned int *width, unsigned int *height); KeySym XStringToKeysym(char *str); /* === Platform dependent options === */ #define UI_COLOR_HAS_RGB #undef SUPPORT_TRUE_TRANSPARENT_BG #ifdef USE_FREETYPE /* XXX pcf fonts isn't scalable, though... */ #define TYPE_XCORE_SCALABLE #else #undef TYPE_XCORE_SCALABLE #endif #define MANAGE_ROOT_WINDOWS_BY_MYSELF #define MANAGE_SUB_WINDOWS_BY_MYSELF /* See also fb/ui_display.c where ui_picture_display_closed() is never called. */ #define INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS #undef SUPPORT_POINT_SIZE_FONT #undef XIM_SPOT_IS_LINE_TOP #undef USE_GC #undef CHANGEABLE_CURSOR #define PLUGIN_MODULE_SUFFIX "fb" #if defined(__NetBSD__) && !defined(USE_GRF) #define KEY_REPEAT_BY_MYSELF #else #undef KEY_REPEAT_BY_MYSELF #endif #define ROTATABLE_DISPLAY #define PSEUDO_COLOR_DISPLAY #if defined(__NetBSD__) || defined(__OpenBSD__) || (defined(__FreeBSD__) && defined(PC98)) /* for old machines */ #define WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE #else #undef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE #endif #undef SUPPORT_URGENT_BELL #undef FORCE_UNICODE #undef NEED_DISPLAY_SYNC_EVERY_TIME #define DRAW_SCREEN_IN_PIXELS #undef NO_DRAW_IMAGE_STRING /* * libpthread is not linked to mlterm explicitly for now. * * Threading is not supported for 8 or less bpp framebuffer imaging * because of ui_display_enable_to_change_cmap() and ui_display_set_cmap(). */ #undef HAVE_PTHREAD #define COMPOSE_DECSP_FONT #ifdef USE_FREETYPE #define USE_REAL_VERTICAL_FONT #else #undef USE_REAL_VERTICAL_FONT #endif #undef NO_DISPLAY_FD #undef FLICK_SCROLL #undef UIWINDOW_SUPPORTS_PREEDITING #endif mlterm-3.8.9/uitoolkit/fb/ui_color.c010064400017600000144000000056421356600660700161420ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_color.h" #include /* strcmp */ #include #include "ui_display.h" /* CMAP_SIZE, ui_cmap_get_closest_color */ /* --- global functions --- */ int ui_load_named_xcolor(ui_display_t *disp, ui_color_t *xcolor, char *name) { vt_color_t color; u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; if (vt_color_parse_rgb_name(&red, &green, &blue, &alpha, name)) { return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, alpha); } if ((color = vt_get_color(name)) != VT_UNKNOWN_COLOR && IS_VTSYS_BASE_COLOR(color)) { /* * 0 : 0x00, 0x00, 0x00 * 1 : 0xff, 0x00, 0x00 * 2 : 0x00, 0xff, 0x00 * 3 : 0xff, 0xff, 0x00 * 4 : 0x00, 0x00, 0xff * 5 : 0xff, 0x00, 0xff * 6 : 0x00, 0xff, 0xff * 7 : 0xe5, 0xe5, 0xe5 */ red = (color & 0x1) ? 0xff : 0; green = (color & 0x2) ? 0xff : 0; blue = (color & 0x4) ? 0xff : 0; } else { if (strcmp(name, "gray") == 0) { red = green = blue = 190; } else if (strcmp(name, "lightgray") == 0) { red = green = blue = 211; } else { return 0; } } return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, 0xff); } int ui_load_rgb_xcolor(ui_display_t *disp, ui_color_t *xcolor, u_int8_t red, u_int8_t green, u_int8_t blue, u_int8_t alpha) { u_long pixel; if (ui_cmap_get_closest_color(&pixel, red, green, blue)) { xcolor->pixel = pixel; ui_cmap_get_pixel_rgb(&xcolor->red, &xcolor->green, &xcolor->blue, pixel); } else { xcolor->red = red; xcolor->green = green; xcolor->blue = blue; xcolor->alpha = alpha; #ifdef USE_WAYLAND /* wl_buffer requires rgb which has been already multiplied by alpha. */ red = red * alpha / 256; green = green * alpha / 256; blue = blue * alpha / 256; #endif xcolor->pixel = RGB_TO_PIXEL(red, green, blue, disp->display->rgbinfo) | (disp->depth == 32 ? (alpha << 24) : 0); } return 1; } void ui_unload_xcolor(ui_display_t *disp, ui_color_t *xcolor) {} void ui_get_xcolor_rgba(u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_int8_t *alpha /* can be NULL */, ui_color_t *xcolor) { *red = xcolor->red; *green = xcolor->green; *blue = xcolor->blue; if (alpha) { *alpha = xcolor->alpha; } } int ui_xcolor_fade(ui_display_t *disp, ui_color_t *xcolor, u_int fade_ratio) { u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; ui_get_xcolor_rgba(&red, &green, &blue, &alpha, xcolor); #if 0 bl_msg_printf("Fading R%d G%d B%d => ", red, green, blue); #endif red = (red * fade_ratio) / 100; green = (green * fade_ratio) / 100; blue = (blue * fade_ratio) / 100; ui_unload_xcolor(disp, xcolor); #if 0 bl_msg_printf("R%d G%d B%d\n", red, green, blue); #endif return ui_load_rgb_xcolor(disp, xcolor, red, green, blue, alpha); } mlterm-3.8.9/uitoolkit/fb/ui_connect_dialog.c010064400017600000144000000071061356600660700177710ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ /* Note that protocols except ssh aren't supported if USE_LIBSSH2 is defined. */ #ifdef USE_LIBSSH2 #include #include #include #include "../ui_connect_dialog.h" #include "../ui_screen.h" #ifdef USE_WAYLAND #include "ui_display.h" #define ui_display_receive_next_event(disp) ui_display_receive_next_event_singly(disp) #endif /* --- static variables --- */ static int end_input; static char *password; static size_t password_len; /* --- static functions --- */ static void key_pressed(ui_window_t *win, XKeyEvent *event) { u_char seq[1]; KeySym ksym; ef_parser_t *parser; if (ui_window_get_str(win, seq, 1, &parser, &ksym, event) == 0) { return; } if (ksym == XK_Return) { if (!password) { password = strdup(""); } end_input = 1; } else { if (ksym == XK_BackSpace) { if (password_len > 0) { password[--password_len] = '\0'; } } else if (0x20 <= seq[0] && seq[0] <= 0x7e) { void *p; if ((p = realloc(password, password_len + 2))) { password = p; password[password_len++] = seq[0]; password[password_len] = '\0'; } } } } /* --- global functions --- */ int ui_connect_dialog(char **uri, /* Should be free'ed by those who call this. */ char **pass, /* Same as uri. If pass is not input, "" is set. */ char **exec_cmd, /* Same as uri. If exec_cmd is not input, NULL is set. */ char **privkey, /* in/out */ int *x11_fwd, /* in/out */ char *display_name, Window parent_window, char *def_server /* (@)(:)(:). */ ) { ui_screen_t *screen; char *prompt; size_t prompt_len; void (*orig_key_pressed)(); prompt_len = 12 + strlen(def_server) + 11; if (!(prompt = alloca(prompt_len + 1))) { return 0; } sprintf(prompt, " Connect to %s. Password:", def_server); if (!(*uri = strdup(def_server))) { return 0; } screen = (ui_screen_t *)parent_window; orig_key_pressed = screen->window.key_pressed; screen->window.key_pressed = key_pressed; ui_window_clear_all(&screen->window); #ifndef USE_CONSOLE ui_window_draw_image_string(&screen->window, ui_get_usascii_font(screen->font_man), ui_get_xcolor(screen->color_man, VT_FG_COLOR), ui_get_xcolor(screen->color_man, VT_BG_COLOR), 0, ui_line_ascent(screen), prompt, prompt_len); #endif do { #ifdef USE_CONSOLE /* * prompt is redrawn every time because ui_display_receive_next_event() receives * "\x1b[8;%d;%d;4;%d;%dt" in startup. */ ui_window_console_draw_string(&screen->window, ui_get_usascii_font(screen->font_man), ui_get_xcolor(screen->color_man, VT_FG_COLOR), ui_get_xcolor(screen->color_man, VT_BG_COLOR), 0, ui_line_ascent(screen), prompt, prompt_len, 0); #endif #ifdef USE_SDL2 { u_int num; ui_get_opened_displays(&num); } #else ui_display_receive_next_event(screen->window.disp); #endif } while (!end_input); end_input = 0; screen->window.key_pressed = orig_key_pressed; if (!password) { free(*uri); return 0; } *pass = password; password = NULL; password_len = 0; *exec_cmd = NULL; #if 0 ui_window_update_all(&screen->window); #endif return 1; } #endif mlterm-3.8.9/uitoolkit/fb/ui_decsp_font.c010064400017600000144000000121631356600660700171440ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_decsp_font.h" #include #include /* malloc */ #include /* strdup */ #include /* --- static functions --- */ static void draw_check(u_char *fb, u_int width_bytes, u_int height) { int y; u_char check1 = 0xaa; u_char check2 = 0x55; for (y = 0; y < height; y++) { if ((y & 1) == 0) { memset(fb, check1, width_bytes); } else { memset(fb, check2, width_bytes); } fb += width_bytes; } } static void draw_vline(u_char *fb, u_int width_bytes, int x, int beg_y, int end_y) { int y; int mask; fb += (width_bytes * beg_y); fb += (x / 8); mask = (1 << (8 - (x&7) - 1)); for (y = beg_y; y <= end_y; y++) { *fb |= mask; fb += width_bytes; } } static void draw_hline(u_char *fb, u_int width_bytes, int beg_x, int end_x, int y) { int x; fb += (width_bytes * y); for (x = beg_x; x <= end_x; x++) { fb[x/8] |= (1 << (8 - (x&7) - 1)); } } static void draw_diamond(u_char *fb, u_int width_bytes, u_int width, u_int height) { int x; int y; u_int mod = height / 2; for (y = 0; y < mod; y++) { x = (width * (mod - y - 1) / mod + 1) / 2; draw_hline(fb, width_bytes, x, width - x - 1, y); } for (; y < height; y++) { x = (width * (y - mod) / mod + 1) / 2; draw_hline(fb, width_bytes, x, width - x - 1, y); } } /* --- global functions --- */ int ui_load_decsp_xfont(XFontStruct *xfont, const char *decsp_id) { u_int width; u_int height; int count; u_int glyph_size; u_char *p; if (sscanf(decsp_id, "decsp-%dx%d", &width, &height) != 2) { return 0; } xfont->file = strdup(decsp_id); xfont->glyph_width_bytes = (width + 7) / 8; xfont->width = xfont->width_full = width; xfont->height = height; xfont->ascent = height - height / 6; xfont->min_char_or_byte2 = 0x1; xfont->max_char_or_byte2 = 0x1e; xfont->num_glyphs = 30; glyph_size = xfont->glyph_width_bytes * height; xfont->glyphs = calloc(30, glyph_size); xfont->glyph_offsets = calloc(30, sizeof(xfont->glyph_offsets[0])); xfont->glyph_indeces = calloc(30, sizeof(xfont->glyph_indeces[0])); xfont->ref_count = 1; for (count = 0; count < 30; count++) { xfont->glyph_offsets[count] = count * glyph_size; xfont->glyph_indeces[count] = count; } /* * Glyph map * * Used , Used , None , None , None , None , None , * None , None , None , Used , Used , Used , Used , Used , * Used , Used , Used , Used , Used , Used , Used , Used , * Used , Used , None , None , None , None , Used */ p = xfont->glyphs; draw_diamond(p, xfont->glyph_width_bytes, width, height); p += glyph_size; draw_check(p, xfont->glyph_width_bytes, height); p += (glyph_size * (0x0a - 0x01)); draw_hline(p, xfont->glyph_width_bytes, 0, width / 2 - 1, height / 2 - 1); draw_vline(p, xfont->glyph_width_bytes, width / 2 - 1, 0, height / 2 - 1); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, 0, width / 2 - 1, height / 2 - 1); draw_vline(p, xfont->glyph_width_bytes, width / 2 - 1, height / 2 - 1, height - 1); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, width / 2 - 1, width - 1, height / 2 - 1); draw_vline(p, xfont->glyph_width_bytes, width / 2 - 1, height / 2 - 1, height - 1); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, width / 2 - 1, width - 1, height / 2 - 1); draw_vline(p, xfont->glyph_width_bytes, width / 2 - 1, 0, height / 2 - 1); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, 0, width - 1, height / 2 - 1); draw_vline(p, xfont->glyph_width_bytes, width / 2 - 1, 0, height - 1); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, 0, width - 1, 0); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, 0, width - 1, height / 4 - 1); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, 0, width - 1, height / 2 - 1); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, 0, width - 1, height * 3 / 4 - 1); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, 0, width - 1, height - 1); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, width / 2 - 1, width - 1, height / 2 - 1); draw_vline(p, xfont->glyph_width_bytes, width / 2 - 1, 0, height - 1); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, 0, width / 2 - 1, height / 2 - 1); draw_vline(p, xfont->glyph_width_bytes, width / 2 - 1, 0, height - 1); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, 0, width - 1, height / 2 - 1); draw_vline(p, xfont->glyph_width_bytes, width / 2 - 1, 0, height / 2 - 1); p += glyph_size; draw_hline(p, xfont->glyph_width_bytes, 0, width - 1, height / 2 - 1); draw_vline(p, xfont->glyph_width_bytes, width / 2 - 1, height / 2 - 1, height - 1); p += glyph_size; draw_vline(p, xfont->glyph_width_bytes, width / 2 - 1, 0, height - 1); p += (glyph_size * (0x1d - 0x18)); draw_hline(p, xfont->glyph_width_bytes, width / 2 - 2, width / 2, height / 2 - 1); draw_vline(p, xfont->glyph_width_bytes, width / 2 - 1, height / 2 - 2, height / 2); return 1; } /* unload_pcf() in ui_font.c completely frees memory. */ mlterm-3.8.9/uitoolkit/fb/ui_decsp_font.h010064400017600000144000000003331356600660700171450ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_DECSP_FONT_H__ #define __UI_DECSP_FONT_H__ #include "../ui.h" int ui_load_decsp_xfont(XFontStruct *xfont, const char *decsp_id); #endif mlterm-3.8.9/uitoolkit/fb/ui_display.c010064400017600000144000001623431356600660700164730ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_display.h" #include /* printf */ #include /* STDIN_FILENO */ #include /* open */ #include /* mmap */ #include /* ioctl */ #include /* memset/memcpy */ #include /* getenv */ #include #include #include /* bl_priv_change_e(u|g)id */ #include /* bl_getuid */ #include #include /* alloca */ #include #include "../ui_window.h" #include "../ui_picture.h" #include "ui_virtual_kbd.h" #define DISP_IS_INITED (_disp.display) #define MOUSE_IS_INITED (_mouse.fd != -1) #define CMAP_IS_INITED (_display.cmap) /* Because ppb is 2, 4 or 8, "% ppb" can be replaced by "& ppb" */ #define MOD_PPB(i, ppb) ((i) & ((ppb)-1)) /* * If the most significant bit stores the pixel at the right side of the screen, * define VRAMBIT_MSBRIGHT. */ #if 0 #define VRAMBIT_MSBRIGHT #endif #if 0 #define ENABLE_2_4_PPB #endif #ifdef ENABLE_2_4_PPB #ifdef VRAMBIT_MSBRIGHT #define FB_SHIFT(ppb, bpp, idx) (MOD_PPB(idx, ppb) * (bpp)) #define FB_SHIFT_0(ppb, bpp) (0) #define FB_SHIFT_NEXT(shift, bpp) ((shift) += (bpp)) #else #define FB_SHIFT(ppb, bpp, idx) (((ppb)-MOD_PPB(idx, ppb) - 1) * (bpp)) #define FB_SHIFT_0(ppb, bpp) (((ppb)-1) * (bpp)) #define FB_SHIFT_NEXT(shift, bpp) ((shift) -= (bpp)) #endif #define FB_MASK(ppb) ((2 << (8 / (ppb)-1)) - 1) #define PLANE(image) (image) #else /* ENABLE_2_4_PPB */ #ifdef VRAMBIT_MSBRIGHT #define FB_SHIFT(ppb, bpp, idx) MOD_PPB(idx, ppb) #define FB_SHIFT_0(ppb, bpp) (0) #define FB_SHIFT_NEXT(shift, bpp) ((shift) += 1) #else #define FB_SHIFT(ppb, bpp, idx) (7 - MOD_PPB(idx, ppb)) #define FB_SHIFT_0(ppb, bpp) (7) #define FB_SHIFT_NEXT(shift, bpp) ((shift) -= 1) #endif #define FB_MASK(ppb) (1) #define PLANE(image) (((image) >> plane) & 0x1) #endif /* ENABLE_2_4_PPB */ #define FB_WIDTH_BYTES(display, x, width) \ ((width) * (display)->bytes_per_pixel / (display)->pixels_per_byte + \ (MOD_PPB(x, (display)->pixels_per_byte) > 0 ? 1 : 0) + \ (MOD_PPB((x) + (width), (display)->pixels_per_byte) > 0 ? 1 : 0)) /* * for 1, 2 or 4 bpp * * XXX * 0xfe (254) indexed color is regarded as BG_MAGIC on 8bpp/8planes (Luna88k). */ #define BG_MAGIC 0xfe /* Enable doube buffering on 1, 2 or 4 bpp */ #if 1 #define ENABLE_DOUBLE_BUFFER #endif /* Parameters of mouse cursor */ #define MAX_CURSOR_SHAPE_WIDTH 15 #define CURSOR_SHAPE_SIZE (7 * 15 * sizeof(u_int32_t)) /* * Note that this structure could be casted to Display. * * x, y, width and height are on the physical display. * (rotate_display is not considered.) */ typedef struct { int fd; /* Same as Display */ int x; int y; int button_state; struct { /* x/y is left/top of the cursor. */ int x; int y; int width; int height; /* x and y offset of cursor_shape */ int x_off; int y_off; int is_drawn; } cursor; u_char saved_image[CURSOR_SHAPE_SIZE]; int hidden_region_saved; } Mouse; /* --- static variables --- */ static Display _display; static ui_display_t _disp; static Mouse _mouse; static ui_display_t _disp_mouse; static ui_display_t *opened_disps[] = {&_disp, &_disp_mouse}; #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE static int use_ansi_colors = 1; #endif static int rotate_display = 0; static struct termios orig_tm; static const char cursor_shape_normal[] = "#######" "#*****#" "###*###" " #*# " " #*# " " #*# " " #*# " " #*# " " #*# " " #*# " " #*# " " #*# " "###*###" "#*****#" "#######"; static const char cursor_shape_rotate[] = "### ###" "#*# #*#" "#*###########*#" "#*************#" "#*###########*#" "#*# #*#" "### ###"; static struct cursor_shape { const char *shape; u_int width; u_int height; int x_off; int y_off; } cursor_shape = { cursor_shape_normal, 7, /* width */ 15, /* height */ -3, /* x_off */ -7 /* y_off */ }; /* --- static functions --- */ static inline ui_window_t *get_window_intern(ui_window_t *win, int x, int y) { u_int count; for (count = 0; count < win->num_children; count++) { ui_window_t *child; if ((child = win->children[count])->is_mapped) { if (child->x <= x && x < child->x + ACTUAL_WIDTH(child) && child->y <= y && y < child->y + ACTUAL_HEIGHT(child)) { return get_window_intern(child, x - child->x, y - child->y); } } } return win; } /* * _disp.roots[1] is ignored. * x and y are rotated values. */ static inline ui_window_t *get_window(int x, /* X in display */ int y /* Y in display */ ) { return get_window_intern(_disp.roots[0], x, y); } static inline u_char *get_fb(int x, int y) { return _display.fb_base + (_display.yoffset + y) * _display.line_length + (_display.xoffset + x) * _display.bytes_per_pixel / _display.pixels_per_byte; } static void put_image_124bpp(int x, int y, u_char *image, size_t size, int write_back_fb, int need_fb_pixel) { u_int ppb; u_int bpp; u_char *new_image; u_char *new_image_p; u_char *fb; int shift; size_t count; int plane; ppb = _display.pixels_per_byte; bpp = 8 / ppb; fb = get_fb(x, y); #ifdef ENABLE_DOUBLE_BUFFER if (write_back_fb) { new_image = _display.back_fb + (fb - _display.fb); } else #endif { /* + 2 is for surplus */ if (!(new_image = alloca(size / ppb + 2))) { return; } } plane = 0; while (1) { new_image_p = new_image; shift = FB_SHIFT(ppb, bpp, x); count = 0; if (need_fb_pixel && memchr(image, BG_MAGIC, size)) { #ifdef ENABLE_DOUBLE_BUFFER if (!write_back_fb) #endif { memcpy(new_image, #ifdef ENABLE_DOUBLE_BUFFER _display.back_fb + (fb - _display.fb), #else fb, #endif size / ppb + 2); } if (shift == _display.shift_0) { aligned_0: #ifndef ENABLE_2_4_PPB if (_disp.depth > 1) { /* _disp.depth == 2, 4, 8 / ppb == 8 */ for (; count + 7 < size; count += 8, new_image_p++) { *new_image_p = #ifdef VRAMBIT_MSBRIGHT (image[count] == BG_MAGIC ? (*new_image_p) & 0x01 : PLANE(image[count]) << 0) | (image[count+1] == BG_MAGIC ? (*new_image_p) & 0x02 : PLANE(image[count+1]) << 1) | (image[count+2] == BG_MAGIC ? (*new_image_p) & 0x04 : PLANE(image[count+2]) << 2) | (image[count+3] == BG_MAGIC ? (*new_image_p) & 0x08 : PLANE(image[count+3]) << 3) | (image[count+4] == BG_MAGIC ? (*new_image_p) & 0x10 : PLANE(image[count+4]) << 4) | (image[count+5] == BG_MAGIC ? (*new_image_p) & 0x20 : PLANE(image[count+5]) << 5) | (image[count+6] == BG_MAGIC ? (*new_image_p) & 0x40 : PLANE(image[count+6]) << 6) | (image[count+7] == BG_MAGIC ? (*new_image_p) & 0x80 : PLANE(image[count+7]) << 7); #else (image[count] == BG_MAGIC ? (*new_image_p) & 0x80 : PLANE(image[count]) << 7) | (image[count+1] == BG_MAGIC ? (*new_image_p) & 0x40 : PLANE(image[count+1]) << 6) | (image[count+2] == BG_MAGIC ? (*new_image_p) & 0x20 : PLANE(image[count+2]) << 5) | (image[count+3] == BG_MAGIC ? (*new_image_p) & 0x10 : PLANE(image[count+3]) << 4) | (image[count+4] == BG_MAGIC ? (*new_image_p) & 0x08 : PLANE(image[count+4]) << 3) | (image[count+5] == BG_MAGIC ? (*new_image_p) & 0x04 : PLANE(image[count+5]) << 2) | (image[count+6] == BG_MAGIC ? (*new_image_p) & 0x02 : PLANE(image[count+6]) << 1) | (image[count+7] == BG_MAGIC ? (*new_image_p) & 0x01 : PLANE(image[count+7]) << 0); #endif } } #else /* ENABLE_2_4_PPB */ if (ppb == 4) { /* _disp.depth == 2 / ppb == 4 */ for (; count + 3 < size; count += 4, new_image_p++) { *new_image_p = #ifdef VRAMBIT_MSBRIGHT (image[count] == BG_MAGIC ? (*new_image_p) & 0x03 : image[count] << 0) | (image[count+1] == BG_MAGIC ? (*new_image_p) & 0x0c : image[count+1] << 2) | (image[count+2] == BG_MAGIC ? (*new_image_p) & 0x30 : image[count+2] << 4) | (image[count+3] == BG_MAGIC ? (*new_image_p) & 0xc0 : image[count+3] << 6); #else (image[count] == BG_MAGIC ? (*new_image_p) & 0xc0 : image[count] << 6) | (image[count+1] == BG_MAGIC ? (*new_image_p) & 0x30 : image[count+1] << 4) | (image[count+2] == BG_MAGIC ? (*new_image_p) & 0x0c : image[count+2] << 2) | (image[count+3] == BG_MAGIC ? (*new_image_p) & 0x03 : image[count+3] << 0); #endif } } else if (ppb == 2) { /* _disp.depth == 4 / ppb == 8 */ for (; count + 1 < size; count += 2, new_image_p++) { *new_image_p = #ifdef VRAMBIT_MSBRIGHT (image[count] == BG_MAGIC ? (*new_image_p) & 0x0f : image[count] << 0) | (image[count+1] == BG_MAGIC ? (*new_image_p) & 0xf0 : image[count+1] << 4) | #else (image[count] == BG_MAGIC ? (*new_image_p) & 0xf0 : image[count] << 4) | (image[count+1] == BG_MAGIC ? (*new_image_p) & 0x0f : image[count+1] << 0); #endif } } #endif /* ENABLE_2_4_PPB */ else { /* _disp.depth == 1 / ppb == 8 */ for (; count + 7 < size; count += 8, new_image_p++) { *new_image_p = #ifdef VRAMBIT_MSBRIGHT (image[count] == BG_MAGIC ? (*new_image_p) & 0x01 : image[count] << 0) | (image[count+1] == BG_MAGIC ? (*new_image_p) & 0x02 : image[count+1] << 1) | (image[count+2] == BG_MAGIC ? (*new_image_p) & 0x04 : image[count+2] << 2) | (image[count+3] == BG_MAGIC ? (*new_image_p) & 0x08 : image[count+3] << 3) | (image[count+4] == BG_MAGIC ? (*new_image_p) & 0x10 : image[count+4] << 4) | (image[count+5] == BG_MAGIC ? (*new_image_p) & 0x20 : image[count+5] << 5) | (image[count+6] == BG_MAGIC ? (*new_image_p) & 0x40 : image[count+6] << 6) | (image[count+7] == BG_MAGIC ? (*new_image_p) & 0x80 : image[count+7] << 7); #else (image[count] == BG_MAGIC ? (*new_image_p) & 0x80 : image[count] << 7) | (image[count+1] == BG_MAGIC ? (*new_image_p) & 0x40 : image[count+1] << 6) | (image[count+2] == BG_MAGIC ? (*new_image_p) & 0x20 : image[count+2] << 5) | (image[count+3] == BG_MAGIC ? (*new_image_p) & 0x10 : image[count+3] << 4) | (image[count+4] == BG_MAGIC ? (*new_image_p) & 0x08 : image[count+4] << 3) | (image[count+5] == BG_MAGIC ? (*new_image_p) & 0x04 : image[count+5] << 2) | (image[count+6] == BG_MAGIC ? (*new_image_p) & 0x02 : image[count+6] << 1) | (image[count+7] == BG_MAGIC ? (*new_image_p) & 0x01 : image[count+7] << 0); #endif } } } if (count < size) { while (1) { if (image[count] != BG_MAGIC) { (*new_image_p) = ((*new_image_p) & ~(_display.mask << shift)) | (PLANE(image[count]) << shift); } if (++count == size) { new_image_p++; break; } #ifdef VRAMBIT_MSBRIGHT if (FB_SHIFT_NEXT(shift, bpp) >= 8) #else if (FB_SHIFT_NEXT(shift, bpp) < 0) #endif { new_image_p++; shift = _display.shift_0; goto aligned_0; } } } } else { if (shift == _display.shift_0) { aligned_1: #ifndef ENABLE_2_4_PPB if (_disp.depth > 1) { /* _disp.depth == 2, 4, 8 / ppb == 8 */ for (; count + 7 < size; count += 8) { *(new_image_p++) = #ifdef VRAMBIT_MSBRIGHT PLANE(image[count]) | (PLANE(image[count + 1]) << 1) | (PLANE(image[count + 2]) << 2) | (PLANE(image[count + 3]) << 3) | (PLANE(image[count + 4]) << 4) | (PLANE(image[count + 5]) << 5) | (PLANE(image[count + 6]) << 6) | (PLANE(image[count + 7]) << 7); #else (PLANE(image[count]) << 7) | (PLANE(image[count + 1]) << 6) | (PLANE(image[count + 2]) << 5) | (PLANE(image[count + 3]) << 4) | (PLANE(image[count + 4]) << 3) | (PLANE(image[count + 5]) << 2) | (PLANE(image[count + 6]) << 1) | PLANE(image[count + 7]); #endif } } #else /* ENABLE_2_4_PPB */ if (ppb == 4) { /* _disp.depth == 2 / ppb = 4 */ for (; count + 3 < size; count += 4) { *(new_image_p++) = #ifdef VRAMBIT_MSBRIGHT image[count] | (image[count + 1] << 2) | (image[count + 2] << 4) | (image[count + 3] << 6); #else (image[count] << 6) | (image[count + 1] << 4) | (image[count + 2] << 2) | image[count + 3]; #endif } } else if (ppb == 2) { /* _disp.depth == 4 / ppb == 2 */ for (; count + 1 < size; count += 2) { *(new_image_p++) = #ifdef VRAMBIT_MSBRIGHT image[count] | (image[count + 1] << 4); #else (image[count] << 4) | image[count + 1]; #endif } } #endif /* ENABLE_2_4_PPB */ else { /* _disp.depth == 1 / ppb == 8 */ for (; count + 7 < size; count += 8) { *(new_image_p++) = #ifdef VRAMBIT_MSBRIGHT image[count] | (image[count + 1] << 1) | (image[count + 2] << 2) | (image[count + 3] << 3) | (image[count + 4] << 4) | (image[count + 5] << 5) | (image[count + 6] << 6) | (image[count + 7] << 7); #else (image[count] << 7) | (image[count + 1] << 6) | (image[count + 2] << 5) | (image[count + 3] << 4) | (image[count + 4] << 3) | (image[count + 5] << 2) | (image[count + 6] << 1) | image[count + 7]; #endif } } } if (count < size) { *new_image_p = #ifdef ENABLE_DOUBLE_BUFFER _display.back_fb[fb - _display.fb + new_image_p - new_image]; #else fb[new_image_p - new_image]; #endif while (1) { *new_image_p = ((*new_image_p) & ~(_display.mask << shift)) | (PLANE(image[count]) << shift); if (++count == size) { new_image_p++; break; } #ifdef VRAMBIT_MSBRIGHT if (FB_SHIFT_NEXT(shift, bpp) >= 8) #else if (FB_SHIFT_NEXT(shift, bpp) < 0) #endif { new_image_p++; shift = _display.shift_0; goto aligned_1; } } } } memcpy(fb, new_image, new_image_p - new_image); #ifndef ENABLE_2_4_PPB if (++plane < _disp.depth) { size_t offset; offset = _display.plane_offset[plane] - _display.plane_offset[plane - 1]; fb += offset; #ifdef ENABLE_DOUBLE_BUFFER if (write_back_fb) { new_image += offset; } #endif } else #endif { break; } } } static void rotate_mouse_cursor_shape(void) { int tmp; cursor_shape.shape = (cursor_shape.shape == cursor_shape_normal) ? cursor_shape_rotate : cursor_shape_normal; tmp = cursor_shape.x_off; cursor_shape.x_off = cursor_shape.y_off; cursor_shape.y_off = tmp; tmp = cursor_shape.width; cursor_shape.width = cursor_shape.height; cursor_shape.height = tmp; } static void update_mouse_cursor_state(void) { if (-cursor_shape.x_off > _mouse.x) { _mouse.cursor.x = 0; _mouse.cursor.x_off = -cursor_shape.x_off - _mouse.x; } else { _mouse.cursor.x = _mouse.x + cursor_shape.x_off; _mouse.cursor.x_off = 0; } _mouse.cursor.width = cursor_shape.width - _mouse.cursor.x_off; if (_mouse.cursor.x + _mouse.cursor.width > _display.width) { _mouse.cursor.width -= (_mouse.cursor.x + _mouse.cursor.width - _display.width); } if (-cursor_shape.y_off > _mouse.y) { _mouse.cursor.y = 0; _mouse.cursor.y_off = -cursor_shape.y_off - _mouse.y; } else { _mouse.cursor.y = _mouse.y + cursor_shape.y_off; _mouse.cursor.y_off = 0; } _mouse.cursor.height = cursor_shape.height - _mouse.cursor.y_off; if (_mouse.cursor.y + _mouse.cursor.height > _display.height) { _mouse.cursor.height -= (_mouse.cursor.y + _mouse.cursor.height - _display.height); } } static void restore_hidden_region(void) { if (!_mouse.cursor.is_drawn) { return; } /* Set 0 before window_exposed is called. */ _mouse.cursor.is_drawn = 0; if (_mouse.hidden_region_saved) { size_t width; u_char *saved; int plane; int num_planes; u_char *fb; u_int count; width = FB_WIDTH_BYTES(&_display, _mouse.cursor.x, _mouse.cursor.width); saved = _mouse.saved_image; if (_display.pixels_per_byte == 8) { num_planes = _disp.depth; } else { num_planes = 1; } for (plane = 0; plane < num_planes; plane++) { fb = get_fb(_mouse.cursor.x, _mouse.cursor.y) + _display.plane_offset[plane]; for (count = 0; count < _mouse.cursor.height; count++) { memcpy(fb, saved, width); saved += width; fb += _display.line_length; } } } else { ui_window_t *win; int cursor_x; int cursor_y; u_int cursor_height; u_int cursor_width; if (rotate_display) { win = get_window(_mouse.y, _display.width - _mouse.x - 1); if (rotate_display > 0) { cursor_x = _mouse.cursor.y; cursor_y = _display.width - _mouse.cursor.x - _mouse.cursor.width; } else { cursor_x = _display.height - _mouse.cursor.y - _mouse.cursor.height; cursor_y = _mouse.cursor.x; } cursor_width = _mouse.cursor.height; cursor_height = _mouse.cursor.width; } else { win = get_window(_mouse.x, _mouse.y); cursor_x = _mouse.cursor.x; cursor_y = _mouse.cursor.y; cursor_width = _mouse.cursor.width; cursor_height = _mouse.cursor.height; } if (win->window_exposed) { (*win->window_exposed)(win, cursor_x - win->x - win->hmargin, cursor_y - win->y - win->vmargin, cursor_width, cursor_height); } } } static void save_hidden_region(void) { size_t width; u_char *saved; int plane; int num_planes; u_char *fb; u_int count; width = FB_WIDTH_BYTES(&_display, _mouse.cursor.x, _mouse.cursor.width); saved = _mouse.saved_image; if (_display.pixels_per_byte == 8) { num_planes = _disp.depth; } else { num_planes = 1; } for (plane = 0; plane < num_planes; plane++) { fb = get_fb(_mouse.cursor.x, _mouse.cursor.y) + _display.plane_offset[plane]; for (count = 0; count < _mouse.cursor.height; count++) { memcpy(saved, fb, width); fb += _display.line_length; saved += width; } } _mouse.hidden_region_saved = 1; } static void draw_mouse_cursor_line(int y) { u_char *fb; ui_window_t *win; char *shape; u_char image[MAX_CURSOR_SHAPE_WIDTH * sizeof(u_int32_t)]; int x; fb = get_fb(_mouse.cursor.x, _mouse.cursor.y + y); if (rotate_display) { if (rotate_display > 0) { win = get_window(_mouse.y, _display.width - _mouse.x - 1); } else { win = get_window(_display.height - _mouse.y - 1, _mouse.x); } } else { win = get_window(_mouse.x, _mouse.y); } shape = cursor_shape.shape + ((_mouse.cursor.y_off + y) * cursor_shape.width + _mouse.cursor.x_off); for (x = 0; x < _mouse.cursor.width; x++) { if (shape[x] == '*') { switch (_display.bytes_per_pixel) { case 1: image[x] = win->fg_color.pixel; break; case 2: ((u_int16_t*)image)[x] = win->fg_color.pixel; break; /* case 4: */ default: ((u_int32_t*)image)[x] = win->fg_color.pixel; break; } } else if (shape[x] == '#') { switch (_display.bytes_per_pixel) { case 1: image[x] = win->bg_color.pixel; break; case 2: ((u_int16_t*)image)[x] = win->bg_color.pixel; break; /* case 4: */ default: ((u_int32_t*)image)[x] = win->bg_color.pixel; break; } } else { switch (_display.bytes_per_pixel) { int tmp; case 1: tmp = rotate_display; rotate_display = 0; image[x] = ui_display_get_pixel2(_mouse.cursor.x + x, _mouse.cursor.y + y); rotate_display = tmp; break; case 2: ((u_int16_t*)image)[x] = TOINT16(fb + 2 * x); break; /* case 4: */ default: ((u_int32_t*)image)[x] = TOINT32(fb + 4 * x); break; } } } if (_display.pixels_per_byte > 1) { put_image_124bpp(_mouse.cursor.x, _mouse.cursor.y + y, image, _mouse.cursor.width, 0, 1); } else { memcpy(fb, image, _mouse.cursor.width * _display.bytes_per_pixel); } } static void draw_mouse_cursor(void) { int y; for (y = 0; y < _mouse.cursor.height; y++) { draw_mouse_cursor_line(y); } _mouse.cursor.is_drawn = 1; } /* XXX defined in fb/ui_window.c */ void ui_window_clear_margin_area(ui_window_t *win); static void expose_window(ui_window_t *win, int x, int y, u_int width, u_int height) { if (x + width <= win->x || win->x + ACTUAL_WIDTH(win) < x || y + height <= win->y || win->y + ACTUAL_HEIGHT(win) < y) { return; } if (x < win->x + win->hmargin || y < win->y + win->vmargin || x - win->x + width > win->hmargin + win->width || y - win->y + height > win->vmargin + win->height) { ui_window_clear_margin_area(win); } if (win->window_exposed) { if (x < win->x + win->hmargin) { width -= (win->x + win->hmargin - x); x = 0; } else { x -= (win->x + win->hmargin); } if (y < win->y + win->vmargin) { height -= (win->y + win->vmargin - y); y = 0; } else { y -= (win->y + win->vmargin); } (*win->window_exposed)(win, x, y, width, height); } } static void expose_display(int x, int y, u_int width, u_int height) { u_int count; ui_window_t *kbd; /* maybe software keyboard */ /* * XXX * ui_im_{status|candidate}_screen can exceed display width or height, * because ui_im_{status|candidate}_screen_new() shows screen at * non-adjusted position. */ if (x + width > _disp.width) { width = _disp.width - x; } if (y + height > _disp.height) { height = _disp.height - y; } expose_window(_disp.roots[0], x, y, width, height); for (count = 0; count < _disp.roots[0]->num_children; count++) { expose_window(_disp.roots[0]->children[count], x, y, width, height); } if ((kbd = ui_is_virtual_kbd_area(y + height - 1))) { expose_window(kbd, x, y, width, height); } } static int check_visibility_of_im_window(void) { static struct { int saved; int x; int y; u_int width; u_int height; } im_region; int redraw_im_win = 0; #ifdef DEBUG if (_disp.num_roots > 2) { bl_debug_printf(BL_DEBUG_TAG" Multiple IM Windows (%d) are activated.\n", _disp.num_roots - 1); } #endif if (IM_WINDOW_IS_ACTIVATED(&_disp)) { if (im_region.saved) { if (im_region.x == _disp.roots[1]->x && im_region.y == _disp.roots[1]->y && im_region.width == ACTUAL_WIDTH(_disp.roots[1]) && im_region.height == ACTUAL_HEIGHT(_disp.roots[1])) { return 0; } if (im_region.x < _disp.roots[1]->x || im_region.y < _disp.roots[1]->y || im_region.x + im_region.width > _disp.roots[1]->x + ACTUAL_WIDTH(_disp.roots[1]) || im_region.y + im_region.height > _disp.roots[1]->y + ACTUAL_HEIGHT(_disp.roots[1])) { expose_display(im_region.x, im_region.y, im_region.width, im_region.height); redraw_im_win = 1; } } im_region.saved = 1; im_region.x = _disp.roots[1]->x; im_region.y = _disp.roots[1]->y; im_region.width = ACTUAL_WIDTH(_disp.roots[1]); im_region.height = ACTUAL_HEIGHT(_disp.roots[1]); } else { if (im_region.saved) { expose_display(im_region.x, im_region.y, im_region.width, im_region.height); im_region.saved = 0; } } return redraw_im_win; } static void receive_event_for_multi_roots(XEvent *xev) { int redraw_im_win; if ((redraw_im_win = check_visibility_of_im_window())) { /* Stop drawing input method window */ _disp.roots[1]->is_mapped = 0; } ui_window_receive_event(_disp.roots[0], xev); if (redraw_im_win && _disp.num_roots == 2) { /* Restart drawing input method window */ _disp.roots[1]->is_mapped = 1; } else if (!check_visibility_of_im_window()) { return; } expose_window(_disp.roots[1], _disp.roots[1]->x, _disp.roots[1]->y, ACTUAL_WIDTH(_disp.roots[1]), ACTUAL_HEIGHT(_disp.roots[1])); } /* * Return value * 0: button is outside the virtual kbd area. * 1: button is inside the virtual kbd area. (bev is converted to kev.) */ static int check_virtual_kbd(XButtonEvent *bev) { XKeyEvent kev; int ret; if (!(ret = ui_is_virtual_kbd_event(&_disp, bev))) { return 0; } if (ret > 0) { /* don't draw mouse cursor in ui_virtual_kbd_read() */ restore_hidden_region(); ret = ui_virtual_kbd_read(&kev, bev); save_hidden_region(); draw_mouse_cursor(); if (ret == 1) { receive_event_for_multi_roots(&kev); } } return 1; } /* --- platform dependent stuff --- */ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #define CMAP_SIZE(cmap) ((cmap)->count) #define BYTE_COLOR_TO_WORD(color) (color) #define WORD_COLOR_TO_BYTE(color) (color) #else /* Linux */ #define CMAP_SIZE(cmap) ((cmap)->len) #define BYTE_COLOR_TO_WORD(color) ((color) << 8 | (color)) #define WORD_COLOR_TO_BYTE(color) ((color)&0xff) #endif static int cmap_init(void); static void cmap_final(void); static int get_active_console(void); static int receive_stdin_key_event(void); #if defined(__FreeBSD__) #include "ui_display_freebsd.c" #elif defined(USE_GRF) #include "ui_display_x68kgrf.c" #elif defined(__NetBSD__) || defined(__OpenBSD__) #include "ui_display_wscons.c" #else /* Linux */ #include "ui_display_linux.c" #endif #ifndef __FreeBSD__ static int get_active_console(void) { struct vt_stat st; if (ioctl(STDIN_FILENO, VT_GETSTATE, &st) == -1) { return -1; } return st.v_active; } static int receive_stdin_key_event(void) { u_char buf[6]; ssize_t len; while ((len = read(_display.fd, buf, sizeof(buf) - 1)) > 0) { static struct { char *str; KeySym ksym; } table[] = { {"[2~", XK_Insert}, {"[3~", XK_Delete}, {"[5~", XK_Prior}, {"[6~", XK_Next}, {"[A", XK_Up}, {"[B", XK_Down}, {"[C", XK_Right}, {"[D", XK_Left}, #if defined(USE_GRF) {"[7~", XK_End}, {"[1~", XK_Home}, {"OP", XK_F1}, {"OQ", XK_F2}, {"OR", XK_F3}, {"OS", XK_F4}, {"[17~", XK_F5}, {"[18~", XK_F6}, {"[19~", XK_F7}, {"[20~", XK_F8}, {"[21~", XK_F9}, {"[29~", XK_F10}, #else /* USE_GRF */ #if defined(__NetBSD__) || defined(__OpenBSD__) {"[8~", XK_End}, {"[7~", XK_Home}, #else {"[F", XK_End}, {"[H", XK_Home}, #endif #if defined(__FreeBSD__) {"OP", XK_F1}, {"OQ", XK_F2}, {"OR", XK_F3}, {"OS", XK_F4}, {"[15~", XK_F5}, #elif defined(__NetBSD__) || defined(__OpenBSD__) {"[11~", XK_F1}, {"[12~", XK_F2}, {"[13~", XK_F3}, {"[14~", XK_F4}, {"[15~", XK_F5}, #else {"[[A", XK_F1}, {"[[B", XK_F2}, {"[[C", XK_F3}, {"[[D", XK_F4}, {"[[E", XK_F5}, #endif {"[17~", XK_F6}, {"[18~", XK_F7}, {"[19~", XK_F8}, {"[20~", XK_F9}, {"[21~", XK_F10}, {"[23~", XK_F11}, {"[24~", XK_F12}, #endif /* USE_GRF */ }; size_t count; XKeyEvent xev; xev.type = KeyPress; xev.state = get_key_state(); xev.ksym = 0; xev.keycode = 0; if (buf[0] == '\x1b' && len > 1) { buf[len] = '\0'; for (count = 0; count < sizeof(table) / sizeof(table[0]); count++) { if (strcmp(buf + 1, table[count].str) == 0) { xev.ksym = table[count].ksym; break; } } /* XXX */ #ifdef __FreeBSD__ if (xev.ksym == 0 && len == 3 && buf[1] == '[') { if ('Y' <= buf[2] && buf[2] <= 'Z') { xev.ksym = XK_F1 + (buf[2] - 'Y'); xev.state = ShiftMask; } else if ('a' <= buf[2] && buf[2] <= 'j') { xev.ksym = XK_F3 + (buf[2] - 'a'); xev.state = ShiftMask; } else if ('k' <= buf[2] && buf[2] <= 'v') { xev.ksym = XK_F1 + (buf[2] - 'k'); xev.state = ControlMask; } else if ('w' <= buf[2] && buf[2] <= 'z') { xev.ksym = XK_F1 + (buf[2] - 'w'); xev.state = ControlMask | ShiftMask; } else if (buf[2] == '@') { xev.ksym = XK_F5; xev.state = ControlMask | ShiftMask; } else if ('[' <= buf[2] && buf[2] <= '\`') { xev.ksym = XK_F6 + (buf[2] - '['); xev.state = ControlMask | ShiftMask; } else if (buf[2] == '{') { xev.ksym = XK_F12; xev.state = ControlMask | ShiftMask; } } #endif } if (xev.ksym) { receive_event_for_multi_roots(&xev); } else { for (count = 0; count < len; count++) { xev.ksym = buf[count]; if ((u_int)xev.ksym <= 0x1f) { if (xev.ksym == '\0') { /* CTL+' ' instead of CTL+@ */ xev.ksym = ' '; } else if (0x01 <= xev.ksym && xev.ksym <= 0x1a) { /* * Lower case alphabets instead of * upper ones. */ xev.ksym = xev.ksym + 0x60; } else { xev.ksym = xev.ksym + 0x40; } xev.state = ControlMask; } receive_event_for_multi_roots(&xev); } } } return 1; } #endif /* __FreeBSD__ */ static fb_cmap_t *cmap_new(int num_colors) { fb_cmap_t *cmap; if (!(cmap = malloc(sizeof(*cmap) + sizeof(*(cmap->red)) * num_colors * 3))) { return NULL; } #if defined(__FreeBSD__) cmap->index = 0; cmap->transparent = NULL; #elif defined(__NetBSD__) || defined(__OpenBSD__) cmap->index = 0; #else cmap->start = 0; cmap->transp = NULL; #endif CMAP_SIZE(cmap) = num_colors; cmap->red = cmap + 1; cmap->green = cmap->red + num_colors; cmap->blue = cmap->green + num_colors; return cmap; } #if defined(__FreeBSD__) && defined(PC98) #include #include /* * rgb_4bpp is * https://github.com/freebsd/freebsd/blob/release/6.4.0/sys/pc98/cbus/gdc.c#L858 * https://github.com/freebsd/freebsd/blob/release/4.1.1/sys/pc98/pc98/pc98gdc.c#L679 * * FBIOPUTCMAP always fails on FreeBSD/PC98. * https://github.com/freebsd/freebsd/blob/release/6.4.0/sys/pc98/cbus/gdc.c#L1439 * https://github.com/freebsd/freebsd/blob/release/4.1.1/sys/pc98/pc98/pc98gdc.c#L1224 */ static u_char rgb_4bpp[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x40, 0x40, 0x40, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff }; static void cmap_fallback(void) { if (_disp.depth == 4) { #if 1 int fd; vt_color_t color; bl_priv_restore_euid(); bl_priv_restore_egid(); if ((fd = open("/dev/io", 000)) >= 0) { for (color = 0; color < 16; color++) { outb(0xa8, color); outb(0xac, _display.cmap->red[color] >> 4); outb(0xaa, _display.cmap->green[color] >> 4); outb(0xae, _display.cmap->blue[color] >> 4); } close(fd); } bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); if (fd < 0) #endif { for (color = 0; color < 16; color++) { _display.cmap->red[color] = rgb_4bpp[color * 3]; _display.cmap->green[color] = rgb_4bpp[color * 3 + 1]; _display.cmap->blue[color] = rgb_4bpp[color * 3 + 2]; } } } } static void cmap_reset(void) { if (_disp.depth == 4) { #if 1 int fd; bl_priv_restore_euid(); bl_priv_restore_egid(); if ((fd = open("/dev/io", 000)) >= 0) { vt_color_t color; for (color = 0; color < 16; color++) { outb(0xa8, color); outb(0xac, rgb_4bpp[color * 3] >> 4); outb(0xaa, rgb_4bpp[color * 3 + 1] >> 4); outb(0xae, rgb_4bpp[color * 3 + 1] >> 4); } close(fd); } bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); #endif } } #else #define cmap_fallback() (0) #define cmap_reset() (0) #endif /* * Note that ui_display_wscons.c has its own cmap_init() because vinfo.depth != * _disp.depth * on NetBSD/luna68k etc. */ static int cmap_init(void) { int num_colors; vt_color_t color; u_int8_t r; u_int8_t g; u_int8_t b; static u_char rgb_1bpp[] = {0x00, 0x00, 0x00, 0xff, 0xff, 0xff}; static u_char rgb_2bpp[] = {0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xff, 0xff, 0xff}; num_colors = (2 << (_disp.depth - 1)); if (!_display.cmap) { #ifndef USE_GRF if (num_colors > 2) { /* * Not get the current cmap because num_colors == 2 doesn't * conform the actual depth (1,2,4). */ if (!(_display.cmap_orig = cmap_new(num_colors))) { return 0; } ioctl(_display.fb_fd, FBIOGETCMAP, _display.cmap_orig); } #else if ((_display.cmap_orig = malloc(sizeof(((fb_reg_t*)_display.fb)->gpal)))) { memcpy(_display.cmap_orig, ((fb_reg_t*)_display.fb)->gpal, sizeof(((fb_reg_t*)_display.fb)->gpal)); } #endif if (!(_display.cmap = cmap_new(num_colors))) { free(_display.cmap_orig); return 0; } if (!(_display.color_cache = calloc(1, sizeof(*_display.color_cache)))) { free(_display.cmap_orig); free(_display.cmap); return 0; } } if (num_colors == 2) { for (color = 0; color < 2; color++) { r = rgb_1bpp[color * 3]; g = rgb_1bpp[color * 3 + 1]; b = rgb_1bpp[color * 3 + 2]; _display.cmap->red[color] = BYTE_COLOR_TO_WORD(r); _display.cmap->green[color] = BYTE_COLOR_TO_WORD(g); _display.cmap->blue[color] = BYTE_COLOR_TO_WORD(b); } } else if (num_colors == 4) { for (color = 0; color < 4; color++) { r = rgb_2bpp[color * 3]; g = rgb_2bpp[color * 3 + 1]; b = rgb_2bpp[color * 3 + 2]; _display.cmap->red[color] = BYTE_COLOR_TO_WORD(r); _display.cmap->green[color] = BYTE_COLOR_TO_WORD(g); _display.cmap->blue[color] = BYTE_COLOR_TO_WORD(b); } } else { for (color = 0; color < num_colors; color++) { vt_get_color_rgba(color, &r, &g, &b, NULL); _display.cmap->red[color] = BYTE_COLOR_TO_WORD(r); _display.cmap->green[color] = BYTE_COLOR_TO_WORD(g); _display.cmap->blue[color] = BYTE_COLOR_TO_WORD(b); } } /* Same processing as ui_display_set_cmap(). */ #ifndef USE_GRF if (ioctl(_display.fb_fd, FBIOPUTCMAP, _display.cmap) < 0) { cmap_fallback(); } #else { u_int count; for (count = 0; count < CMAP_SIZE(_display.cmap); count++) { ((fb_reg_t*)_display.fb)->gpal[count] = (_display.cmap->red[count] >> 3) << 6 | (_display.cmap->green[count] >> 3) << 11 | (_display.cmap->blue[count] >> 3) << 1; } } #endif return 1; } static void cmap_final(void) { if (_display.cmap_orig) { #ifndef USE_GRF if (ioctl(_display.fb_fd, FBIOPUTCMAP, _display.cmap_orig) < 0) { cmap_reset(); } #else memcpy(((fb_reg_t*)_display.fb)->gpal, _display.cmap_orig, sizeof(((fb_reg_t*)_display.fb)->gpal)); #endif free(_display.cmap_orig); } free(_display.cmap); free(_display.color_cache); } /* --- global functions --- */ ui_display_t *ui_display_open(char *disp_name, u_int depth) { if (!DISP_IS_INITED) { if (!open_display(depth)) { return NULL; } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Framebuffer: " "len %d line_len %d xoff %d yoff %d depth %db/%dB w %d h %d\n", _display.smem_len, _display.line_length, _display.xoffset, _display.yoffset, _disp.depth, _display.bytes_per_pixel, _display.width, _display.height); #endif if (rotate_display) { u_int tmp; if (_display.pixels_per_byte > 1) { rotate_display = 0; rotate_mouse_cursor_shape(); } else { tmp = _disp.width; _disp.width = _disp.height; _disp.height = tmp; } } if (!(_disp.name = getenv("DISPLAY"))) { _disp.name = ":0.0"; } fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | O_NONBLOCK); /* Hide the cursor of default console. */ write(STDIN_FILENO, "\x1b[?25l", 6); } return &_disp; } void ui_display_close(ui_display_t *disp) { if (disp == &_disp) { ui_display_close_all(); } } void ui_display_close_all(void) { if (DISP_IS_INITED) { /* inline pictures are alive until vt_term_t is destroyed. */ #if 0 ui_picture_display_closed(_disp.display); #endif ui_virtual_kbd_hide(); if (MOUSE_IS_INITED) { close(_mouse.fd); } #ifdef ENABLE_DOUBLE_BUFFER free(_display.back_fb); #endif write(STDIN_FILENO, "\x1b[?25h", 6); tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_tm); #if defined(__FreeBSD__) ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE); #ifdef PC98 if (_disp.depth == 4 || _disp.depth == 8) { ioctl(_display.fb_fd, SW_PC98_80x25, NULL); } #endif #elif defined(__NetBSD__) #ifdef USE_GRF close_grf0(); setup_reg((fb_reg_t*)_display.fb, &orig_reg); #else ioctl(STDIN_FILENO, WSDISPLAYIO_SMODE, &orig_console_mode); ui_event_source_remove_fd(-10); #endif #elif defined(__OpenBSD__) ioctl(STDIN_FILENO, WSDISPLAYIO_SMODE, &orig_console_mode); #else set_use_console_backscroll(1); #endif if (CMAP_IS_INITED) { cmap_final(); } if (_display.fd != STDIN_FILENO) { close(_display.fd); } munmap(_display.fb, _display.smem_len); close(_display.fb_fd); free(_disp.roots); /* DISP_IS_INITED is false from here. */ _disp.display = NULL; } } ui_display_t **ui_get_opened_displays(u_int *num) { if (!DISP_IS_INITED #ifndef __FreeBSD__ || console_id != get_active_console() #endif ) { *num = 0; return NULL; } if (MOUSE_IS_INITED) { *num = 2; } else { *num = 1; } return opened_disps; } int ui_display_fd(ui_display_t *disp) { return disp->display->fd; } int ui_display_show_root(ui_display_t *disp, ui_window_t *root, int x, int y, int hint, char *app_name, Window parent_window /* Ignored */ ) { void *p; if ((p = realloc(disp->roots, sizeof(ui_window_t*) * (disp->num_roots + 1))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif return 0; } disp->roots = p; root->disp = disp; root->parent = NULL; root->parent_window = disp->my_window; root->gc = disp->gc; root->x = x; root->y = y; if (app_name) { root->app_name = app_name; } disp->roots[disp->num_roots++] = root; /* Cursor is drawn internally by calling ui_display_put_image2(). */ if (!ui_window_show(root, hint)) { return 0; } if (MOUSE_IS_INITED) { update_mouse_cursor_state(); save_hidden_region(); draw_mouse_cursor(); } return 1; } int ui_display_remove_root(ui_display_t *disp, ui_window_t *root) { u_int count; for (count = 0; count < disp->num_roots; count++) { if (disp->roots[count] == root) { /* XXX ui_window_unmap resize all windows internally. */ #if 0 ui_window_unmap(root); #endif ui_window_final(root); disp->num_roots--; if (count == disp->num_roots) { disp->roots[count] = NULL; } else { disp->roots[count] = disp->roots[disp->num_roots]; } return 1; } } return 0; } void ui_display_idling(ui_display_t *disp) { u_int count; for (count = 0; count < disp->num_roots; count++) { ui_window_idling(disp->roots[count]); } } int ui_display_receive_next_event(ui_display_t *disp) { if (disp == &_disp_mouse) { return receive_mouse_event(); } else { return receive_key_event(); } } /* * Folloing functions called from ui_window.c */ int ui_display_own_selection(ui_display_t *disp, ui_window_t *win) { if (_disp.selection_owner) { ui_display_clear_selection(&_disp, _disp.selection_owner); } _disp.selection_owner = win; return 1; } int ui_display_clear_selection(ui_display_t *disp /* can be NULL */, ui_window_t *win) { if (_disp.selection_owner == NULL || _disp.selection_owner != win) { return 0; } if (_disp.selection_owner->selection_cleared) { (*_disp.selection_owner->selection_cleared)(_disp.selection_owner); } _disp.selection_owner = NULL; return 1; } XModifierKeymap *ui_display_get_modifier_mapping(ui_display_t *disp) { return disp->modmap.map; } void ui_display_update_modifier_mapping(ui_display_t *disp, u_int serial) { /* dummy */ } XID ui_display_get_group_leader(ui_display_t *disp) { return None; } int ui_display_reset_cmap(void) { if (_display.color_cache) { memset(_display.color_cache, 0, sizeof(*_display.color_cache)); } return _display.cmap && cmap_init() #ifdef USE_GRF && gpal_init(((fb_reg_t*)_display.fb)->gpal) #endif ; } #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE void ui_display_set_use_ansi_colors(int use) { use_ansi_colors = use; } void ui_display_enable_to_change_cmap(int flag) { if (flag) { #ifdef USE_GRF x68k_set_use_tvram_colors(1); #endif if (!use_ansi_colors) { use_ansi_colors = -1; } } else { #ifdef USE_GRF x68k_set_use_tvram_colors(0); #endif if (use_ansi_colors == -1) { use_ansi_colors = 0; } } } int ui_display_is_changeable_cmap(void) { return #ifdef USE_GRF use_tvram_cmap || #endif (_disp.depth == 4 && use_ansi_colors == -1); } void ui_display_set_cmap(u_int32_t *pixels, u_int cmap_size) { if ( #ifdef USE_GRF !x68k_set_tvram_cmap(pixels, cmap_size) && #endif use_ansi_colors == -1 && cmap_size <= 16 && _disp.depth == 4) { u_int count; vt_color_t color; if (cmap_size < 16) { color = VT_RED; } else { color = VT_BLACK; } for (count = 0; count < cmap_size; count++, color++) { if (color == VT_WHITE && cmap_size < 15) { color++; } _display.cmap->red[color] = BYTE_COLOR_TO_WORD((pixels[count] >> 16) & 0xff); _display.cmap->green[color] = BYTE_COLOR_TO_WORD((pixels[count] >> 8) & 0xff); _display.cmap->blue[color] = BYTE_COLOR_TO_WORD(pixels[count] & 0xff); } /* Same processing as cmap_init(). */ #ifndef USE_GRF if (ioctl(_display.fb_fd, FBIOPUTCMAP, _display.cmap) < 0) { cmap_fallback(); } #else for (count = 0; count < CMAP_SIZE(_display.cmap); count++) { ((fb_reg_t*)_display.fb)->gpal[count] = (_display.cmap->red[count] >> 3) << 6 | (_display.cmap->green[count] >> 3) << 11 | (_display.cmap->blue[count] >> 3) << 1; } gpal_init(((fb_reg_t*)_display.fb)->gpal); #endif if (_display.color_cache) { memset(_display.color_cache, 0, sizeof(*_display.color_cache)); } bl_msg_printf("Palette changed.\n"); } } #endif void ui_display_rotate(int rotate /* 1: clockwise, -1: counterclockwise */ ) { if (rotate == rotate_display || /* rotate is available for 8 or more bpp */ _display.pixels_per_byte > 1) { return; } if (DISP_IS_INITED) { ui_virtual_kbd_hide(); } if (rotate_display + rotate != 0) { int tmp; tmp = _disp.width; _disp.width = _disp.height; _disp.height = tmp; rotate_mouse_cursor_shape(); rotate_display = rotate; if (_disp.num_roots > 0) { ui_window_resize_with_margin(_disp.roots[0], _disp.width, _disp.height, NOTIFY_TO_MYSELF); } } else { /* If rotate_display == -1 rotate == 1 or vice versa, don't swap. */ rotate_display = rotate; if (_disp.num_roots > 0) { ui_window_update_all(_disp.roots[0]); } } } u_long ui_display_get_pixel2(int x, int y) { u_char *fb; u_long pixel; if (_display.pixels_per_byte > 1) { return BG_MAGIC; } if (rotate_display) { int tmp; if (rotate_display > 0) { tmp = x; x = _disp.height - y - 1; y = tmp; } else { tmp = x; x = y; y = _disp.width - tmp - 1; } } fb = get_fb(x, y); switch (_display.bytes_per_pixel) { case 1: pixel = *fb; break; case 2: pixel = TOINT16(fb); break; /* case 4: */ default: pixel = TOINT32(fb); } return pixel; } void ui_display_put_image2(int x, int y, u_char *image, size_t size, int need_fb_pixel) { if (_display.pixels_per_byte > 1) { put_image_124bpp(x, y, image, size, 1, need_fb_pixel); } else if (!rotate_display) { memcpy(get_fb(x, y), image, size); } else { /* Display is rotated. */ u_char *fb; int tmp; int line_length; size_t count; tmp = x; if (rotate_display > 0) { x = _disp.height - y - 1; y = tmp; line_length = _display.line_length; } else { x = y; y = _disp.width - tmp - 1; line_length = -_display.line_length; } fb = get_fb(x, y); if (_display.bytes_per_pixel == 1) { for (count = 0; count < size; count++) { *fb = image[count]; fb += line_length; } } else if (_display.bytes_per_pixel == 2) { size /= 2; for (count = 0; count < size; count++) { *((u_int16_t*)fb) = ((u_int16_t*)image)[count]; fb += line_length; } } else /* if( _display.bytes_per_pixel == 4) */ { size /= 4; for (count = 0; count < size; count++) { *((u_int32_t*)fb) = ((u_int32_t*)image)[count]; fb += line_length; } } if (rotate_display < 0) { y -= (size - 1); } if (/* MOUSE_IS_INITED && */ _mouse.cursor.is_drawn && _mouse.cursor.x <= x && x < _mouse.cursor.x + _mouse.cursor.width) { if (y <= _mouse.cursor.y + _mouse.cursor.height && _mouse.cursor.y < y + size) { _mouse.hidden_region_saved = 0; /* draw_mouse_cursor() */ } } return; } if (/* MOUSE_IS_INITED && */ _mouse.cursor.is_drawn && _mouse.cursor.y <= y && y < _mouse.cursor.y + _mouse.cursor.height) { size /= _display.bytes_per_pixel; if (x <= _mouse.cursor.x + _mouse.cursor.width && _mouse.cursor.x < x + size) { _mouse.hidden_region_saved = 0; draw_mouse_cursor_line(y - _mouse.cursor.y); } } } /* * For 8 or less bpp. * Check if bytes_per_pixel == 1 or not by the caller. */ void ui_display_fill_with(int x, int y, u_int width, u_int height, u_int8_t pixel) { u_char *fb; u_int ppb; u_char *buf; int y_off; fb = get_fb(x, y); if ((ppb = _display.pixels_per_byte) > 1) { u_char *fb_orig; u_int bpp; int plane; u_char *fb_end; u_char *buf_end; u_int surplus; u_int surplus_end; int packed_pixel; u_int count; int shift; bpp = 8 / ppb; plane = 0; fb_orig = fb; fb_end = get_fb(x + width, y); #ifndef ENABLE_DOUBLE_BUFFER if (!(buf = alloca(fb_end - fb + 1))) { return; } buf_end = buf + (fb_end - fb); #endif while (1) { #ifdef ENABLE_DOUBLE_BUFFER fb_end = _display.back_fb + (fb_end - _display.fb); #endif surplus = MOD_PPB(x, ppb); surplus_end = MOD_PPB(x + width, ppb); packed_pixel = 0; if (pixel) { if (ppb == 8) { if (_disp.depth == 1 || PLANE(pixel)) { packed_pixel = 0xff; } } else { shift = _display.shift_0; for (count = 0; count < ppb; count++) { packed_pixel |= (pixel << shift); FB_SHIFT_NEXT(shift, bpp); } } } for (y_off = 0; y_off < height; y_off++) { u_char *buf_p; u_int8_t pix; size_t size; #ifdef ENABLE_DOUBLE_BUFFER buf = fb = _display.back_fb + (fb - _display.fb); buf_end = fb_end; #endif buf_p = buf; shift = _display.shift_0; count = 0; pix = 0; if (surplus > 0) { for (; count < surplus; count++) { pix |= (fb[0] & (_display.mask << shift)); FB_SHIFT_NEXT(shift, bpp); } if (buf_p != buf_end) { if (pixel) { for (; count < ppb; count++) { pix |= (PLANE(pixel) << shift); FB_SHIFT_NEXT(shift, bpp); } } *(buf_p++) = pix; shift = _display.shift_0; count = 0; pix = 0; } } if (surplus_end > 0) { if (pixel) { for (; count < surplus_end; count++) { pix |= (PLANE(pixel) << shift); FB_SHIFT_NEXT(shift, bpp); } } else { count = surplus_end; shift = FB_SHIFT(ppb, bpp, surplus_end); } for (; count < ppb; count++) { pix |= (fb_end[0] & (_display.mask << shift)); FB_SHIFT_NEXT(shift, bpp); } *buf_end = pix; shift = _display.shift_0; pix = 0; size = buf_end - buf + 1; } else { size = buf_end - buf; } if (buf_p < buf_end) { /* * XXX * If ENABLE_DOUBLE_BUFFER is off, it is not necessary * to memset every time because the pointer of buf * points the same address. */ memset(buf_p, packed_pixel, buf_end - buf_p); } #ifdef ENABLE_DOUBLE_BUFFER fb = _display.fb + (fb - _display.back_fb); #endif memcpy(fb, buf, size); fb += _display.line_length; fb_end += _display.line_length; } #ifndef ENABLE_2_4_PPB if (++plane < _disp.depth) { fb = fb_orig + _display.plane_offset[plane]; fb_end = fb + (buf_end - buf); } else #endif { break; } } } else { if (rotate_display) { u_int tmp; if (rotate_display > 0) { fb = get_fb(_disp.height - y - height, x); } else /* if( rotate_display < 0) */ { fb = get_fb(y, _disp.width - x - width); } tmp = width; width = height; height = tmp; } if (!(buf = alloca(width))) { return; } for (y_off = 0; y_off < height; y_off++) { memset(buf, pixel, width); memcpy(fb, buf, width); fb += _display.line_length; } } } void ui_display_copy_lines2(int src_x, int src_y, int dst_x, int dst_y, u_int width, u_int height) { u_char *src; u_char *dst; u_int copy_len; u_int count; int num_planes; int plane; /* XXX cheap implementation. */ restore_hidden_region(); if (rotate_display) { int tmp; if (rotate_display > 0) { tmp = src_x; src_x = _disp.height - src_y - height; src_y = tmp; tmp = dst_x; dst_x = _disp.height - dst_y - height; dst_y = tmp; } else { tmp = src_x; src_x = src_y; src_y = _disp.width - tmp - width; tmp = dst_x; dst_x = dst_y; dst_y = _disp.width - tmp - width; } tmp = height; height = width; width = tmp; } /* XXX could be different from FB_WIDTH_BYTES(display, dst_x, width) */ copy_len = FB_WIDTH_BYTES(&_display, src_x, width); if (_display.pixels_per_byte == 8) { num_planes = _disp.depth; } else { num_planes = 1; } for (plane = 0; plane < num_planes; plane++) { if (src_y <= dst_y) { src = get_fb(src_x, src_y + height - 1) + _display.plane_offset[plane]; dst = get_fb(dst_x, dst_y + height - 1) + _display.plane_offset[plane]; #ifdef ENABLE_DOUBLE_BUFFER if (_display.back_fb) { u_char *src_back; u_char *dst_back; src_back = _display.back_fb + (src - _display.fb); dst_back = _display.back_fb + (dst - _display.fb); if (dst_y == src_y) { for (count = 0; count < height; count++) { memmove(dst_back, src_back, copy_len); memcpy(dst, src_back, copy_len); dst -= _display.line_length; dst_back -= _display.line_length; src_back -= _display.line_length; } } else { for (count = 0; count < height; count++) { memcpy(dst_back, src_back, copy_len); memcpy(dst, src_back, copy_len); dst -= _display.line_length; dst_back -= _display.line_length; src_back -= _display.line_length; } } } else #endif { if (src_y == dst_y) { for (count = 0; count < height; count++) { memmove(dst, src, copy_len); dst -= _display.line_length; src -= _display.line_length; } } else { for (count = 0; count < height; count++) { memcpy(dst, src, copy_len); dst -= _display.line_length; src -= _display.line_length; } } } } else { src = get_fb(src_x, src_y) + _display.plane_offset[plane]; dst = get_fb(dst_x, dst_y) + _display.plane_offset[plane]; #ifdef ENABLE_DOUBLE_BUFFER if (_display.back_fb) { u_char *src_back; u_char *dst_back; src_back = _display.back_fb + (src - _display.fb); dst_back = _display.back_fb + (dst - _display.fb); for (count = 0; count < height; count++) { memcpy(dst_back, src_back, copy_len); memcpy(dst, src_back, copy_len); dst += _display.line_length; dst_back += _display.line_length; src_back += _display.line_length; } } else #endif { for (count = 0; count < height; count++) { memcpy(dst, src, copy_len); dst += _display.line_length; src += _display.line_length; } } } } } /* XXX for input method window */ void ui_display_reset_input_method_window(void) { #if 0 if (IM_WINDOW_IS_ACTIVATED(&_disp)) #endif { check_visibility_of_im_window(); ui_window_clear_margin_area(_disp.roots[1]); } } /* seek the closest color */ int ui_cmap_get_closest_color(u_long *closest, int red, int green, int blue) { u_int segment; u_int offset; u_int color; u_int min = 0xffffff; u_int diff; int diff_r, diff_g, diff_b; u_int linear_search_max; if (!_display.cmap) { return 0; } #ifndef COLOR_CACHE_MINIMUM segment = 0; /* * R G B * 11111111 11111111 11111111 * ^^^^^ ^^^^^ ^^^^ */ offset = ((red << 6) & 0x3e00) | ((green << 1) & 0x1f0) | ((blue >> 4) & 0xf); if (_display.color_cache->flags[offset / 32] & (1 << (offset & 31))) #else /* * R G B * 11111111 11111111 11111111 * ^ ^ ^ */ segment = ((red >> 5) & 0x4) | ((green >> 6) & 0x2) | ((blue >> 7) & 0x1); /* * R G B * 11111111 11111111 11111111 * ^^^^ ^^^^ ^^^ */ offset = ((red << 4) & 0x780) | (green & 0x78) | ((blue >> 4) & 0x7); if (_display.color_cache->segments[offset] == (segment | 0x80)) #endif { *closest = _display.color_cache->pixels[offset]; #ifdef __DEBUG bl_debug_printf("CACHED PIXEL %x <= r%x g%x b%x segment %x offset %x\n", *closest, red, green, blue, segment, offset); #endif return 1; } if ((linear_search_max = CMAP_SIZE(_display.cmap)) == 256) { vt_color_t tmp; linear_search_max = vt_get_closest_256_color(&tmp, &min, red, green, blue, COLOR_DISTANCE_THRESHOLD); *closest = tmp; /* XXX needs for LP64 */ if (linear_search_max == 0) { goto end; } } for (color = 0; color < linear_search_max; color++) { #ifdef USE_GRF if (grf0_fd != -1 && !use_tvram_cmap && color == TP_COLOR) { continue; } #endif /* lazy color-space conversion */ diff_r = red - WORD_COLOR_TO_BYTE(_display.cmap->red[color]); diff_g = green - WORD_COLOR_TO_BYTE(_display.cmap->green[color]); diff_b = blue - WORD_COLOR_TO_BYTE(_display.cmap->blue[color]); diff = COLOR_DISTANCE(diff_r, diff_g, diff_b); if (diff < min) { min = diff; *closest = color; /* no one may notice the difference (4[2^3/2]*4*9+4*4*30+4*4) */ if (diff < COLOR_DISTANCE_THRESHOLD) { break; } } } end: #ifndef COLOR_CACHE_MINIMUM _display.color_cache->flags[offset / 32] |= (1 << (offset & 31)); #else _display.color_cache->segments[offset] = (segment | 0x80); #endif _display.color_cache->pixels[offset] = *closest; #ifdef __DEBUG bl_debug_printf("NEW PIXEL %x <= r%x g%x b%x segment %x offset %x\n", *closest, red, green, blue, segment, offset); #endif return 1; } int ui_cmap_get_pixel_rgb(u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_long pixel) { #ifdef USE_GRF if (grf0_fd != -1 && !use_tvram_cmap && pixel == TP_COLOR) { return 0; } #endif *red = WORD_COLOR_TO_BYTE(_display.cmap->red[pixel]); *green = WORD_COLOR_TO_BYTE(_display.cmap->green[pixel]); *blue = WORD_COLOR_TO_BYTE(_display.cmap->blue[pixel]); return 1; } mlterm-3.8.9/uitoolkit/fb/ui_display.h010064400017600000144000000036301356600660700164710ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_DISPLAY_H__ #define ___UI_DISPLAY_H__ #include "../ui_display.h" #ifdef __FreeBSD__ #include /* NLKED */ #else #define CLKED 1 #define NLKED 2 #define SLKED 4 #define ALKED 8 #endif #define KeyPress 2 /* Private in fb/ */ #define ButtonPress 4 /* Private in fb/ */ #define ButtonRelease 5 /* Private in fb/ */ #define MotionNotify 6 /* Private in fb/ */ #define IM_WINDOW_IS_ACTIVATED(disp) ((disp)->num_roots > 1 && (disp)->roots[1]->is_mapped) #ifdef USE_GRF #define TP_COLOR 12 #endif /* common functions for ui_window.c */ #define ui_display_get_pixel(disp, x, y) ui_display_get_pixel2(x, y) u_long ui_display_get_pixel2(int x, int y); #define ui_display_put_image(disp, x, y, image, size, need_fb_pixel) \ ui_display_put_image2(x, y, image, size, need_fb_pixel) void ui_display_put_image2(int x, int y, u_char *image, size_t size, int need_fb_pixel); #define ui_display_copy_lines(disp, src_x, src_y, dst_x, dst_y, width, height) \ ui_display_copy_lines2(src_x, src_y, dst_x, dst_y, width, height) void ui_display_copy_lines2(int src_x, int src_y, int dst_x, int dst_y, u_int width, u_int height); /* common functions for ui_window.c (pseudo color) */ void ui_display_fill_with(int x, int y, u_int width, u_int height, u_int8_t pixel); int ui_cmap_get_closest_color(u_long *closest, int red, int green, int blue); int ui_cmap_get_pixel_rgb(u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_long pixel); /* platform specific functions for ui_window.c */ #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE void ui_display_enable_to_change_cmap(int flag); int ui_display_is_changeable_cmap(void); void ui_display_set_cmap(u_int32_t *cmap, u_int cmap_size); #endif #ifdef USE_GRF int x68k_tvram_is_enabled(void); int x68k_tvram_set_wall_picture(u_short *image, u_int width, u_int height); #endif #endif mlterm-3.8.9/uitoolkit/fb/ui_display_freebsd.c010064400017600000144000000324711356600660700201630ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include #if __FreeBSD__ >= 5 #include #define MOUSE_DEV "/dev/sysmouse" #define PACKET_SIZE 8 #elif defined(PC98) #define MOUSE_DEV "/dev/mse0" #define PACKET_SIZE 5 #else #define MOUSE_DEV "/dev/psm0" #define PACKET_SIZE 3 #endif /* --- static variables --- */ static keymap_t keymap; /* --- static functions --- */ static int open_display(u_int depth) { char *dev; int vmode; video_info_t vinfo; video_adapter_info_t vainfo; video_display_start_t vstart; struct termios tm; bl_priv_restore_euid(); bl_priv_restore_egid(); _display.fb_fd = open((dev = getenv("FRAMEBUFFER")) ? dev : "/dev/ttyv0", O_RDWR); bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); if (_display.fb_fd < 0) { bl_error_printf("Couldn't open %s.\n", dev ? dev : "/dev/ttyv0"); return 0; } bl_file_set_cloexec(_display.fb_fd); #ifdef PC98 /* XXX 256 colors is not supported for now. */ #if 0 if (depth == 8) { ioctl(_display.fb_fd, SW_PC98_PEGC640x400, NULL); } else #endif { ioctl(_display.fb_fd, SW_PC98_EGC640x400, NULL); } #endif ioctl(_display.fb_fd, FBIO_GETMODE, &vmode); vinfo.vi_mode = vmode; ioctl(_display.fb_fd, FBIO_MODEINFO, &vinfo); ioctl(_display.fb_fd, FBIO_ADPINFO, &vainfo); ioctl(_display.fb_fd, FBIO_GETDISPSTART, &vstart); if ((_display.fb = _display.fb_base = mmap(NULL, (_display.smem_len = vainfo.va_window_size), PROT_WRITE | PROT_READ, MAP_SHARED, _display.fb_fd, (off_t)0)) == MAP_FAILED) { bl_error_printf("Retry another mode of resolution and depth.\n"); goto error; } _disp.depth = vinfo.vi_depth; if ((_display.bytes_per_pixel = (_disp.depth + 7) / 8) == 3) { _display.bytes_per_pixel = 4; } if (_disp.depth < 15) { #ifdef M_PC98_EGC640x400 if (vainfo.va_mode == M_PC98_EGC640x400) { _display.pixels_per_byte = 8; _disp.depth = 4; _display.shift_0 = 7; _display.mask = 1; _display.plane_offset[0] = 0; /* 0xA8000 */ _display.plane_offset[1] = 0x8000; /* 0xB0000 */ _display.plane_offset[2] = 0x10000; /* 0xB8000 */ _display.plane_offset[3] = 0x38000; /* 0xE0000 */ } else #endif if (_disp.depth < 8) { #ifdef ENABLE_2_4_PPB _display.pixels_per_byte = 8 / _disp.depth; #else /* XXX Forcibly set 1 bpp */ _display.pixels_per_byte = 8; _disp.depth = 1; #endif _display.shift_0 = FB_SHIFT_0(_display.pixels_per_byte, _disp.depth); _display.mask = FB_MASK(_display.pixels_per_byte); } else { _display.pixels_per_byte = 1; } if (!cmap_init()) { goto error; } } else { _display.pixels_per_byte = 1; } #ifdef ENABLE_DOUBLE_BUFFER if (_display.pixels_per_byte > 1 && !(_display.back_fb = malloc(_display.smem_len))) { cmap_final(); goto error; } #endif _display.line_length = vainfo.va_line_width; _display.xoffset = vstart.x; _display.yoffset = vstart.y; _display.width = _disp.width = vinfo.vi_width; _display.height = _disp.height = vinfo.vi_height; _display.rgbinfo.r_limit = 8 - vinfo.vi_pixel_fsizes[0]; _display.rgbinfo.g_limit = 8 - vinfo.vi_pixel_fsizes[1]; _display.rgbinfo.b_limit = 8 - vinfo.vi_pixel_fsizes[2]; _display.rgbinfo.r_offset = vinfo.vi_pixel_fields[0]; _display.rgbinfo.g_offset = vinfo.vi_pixel_fields[1]; _display.rgbinfo.b_offset = vinfo.vi_pixel_fields[2]; tcgetattr(STDIN_FILENO, &tm); orig_tm = tm; tm.c_iflag = tm.c_oflag = 0; tm.c_cflag &= ~CSIZE; tm.c_cflag |= CS8; tm.c_lflag &= ~(ECHO | ISIG | IEXTEN | ICANON); tm.c_cc[VMIN] = 1; tm.c_cc[VTIME] = 0; tcsetattr(STDIN_FILENO, TCSAFLUSH, &tm); ioctl(STDIN_FILENO, GIO_KEYMAP, &keymap); ioctl(STDIN_FILENO, KDSKBMODE, K_CODE); ioctl(STDIN_FILENO, KDGKBSTATE, &_display.lock_state); _display.fd = STDIN_FILENO; _disp.display = &_display; bl_priv_restore_euid(); bl_priv_restore_egid(); _mouse.fd = open(MOUSE_DEV, O_RDWR | O_NONBLOCK); bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); if (_mouse.fd != -1) { struct mouse_info info; #ifdef MOUSE_SETLEVEL int level; mousemode_t mode; level = 1; ioctl(_mouse.fd, MOUSE_SETLEVEL, &level); ioctl(_mouse.fd, MOUSE_GETMODE, &mode); if (mode.packetsize != PACKET_SIZE) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to open " MOUSE_DEV ".\n"); #endif close(_mouse.fd); _mouse.fd = -1; } else #endif { bl_file_set_cloexec(_mouse.fd); _mouse.x = _display.width / 2; _mouse.y = _display.height / 2; _disp_mouse.display = (Display*)&_mouse; tcgetattr(_mouse.fd, &tm); tm.c_iflag = IGNBRK | IGNPAR; tm.c_oflag = 0; tm.c_lflag = 0; tm.c_cc[VTIME] = 0; tm.c_cc[VMIN] = 1; tm.c_cflag = CS8 | CSTOPB | CREAD | CLOCAL | HUPCL; cfsetispeed(&tm, B1200); cfsetospeed(&tm, B1200); tcsetattr(_mouse.fd, TCSAFLUSH, &tm); info.operation = MOUSE_HIDE; ioctl(STDIN_FILENO, CONS_MOUSECTL, &info); } } #ifdef DEBUG else { bl_debug_printf(BL_DEBUG_TAG " Failed to open " MOUSE_DEV ".\n"); } #endif return 1; error: if (_display.fb) { munmap(_display.fb, _display.smem_len); _display.fb = _display.fb_base = NULL; } close(_display.fb_fd); return 0; } static int receive_mouse_event(void) { u_char buf[PACKET_SIZE * 8]; ssize_t len; while ((len = read(_mouse.fd, buf, sizeof(buf))) > 0) { static u_char packet[PACKET_SIZE]; static ssize_t packet_len; ssize_t count; for (count = 0; count < len; count++) { int x; int y; int move; struct timeval tv; XButtonEvent xev; ui_window_t *win; #if __FreeBSD__ >= 5 int z; if (packet_len == 0) { if ((buf[count] & 0xf8) != 0x80) { /* is not packet header */ continue; } } #endif packet[packet_len++] = buf[count]; if (packet_len < PACKET_SIZE) { continue; } packet_len = 0; /* set mili seconds */ gettimeofday(&tv, NULL); xev.time = tv.tv_sec * 1000 + tv.tv_usec / 1000; #if __FreeBSD__ >= 5 x = (char)packet[1] + (char)packet[3]; y = (char)packet[2] + (char)packet[4]; z = ((char)(packet[5] << 1) + (char)(packet[6] << 1)) >> 1; #else x = (char)packet[1]; y = (char)packet[2]; #ifndef PC98 /* XXX */ if (packet[0] & 0x40) { if (packet[0] & 0x10) { x -= 128; } else { x += 128; } } if (packet[0] & 0x80) { if (packet[0] & 0x20) { y -= 128; } else { y += 128; } } #endif #endif move = 0; if (x != 0) { restore_hidden_region(); _mouse.x += x; if (_mouse.x < 0) { _mouse.x = 0; } else if (_display.width <= _mouse.x) { _mouse.x = _display.width - 1; } move = 1; } if (y != 0) { restore_hidden_region(); _mouse.y -= y; if (_mouse.y < 0) { _mouse.y = 0; } else if (_display.height <= _mouse.y) { _mouse.y = _display.height - 1; } move = 1; } if (move) { update_mouse_cursor_state(); } #if __FreeBSD__ >= 5 if (~packet[0] & 0x04) { xev.button = Button1; _mouse.button_state = Button1Mask; } else if (~packet[0] & 0x02) { xev.button = Button2; _mouse.button_state = Button2Mask; } else if (~packet[0] & 0x01) { xev.button = Button3; _mouse.button_state = Button3Mask; } else if (z < 0) { xev.button = Button4; _mouse.button_state = Button4Mask; } else if (z > 0) { xev.button = Button5; _mouse.button_state = Button5Mask; } #elif defined(PC98) if ((packet[0] & 0x4) == 0) { xev.button = Button1; _mouse.button_state = Button1Mask; } else if ((packet[0] & 0x2) == 0) { xev.button = Button2; _mouse.button_state = Button2Mask; } else if ((packet[0] & 0x01) == 0) { xev.button = Button3; _mouse.button_state = Button3Mask; } #else if (packet[0] & 0x1) { xev.button = Button1; _mouse.button_state = Button1Mask; } else if (packet[0] & 0x4) { xev.button = Button2; _mouse.button_state = Button2Mask; } else if (packet[0] & 0x02) { xev.button = Button3; _mouse.button_state = Button3Mask; } #endif else { xev.button = 0; } if (move) { xev.type = MotionNotify; xev.state = _mouse.button_state | _display.key_state; } else { if (xev.button) { xev.type = ButtonPress; } else { xev.type = ButtonRelease; if (_mouse.button_state & Button1Mask) { xev.button = Button1; } else if (_mouse.button_state & Button2Mask) { xev.button = Button2; } else if (_mouse.button_state & Button3Mask) { xev.button = Button3; } else if (_mouse.button_state & Button4Mask) { xev.button = Button4; } else if (_mouse.button_state & Button5Mask) { xev.button = Button5; } /* Reset button_state in releasing button */ _mouse.button_state = 0; } xev.state = _display.key_state; } if (rotate_display) { if (rotate_display > 0) { xev.x = _mouse.y; xev.y = _display.width - _mouse.x - 1; } else { xev.x = _display.height - _mouse.y - 1; xev.y = _mouse.x; } } else { xev.x = _mouse.x; xev.y = _mouse.y; } #ifdef __DEBUG bl_debug_printf( BL_DEBUG_TAG "Button is %s x %d y %d btn %d time %u\n", xev.type == ButtonPress ? "pressed" : xev.type == MotionNotify ? "motion" : "released", xev.x, xev.y, xev.button, xev.time); #endif if (!check_virtual_kbd(&xev)) { win = get_window(xev.x, xev.y); xev.x -= win->x; xev.y -= win->y; ui_window_receive_event(win, &xev); } if (move) { save_hidden_region(); draw_mouse_cursor(); } } } return 1; } /* http://kaworu.jpn.org/doc/FreeBSD/jman.ORG/man4/keyboard.4.php */ static int receive_key_event(void) { u_char code; while (read(_display.fd, &code, 1) == 1) { XKeyEvent xev; int pressed; int idx; if (code & 0x80) { pressed = 0; code &= 0x7f; } else { pressed = 1; } if (code >= keymap.n_keys) { continue; } if (keymap.key[code].flgs & 2) { /* The key should react on num-lock(2). (Keypad keys) */ int kcode; if ((kcode = keymap.key[code].map[0]) != 0 && pressed) { /* * KEY_KP0 etc are 0x100 larger than KEY_INSERT etc to * distinguish them. * (see ui.h) */ xev.ksym = kcode + 0x200; goto send_event; } else { continue; } } if (_display.key_state) { /* CommandMask is ignored. */ idx = (_display.key_state & ShiftMask); if (_display.key_state & ControlMask) { idx |= 2; } if (_display.key_state & ModMask) { idx |= 4; } } else { idx = 0; } if (!(keymap.key[code].spcl & (1 << (7 - idx)))) { /* Character keys */ if (pressed) { if ((keymap.key[code].flgs & 1) && (_display.lock_state & CLKED)) { /* xor shift bit(1) */ idx ^= 1; } #if 1 if (code == 41) { xev.ksym = XK_Zenkaku_Hankaku; } else if (code == 121) { xev.ksym = XK_Henkan_Mode; } else if (code == 123) { xev.ksym = XK_Muhenkan; } else #endif { xev.ksym = keymap.key[code].map[idx]; } goto send_event; } } else { /* Function keys */ int kcode; if ((kcode = keymap.key[code].map[0]) == 0) { /* do nothing */ } else if (pressed) { if (kcode == KEY_RIGHTSHIFT || kcode == KEY_LEFTSHIFT) { _display.key_state |= ShiftMask; } else if (kcode == KEY_RIGHTCTRL || kcode == KEY_LEFTCTRL) { _display.key_state |= ControlMask; } else if (kcode == KEY_RIGHTALT || kcode == KEY_LEFTALT) { _display.key_state |= Mod1Mask; } else if (kcode == KEY_NUMLOCK) { _display.lock_state ^= NLKED; } else if (kcode == KEY_CAPSLOCK) { _display.lock_state ^= CLKED; } else { xev.ksym = kcode + 0x100; goto send_event; } } else { if (kcode == KEY_RIGHTSHIFT || kcode == KEY_LEFTSHIFT) { _display.key_state &= ~ShiftMask; } else if (kcode == KEY_RIGHTCTRL || kcode == KEY_LEFTCTRL) { _display.key_state &= ~ControlMask; } else if (kcode == KEY_RIGHTALT || kcode == KEY_LEFTALT) { _display.key_state &= ~Mod1Mask; } } } continue; send_event: xev.type = KeyPress; xev.state = _mouse.button_state | _display.key_state; xev.keycode = code; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "scancode %d -> ksym 0x%x state 0x%x\n", code, xev.ksym, xev.state); #endif receive_event_for_multi_roots(&xev); } return 1; } mlterm-3.8.9/uitoolkit/fb/ui_display_linux.c010064400017600000144000000356441356600660700177150ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include #include /* VT_GETSTATE */ #define _GNU_SOURCE /* strcasestr */ #include #if 0 #define READ_CTRL_KEYMAP #endif /* --- static variables --- */ static int console_id = -1; /* --- static functions --- */ static int get_key_state(void) { int ret; char state; state = 6; ret = ioctl(STDIN_FILENO, TIOCLINUX, &state); if (ret == -1) { return 0; } else { /* ShiftMask and ControlMask is the same. */ return state | ((state & (1 << KG_ALT)) ? Mod1Mask : 0); } } static int kcode_to_ksym(int kcode, int state) { if (kcode == KEY_ENTER || kcode == KEY_KPENTER) { /* KDGKBENT returns '\n'(0x0a) */ return 0x0d; } else if (kcode == KEY_BACKSPACE) { /* KDGKBDENT returns 0x7f */ return 0x08; } else if (kcode <= KEY_SLASH || kcode == KEY_SPACE || kcode == KEY_YEN || kcode == KEY_RO) { struct kbentry ent; if (state & ShiftMask) { ent.kb_table = (1 << KG_SHIFT); } #ifdef READ_CTRL_KEYMAP else if (state & ControlMask) { ent.kb_table = (1 << KG_CTRL); } #endif else { ent.kb_table = 0; } ent.kb_index = kcode; if (ioctl(STDIN_FILENO, KDGKBENT, &ent) == 0 && ent.kb_value != K_HOLE && ent.kb_value != K_NOSUCHMAP) { ent.kb_value &= 0xff; #if 1 /* XXX linux returns KEY_GRAVE for HankakuZenkaku key. */ if (kcode == KEY_GRAVE && ent.kb_value == '\x1b') { static int is_jp106 = -1; if (is_jp106 == -1) { struct kbentry ent; is_jp106 = 0; ent.kb_table = (1 << KG_SHIFT); ent.kb_index = KEY_MINUS; if (ioctl(STDIN_FILENO, KDGKBENT, &ent) == 0 && ent.kb_value != K_HOLE && ent.kb_value != K_NOSUCHMAP && ent.kb_value == '=') { /* is jp106 or netherland */ is_jp106 = 1; } } if (is_jp106) { return KEY_ZENKAKUHANKAKU + 0x100; } } #endif return ent.kb_value; } } return kcode + 0x100; } static void set_use_console_backscroll(int use) { struct kbentry ent; bl_priv_restore_euid(); bl_priv_restore_egid(); ent.kb_table = (1 << KG_SHIFT); ent.kb_index = KEY_PAGEUP; ent.kb_value = use ? K_SCROLLBACK : K_PGUP; ioctl(STDIN_FILENO, KDSKBENT, &ent); ent.kb_index = KEY_PAGEDOWN; ent.kb_value = use ? K_SCROLLFORW : K_PGDN; ioctl(STDIN_FILENO, KDSKBENT, &ent); bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); } static void get_event_device_num_intern(int *kbd, int *mouse, const char *fmt) { char *class; int count; FILE* fp; *kbd = *mouse = -1; if (!(class = alloca(strlen(fmt) - 2 /* %d */ + 3 /* 0 - 999 */ + 1))) { return; } for (count = 0;; count++) { sprintf(class, fmt, count); if (!(fp = fopen(class, "r"))) { break; } else { char buf[128]; if (fgets(buf, sizeof(buf), fp)) { if (strcasestr(buf, "key")) { *kbd = count; } else { static char *mouse_names[] = {"mouse", "touch"}; u_int idx; for (idx = 0; idx < sizeof(mouse_names) / sizeof(mouse_names[0]); idx++) { if (strcasestr(buf, mouse_names[idx])) { *mouse = count; break; } } } } fclose(fp); if (*kbd != -1 && *mouse != -1) { break; } } } } static void get_event_device_num(int *kbd, int *mouse) { get_event_device_num_intern(kbd, mouse, "/sys/class/input/event%d/device/name"); if (*kbd == -1 || *mouse == -1) { int k; int m; /* * XXX * /sys/class/input/input%d/event%d * => Note that The first %d and the second %d might not be the same number. */ get_event_device_num_intern(&k, &m, "/sys/class/input/input%d/name"); if (*kbd == -1) { *kbd = k; } if (*mouse == -1) { *mouse = m; } } } static int open_event_device(u_int num, const char *path) { char event[16 + 3 /* 0 - 999 */ + 1]; int fd; if (!path) { if (num >= 1000) { /* num < 0 is impossible because num is u_int. */ return -1; } sprintf(event, "/dev/input/event%d", num); path = event; } bl_priv_restore_euid(); bl_priv_restore_egid(); if ((fd = open(path, O_RDONLY | O_NONBLOCK)) == -1) { bl_error_printf("Couldn't open %s.\n", path); } #if 0 else { /* Occupy /dev/input/eventN */ ioctl(fd, EVIOCGRAB, 1); } #endif bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); return fd; } static void convert_input_num(int *num, const char *str) { if (strcmp(str, "-1") == 0) { *num = -1; } else if ('0' <= *str && *str <= '9') { *num = atoi(str); } } static int open_display(u_int depth) { char *dev; struct fb_fix_screeninfo finfo; struct fb_var_screeninfo vinfo; int kbd_num; int mouse_num; struct termios tm; bl_priv_restore_euid(); bl_priv_restore_egid(); _display.fb_fd = open((dev = getenv("FRAMEBUFFER")) ? dev : "/dev/fb0", O_RDWR); bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); if (_display.fb_fd < 0) { bl_error_printf("Couldn't open %s.\n", dev ? dev : "/dev/fb0"); return 0; } bl_file_set_cloexec(_display.fb_fd); ioctl(_display.fb_fd, FBIOGET_FSCREENINFO, &finfo); ioctl(_display.fb_fd, FBIOGET_VSCREENINFO, &vinfo); if ((_disp.depth = vinfo.bits_per_pixel) < 8) { #ifdef ENABLE_2_4_PPB _display.pixels_per_byte = 8 / _disp.depth; #else /* XXX Forcibly set 1 bpp */ _display.pixels_per_byte = 8; _disp.depth = 1; #endif _display.shift_0 = FB_SHIFT_0(_display.pixels_per_byte, _disp.depth); _display.mask = FB_MASK(_display.pixels_per_byte); } else { _display.pixels_per_byte = 1; } if ((_display.fb = _display.fb_base = mmap(NULL, (_display.smem_len = finfo.smem_len), PROT_WRITE | PROT_READ, MAP_SHARED, _display.fb_fd, (off_t)0)) == MAP_FAILED) { goto error; } if ((_display.bytes_per_pixel = (_disp.depth + 7) / 8) == 3) { _display.bytes_per_pixel = 4; } if (_disp.depth < 15 && !cmap_init()) { goto error; } #ifdef ENABLE_DOUBLE_BUFFER if (_display.pixels_per_byte > 1 && !(_display.back_fb = malloc(_display.smem_len))) { cmap_final(); goto error; } #endif _display.line_length = finfo.line_length; _display.xoffset = vinfo.xoffset; _display.yoffset = vinfo.yoffset; _display.width = _disp.width = vinfo.xres; _display.height = _disp.height = vinfo.yres; _display.rgbinfo.r_limit = 8 - vinfo.red.length; _display.rgbinfo.g_limit = 8 - vinfo.green.length; _display.rgbinfo.b_limit = 8 - vinfo.blue.length; _display.rgbinfo.r_offset = vinfo.red.offset; _display.rgbinfo.g_offset = vinfo.green.offset; _display.rgbinfo.b_offset = vinfo.blue.offset; get_event_device_num(&kbd_num, &mouse_num); if ((dev = getenv("KBD_INPUT_NUM"))) { convert_input_num(&kbd_num, dev); } if ((dev = getenv("MOUSE_INPUT_NUM"))) { convert_input_num(&mouse_num, dev); } tcgetattr(STDIN_FILENO, &tm); orig_tm = tm; tm.c_iflag = tm.c_oflag = 0; tm.c_cflag &= ~CSIZE; tm.c_cflag |= CS8; tm.c_lflag &= ~(ECHO | ISIG | ICANON); tm.c_cc[VMIN] = 1; tm.c_cc[VTIME] = 0; tcsetattr(STDIN_FILENO, TCSAFLUSH, &tm); /* Disable backscrolling of default console. */ set_use_console_backscroll(0); if (kbd_num == -1 || (_display.fd = open_event_device(kbd_num, NULL)) == -1) { _display.fd = STDIN_FILENO; } else { bl_file_set_cloexec(_display.fd); } _disp.display = &_display; if ((mouse_num == -1 || (_mouse.fd = open_event_device(mouse_num, NULL)) == -1) && (_mouse.fd = open_event_device(0, "/dev/input/mice")) == -1 && (_mouse.fd = open_event_device(0, "/dev/input/mouse0")) == -1) { _mouse.fd = -1; } else { bl_file_set_cloexec(_mouse.fd); _mouse.x = _display.width / 2; _mouse.y = _display.height / 2; _disp_mouse.display = (Display*)&_mouse; } console_id = get_active_console(); return 1; error: if (_display.fb) { munmap(_display.fb, _display.smem_len); _display.fb = _display.fb_base = NULL; } close(_display.fb_fd); return 0; } static int receive_mouse_event(void) { struct input_event ev; if (console_id != get_active_console()) { return 0; } while (read(_mouse.fd, &ev, sizeof(ev)) > 0) { if (ev.type == EV_ABS) { #ifdef EVIOCGABS static int max_abs_x; static int max_abs_y; if (max_abs_x == 0 /* || max_abs_y == 0 */) { struct input_absinfo info; ioctl(_mouse.fd, EVIOCGABS(ABS_X), &info); max_abs_x = info.maximum; ioctl(_mouse.fd, EVIOCGABS(ABS_Y), &info); max_abs_y = info.maximum; } if (ev.code == ABS_PRESSURE) { ev.type = EV_KEY; ev.code = BTN_LEFT; ev.value = 1; /* ButtonPress */ } else if (ev.code == ABS_X) { ev.type = EV_REL; ev.code = REL_X; ev.value = ev.value * _display.width / max_abs_x - _mouse.x; } else if (ev.code == ABS_Y) { ev.type = EV_REL; ev.code = REL_Y; ev.value = ev.value * _display.height / max_abs_y - _mouse.y; } else #endif { continue; } } if (ev.type == EV_KEY) { XButtonEvent xev; ui_window_t *win; if (ev.code == BTN_LEFT) { xev.button = Button1; _mouse.button_state = Button1Mask; } else if (ev.code == BTN_MIDDLE) { xev.button = Button2; _mouse.button_state = Button2Mask; } else if (ev.code == BTN_RIGHT) { xev.button = Button3; _mouse.button_state = Button3Mask; } else { continue; while (1) { button4: xev.button = Button4; _mouse.button_state = Button4Mask; break; button5: xev.button = Button5; _mouse.button_state = Button5Mask; break; button6: xev.button = Button6; _mouse.button_state = Button6Mask; break; button7: xev.button = Button7; _mouse.button_state = Button7Mask; break; } ev.value = 1; } if (ev.value == 1) { xev.type = ButtonPress; } else if (ev.value == 0) { xev.type = ButtonRelease; /* Reset button_state in releasing button. */ _mouse.button_state = 0; } else { continue; } xev.time = ev.time.tv_sec * 1000 + ev.time.tv_usec / 1000; if (rotate_display) { if (rotate_display > 0) { xev.x = _mouse.y; xev.y = _display.width - _mouse.x - 1; } else { xev.x = _display.height - _mouse.y - 1; xev.y = _mouse.x; } } else { xev.x = _mouse.x; xev.y = _mouse.y; } xev.state = _display.key_state; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "Button is %s x %d y %d btn %d time %d\n", xev.type == ButtonPress ? "pressed" : "released", xev.x, xev.y, xev.button, xev.time); #endif if (!check_virtual_kbd(&xev)) { win = get_window(xev.x, xev.y); xev.x -= win->x; xev.y -= win->y; ui_window_receive_event(win, &xev); } } else if (ev.type == EV_REL) { XMotionEvent xev; ui_window_t *win; if (ev.code == REL_X) { restore_hidden_region(); _mouse.x += (int)ev.value; if (_mouse.x < 0) { _mouse.x = 0; } else if (_display.width <= _mouse.x) { _mouse.x = _display.width - 1; } } else if (ev.code == REL_Y) { restore_hidden_region(); _mouse.y += (int)ev.value; if (_mouse.y < 0) { _mouse.y = 0; } else if (_display.height <= _mouse.y) { _mouse.y = _display.height - 1; } } else if (ev.code == REL_WHEEL) { if (ev.value > 0) { /* Up */ goto button4; } else if (ev.value < 0) { /* Down */ goto button5; } } else if (ev.code == REL_HWHEEL) { if (ev.value < 0) { /* Left */ goto button6; } else if (ev.value > 0) { /* Right */ goto button7; } } else { continue; } update_mouse_cursor_state(); xev.type = MotionNotify; if (rotate_display) { if (rotate_display > 0) { xev.x = _mouse.y; xev.y = _display.width - _mouse.x - 1; } else { xev.x = _display.height - _mouse.y - 1; xev.y = _mouse.x; } } else { xev.x = _mouse.x; xev.y = _mouse.y; } xev.time = ev.time.tv_sec * 1000 + ev.time.tv_usec / 1000; xev.state = _mouse.button_state | _display.key_state; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Button is moved %d x %d y %d btn %d time %d\n", xev.type, xev.x, xev.y, xev.state, xev.time); #endif win = get_window(xev.x, xev.y); xev.x -= win->x; xev.y -= win->y; ui_window_receive_event(win, &xev); save_hidden_region(); draw_mouse_cursor(); } } return 1; } static int receive_key_event(void) { if (_display.fd == STDIN_FILENO) { return receive_stdin_key_event(); } else { struct input_event ev; if (console_id != get_active_console()) { return 0; } while (read(_display.fd, &ev, sizeof(ev)) > 0) { if (ev.type == EV_KEY && ev.code < 0x100 /* Key event is less than 0x100 */) { if (ev.value == 1 /* Pressed */ || ev.value == 2 /* auto repeat */) { if (ev.code == KEY_RIGHTSHIFT || ev.code == KEY_LEFTSHIFT) { _display.key_state |= ShiftMask; } else if (ev.code == KEY_CAPSLOCK) { if (_display.key_state & ShiftMask) { _display.key_state &= ~ShiftMask; } else { _display.key_state |= ShiftMask; } } else if (ev.code == KEY_RIGHTCTRL || ev.code == KEY_LEFTCTRL) { _display.key_state |= ControlMask; } else if (ev.code == KEY_RIGHTALT || ev.code == KEY_LEFTALT) { _display.key_state |= Mod1Mask; } else if (ev.code == KEY_NUMLOCK) { _display.lock_state ^= NLKED; } else { XKeyEvent xev; xev.type = KeyPress; xev.ksym = kcode_to_ksym(ev.code, _display.key_state); xev.keycode = ev.code; xev.state = _mouse.button_state | _display.key_state; receive_event_for_multi_roots(&xev); } } else if (ev.value == 0 /* Released */) { if (ev.code == KEY_RIGHTSHIFT || ev.code == KEY_LEFTSHIFT) { _display.key_state &= ~ShiftMask; } else if (ev.code == KEY_RIGHTCTRL || ev.code == KEY_LEFTCTRL) { _display.key_state &= ~ControlMask; } else if (ev.code == KEY_RIGHTALT || ev.code == KEY_LEFTALT) { _display.key_state &= ~Mod1Mask; } } } } } return 1; } mlterm-3.8.9/uitoolkit/fb/ui_display_wscons.c010064400017600000144000000543041356600660700200640ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include /* MACHINE */ #include /* VT_GETSTATE */ #ifdef __NetBSD__ #include "../ui_event_source.h" #endif #ifdef __NetBSD__ #define KEY_REPEAT_UNIT 25 /* msec (see ui_event_source.c) */ #define DEFAULT_KEY_REPEAT_1 400 /* msec */ #define DEFAULT_KEY_REPEAT_N 50 /* msec */ #define DEFAULT_FBDEV "/dev/ttyE0" #else /* __OpenBSD__ */ #define DEFAULT_FBDEV "/dev/ttyC0" #endif #define get_key_state() (0) /* --- static variables --- */ static u_int kbd_type; static struct wskbd_map_data keymap; static int console_id = -1; static struct wscons_event prev_key_event; u_int fb_width = 640; u_int fb_height = 480; u_int fb_depth = 8; #ifdef __NetBSD__ static int kbd_repeat_wait = (DEFAULT_KEY_REPEAT_1 + KEY_REPEAT_UNIT / 2) / KEY_REPEAT_UNIT; int kbd_repeat_1 = DEFAULT_KEY_REPEAT_1; int kbd_repeat_N = DEFAULT_KEY_REPEAT_N; #endif static int orig_console_mode = WSDISPLAYIO_MODE_EMUL; /* 0 */ static int wskbd_mode_switch = 0; /* --- static functions --- */ /* For iBus which requires ps/2 keycode. */ static u_int get_ps2_kcode(u_int kcode) { if (kbd_type == WSKBD_TYPE_USB) { static u_char map_table1[] = { 30, /* A (4) */ 48, /* B */ 46, /* C */ 32, /* D */ 18, /* E */ 33, /* F */ 34, /* G (10) */ 35, /* H */ 23, /* I */ 36, /* J */ 37, /* K */ 38, /* L */ 50, /* M */ 49, /* N */ 24, /* O */ 25, /* P */ 16, /* Q (20) */ 19, /* R */ 31, /* S */ 20, /* T */ 22, /* U */ 47, /* V */ 17, /* W */ 45, /* X */ 21, /* Y */ 44, /* Z */ 2, /* 1 (30) */ 3, /* 2 */ 4, /* 3 */ 5, /* 4 */ 6, /* 5 */ 7, /* 6 */ 8, /* 7 */ 9, /* 8 */ 10, /* 9 */ 11, /* 0 */ 28, /* Enter (40) */ 1, /* ESC */ 14, /* BackSpace */ 15, /* Tab */ 57, /* Space */ 12, /* _ - */ 13, /* + = */ 26, /* { [ */ 27, /* } ] */ 43, /* \ | */ 0, /* (50) */ 39, /* : ; */ 40, /* " ' */ 41, /* ~ ` */ 51, /* < , */ 52, /* > . */ 53, /* ? / */ 58, /* CapsLock */ 59, /* F1 */ 60, /* F2 */ 61, /* F3 (60) */ 62, /* F4 */ 63, /* F5 */ 64, /* F6 */ 65, /* F7 */ 66, /* F8 */ 67, /* F9 */ 68, /* F10 */ 87, /* F11 */ 88, /* F12 */ 0, /* Print Screen (70) */ 70, /* ScreenLock */ 0, /* Pause */ 110, /* Insert */ 102, /* Home */ 104, /* Page Up */ 111, /* Delete */ 107, /* End */ 109, /* Page Down */ 106, /* Right */ 105, /* Left (80) */ 108, /* Down */ 103, /* Up */ 69, /* NumLock */ 0, /* Num / */ 55, /* Num * */ 74, /* Num - */ 78, /* Num + */ 0, /* Num Enter */ 79, /* Num 1 */ 80, /* Num 2 (90) */ 81, /* Num 3 */ 75, /* Num 4 */ 76, /* Num 5 */ 77, /* Num 6 */ 71, /* Num 7 */ 72, /* Num 8 */ 73, /* Num 9 */ 82, /* Num 0 */ 83, /* Num . */ }; static u_char map_table2[] = { 29, /* Control L (224) */ 42, /* Shift L */ 56, /* Alt L */ 0, /* Windows L */ 97, /* Control R */ 54, /* Shift R */ 100, /* Alt R (230) */ 0, /* Windows R */ }; if (4 <= kcode) { if (kcode <= 99) { return map_table1[kcode - 4]; } else if (224 <= kcode) { if (kcode <= 231) { return map_table2[kcode - 224]; } } } return 0; } else { return kcode; } } static void process_wskbd_event(struct wscons_event *ev) { keysym_t ksym; if (keymap.map[ev->value].command == KS_Cmd_ResetEmul) { /* XXX */ ksym = XK_BackSpace; } else { keysym_t *group; if (wskbd_mode_switch) { group = keymap.map[ev->value].group2; } else { group = keymap.map[ev->value].group1; } if (_display.key_state & ShiftMask) { ksym = group[1]; } else { ksym = group[0]; } if (KS_f1 <= ksym && ksym <= KS_f20) { /* KS_f1 => KS_F1 */ ksym += (KS_F1 - KS_f1); } else if (_display.lock_state & CLKED) { if (KS_a <= ksym && ksym <= KS_z) { ksym += (KS_A - KS_a); } else if (KS_agrave <= ksym && ksym <= KS_thorn && ksym != KS_division) { ksym += (KS_Agrave - KS_agrave); } } } if (ev->type == WSCONS_EVENT_KEY_DOWN) { if (ksym == KS_Shift_R || ksym == KS_Shift_L) { _display.key_state |= ShiftMask; } else if (ksym == KS_Caps_Lock) { _display.lock_state ^= CLKED; } else if (ksym == KS_Control_R || ksym == KS_Control_L) { _display.key_state |= ControlMask; } else if (ksym == KS_Alt_R || ksym == KS_Alt_L) { _display.key_state |= Mod1Mask; } else if (ksym == KS_Mode_switch) { wskbd_mode_switch = 1; } else if (ksym == KS_Num_Lock) { _display.lock_state ^= NLKED; } else { XKeyEvent xev; xev.type = KeyPress; xev.ksym = ksym; xev.state = _mouse.button_state | _display.key_state; xev.keycode = get_ps2_kcode(ev->value); receive_event_for_multi_roots(&xev); prev_key_event = *ev; #ifdef __NetBSD__ kbd_repeat_wait = (kbd_repeat_1 + KEY_REPEAT_UNIT / 2) / KEY_REPEAT_UNIT; #endif } } else if (ev->type == WSCONS_EVENT_KEY_UP) { if (ksym == KS_Shift_R || ksym == KS_Shift_L) { _display.key_state &= ~ShiftMask; } else if (ksym == KS_Control_R || ksym == KS_Control_L) { _display.key_state &= ~ControlMask; } else if (ksym == KS_Alt_R || ksym == KS_Alt_L) { _display.key_state &= ~Mod1Mask; } else if (ksym == KS_Mode_switch) { wskbd_mode_switch = 0; } else if (ev->value == prev_key_event.value) { prev_key_event.value = 0; } } } #ifdef __NetBSD__ static void auto_repeat(void) { if (prev_key_event.value && --kbd_repeat_wait == 0) { process_wskbd_event(&prev_key_event); kbd_repeat_wait = (kbd_repeat_N + KEY_REPEAT_UNIT / 2) / KEY_REPEAT_UNIT; } } #endif static fb_cmap_t *cmap_new(int num_colors); static int open_display(u_int depth /* used on luna68k alone. */ ) { char *dev; struct wsdisplay_fbinfo vinfo; #ifdef WSDISPLAYIO_GET_FBINFO struct wsdisplayio_fbinfo vinfo2; #endif int fboffset; int mode; int wstype; struct rgb_info rgbinfos[] = { {3, 3, 3, 10, 5, 0}, {3, 2, 3, 11, 5, 0}, {0, 0, 0, 16, 8, 0}, }; struct termios tm; static struct wscons_keymap map[KS_NUMKEYCODES]; bl_priv_restore_euid(); bl_priv_restore_egid(); _display.fb_fd = open((dev = getenv("FRAMEBUFFER")) ? dev : DEFAULT_FBDEV, O_RDWR); bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); if (_display.fb_fd < 0) { bl_error_printf("Couldn't open %s.\n", dev ? dev : DEFAULT_FBDEV); return 0; } bl_file_set_cloexec(_display.fb_fd); ioctl(STDIN_FILENO, WSDISPLAYIO_GMODE, &orig_console_mode); #ifdef __OpenBSD__ { struct wsdisplay_gfx_mode gfx_mode; gfx_mode.width = fb_width; gfx_mode.height = fb_height; gfx_mode.depth = fb_depth; if (ioctl(_display.fb_fd, WSDISPLAYIO_SETGFXMODE, &gfx_mode) == -1) { bl_error_printf("Couldn't set screen resolution (gfx mode).\n"); } } #endif mode = WSDISPLAYIO_MODE_DUMBFB; if (ioctl(STDIN_FILENO, WSDISPLAYIO_SMODE, &mode) == -1) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " WSDISPLAYIO_SMODE failed.\n"); #endif goto error; } if (ioctl(_display.fb_fd, WSDISPLAYIO_GTYPE, &wstype) == -1) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " WSDISPLAYIO_GTYPE failed.\n"); #endif goto error; } #ifdef WSDISPLAYIO_GET_FBINFO vinfo2.fbi_stride = 0; if (ioctl(_display.fb_fd, WSDISPLAYIO_GET_FBINFO, &vinfo2) == 0) { vinfo.width = vinfo2.fbi_width; vinfo.height = vinfo2.fbi_height; vinfo.depth = vinfo2.fbi_bitsperpixel; vinfo.cmsize = vinfo2.fbi_subtype.fbi_cmapinfo.cmap_entries; fboffset = vinfo2.fbi_fboffset; } else #endif if (ioctl(_display.fb_fd, WSDISPLAYIO_GINFO, &vinfo) == 0) { #ifdef WSDISPLAY_TYPE_LUNA if (wstype == WSDISPLAY_TYPE_LUNA) { fboffset = 8; } else #endif { fboffset = 0; } } else { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " WSDISPLAYIO_GTYPE and WSDISPLAYIO_GET_FBINFO failed.\n"); #endif goto error; } _display.xoffset = 0; _display.yoffset = 0; _display.width = _disp.width = vinfo.width; _display.height = _disp.height = vinfo.height; _disp.depth = vinfo.depth; #ifdef WSDISPLAY_TYPE_LUNA if (wstype == WSDISPLAY_TYPE_LUNA) { /* always 8 or less bpp */ if (_disp.depth > 8) { goto error; } else if (depth == 1 || depth == 4 || depth == 8) { _disp.depth = depth; } _display.pixels_per_byte = 8; _display.shift_0 = 7; _display.mask = 1; } else #endif if (_disp.depth < 8) { #ifdef ENABLE_2_4_PPB _display.pixels_per_byte = 8 / _disp.depth; #else /* XXX Forcibly set 1 bpp */ _disp.depth = 1; _display.pixels_per_byte = 8; #endif _display.shift_0 = FB_SHIFT_0(_display.pixels_per_byte, _disp.depth); _display.mask = FB_MASK(_display.pixels_per_byte); } else { _display.pixels_per_byte = 1; } if ((_display.bytes_per_pixel = (_disp.depth + 7) / 8) == 3) { _display.bytes_per_pixel = 4; } #ifdef WSDISPLAYIO_GET_FBINFO if (vinfo2.fbi_stride > 0) { _display.line_length = vinfo2.fbi_stride; } else #endif if (ioctl(_display.fb_fd, WSDISPLAYIO_LINEBYTES, &_display.line_length) == -1) { /* WSDISPLAYIO_LINEBYTES isn't defined in some ports. */ #ifdef MACHINE /* XXX Hack for NetBSD 5.ui.hpcmips */ if (strcmp(MACHINE, "hpcmips") == 0 && _disp.depth == 16) { _display.line_length = _display.width * 5 / 2; } else #endif { _display.line_length = _display.width * _display.bytes_per_pixel / _display.pixels_per_byte; } } #ifdef WSDISPLAY_TYPE_LUNA if (wstype == WSDISPLAY_TYPE_LUNA && (_disp.depth == 4 || _disp.depth == 8)) { u_int plane; _display.smem_len = fboffset + 0x40000 * _disp.depth; for (plane = 0; plane < _disp.depth; plane++) { _display.plane_offset[plane] = 0x40000 * plane; } } else #endif { _display.smem_len = fboffset + _display.line_length * _display.height; } if ((_display.fb = mmap(NULL, _display.smem_len, PROT_WRITE | PROT_READ, MAP_SHARED, _display.fb_fd, (off_t)0)) == MAP_FAILED) { bl_error_printf("Retry another mode of resolution and depth.\n"); goto error; } _display.fb_base = _display.fb + fboffset; if (_disp.depth < 15) { if (vinfo.depth >= 2 && _disp.depth == 1) { int num_colors; vt_color_t color; num_colors = (2 << (vinfo.depth - 1)); if (!_display.cmap) { if (!(_display.cmap_orig = cmap_new(num_colors))) { goto error; } ioctl(_display.fb_fd, FBIOGETCMAP, _display.cmap_orig); if (!(_display.cmap = cmap_new(num_colors))) { free(_display.cmap_orig); goto error; } if (!(_display.color_cache = calloc(1, sizeof(*_display.color_cache)))) { free(_display.cmap_orig); free(_display.cmap); goto error; } } for (color = 0; color < num_colors; color++) { _display.cmap->red[color] = (color & 1) ? 0xff : 0; _display.cmap->green[color] = (color & 1) ? 0xff : 0; _display.cmap->blue[color] = (color & 1) ? 0xff : 0; } ioctl(_display.fb_fd, FBIOPUTCMAP, _display.cmap); } else if (!cmap_init()) { goto error; } } #ifdef WSDISPLAYIO_GET_FBINFO else if (vinfo2.fbi_stride > 0) { _display.rgbinfo.r_limit = 8 - vinfo2.fbi_subtype.fbi_rgbmasks.red_size; _display.rgbinfo.g_limit = 8 - vinfo2.fbi_subtype.fbi_rgbmasks.green_size; _display.rgbinfo.b_limit = 8 - vinfo2.fbi_subtype.fbi_rgbmasks.blue_size; _display.rgbinfo.r_offset = vinfo2.fbi_subtype.fbi_rgbmasks.red_offset; _display.rgbinfo.g_offset = vinfo2.fbi_subtype.fbi_rgbmasks.green_offset; _display.rgbinfo.b_offset = vinfo2.fbi_subtype.fbi_rgbmasks.blue_offset; #ifdef DEBUG bl_debug_printf("FBINFO: (limit)r%d g%d b%d (offset)r%d g%d b%d\n", _display.rgbinfo.r_limit, _display.rgbinfo.g_limit, _display.rgbinfo.b_limit, _display.rgbinfo.r_offset, _display.rgbinfo.g_offset, _display.rgbinfo.b_offset); #endif } #endif else { if (_disp.depth == 15) { _display.rgbinfo = rgbinfos[0]; } else if (_disp.depth == 16) { _display.rgbinfo = rgbinfos[1]; } else /* if( _disp.depth >= 24) */ { _display.rgbinfo = rgbinfos[2]; } if (wstype == WSDISPLAY_TYPE_SUN24 || wstype == WSDISPLAY_TYPE_SUNCG12 || wstype == WSDISPLAY_TYPE_SUNCG14 || wstype == WSDISPLAY_TYPE_SUNTCX || wstype == WSDISPLAY_TYPE_SUNFFB #ifdef WSDISPLAY_TYPE_XVR1000 || wstype == WSDISPLAY_TYPE_XVR1000 #endif #ifdef WSDISPLAY_TYPE_VC4 || wstype == WSDISPLAY_TYPE_VC4 #endif ) { /* RRGGBB => BBGGRR */ u_int tmp; tmp = _display.rgbinfo.r_offset; _display.rgbinfo.r_offset = _display.rgbinfo.b_offset; _display.rgbinfo.b_offset = tmp; } } #ifdef ENABLE_DOUBLE_BUFFER if (_display.pixels_per_byte > 1 && !(_display.back_fb = malloc(_display.smem_len))) { goto error; } #endif tcgetattr(STDIN_FILENO, &tm); orig_tm = tm; tm.c_iflag = tm.c_oflag = 0; tm.c_cflag &= ~CSIZE; tm.c_cflag |= CS8; tm.c_lflag &= ~(ECHO | ISIG | IEXTEN | ICANON); tm.c_cc[VMIN] = 1; tm.c_cc[VTIME] = 0; tcsetattr(STDIN_FILENO, TCSAFLUSH, &tm); bl_priv_restore_euid(); bl_priv_restore_egid(); if (!getenv("WSKBD") || /* If you want to use /dev/wskbd0, export WSKBD=/dev/wskbd0 */ (_display.fd = open(getenv("WSKBD"), O_RDWR | O_NONBLOCK | O_EXCL)) == -1) { _display.fd = open("/dev/wskbd", O_RDWR | O_NONBLOCK | O_EXCL); } _mouse.fd = open("/dev/wsmouse", O_RDWR | O_NONBLOCK | O_EXCL); bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); if (_display.fd == -1) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to open /dev/wskbd.\n"); #endif _display.fd = STDIN_FILENO; } else { bl_file_set_cloexec(_display.fd); #ifdef WSKBDIO_EVENT_VERSION mode = WSKBDIO_EVENT_VERSION; ioctl(_display.fd, WSKBDIO_SETVERSION, &mode); #endif ioctl(_display.fd, WSKBDIO_GTYPE, &kbd_type); keymap.maplen = KS_NUMKEYCODES; keymap.map = map; ioctl(_display.fd, WSKBDIO_GETMAP, &keymap); #if 0 bl_debug_printf("DUMP KEYMAP (LEN %d)\n", keymap.maplen); { int count; for (count = 0; count < keymap.maplen; count++) { bl_debug_printf("%d: %x %x %x %x %x\n", count, keymap.map[count].command, keymap.map[count].group1[0], keymap.map[count].group1[1], keymap.map[count].group2[0], keymap.map[count].group2[1]); } } #endif tcgetattr(_display.fd, &tm); tm.c_iflag = IGNBRK | IGNPAR; tm.c_oflag = 0; tm.c_lflag = 0; tm.c_cc[VTIME] = 0; tm.c_cc[VMIN] = 1; tm.c_cflag = CS8 | CSTOPB | CREAD | CLOCAL | HUPCL; cfsetispeed(&tm, B1200); cfsetospeed(&tm, B1200); tcsetattr(_display.fd, TCSAFLUSH, &tm); ioctl(_display.fd, WSKBDIO_GETLEDS, &_display.lock_state); #ifdef __NetBSD__ ui_event_source_add_fd(-10, auto_repeat); #endif } _disp.display = &_display; if (_mouse.fd != -1) { bl_file_set_cloexec(_mouse.fd); #ifdef WSMOUSE_EVENT_VERSION mode = WSMOUSE_EVENT_VERSION; ioctl(_mouse.fd, WSMOUSEIO_SETVERSION, &mode); #endif _mouse.x = _display.width / 2; _mouse.y = _display.height / 2; _disp_mouse.display = (Display*)&_mouse; tcgetattr(_mouse.fd, &tm); tm.c_iflag = IGNBRK | IGNPAR; tm.c_oflag = 0; tm.c_lflag = 0; tm.c_cc[VTIME] = 0; tm.c_cc[VMIN] = 1; tm.c_cflag = CS8 | CSTOPB | CREAD | CLOCAL | HUPCL; cfsetispeed(&tm, B1200); cfsetospeed(&tm, B1200); tcsetattr(_mouse.fd, TCSAFLUSH, &tm); } #ifdef DEBUG else { bl_debug_printf(BL_DEBUG_TAG " Failed to open /dev/wsmouse.\n"); } #endif console_id = get_active_console(); return 1; error: if (_display.fb) { munmap(_display.fb, _display.smem_len); _display.fb = _display.fb_base = NULL; } close(_display.fb_fd); ioctl(STDIN_FILENO, WSDISPLAYIO_SMODE, &orig_console_mode); return 0; } static int receive_mouse_event(void) { struct wscons_event ev; ssize_t len; if (console_id != get_active_console()) { return 0; } while ((len = read(_mouse.fd, memset(&ev, 0, sizeof(ev)), sizeof(ev))) > 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " MOUSE event (len)%d (type)%d (val)%d\n", len, ev.type, ev.value); #endif if (ev.type == WSCONS_EVENT_MOUSE_ABSOLUTE_X) { _mouse.x = ev.value; continue; /* Wait for ABSOLUTE_Y */ } else if (ev.type == WSCONS_EVENT_MOUSE_ABSOLUTE_Y) { restore_hidden_region(); _mouse.y = ev.value; update_mouse_cursor_state(); /* XXX MotionNotify event is not sent. */ save_hidden_region(); draw_mouse_cursor(); ev.type = WSCONS_EVENT_MOUSE_DOWN; ev.value = 0; /* Button1 */ } if (ev.type == WSCONS_EVENT_MOUSE_DOWN || ev.type == WSCONS_EVENT_MOUSE_UP) { XButtonEvent xev; ui_window_t *win; if (ev.value == 0) { xev.button = Button1; _mouse.button_state = Button1Mask; } else if (ev.value == 1) { xev.button = Button2; _mouse.button_state = Button2Mask; } else if (ev.value == 2) { xev.button = Button3; _mouse.button_state = Button3Mask; } else { continue; while (1) { button4: xev.button = Button4; _mouse.button_state = Button4Mask; break; button5: xev.button = Button5; _mouse.button_state = Button5Mask; break; button6: xev.button = Button6; _mouse.button_state = Button6Mask; break; button7: xev.button = Button7; _mouse.button_state = Button7Mask; break; } ev.value = 1; } if (ev.type != WSCONS_EVENT_MOUSE_UP) { /* * WSCONS_EVENT_MOUSE_UP, * WSCONS_EVENT_MOUSE_DELTA_Z * WSCONS_EVENT_MOUSE_DELTA_W */ xev.type = ButtonPress; } else /* if( ev.type == WSCONS_EVENT_MOUSE_UP) */ { xev.type = ButtonRelease; /* Reset button_state in releasing button. */ _mouse.button_state = 0; } xev.time = ev.time.tv_sec * 1000 + ev.time.tv_nsec / 1000000; if (rotate_display) { if (rotate_display > 0) { xev.x = _mouse.y; xev.y = _display.width - _mouse.x - 1; } else { xev.x = _display.height - _mouse.y - 1; xev.y = _mouse.x; } } else { xev.x = _mouse.x; xev.y = _mouse.y; } xev.state = _display.key_state; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "Button is %s x %d y %d btn %d time %d\n", xev.type == ButtonPress ? "pressed" : "released", xev.x, xev.y, xev.button, xev.time); #endif if (!check_virtual_kbd(&xev)) { win = get_window(xev.x, xev.y); xev.x -= win->x; xev.y -= win->y; ui_window_receive_event(win, &xev); } } else if (ev.type == WSCONS_EVENT_MOUSE_DELTA_X || ev.type == WSCONS_EVENT_MOUSE_DELTA_Y || ev.type == WSCONS_EVENT_MOUSE_DELTA_Z || ev.type == WSCONS_EVENT_MOUSE_DELTA_W) { XMotionEvent xev; ui_window_t *win; if (ev.type == WSCONS_EVENT_MOUSE_DELTA_X) { restore_hidden_region(); _mouse.x += (int)ev.value; if (_mouse.x < 0) { _mouse.x = 0; } else if (_display.width <= _mouse.x) { _mouse.x = _display.width - 1; } } else if (ev.type == WSCONS_EVENT_MOUSE_DELTA_Y) { restore_hidden_region(); _mouse.y -= (int)ev.value; if (_mouse.y < 0) { _mouse.y = 0; } else if (_display.height <= _mouse.y) { _mouse.y = _display.height - 1; } } else if (ev.type == WSCONS_EVENT_MOUSE_DELTA_Z) { if (ev.value < 0) { /* Up */ goto button4; } else if (ev.value > 0) { /* Down */ goto button5; } } else /* if( ev.type == WSCONS_EVENT_MOUSE_DELTA_W) */ { if (ev.value < 0) { /* Left */ goto button6; } else if (ev.value > 0) { /* Right */ goto button7; } } update_mouse_cursor_state(); xev.type = MotionNotify; if (rotate_display) { if (rotate_display > 0) { xev.x = _mouse.y; xev.y = _display.width - _mouse.x - 1; } else { xev.x = _display.height - _mouse.y - 1; xev.y = _mouse.x; } } else { xev.x = _mouse.x; xev.y = _mouse.y; } xev.time = ev.time.tv_sec * 1000 + ev.time.tv_nsec / 1000000; xev.state = _mouse.button_state | _display.key_state; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Button is moved %d x %d y %d btn %d time %d\n", xev.type, xev.x, xev.y, xev.state, xev.time); #endif win = get_window(xev.x, xev.y); xev.x -= win->x; xev.y -= win->y; ui_window_receive_event(win, &xev); save_hidden_region(); draw_mouse_cursor(); } } return 1; } static int receive_key_event(void) { if (_display.fd == STDIN_FILENO) { return receive_stdin_key_event(); } else { ssize_t len; struct wscons_event ev; if (console_id != get_active_console()) { return 0; } while ((len = read(_display.fd, memset(&ev, 0, sizeof(ev)), sizeof(ev))) > 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " KEY event (len)%d (type)%d (val)%d\n", len, ev.type, ev.value); #endif process_wskbd_event(&ev); } } return 1; } mlterm-3.8.9/uitoolkit/fb/ui_display_x68kgrf.c010064400017600000144000000520621356600660700200460ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include /* VT_GETSTATE */ #include #include #include #define get_key_state() (0) typedef struct fb_reg { /* CRT controller */ struct { u_short r00, r01, r02, r03, r04, r05, r06, r07; u_short r08, r09, r10, r11, r12, r13, r14, r15; u_short r16, r17, r18, r19, r20, r21, r22, r23; char pad0[0x450]; u_short ctrl; char pad1[0x1b7e]; } crtc; u_short gpal[256]; /* graphic palette */ u_short tpal[256]; /* text palette */ /* video controller */ struct { u_short r0; char pad0[0xfe]; u_short r1; char pad1[0xfe]; u_short r2; char pad2[0x19fe]; } videoc; u_short pad0[0xa000]; /* system port */ struct { u_short r1, r2, r3, r4; u_short pad0[2]; u_short r5, r6; u_short pad[0x1ff0]; } sysport; } fb_reg_t; typedef struct fb_reg_conf { struct { u_short r00, r01, r02, r03, r04, r05, r06, r07, r08, r20; } crtc; struct { u_short r0, r1, r2; } videoc; } fb_reg_conf_t; /* --- static variables --- */ static int console_id = -1; u_int fb_width = 768; u_int fb_height = 512; u_int fb_depth = 4; int separate_wall_picture = 1; static fb_reg_conf_t orig_reg; static int grf0_fd = -1; static size_t grf0_len; static fb_reg_t *grf0_reg; static u_short *tpal_orig; static u_short gpal_12_orig; static int use_tvram_cmap; static fb_cmap_t *tcmap; /* If NULL, T-VRAM palette is the same as G-VRAM. */ static fb_cmap_t *gcmap; /* --- static functions --- */ static void close_grf0(void) { if (grf0_fd != -1) { if (tcmap) { free(tcmap); tcmap = NULL; } grf0_reg->gpal[TP_COLOR] = gpal_12_orig; if (tpal_orig) { memcpy(grf0_reg->tpal, tpal_orig, sizeof(u_short) * 16); free(tpal_orig); } grf0_reg->videoc.r2 = 0x0010; munmap(grf0_reg, grf0_len); close(grf0_fd); grf0_fd = -1; } } static void setup_reg(fb_reg_t *reg, fb_reg_conf_t *conf) { if ((reg->crtc.r20 & 0x3) < (conf->crtc.r20 & 0x3) || ((reg->crtc.r20 & 0x3) == (conf->crtc.r20 & 0x3) && (reg->crtc.r20 & 0x10) < (conf->crtc.r20 & 0x10))) { /* to higher resolution */ reg->crtc.r00 = conf->crtc.r00; reg->crtc.r01 = conf->crtc.r01; reg->crtc.r02 = conf->crtc.r02; reg->crtc.r03 = conf->crtc.r03; reg->crtc.r04 = conf->crtc.r04; reg->crtc.r05 = conf->crtc.r05; reg->crtc.r06 = conf->crtc.r06; reg->crtc.r07 = conf->crtc.r07; reg->crtc.r20 = conf->crtc.r20; } else { /* to lower resolution */ reg->crtc.r20 = conf->crtc.r20; reg->crtc.r01 = conf->crtc.r01; reg->crtc.r02 = conf->crtc.r02; reg->crtc.r03 = conf->crtc.r03; reg->crtc.r04 = conf->crtc.r04; reg->crtc.r05 = conf->crtc.r05; reg->crtc.r06 = conf->crtc.r06; reg->crtc.r07 = conf->crtc.r07; reg->crtc.r00 = conf->crtc.r00; } reg->crtc.r08 = conf->crtc.r08; reg->videoc.r0 = conf->videoc.r0; reg->videoc.r1 = conf->videoc.r1; reg->videoc.r2 = conf->videoc.r2; } static int open_display(u_int depth) { char *dev; struct grfinfo vinfo; fb_reg_t *reg; fb_reg_conf_t *conf; fb_reg_conf_t conf_512_512_15 = {{91, 9, 17, 81, 567, 5, 40, 552, 27, 789}, {3, 0x21e4, 0x000f}}; fb_reg_conf_t conf_512_512_8 = {{91, 9, 17, 81, 567, 5, 40, 552, 27, 277}, {1, 0x21e4, 0x0003}}; fb_reg_conf_t conf_768_512_4 = {{137, 14, 28, 124, 567, 5, 40, 552, 27, 1046}, {4, 0x24e4 /* Graphic vram is prior to text one. */, 0x0010}}; fb_reg_conf_t conf_1024_768_4 = {{169, 14, 28, 156, 439, 5, 40, 424, 27, 1050}, {4, 0x21e4, 0x0010}}; struct rgb_info rgb_info_15bpp = {3, 3, 3, 6, 11, 1}; struct termios tm; bl_priv_restore_euid(); bl_priv_restore_egid(); _display.fb_fd = open((dev = getenv("FRAMEBUFFER")) ? dev : "/dev/grf1", O_RDWR); bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); if (_display.fb_fd < 0) { bl_error_printf("Couldn't open %s.\n", dev ? dev : "/dev/grf1"); return 0; } bl_file_set_cloexec(_display.fb_fd); if (ioctl(_display.fb_fd, GRFIOCGINFO, &vinfo) == -1) { goto error; } _display.smem_len = vinfo.gd_fbsize + vinfo.gd_regsize; if ((_display.fb = _display.fb_base = mmap(NULL, _display.smem_len, PROT_WRITE | PROT_READ, MAP_FILE | MAP_SHARED, _display.fb_fd, (off_t)0)) == MAP_FAILED) { bl_error_printf("Retry another mode of resolution and depth.\n"); goto error; } reg = _display.fb; /* XXX Here reg->crtc.rXX are 0 which will slide the screen unexpectedly on * exit. */ #if 0 orig_reg.crtc.r00 = reg->crtc.r00; orig_reg.crtc.r01 = reg->crtc.r01; orig_reg.crtc.r02 = reg->crtc.r02; orig_reg.crtc.r03 = reg->crtc.r03; orig_reg.crtc.r04 = reg->crtc.r04; orig_reg.crtc.r05 = reg->crtc.r05; orig_reg.crtc.r06 = reg->crtc.r06; orig_reg.crtc.r07 = reg->crtc.r07; orig_reg.crtc.r08 = reg->crtc.r08; orig_reg.crtc.r20 = reg->crtc.r20; orig_reg.videoc.r0 = reg->videoc.r0; orig_reg.videoc.r1 = reg->videoc.r1; orig_reg.videoc.r2 = reg->videoc.r2; bl_debug_printf(BL_DEBUG_TAG " crtc %d %d %d %d %d %d %d %d %d 0x%x videoc 0x%x 0x%x 0x%x\n", orig_reg.crtc.r00, orig_reg.crtc.r01, orig_reg.crtc.r02, orig_reg.crtc.r03, orig_reg.crtc.r04, orig_reg.crtc.r05, orig_reg.crtc.r06, orig_reg.crtc.r07, orig_reg.crtc.r08, orig_reg.crtc.r20, orig_reg.videoc.r0, orig_reg.videoc.r1, orig_reg.videoc.r2); #else orig_reg = conf_768_512_4; orig_reg.videoc.r2 = 0x20; #endif if (fb_depth == 15) { conf = &conf_512_512_15; _display.width = _disp.width = 512; _display.height = _disp.height = 512; _disp.depth = 15; _display.rgbinfo = rgb_info_15bpp; } else { if (fb_depth == 8) { conf = &conf_512_512_8; _display.width = _disp.width = 512; _display.height = _disp.height = 512; _disp.depth = 8; } else /* if( fb_depth == 4) */ { if (fb_width == 1024 && fb_height == 768) { conf = &conf_1024_768_4; _display.width = _disp.width = 1024; _display.height = _disp.height = 768; } else { conf = &conf_768_512_4; _display.width = _disp.width = 768; _display.height = _disp.height = 512; } if (fb_depth == 1) { _disp.depth = 1; } else { _disp.depth = 4; } } if (!cmap_init()) { goto error; } } _display.bytes_per_pixel = 2; _display.pixels_per_byte = 1; _display.line_length = (_disp.width * 2 + 1023) / 1024 * 1024; _display.xoffset = 0; /* XXX gd_regsize is regarded as multiple of line_length */ _display.yoffset = vinfo.gd_regsize / _display.line_length; setup_reg(reg, conf); #ifdef ENABLE_DOUBLE_BUFFER if (_display.pixels_per_byte > 1 && !(_display.back_fb = malloc(_display.smem_len))) { goto error; } #endif tcgetattr(STDIN_FILENO, &tm); orig_tm = tm; tm.c_iflag = tm.c_oflag = 0; tm.c_cflag &= ~CSIZE; tm.c_cflag |= CS8; tm.c_lflag &= ~(ECHO | ISIG | IEXTEN | ICANON); tm.c_cc[VMIN] = 1; tm.c_cc[VTIME] = 0; tcsetattr(STDIN_FILENO, TCSAFLUSH, &tm); bl_priv_restore_euid(); bl_priv_restore_egid(); if ((_display.fd = open("/dev/kbd", O_RDONLY)) >= 0) { int mode; fcntl(_display.fd, F_SETOWN, getpid()); fcntl(_display.fd, F_SETFL, O_NONBLOCK | O_ASYNC); mode = 1; ioctl(_display.fd, KIOCSDIRECT, &mode); } else { _display.fd = STDIN_FILENO; } if ((_mouse.fd = open("/dev/mouse", O_RDONLY)) >= 0) { int format; format = VUID_FIRM_EVENT; ioctl(_mouse.fd, VUIDSFORMAT, &format); fcntl(_mouse.fd, F_SETOWN, getpid()); fcntl(_mouse.fd, F_SETFL, O_NONBLOCK | O_ASYNC); } bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); if (_mouse.fd != -1) { bl_file_set_cloexec(_mouse.fd); _mouse.x = _display.width / 2; _mouse.y = _display.height / 2; _disp_mouse.display = (Display*)&_mouse; #if 0 tcgetattr(_mouse.fd, &tm); tm.c_iflag = IGNBRK | IGNPAR; tm.c_oflag = 0; tm.c_lflag = 0; tm.c_cc[VTIME] = 0; tm.c_cc[VMIN] = 1; tm.c_cflag = CS8 | CSTOPB | CREAD | CLOCAL | HUPCL; cfsetispeed(&tm, B1200); cfsetospeed(&tm, B1200); tcsetattr(_mouse.fd, TCSAFLUSH, &tm); #endif } #ifdef DEBUG else { bl_debug_printf(BL_DEBUG_TAG " Failed to open /dev/wsmouse.\n"); } #endif _disp.display = &_display; console_id = get_active_console(); return 1; error: cmap_final(); if (_display.fb) { setup_reg(reg, &orig_reg); munmap(_display.fb, _display.smem_len); _display.fb = _display.fb_base = NULL; } close(_display.fb_fd); ioctl(_display.fb_fd, GRFIOCOFF, 0); return 0; } static int receive_mouse_event(void) { #define MS_LEFT 0x7f20 /* left mouse button */ #define MS_MIDDLE 0x7f21 /* middle mouse button */ #define MS_RIGHT 0x7f22 /* right mouse button */ #define LOC_X_DELTA 0x7f80 /* mouse delta-X */ #define LOC_Y_DELTA 0x7f81 /* mouse delta-Y */ #define VKEY_UP 0 #define VKEY_DOWN 1 Firm_event ev; ssize_t len; if (console_id != get_active_console()) { return 0; } while ((len = read(_mouse.fd, memset(&ev, 0, sizeof(ev)), sizeof(ev))) > 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " MOUSE event (len)%d (id)%d (val)%d\n", len, ev.id, ev.value); #endif if (ev.value == VKEY_DOWN || ev.value == VKEY_UP) { XButtonEvent xev; ui_window_t *win; if (ev.id == MS_LEFT) { xev.button = Button1; _mouse.button_state = Button1Mask; } else if (ev.id == MS_MIDDLE) { xev.button = Button2; _mouse.button_state = Button2Mask; } else if (ev.id == MS_RIGHT) { xev.button = Button3; _mouse.button_state = Button3Mask; } else { continue; } if (ev.value == VKEY_DOWN) { xev.type = ButtonPress; } else /* if( ev.value == VKEY_UP) */ { xev.type = ButtonRelease; /* Reset button_state in releasing button. */ _mouse.button_state = 0; } xev.time = ev.time.tv_sec * 1000 + ev.time.tv_usec / 1000; xev.x = _mouse.x; xev.y = _mouse.y; xev.state = _display.key_state; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "Button is %s x %d y %d btn %d time %d\n", xev.type == ButtonPress ? "pressed" : "released", xev.x, xev.y, xev.button, xev.time); #endif if (!check_virtual_kbd(&xev)) { win = get_window(xev.x, xev.y); xev.x -= win->x; xev.y -= win->y; ui_window_receive_event(win, &xev); } } else if (ev.id == LOC_X_DELTA || ev.id == LOC_Y_DELTA) { XMotionEvent xev; ui_window_t *win; restore_hidden_region(); if (ev.id == LOC_X_DELTA) { _mouse.x += ((int)ev.value * 2); if (_mouse.x < 0) { _mouse.x = 0; } else if (_display.width <= _mouse.x) { _mouse.x = _display.width - 1; } } else /* if( ev.id == LOC_Y_DELTA) */ { _mouse.y -= ((int)ev.value * 2); if (_mouse.y < 0) { _mouse.y = 0; } else if (_display.height <= _mouse.y) { _mouse.y = _display.height - 1; } } update_mouse_cursor_state(); xev.type = MotionNotify; xev.x = _mouse.x; xev.y = _mouse.y; xev.time = ev.time.tv_sec * 1000 + ev.time.tv_usec / 1000; xev.state = _mouse.button_state | _display.key_state; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Button is moved %d x %d y %d btn %d time %d\n", xev.type, xev.x, xev.y, xev.state, xev.time); #endif win = get_window(xev.x, xev.y); xev.x -= win->x; xev.y -= win->y; ui_window_receive_event(win, &xev); save_hidden_region(); draw_mouse_cursor(); } } return 1; } static int receive_key_event(void) { static u_int16_t keymap[] = { XK_Escape, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '^', '\\', XK_BackSpace, XK_Tab, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '@', '[', XK_Return, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', ':', ']', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, ' ', XK_Home, XK_Delete, XK_Prior, XK_Next, 0 /* XK_Undo */, XK_Left, XK_Up, XK_Right, XK_Down, XK_Clear, XK_KP_Divide, XK_KP_Multiply, XK_KP_Subtract, XK_KP_7, XK_KP_8, XK_KP_9, XK_KP_Add, XK_KP_4, XK_KP_5, XK_KP_6, '=' /* XK_KP_Equal */, XK_KP_1, XK_KP_2, XK_KP_3, XK_Return /* XK_KP_Enter */, XK_KP_0, ',', '.', 0, 0 /* XK_Touroku */, XK_Help, XK_Alt_L, XK_Meta_L, XK_Meta_R, XK_Alt_R, XK_Control_R, 0 /* XK_Kana_Lock */, 0 /* XK_Romaji */, 0, XK_Caps_Lock, XK_Insert, XK_Hiragana_Katakana, XK_Zenkaku_Hankaku, 0 /* XK_Break */, XK_Print, XK_F1, XK_F2, XK_F3, XK_F4, XK_F5, XK_F6, XK_F7, XK_F8, XK_F9, XK_F10, 0, 0, 0, XK_Shift_L, XK_Control_L, XK_Super_L, XK_Super_R, }; static u_int8_t shift_keymap[] = { 0, '!', '\"', '#', '$', '%', '&', '\'', '(', ')', 0, '=', '~', '|', 0, 0, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '`', '{', 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '+', '*', '}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', '_', }; Firm_event ev; if (_display.fd == STDIN_FILENO) { return receive_stdin_key_event(); } if (console_id != get_active_console()) { return 0; } while (read(_display.fd, memset(&ev, 0, sizeof(ev)), sizeof(ev)) > 0) { XKeyEvent xev; int pressed; int shift; pressed = (ev.value == VKEY_DOWN); ev.id--; ev.id &= 0x7f; if (_display.lock_state & CLKED) { shift = !(_display.key_state & ShiftMask); } else { shift = _display.key_state & ShiftMask; } if (!shift || ev.id >= sizeof(shift_keymap) / sizeof(*shift_keymap) || !(xev.ksym = shift_keymap[ev.id])) { if (ev.id >= sizeof(keymap) / sizeof(*keymap) || !(xev.ksym = keymap[ev.id])) { continue; } } if (pressed) { if (xev.ksym == XK_Shift_R || xev.ksym == XK_Shift_L) { _display.key_state |= ShiftMask; } else if (xev.ksym == XK_Control_R || xev.ksym == XK_Control_L) { _display.key_state |= ControlMask; } else if (xev.ksym == XK_Alt_R || xev.ksym == XK_Alt_L || xev.ksym == XK_Meta_R || xev.ksym == XK_Meta_L) { _display.key_state |= Mod1Mask; } else if (xev.ksym == XK_Num_Lock) { _display.lock_state ^= NLKED; } else if (xev.ksym == XK_Caps_Lock) { _display.lock_state ^= CLKED; } else { xev.type = KeyPress; xev.state = _mouse.button_state | _display.key_state; xev.keycode = ev.id + 1; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "scancode %d -> ksym 0x%x state 0x%x\n", ev.id, xev.ksym, xev.state); #endif receive_event_for_multi_roots(&xev); } } else { if (xev.ksym == XK_Shift_R || xev.ksym == XK_Shift_L) { _display.key_state &= ~ShiftMask; } else if (xev.ksym == XK_Control_R || xev.ksym == XK_Control_L) { _display.key_state &= ~ControlMask; } else if (xev.ksym == XK_Alt_R || xev.ksym == XK_Alt_L || xev.ksym == XK_Meta_R || xev.ksym == XK_Meta_L) { _display.key_state &= ~Mod1Mask; } } } return 1; } static int gpal_init(u_short *gpal) { if (grf0_fd != -1) { u_long color; if (ui_cmap_get_closest_color(&color, 0, 0, 0)) { /* Opaque black */ gpal[color] |= 0x1; } /* Transparent (Wall paper is visible) */ gpal_12_orig = gpal[TP_COLOR]; gpal[TP_COLOR] = 0x0; } return 1; } static void x68k_set_use_tvram_colors(int use) { if (separate_wall_picture && _disp.depth == 4 && use) { if (tcmap) { free(tcmap); tcmap = NULL; } use_tvram_cmap = 1; } else { if (_display.cmap == tcmap) { _display.cmap = gcmap; if (_display.color_cache) { memset(_display.color_cache, 0, sizeof(*_display.color_cache)); } } use_tvram_cmap = 0; } } static fb_cmap_t *cmap_new(int num_colors); static int x68k_set_tvram_cmap(u_int32_t *pixels, u_int cmap_size) { if (use_tvram_cmap) { if (cmap_size > 16) { bl_warn_printf("Colormap size for text vram should be 16 or less.\n"); return 0; } if ((tcmap = cmap_new(cmap_size))) { u_int count; for (count = 0; count < cmap_size; count++) { tcmap->red[count] = (pixels[count] >> 16) & 0xff; tcmap->green[count] = (pixels[count] >> 8) & 0xff; tcmap->blue[count] = pixels[count] & 0xff; } gcmap = _display.cmap; _display.cmap = tcmap; if (_display.color_cache) { memset(_display.color_cache, 0, sizeof(*_display.color_cache)); } return 1; } } return 0; } /* --- global functions --- */ int x68k_tvram_is_enabled(void) { return (grf0_fd != -1) ? 1 : 0; } /* * On success, if /dev/grf0 is opened just now, 2 is returned, while if * /dev/grf0 has been already opened, 1 is returned. */ int x68k_tvram_set_wall_picture(u_short *image, u_int width, u_int height) { int ret; static u_char *vram; u_char *pl0; u_char *pl1; u_char *pl2; u_char *pl3; u_short *img; int y; int img_y; if (!separate_wall_picture || _disp.depth != 4 || width < 8 || !image) { close_grf0(); return 0; } ret = 1; while (grf0_fd == -1) { struct grfinfo vinfo; bl_priv_restore_euid(); bl_priv_restore_egid(); grf0_fd = open("/dev/grf0", O_RDWR); bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); if (grf0_fd >= 0) { bl_file_set_cloexec(grf0_fd); if (ioctl(grf0_fd, GRFIOCGINFO, &vinfo) >= 0) { grf0_len = vinfo.gd_fbsize + vinfo.gd_regsize; if ((grf0_reg = mmap(NULL, grf0_len, PROT_WRITE | PROT_READ, MAP_FILE | MAP_SHARED, grf0_fd, (off_t)0)) != MAP_FAILED) { /* Enale the text vram. */ grf0_reg->videoc.r2 = 0x0030; /* Initialize scroll registers. */ grf0_reg->crtc.r10 = grf0_reg->crtc.r11 = 0; grf0_reg->crtc.r21 = 0; if ((tpal_orig = malloc(sizeof(u_short) * 16))) { memcpy(tpal_orig, grf0_reg->tpal, sizeof(u_short) * 16); } vram = ((u_char*)grf0_reg) + vinfo.gd_regsize; gpal_init(grf0_reg->gpal); ret = 2; break; } } close(grf0_fd); grf0_fd = -1; } return 0; } bl_msg_printf("Wall picture on Text VRAM. %s\n", tcmap ? "" : "(ANSI 16 colors)"); if (tcmap) { u_int count; for (count = 0; count < CMAP_SIZE(tcmap); count++) { grf0_reg->tpal[count] = (tcmap->red[count] >> 3) << 6 | (tcmap->green[count] >> 3) << 11 | (tcmap->blue[count] >> 3) << 1; } free(tcmap); tcmap = NULL; } else { /* Reset text palette. */ memcpy(grf0_reg->tpal, grf0_reg->gpal, sizeof(u_short) * 16); grf0_reg->tpal[TP_COLOR] = gpal_12_orig; } pl0 = vram; pl1 = pl0 + 0x20000; pl2 = pl1 + 0x20000; pl3 = pl2 + 0x20000; img = image; /* Don't use _disp.height because this function doesn't concern display * rotation. */ for (y = 0, img_y = 0; y < _display.height; y++, img_y++) { int x; int img_x; if (img_y >= height) { img = image; img_y = 0; } img_x = 0; /* 128 bytes per line */ for (x = 0; x < 128; x++) { *(pl3++) = ((img[img_x] & 0x8) << 4) | ((img[img_x + 1] & 0x8) << 3) | ((img[img_x + 2] & 0x8) << 2) | ((img[img_x + 3] & 0x8) << 1) | (img[img_x + 4] & 0x8) | ((img[img_x + 5] & 0x8) >> 1) | ((img[img_x + 6] & 0x8) >> 2) | ((img[img_x + 7] & 0x8) >> 3); *(pl2++) = ((img[img_x] & 0x4) << 5) | ((img[img_x + 1] & 0x4) << 4) | ((img[img_x + 2] & 0x4) << 3) | ((img[img_x + 3] & 0x4) << 2) | ((img[img_x + 4] & 0x4) << 1) | (img[img_x + 5] & 0x4) | ((img[img_x + 6] & 0x4) >> 1) | ((img[img_x + 7] & 0x4) >> 2); *(pl1++) = ((img[img_x] & 0x2) << 6) | ((img[img_x + 1] & 0x2) << 5) | ((img[img_x + 2] & 0x2) << 4) | ((img[img_x + 3] & 0x2) << 3) | ((img[img_x + 4] & 0x2) << 2) | ((img[img_x + 5] & 0x2) << 1) | (img[img_x + 6] & 0x2) | ((img[img_x + 7] & 0x2) >> 1); *(pl0++) = ((img[img_x] & 0x1) << 7) | ((img[img_x + 1] & 0x1) << 6) | ((img[img_x + 2] & 0x1) << 5) | ((img[img_x + 3] & 0x1) << 4) | ((img[img_x + 4] & 0x1) << 3) | ((img[img_x + 5] & 0x1) << 2) | ((img[img_x + 6] & 0x1) << 1) | (img[img_x + 7] & 0x1); if ((img_x += 8) >= width) { /* XXX tiling with chopping the last 7 or less pixels. */ img_x = 0; } } img += width; } if (y < 1024) { u_long color; if (ui_cmap_get_closest_color(&color, 0, 0, 0)) { size_t len; len = (1024 - y) * 128; memset(pl3, (color & 0x8) ? 0xff : 0, len); memset(pl2, (color & 0x4) ? 0xff : 0, len); memset(pl1, (color & 0x2) ? 0xff : 0, len); memset(pl0, (color & 0x1) ? 0xff : 0, len); } } return ret; } mlterm-3.8.9/uitoolkit/fb/ui_dnd.c010064400017600000144000000006671356600660700155730ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef DISABLE_XDND #include "../ui_window.h" #include "../ui_dnd.h" /* --- global functions --- */ /* * XFilterEvent(event, w) analogue. * return 0 if the event should be processed in the mlterm mail loop. * return 1 if nothing to be done is left for the event. */ int ui_dnd_filter_event(XEvent *event, ui_window_t *win) { return 0; } #endif /* DISABLE_XDND */ mlterm-3.8.9/uitoolkit/fb/ui_font.c010064400017600000144000001744131356600660700157750ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #define _GNU_SOURCE /* strcasestr */ #include "ui_font.h" #include #include /* open */ #include /* close */ #include /* memcmp */ #include /* fstat */ #include /* utime */ #include /* WORDS_BIGENDIAN */ #include #include /* strdup */ #include #include /* bl_basename */ #include /* bl_get_user_rc_path */ #include /* TOINT32 */ #include #ifdef __ANDROID__ #include #endif #ifdef USE_WIN32API #define mmap(a, b, c, d, e, f) (NULL) #define munmap(a, b) (0) #define strcasestr(a, b) strstr(a, b) #else #include /* mmap */ #endif #ifdef USE_OT_LAYOUT #include #endif #include "ui_decsp_font.h" #define DIVIDE_ROUNDING(a, b) (((int)((a)*10 + (b)*5)) / ((int)((b)*10))) #define DIVIDE_ROUNDINGUP(a, b) (((int)((a)*10 + (b)*10 - 1)) / ((int)((b)*10))) #define DIVIDE_ROUNDINGDOWN(a, b) (((int)(a)*10) / ((int)((b)*10))) #ifdef WORDS_BIGENDIAN #define _TOINT32(p, is_be) ((is_be) ? TOINT32(p) : LE32DEC(p)) #define _TOINT16(p, is_be) ((is_be) ? TOINT16(p) : LE16DEC(p)) #else #define _TOINT32(p, is_be) ((is_be) ? BE32DEC(p) : TOINT32(p)) #define _TOINT16(p, is_be) ((is_be) ? BE16DEC(p) : TOINT16(p)) #endif #define PCF_PROPERTIES (1 << 0) #define PCF_ACCELERATORS (1 << 1) #define PCF_METRICS (1 << 2) #define PCF_BITMAPS (1 << 3) #define PCF_INK_METRICS (1 << 4) #define PCF_BDF_ENCODINGS (1 << 5) #define PCF_SWIDTHS (1 << 6) #define PCF_GLYPH_NAMES (1 << 7) #define PCF_BDF_ACCELERATORS (1 << 8) #define MAX_GLYPH_TABLES 512 #define GLYPH_TABLE_SIZE 128 #define INITIAL_GLYPH_INDEX_TABLE_SIZE 0x1000 #if 0 #define __DEBUG #endif /* --- static variables --- */ static XFontStruct **xfonts; static u_int num_xfonts; static XFontStruct *get_cached_xfont(const char *file, int32_t format, int is_aa); static int add_xfont_to_cache(XFontStruct *xfont); static void xfont_unref(XFontStruct *xfont); /* ===== PCF ===== */ /* --- static functions --- */ static int load_bitmaps(XFontStruct *xfont, u_char *p, size_t size, int is_be, int glyph_pad_type) { int32_t *offsets; int32_t bitmap_sizes[4]; int32_t count; /* 0 -> byte , 1 -> short , 2 -> int */ xfont->glyph_width_bytes = (glyph_pad_type == 2 ? 4 : (glyph_pad_type == 1 ? 2 : 1)); xfont->num_glyphs = _TOINT32(p, is_be); p += 4; if (size < 8 + sizeof(*offsets) * xfont->num_glyphs) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " size %d is too small.\n", size); #endif return 0; } if (!(xfont->glyph_offsets = malloc(sizeof(*offsets) * xfont->num_glyphs))) { return 0; } #ifdef WORDS_BIGENDIAN if (is_be) #else if (!is_be) #endif { memcpy(xfont->glyph_offsets, p, sizeof(*offsets) * xfont->num_glyphs); p += (sizeof(*offsets) * xfont->num_glyphs); } else { for (count = 0; count < xfont->num_glyphs; count++) { xfont->glyph_offsets[count] = _TOINT32(p, is_be); p += 4; } } for (count = 0; count < 4; count++) { bitmap_sizes[count] = _TOINT32(p, is_be); p += 4; } if (size < 8 + sizeof(*offsets) * xfont->num_glyphs + 16 + bitmap_sizes[glyph_pad_type]) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " size %d is too small.\n", size); #endif return 0; } if (!(xfont->glyphs = malloc(bitmap_sizes[glyph_pad_type]))) { return 0; } if (is_be) { /* Regard the bit order of p as msb first */ memcpy(xfont->glyphs, p, bitmap_sizes[glyph_pad_type]); } else { /* Regard the bit order of p as lsb first. Reorder it to msb first. */ for (count = 0; count < bitmap_sizes[glyph_pad_type]; count++) { xfont->glyphs[count] = ((p[count] << 7) & 0x80) | ((p[count] << 5) & 0x40) | ((p[count] << 3) & 0x20) | ((p[count] << 1) & 0x10) | ((p[count] >> 1) & 0x08) | ((p[count] >> 3) & 0x04) | ((p[count] >> 5) & 0x02) | ((p[count] >> 7) & 0x01); } } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "GLYPH COUNT %d x WIDTH BYTE %d = SIZE %d\n", xfont->num_glyphs, xfont->glyph_width_bytes, bitmap_sizes[glyph_pad_type]); { FILE* fp; p = xfont->glyphs; fp = fopen("log.txt", "w"); for (count = 0; count < xfont->num_glyphs; count++) { fprintf(fp, "NUM %x\n", count); fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n", _TOINT32(p, is_be)); p += 4; fprintf(fp, "%x\n\n", _TOINT32(p, is_be)); p += 4; } fclose(fp); } #endif return 1; } static int load_encodings(XFontStruct *xfont, u_char *p, size_t size, int is_be) { size_t idx_size; xfont->min_char_or_byte2 = _TOINT16(p, is_be); p += 2; xfont->max_char_or_byte2 = _TOINT16(p, is_be); p += 2; xfont->min_byte1 = _TOINT16(p, is_be); p += 2; xfont->max_byte1 = _TOINT16(p, is_be); p += 2; /* skip default_char */ p += 2; idx_size = (xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1) * (xfont->max_byte1 - xfont->min_byte1 + 1) * sizeof(int16_t); if (size < 14 + idx_size) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " size %d is too small.\n", size); #endif return 0; } if (!(xfont->glyph_indeces = malloc(idx_size))) { return 0; } #ifdef WORDS_BIGENDIAN if (is_be) #else if (!is_be) #endif { memcpy(xfont->glyph_indeces, p, idx_size); } else { size_t count; for (count = 0; count < (idx_size / sizeof(int16_t)); count++) { xfont->glyph_indeces[count] = _TOINT16(p, is_be); p += 2; } } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "GLYPH INDEX %d %d %d %d\n", xfont->min_char_or_byte2, xfont->max_char_or_byte2, xfont->min_byte1, xfont->max_byte1); { int count; int16_t *p; p = xfont->glyph_indeces; for (count = xfont->min_char_or_byte2; count <= xfont->max_char_or_byte2; count++) { bl_msg_printf("%d %x\n", count, (int)*p); p++; } } #endif return 1; } static int get_metrics(u_int8_t *width, u_int8_t *width_full, u_int8_t *height, u_int8_t *ascent, u_char *p, size_t size, int is_be, int is_compressed) { int16_t num_metrics; /* XXX Proportional font is not considered. */ if (is_compressed) { num_metrics = _TOINT16(p, is_be); p += 2; *width = p[2] - 0x80; *ascent = p[3] - 0x80; *height = *ascent + (p[4] - 0x80); if (num_metrics > 0x3000) { /* U+3000: Unicode ideographic space (Full width) */ p += (5 * 0x3000); *width_full = p[2] - 0x80; } else { *width_full = *width; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " COMPRESSED METRICS %d %d %d %d %d\n", num_metrics, *width, *width_full, *height, *ascent); #endif } else { num_metrics = _TOINT32(p, is_be); p += 4; /* skip {left|right}_sided_bearing */ p += 4; *width = _TOINT16(p, is_be); p += 2; *ascent = _TOINT16(p, is_be); p += 2; *height = *ascent + _TOINT16(p, is_be); if (num_metrics > 0x3000) { /* skip character_descent and character attributes */ p += 4; /* U+3000: Unicode ideographic space (Full width) */ p += (12 * 0x2999); /* skip {left|right}_sided_bearing */ p += 4; *width_full = _TOINT16(p, is_be); } else { *width_full = *width; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " NOT COMPRESSED METRICS %d %d %d %d %d\n", num_metrics, *width, *width_full, *height, *ascent); #endif } return 1; } static char *gunzip(const char *file_path, struct stat *st) { size_t len; char *new_file_path; struct stat new_st; char *cmd; struct utimbuf ut; if (stat(file_path, st) == -1) { return NULL; } if ((len = strlen(file_path)) <= 3 || strcmp(file_path + len - 3, ".gz") != 0) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " USE UNCOMPRESSED FONT\n"); #endif return strdup(file_path); } if (!(new_file_path = alloca(7 + len + 1))) { goto error; } sprintf(new_file_path, "mlterm/%s", bl_basename(file_path)); new_file_path[strlen(new_file_path) - 3] = '\0'; /* remove ".gz" */ if (!(new_file_path = bl_get_user_rc_path(new_file_path))) { goto error; } if (stat(new_file_path, &new_st) == 0) { if (st->st_mtime <= new_st.st_mtime) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " USE CACHED UNCOMPRESSED FONT.\n"); #endif *st = new_st; return new_file_path; } } if (!(cmd = alloca(10 + len + 3 + strlen(new_file_path) + 1))) { goto error; } sprintf(cmd, "gunzip -c %s > %s", file_path, new_file_path); /* * The returned value is not checked because -1 with errno=ECHILD may be * returned even if cmd is executed successfully. */ system(cmd); /* st->st_size can be 0 if file_path points an illegally gzipped file. */ if (stat(new_file_path, st) == -1 || st->st_size <= 8) { unlink(new_file_path); goto error; } /* * The atime and mtime of the uncompressed pcf font is the same * as those of the original gzipped font. */ ut.actime = st->st_atime; ut.modtime = st->st_mtime; utime(new_file_path, &ut); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " USE NEWLY UNCOMPRESSED FONT\n"); #endif return new_file_path; error: #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to gunzip %s.\n", file_path); #endif free(new_file_path); return NULL; } static int load_pcf(XFontStruct *xfont, const char *file_path) { char *uzfile_path; int fd; struct stat st; u_char *pcf = NULL; u_char *p; int32_t num_tables; int table_load_count; int32_t count; if (!(uzfile_path = gunzip(file_path, &st))) { return 0; } fd = open(uzfile_path, O_RDONLY); free(uzfile_path); if (fd == -1) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to open %s.", xfont->file); #endif return 0; } if (!(xfont->file = strdup(file_path))) { close(fd); return 0; } table_load_count = 0; /* "st.st_size > 8" is ensured. (see gunzip()) */ if (!(p = pcf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) || memcmp(p, "\1fcp", 4) != 0) { goto end; } p += 4; num_tables = _TOINT32(p, 0); p += 4; if (st.st_size <= 8 + 16 * num_tables) { goto end; } for (count = 0; count < num_tables; count++) { int32_t type; int32_t format; int32_t size; int32_t offset; type = _TOINT32(p, 0); p += 4; format = _TOINT32(p, 0); p += 4; size = _TOINT32(p, 0); p += 4; offset = _TOINT32(p, 0); p += 4; if (/* (format & 8) != 0 || */ /* MSBit first */ ((format >> 4) & 3) != 0 || /* the bits aren't stored in bytes(0) but in short(1) or int(2). */ offset + size > st.st_size || format != _TOINT32(pcf + offset, 0)) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " %s is unsupported pcf format.\n", xfont->file); #endif } else if (type == PCF_BITMAPS) { if (!load_bitmaps(xfont, pcf + offset + 4, size, format & 4, format & 3)) { goto end; } table_load_count++; } else if (type == PCF_BDF_ENCODINGS) { if (!load_encodings(xfont, pcf + offset + 4, size, format & 4)) { goto end; } table_load_count++; } else if (type == PCF_METRICS) { if (!get_metrics(&xfont->width, &xfont->width_full, &xfont->height, &xfont->ascent, pcf + offset + 4, size, format & 4, format & 0x100)) { goto end; } table_load_count++; } } #ifdef __DEBUG { #if 1 u_char ch[] = "\x97\xf3"; #elif 0 u_char ch[] = "a"; #else u_char ch[] = "\x06\x22"; /* UCS2 */ #endif u_char *bitmap; int i; int j; if ((bitmap = ui_get_bitmap(xfont, ch, sizeof(ch) - 1, 0, NULL))) { for (j = 0; j < xfont->height; j++) { u_char *line; ui_get_bitmap_line(xfont, bitmap, j * xfont->glyph_width_bytes, line); for (i = 0; i < xfont->width; i++) { bl_msg_printf("%d", (line && ui_get_bitmap_cell(line, i)) ? 1 : 0); } bl_msg_printf("\n"); } } } #endif end: close(fd); if (pcf) { munmap(pcf, st.st_size); } if (table_load_count == 3) { return 1; } return 0; } static void unload_pcf(XFontStruct *xfont) { free(xfont->file); free(xfont->glyphs); free(xfont->glyph_offsets); free(xfont->glyph_indeces); } #ifdef USE_FREETYPE static int is_pcf(const char *file_path) { return (strcasecmp(file_path + strlen(file_path) - 6, "pcf.gz") == 0 || strcasecmp(file_path + strlen(file_path) - 3, "pcf") == 0); } #else #define is_pcf(path) (1) #endif /* ===== FREETYPE ===== */ #ifdef USE_FREETYPE #include #include FT_FREETYPE_H #ifdef FT_LCD_FILTER_H #include FT_LCD_FILTER_H #endif #include FT_OUTLINE_H /* 0 - 511 */ #define SEG(idx) (((idx) >> 7) & 0x1ff) /* 0 - 127 */ #define OFF(idx) ((idx) & 0x7f) /* +3 is for storing glyph position info. */ #define HAS_POSITION_INFO_BY_GLYPH(xfont) \ ((xfont)->glyph_size == (xfont)->glyph_width_bytes * (xfont)->height + 3) #define FONT_ROTATED (FONT_ITALIC << 1) /* --- static variables --- */ static FT_Library library; /* --- static functions --- */ static int get_glyph_index(FT_Face face, u_int32_t code) { int idx; if ((idx = FT_Get_Char_Index(face, code)) == 0) { /* XXX Some glyph indeces of ISCII fonts becomes 0 wrongly. */ if (0x80 <= code && code <= 0xff) { u_int32_t prev_idx; u_int32_t next_idx; u_int32_t c; for (c = code + 1; c <= 0xff; c++) { if ((next_idx = FT_Get_Char_Index(face, c)) > 0) { for (c = code - 1; c >= 80; c--) { if ((prev_idx = FT_Get_Char_Index(face, c)) > 0) { if (prev_idx + 1 < next_idx) { idx = prev_idx + 1; break; } } } break; } } } } return idx; } static int load_glyph(FT_Face face, int32_t format, u_int32_t code, int is_aa) { FT_Glyph_Format orig_glyph_format; if (is_aa) { FT_Load_Glyph(face, code, FT_LOAD_NO_BITMAP); if (face->glyph->format == FT_GLYPH_FORMAT_BITMAP) { return 0; } } else { FT_Load_Glyph(face, code, 0); } orig_glyph_format = face->glyph->format; if (format & FONT_ROTATED) { FT_Matrix matrix; matrix.xx = 0; matrix.xy = 0x10000L; /* (FT_Fixed)(-sin((-90.0 / 360.0) * 3.141592 * 2) * 0x10000L */ matrix.yx = -0x10000L; /* (FT_Fixed)(sin((-90.0 / 360.0) * 3.141592 * 2) * 0x10000L */ matrix.yy = 0; FT_Outline_Transform(&face->glyph->outline, &matrix); } else if (format & FONT_ITALIC) { FT_Matrix matrix; matrix.xx = 1 << 16; matrix.xy = 0x3000; matrix.yx = 0; matrix.yy = 1 << 16; FT_Outline_Transform(&face->glyph->outline, &matrix); } if (format & FONT_BOLD) { FT_Outline_Embolden(&face->glyph->outline, 1 << 5); } if (is_aa) { FT_Render_Glyph(face->glyph, FT_RENDER_MODE_LCD); } else { FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO); } /* * get_ft_bitmap_intern() uses face->glyph->format to check if glyph is actually rotated. * (face->glyph->format == FT_GLYPH_FORMAT_BITMAP just after FT_Load_Glyph() means that * glyphs is not rotated.) * * Note that FT_Render_Glyph() turns face->glyph->format from FT_GLYPH_FORMAT_OUTLINE * to FT_GLYPH_FORMAT_BITMAP. */ face->glyph->format = orig_glyph_format; return 1; } static int load_ft(XFontStruct *xfont, const char *file_path, int32_t format, int is_aa, u_int force_height) { u_int count; FT_Face face; u_int fontsize; if (!library) { if (FT_Init_FreeType(&library)) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "FT_Init_FreeType() failed.\n"); #endif return 0; } #ifdef FT_LCD_FILTER_H FT_Library_SetLcdFilter(library, FT_LCD_FILTER_DEFAULT); #endif } fontsize = (format & ~(FONT_BOLD | FONT_ITALIC | FONT_ROTATED)); for (count = 0; count < num_xfonts; count++) { if (strcmp(xfonts[count]->file, file_path) == 0 && /* The same face is used for normal, italic and bold. */ (xfonts[count]->format & ~(FONT_BOLD | FONT_ITALIC | FONT_ROTATED)) == fontsize) { face = xfonts[count]->face; goto face_found; } } if (FT_New_Face(library, file_path, 0, &face)) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG "FT_New_Face() failed.\n"); #endif return 0; } face_found: if (face->units_per_EM == 0 /* units_per_EM can be 0 ("Noto Color Emoji") */) { goto error; } FT_Set_Pixel_Sizes(face, fontsize, fontsize); if (!load_glyph(face, format, get_glyph_index(face, 'M'), is_aa)) { bl_msg_printf("%s doesn't have outline glyphs.\n", file_path); goto error; } xfont->format = format; xfont->face = face; xfont->is_aa = is_aa; xfont->num_indeces = INITIAL_GLYPH_INDEX_TABLE_SIZE; if (!(xfont->file = strdup(file_path)) || !(xfont->glyph_indeces = calloc(xfont->num_indeces, sizeof(u_int16_t))) || !(xfont->glyphs = calloc(MAX_GLYPH_TABLES, sizeof(u_char*)))) { goto error; } face->generic.data = ((int)face->generic.data) + 1; /* ref_count */ if (force_height) { xfont->height = force_height; } else { /* XXX face->max_advance_height might be unexpectedly big. (e.g. NotoSansCJKjp-Reguar.otf) */ xfont->height = (face->height * face->size->metrics.y_ppem + face->units_per_EM - 1) / face->units_per_EM; #ifdef __DEBUG bl_debug_printf("height %d (max height %d) ppem %d units %d => h %d\n", face->height, face->max_advance_height, face->size->metrics.y_ppem, face->units_per_EM, xfont->height); #endif } if (format & FONT_ROTATED) { xfont->width = xfont->width_full = xfont->height; xfont->ascent = 0; } else { xfont->width_full = (face->max_advance_width * face->size->metrics.x_ppem + face->units_per_EM - 1) / face->units_per_EM; #ifdef __DEBUG bl_debug_printf("maxw %d ppem %d units %d => xfont->width_full %d\n", face->max_advance_width, face->size->metrics.x_ppem, face->units_per_EM, xfont->width_full); #endif if (is_aa) { xfont->width = face->glyph->bitmap.width / 3; } else { xfont->width = face->glyph->bitmap.width; } xfont->ascent = (face->ascender * face->size->metrics.y_ppem + face->units_per_EM - 1) / face->units_per_EM; if (load_glyph(face, format, get_glyph_index(face, 'j'), is_aa)) { int descent = face->glyph->bitmap.rows - face->glyph->bitmap_top; if (descent > xfont->height - xfont->ascent) { #ifdef __DEBUG bl_debug_printf("Modify xfont->height to %d\n", xfont->ascent + descent); #endif xfont->height = xfont->ascent + descent; } } if (load_glyph(face, format, get_glyph_index(face, 'W'), is_aa)) { u_int w; if (is_aa) { w = face->glyph->bitmap.width / 3; } else { w = face->glyph->bitmap.width; } if (xfont->width_full < w) { #ifdef __DEBUG bl_debug_printf("Modify xfont->width_full to %d\n", w); #endif xfont->width_full = w; } } } if (is_aa) { xfont->glyph_width_bytes = xfont->width_full * 3; } else { xfont->glyph_width_bytes = (xfont->width_full + 7) / 8; } xfont->glyph_size = xfont->glyph_width_bytes * xfont->height; #if 0 bl_debug_printf("w %d %d h %d a %d\n", xfont->width, xfont->width_full, xfont->height, xfont->ascent); #endif return 1; error: FT_Done_Face(face); free(xfont->file); free(xfont->glyph_indeces); return 0; } static void init_iscii_ft(FT_Face face) { int count; for (count = 0; count < face->num_charmaps; count++) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " ISCII font encoding %c%c%c%c\n", ((face->charmaps[count]->encoding) >> 24) & 0xff, ((face->charmaps[count]->encoding) >> 16) & 0xff, ((face->charmaps[count]->encoding) >> 8) & 0xff, (face->charmaps[count]->encoding & 0xff)); #endif if (face->charmaps[count]->encoding == FT_ENCODING_APPLE_ROMAN) { FT_Set_Charmap(face, face->charmaps[count]); return; } } } static void clear_glyph_cache_ft(XFontStruct *xfont) { int count; for (count = 0; ((u_char**)xfont->glyphs)[count]; count++) { free(((u_char**)xfont->glyphs)[count]); } memset(xfont->glyphs, 0, MAX_GLYPH_TABLES * sizeof(u_char*)); xfont->num_glyphs = 0; memset(xfont->glyph_indeces, 0, xfont->num_indeces * sizeof(u_int16_t)); } static void enable_position_info_by_glyph(XFontStruct *xfont) { /* Shrink glyph size (+1 is margin) */ xfont->glyph_width_bytes = (xfont->width_full / 2 + 1) * 3; /* +3 is for storing glyph position info. */ xfont->glyph_size = xfont->glyph_width_bytes * xfont->height + 3; } static void unload_ft(XFontStruct *xfont) { FT_Face face; int count; free(xfont->file); face = xfont->face; face->generic.data = ((int)face->generic.data) - 1; if (!face->generic.data) { FT_Done_Face(xfont->face); } for (count = 0; ((u_char**)xfont->glyphs)[count]; count++) { free(((u_char**)xfont->glyphs)[count]); } free(xfont->glyphs); free(xfont->glyph_indeces); if (num_xfonts == 0 && library) { FT_Done_FreeType(library); library = NULL; } } static int is_rotated_char(u_int32_t ch) { if (ch < 0x80) { return 1; } else if ((ch & 0xffffff00) == 0x3000) { if ((0x3008 <= ch && ch <= 0x3011) || (0x3013 <= ch && ch <= 0x301c) || ch == 0x30fc) { return 1; } } else if ((ch & 0xffffff00) == 0xff00) { if ((0xff08 <= ch && ch <= 0xff09) || ch == 0xff0d || (0xff1a <= ch && ch <= 0xff1e) || ch == 0xff3b || ch == 0xff3d || (0xff5b <= ch && ch <= 0xff5e) || (0xff62 <= ch && ch <= 0xff63)) { return 1; } } return 0; } static int is_right_aligned_char(u_int32_t ch) { if ((ch & 0xffffff00) == 0x3000) { if ((0x3001 <= ch && ch <= 0x3002) || ch == 0x3063 || ch == 0x30c3 || (((0x3041 <= ch && ch <= 0x3049) || (0x3083 <= ch && ch <= 0x3087) || (0x30a1 <= ch && ch <= 0x30a9) || (0x30e3 <= ch && ch <= 0x30e7)) && ch % 2 == 1)) { return 1; } } else if ((ch & 0xffffff00) == 0xff00) { if (ch == 0xff0c || ch == 0xff61 || ch == 0xff64) { return 1; } } return 0; } static u_char *get_ft_bitmap_intern(XFontStruct *xfont, u_int32_t code /* glyph index */, u_int32_t ch) { u_int16_t *indeces; int idx; u_char **glyphs; u_char *glyph; if (code >= xfont->num_indeces) { if (!(indeces = realloc(xfont->glyph_indeces, sizeof(u_int16_t) * (code + 1)))) { return NULL; } memset(indeces + xfont->num_indeces, 0, sizeof(u_int16_t) * (code + 1 - xfont->num_indeces)); xfont->num_indeces = code + 1; xfont->glyph_indeces = indeces; } else { indeces = xfont->glyph_indeces; } glyphs = xfont->glyphs; /* Cast to u_char* to u_char** */ if (!(idx = indeces[code])) { FT_Face face; int y; u_char *src; u_char *dst; int left_pitch; int pitch; int rows; int32_t format; if (xfont->num_glyphs >= GLYPH_TABLE_SIZE * MAX_GLYPH_TABLES - 1) { bl_msg_printf("Unable to show U+%x because glyph cache is full.\n", code); return NULL; } face = xfont->face; format = xfont->format; left_pitch = 0; /* CJK characters etc aren't rotated. */ if (format & FONT_ROTATED) { if (is_rotated_char(ch)) { if (!load_glyph(face, xfont->format & ~FONT_ROTATED, code, xfont->is_aa)) { return NULL; } left_pitch = (face->max_advance_height - face->ascender) * face->size->metrics.y_ppem / face->units_per_EM; if (face->glyph->bitmap.rows > face->glyph->bitmap_top) { if ((left_pitch -= (face->glyph->bitmap.rows - face->glyph->bitmap_top)) < 0) { left_pitch = 0; } } /* XXX 'if (xfont->is_aa) { left_pitch *= 3 }' is in the following block. */ } else { format &= ~FONT_ROTATED; } } if (!load_glyph(face, format, code, xfont->is_aa)) { return NULL; } if (OFF(xfont->num_glyphs) == 0) { if (!(glyphs[SEG(xfont->num_glyphs)] = calloc(GLYPH_TABLE_SIZE, xfont->glyph_size))) { return NULL; } } /* idx can be changed if (pitch + left_pitch - 1) / xfont->glyph_width_bytes > 0. */ idx = ++xfont->num_glyphs; #if 0 bl_debug_printf("%x %c w %d %d(%d) h %d(%d) at %d %d\n", code, code, face->glyph->bitmap.width, face->glyph->bitmap.pitch, xfont->glyph_width_bytes, face->glyph->bitmap.rows, xfont->height, face->glyph->bitmap_left, face->glyph->bitmap_top); #endif indeces[code] = idx; if (xfont->format & FONT_ROTATED) { if (!(format & FONT_ROTATED) || face->glyph->format == FT_GLYPH_FORMAT_BITMAP) { /* Glyph isn't rotated. */ if (is_right_aligned_char(ch)) { /* XXX Hack for vertical kutouten and sokuon */ left_pitch += (xfont->width / 2); } else if (face->glyph->bitmap_left + face->glyph->bitmap.width <= xfont->width / 2) { left_pitch += (xfont->width / 4); } } if (face->glyph->bitmap.rows < xfont->height) { rows = face->glyph->bitmap.rows; y = (xfont->height - face->glyph->bitmap.rows) / 2; } else { rows = xfont->height; y = 0; } } else { if (xfont->ascent > face->glyph->bitmap_top) { y = xfont->ascent - face->glyph->bitmap_top; } else { y = 0; } if (face->glyph->bitmap.rows < xfont->height) { rows = face->glyph->bitmap.rows; if (rows + y > xfont->height) { y = xfont->height - rows; } } else { rows = xfont->height; y = 0; } } if (face->glyph->bitmap_left > 0) { left_pitch += face->glyph->bitmap_left; } if (xfont->is_aa) { left_pitch *= 3; if (HAS_POSITION_INFO_BY_GLYPH(xfont)) { int additional_glyphs; int count; pitch = face->glyph->bitmap.pitch; additional_glyphs = (pitch + left_pitch - 1) / xfont->glyph_width_bytes; #if 0 bl_debug_printf("Use %d(=(%d+%d-1)/%d) glyph slots for one glyph.\n", 1 + additional_glyphs, pitch, left_pitch, xfont->glyph_width_bytes); #endif for (count = 0; count < additional_glyphs; count++) { if (OFF(xfont->num_glyphs + count) == 0) { if (1 + additional_glyphs > GLYPH_TABLE_SIZE || !(glyphs[SEG(xfont->num_glyphs + count)] = calloc(GLYPH_TABLE_SIZE, xfont->glyph_size))) { xfont->num_glyphs--; indeces[code] = 0; return NULL; } xfont->num_glyphs += (1 + count); indeces[code] = idx = xfont->num_glyphs; } } xfont->num_glyphs += additional_glyphs; } else if (face->glyph->bitmap.pitch < xfont->glyph_width_bytes) { pitch = face->glyph->bitmap.pitch; if (pitch + left_pitch > xfont->glyph_width_bytes) { left_pitch = xfont->glyph_width_bytes - pitch; } } else { pitch = xfont->glyph_width_bytes; left_pitch = 0; } } else { if (face->glyph->bitmap.pitch <= xfont->glyph_width_bytes) { pitch = face->glyph->bitmap.pitch; if (left_pitch >= (xfont->glyph_width_bytes - pitch + 1) * 8) { left_pitch = 7; } } else { pitch = xfont->glyph_width_bytes; left_pitch = 0; } } glyph = glyphs[SEG(idx - 1)] + xfont->glyph_size * OFF(idx - 1); src = face->glyph->bitmap.buffer; dst = glyph + (xfont->glyph_width_bytes * y); if (xfont->is_aa) { if (HAS_POSITION_INFO_BY_GLYPH(xfont)) { /* Storing glyph position info. (ISCII or ISO10646_UCS4_1_V) */ glyph[0] = (face->glyph->advance.x >> 6); /* advance */ glyph[2] = (face->glyph->bitmap.width + left_pitch) / 3; /* width */ if (face->glyph->bitmap_left < 0) { glyph[1] = -face->glyph->bitmap_left; /* retreat */ } else { glyph[1] = 0; } if (glyph[0] == 0 && glyph[2] > glyph[0] + glyph[1]) { glyph[1] = glyph[2] - glyph[0]; /* retreat */ } dst = glyph + glyph[2] * 3 * y + 3; #if 0 bl_debug_printf("%x %c A %d R %d W %d-> A %d R %d W %d\n", code, code, face->glyph->advance.x >> 6, face->glyph->bitmap_left, face->glyph->bitmap.width, glyph[0], glyph[1], glyph[2]); #endif for (y = 0; y < rows; y++) { memcpy(dst + left_pitch, src, pitch); src += face->glyph->bitmap.pitch; dst += (glyph[2] * 3); } } else { if (face->glyph->bitmap_left < 0 && left_pitch == 0 && xfont->width * 3 < face->glyph->bitmap.width /* pitch? */) { /* For 'A' and 'W' (bitmap_left can be -1) of Incosnolata font */ int left_pitch_minus = face->glyph->bitmap_left * 3; if (pitch + left_pitch_minus < 0) { left_pitch_minus = -pitch; } src -= left_pitch_minus; for (y = 0; y < rows - 1; y++) { memcpy(dst, src, pitch); src += face->glyph->bitmap.pitch; dst += xfont->glyph_width_bytes; } memcpy(dst, src, pitch + left_pitch_minus); } else { for (y = 0; y < rows; y++) { memcpy(dst + left_pitch, src, pitch); src += face->glyph->bitmap.pitch; dst += xfont->glyph_width_bytes; } } } } else { int shift; if ((shift = left_pitch / 8) > 0) { left_pitch -= (shift * 8); dst += shift; } if (left_pitch == 0) { for (y = 0; y < rows; y++) { memcpy(dst, src, pitch); src += face->glyph->bitmap.pitch; dst += xfont->glyph_width_bytes; } } else { /* XXX TODO: Support face->glyph->bitmap_left < 0 */ int count; for (y = 0; y < rows; y++) { dst[0] = (src[0] >> left_pitch); for (count = 1; count < pitch; count++) { dst[count] = (src[count - 1] << (8 - left_pitch)) | (src[count] >> left_pitch); } if (shift + pitch < xfont->glyph_width_bytes) { dst[count] = (src[count - 1] << (8 - left_pitch)); } src += face->glyph->bitmap.pitch; dst += xfont->glyph_width_bytes; } } } } else { glyph = glyphs[SEG(idx - 1)] + xfont->glyph_size * OFF(idx - 1); } return glyph; } static int load_xfont(XFontStruct *xfont, const char *file_path, int32_t format, ef_charset_t cs, int is_aa) { if (!is_pcf(file_path)) { return load_ft(xfont, file_path, format, is_aa, 0); } else { return load_pcf(xfont, file_path); } } static void unload_xfont(XFontStruct *xfont) { if (xfont->face) { unload_ft(xfont); } else { unload_pcf(xfont); } } #ifdef USE_FONTCONFIG #include static int use_fontconfig; static double dpi_for_fc; static FcPattern *compl_pattern; static char **fc_files; static u_int num_fc_files; static FcCharSet **fc_charsets; static void compl_final(void) { if (compl_pattern) { u_int count; FcPatternDestroy(compl_pattern); compl_pattern = NULL; if (fc_files) { for (count = 0; count < num_fc_files; count++) { free(fc_files[count]); FcCharSetDestroy(fc_charsets[count]); } free(fc_files); /* fc_charsets is also free'ed */ fc_files = NULL; fc_charsets = NULL; } } } static void compl_xfonts_destroy(XFontStruct **xfonts) { if (xfonts) { u_int count; for (count = 0; count < num_fc_files; count++) { if (xfonts[count]) { xfont_unref(xfonts[count]); } } free(xfonts); } } /* Same processing as win32/ui_font.c (partially) and libtype/ui_font_ft.c */ static int parse_fc_font_name(char **font_family, int *is_bold, /* if bold is not specified in font_name, not changed. */ int *is_italic, /* if italic is not specified in font_name, not changed. */ u_int *percent, /* if percent is not specified in font_name, not changed. */ char *font_name /* modified by this function. */ ) { char *p; size_t len; /* * [Family]( [WEIGHT] [SLANT] [SIZE]:[Percentage]) */ *font_family = font_name; p = font_name + strlen(font_name) - 1; if ('0' <= *p && *p <= '9') { do { p--; } while ('0' <= *p && *p <= '9'); if (*p == ':' && bl_str_to_uint(percent, p + 1)) { /* Parsing ":[Percentage]" */ *p = '\0'; } } p = font_name; while (1) { if (*p == '\\' && *(p + 1)) { /* Compat with 3.6.3 or before. (e.g. Foo\-Bold-iso10646-1) */ /* skip backslash */ p++; } else if (*p == '\0') { /* encoding and percentage is not specified. */ *font_name = '\0'; break; } *(font_name++) = *(p++); } /* * Parsing "[Family] [WEIGHT] [SLANT] [SIZE]". * Following is the same as ui_font_win32.c:parse_font_name() * except FC_*. */ #if 0 bl_debug_printf("Parsing %s for [Family] [Weight] [Slant]\n", *font_family); #endif p = bl_str_chop_spaces(*font_family); len = strlen(p); while (len > 0) { size_t step = 0; if (*p == ' ') { char *orig_p; orig_p = p; do { p++; len--; } while (*p == ' '); if (len == 0) { *orig_p = '\0'; break; } else { int count; char *styles[] = { "italic", "bold", "oblique", "light", "semi-bold", "heavy", "semi-condensed", }; for (count = 0; count < sizeof(styles) / sizeof(styles[0]); count++) { size_t len_v; len_v = strlen(styles[count]); /* XXX strncasecmp is not portable? */ if (len >= len_v && strncasecmp(p, styles[count], len_v) == 0) { /* [WEIGHT] [SLANT] */ *orig_p = '\0'; step = len_v; if (count <= 1) { if (count == 0) { *is_italic = 1; } else { *is_bold = 1; } } goto next_char; } } if (*p != '0' || /* In case of "DevLys 010" font family. */ *(p + 1) == '\0') /* "MS Gothic 0" => "MS Gothic" + "0" */ { char *end; double size; size = strtod(p, &end); if (*end == '\0') { /* [SIZE] */ *orig_p = '\0'; break; /* p has no more parameters. */ } } step = 1; } } else { step = 1; } next_char: p += step; len -= step; } return 1; } static int is_same_family(FcPattern *pattern, const char *family) { int count; FcValue val; for (count = 0; FcPatternGet(pattern, FC_FAMILY, count, &val) == FcResultMatch; count++) { if (strcmp(family, val.u.s) == 0) { return 1; } } return 0; } static u_int strip_pattern(FcPattern *pattern, FcPattern *remove) { u_int count = 0; FcValue val; while (FcPatternGet(pattern, FC_FAMILY, count, &val) == FcResultMatch) { if (is_same_family(remove, val.u.s)) { /* Remove not only matched name but also alias names */ FcPatternRemove(pattern, FC_FAMILY, count); } else { int count2 = ++count; FcValue val2; while(FcPatternGet(pattern, FC_FAMILY, count2, &val2) == FcResultMatch) { if (strcmp(val.u.s, val2.u.s) == 0) { FcPatternRemove(pattern, FC_FAMILY, count2); } else { count2++; } } } } return count; } static FcPattern *fc_pattern_create(const FcChar8* family) { FcPattern *pattern; if (family && (pattern = FcNameParse(family))) { /* do nothing */ } else if ((pattern = FcPatternCreate())) { if (family) { FcPatternAddString(pattern, FC_FAMILY, family); } } else { return NULL; } FcConfigSubstitute(NULL, pattern, FcMatchPattern); FcPatternRemove(pattern, FC_FAMILYLANG, 0); FcPatternRemove(pattern, FC_STYLELANG, 0); FcPatternRemove(pattern, FC_FULLNAMELANG, 0); #ifdef FC_NAMELANG FcPatternRemove(pattern, FC_NAMELANG, 0); #endif FcPatternRemove(pattern, FC_LANG, 0); FcDefaultSubstitute(pattern); return pattern; } /* XXX Lazy check */ static int check_iscii_font(FcPattern *pattern) { FcValue val; if (FcPatternGet(pattern, FC_FAMILY, 0, &val) == FcResultMatch && strstr(val.u.s, "-TT")) { return 1; } else { return 0; } } static FcPattern *parse_font_name(const char *fontname, int *is_bold, int *is_italic, u_int *percent, ef_charset_t cs) { FcPattern *pattern; FcPattern *match; FcResult result; char *family; *percent = 0; *is_bold = 0; *is_italic = 0; if (!fontname) { family = NULL; } else { char *p; if ((p = alloca(strlen(fontname) + 1))) { parse_fc_font_name(&family, is_bold, is_italic, percent, strcpy(p, fontname)); } } if ((pattern = fc_pattern_create(family))) { match = FcFontMatch(NULL, pattern, &result); if (IS_ISCII(cs) && match && !check_iscii_font(match)) { FcPatternDestroy(match); FcPatternDestroy(pattern); return NULL; } if (compl_pattern == NULL && match) { num_fc_files = strip_pattern((compl_pattern = pattern), match); /* * XXX * FcFontList() is not used. * If you want to match complementary fonts, add ... * to ~/.fonts.conf */ #if 0 { FcPattern *pat = FcPatternCreate(); FcObjectSet *objset = FcObjectSetBuild(FC_FAMILY, NULL); FcFontSet *fontset = FcFontList(NULL, pat, objset); FcValue val; int count; for (count = 0; count < fontset->nfont; count++) { FcPatternGet(fontset->fonts[count], FC_FAMILY, 0, &val); if (!is_same_family(compl_pattern, val.u.s)) { FcPatternAdd(compl_pattern, FC_FAMILY, val, FcTrue /* append */); num_fc_files++; #if 0 bl_debug_printf("Add Font List %s [%]\n", val.u.s); #endif } } } #endif } else { FcPatternDestroy(pattern); } } else { match = NULL; } return match; } #ifdef USE_WIN32API static void init_fontconfig(void) { if (!getenv("FONTCONFIG_PATH") && !getenv("FONTCONFIG_FILE")) { /* * See fontconfig-x.x.x/src/fccfg.c * (DllMain(), FcConfigFileExists(), FcConfigGetPath() and FcConfigFilename()) * * [commant in DllMain] * If the fontconfig DLL is in a "bin" or "lib" subfolder, assume it's a Unix-style * installation tree, and use "etc/fonts" in there as FONTCONFIG_PATH. * Otherwise use the folder where the DLL is as FONTCONFIG_PATH. * * [comment in FcConfigFileExists] * make sure there's a single separator * (=> If FONTCONFIG_PATH="", FONTCONFIG_FILE="/...") */ putenv("FONTCONFIG_PATH=."); } } #endif #endif /* USE_FONTCONFIG */ static u_char *get_ft_bitmap(XFontStruct *xfont, u_int32_t ch, int use_ot_layout, XFontStruct **compl_xfont) { #ifdef USE_FONTCONFIG u_int count; #endif u_char *bitmap; u_int32_t code; if (!use_ot_layout) { /* char => glyph index */ if (ch == 0x20) { return NULL; } if ((code = get_glyph_index(xfont->face, ch)) == 0) { goto compl_font; } } else { code = ch; ch = 0xffffffff; /* check_rotate() always returns 0. */ } return get_ft_bitmap_intern(xfont, code, ch); compl_font: /* * Complementary glyphs are searched only if xfont->face && !IS_PROPOTIONAL && !use_ot_layout. */ #ifdef USE_FONTCONFIG if (!compl_pattern) { return NULL; } if (!fc_files) { if (!(fc_files = calloc(num_fc_files, sizeof(*fc_charsets) + sizeof(*fc_files)))) { return NULL; } fc_charsets = fc_files + num_fc_files; } if (!xfont->compl_xfonts && !(xfont->compl_xfonts = calloc(num_fc_files, sizeof(*xfont->compl_xfonts)))) { return NULL; } for (count = 0; count < num_fc_files;) { if (!fc_files[count]) { FcResult result; FcPattern *match; match = FcFontMatch(NULL, compl_pattern, &result); FcPatternRemove(compl_pattern, FC_FAMILY, 0); if (match) { num_fc_files = count + 1 + strip_pattern(compl_pattern, match); if (FcPatternGetCharSet(match, FC_CHARSET, 0, &fc_charsets[count]) == FcResultMatch) { FcValue val; fc_charsets[count] = FcCharSetCopy(fc_charsets[count]); if (FcPatternGet(match, FC_FILE, 0, &val) == FcResultMatch) { fc_files[count] = strdup(val.u.s); } } FcPatternDestroy(match); } if (!fc_files[count]) { num_fc_files --; if (fc_charsets[count]) { FcCharSetDestroy(fc_charsets[count]); } continue; } } if (FcCharSetHasChar(fc_charsets[count], ch)) { XFontStruct *compl; if (!xfont->compl_xfonts[count]) { if (!(compl = get_cached_xfont(fc_files[count], xfont->format, xfont->is_aa))) { if (!(compl = calloc(1, sizeof(XFontStruct)))) { continue; } /* * XXX * If xfont->height is 17 and compl->height is 15, garbage is left in drawing glyphs * by compl. * force_height (xfont->height) forcibly changes the height of the font from natural one * to the same one as xfont->height. */ else if (!load_ft(compl, fc_files[count], xfont->format, xfont->is_aa, xfont->height)) { free(compl); continue; } if (!add_xfont_to_cache(compl)) { continue; } } xfont->compl_xfonts[count] = compl; } else { compl = xfont->compl_xfonts[count]; } if (HAS_POSITION_INFO_BY_GLYPH(xfont) && !HAS_POSITION_INFO_BY_GLYPH(compl)) { clear_glyph_cache_ft(compl); enable_position_info_by_glyph(compl); } if ((code = get_glyph_index(compl->face, ch)) > 0) { if ((bitmap = get_ft_bitmap_intern(compl, code, ch))) { if (compl_xfont) { *compl_xfont = compl; } #ifdef __DEBUG bl_debug_printf("Use %s font to show U+%x\n", compl->file, ch); #endif return bitmap; } } } count++; } #endif return NULL; } #else /* USE_FREETYPE */ #define load_xfont(xfont, file_path, format, cs, is_aa) load_pcf(xfont, file_path) #define unload_xfont(xfont) unload_pcf(xfont) #endif /* USE_FREETYPE */ static XFontStruct *get_cached_xfont(const char *file, int32_t format, int is_aa) { u_int count; for (count = 0; count < num_xfonts; count++) { if (strcmp(xfonts[count]->file, file) == 0 #ifdef USE_FREETYPE && (xfonts[count]->face == NULL || xfonts[count]->format == format) && xfonts[count]->is_aa == is_aa #endif ) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Use cached XFontStruct for %s.\n", xfonts[count]->file); #endif xfonts[count]->ref_count++; return xfonts[count]; } } return NULL; } static int add_xfont_to_cache(XFontStruct *xfont) { void *p; if (!(p = realloc(xfonts, sizeof(XFontStruct*) * (num_xfonts + 1)))) { unload_xfont(xfont); free(xfont); return 0; } xfonts = p; xfonts[num_xfonts++] = xfont; xfont->ref_count = 1; return 1; } static void xfont_unref(XFontStruct *xfont) { if (--xfont->ref_count == 0) { u_int count; #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG) compl_xfonts_destroy(xfont->compl_xfonts); #endif for (count = 0; count < num_xfonts; count++) { if (xfonts[count] == xfont) { if (--num_xfonts > 0) { xfonts[count] = xfonts[num_xfonts]; } else { free(xfonts); xfonts = NULL; #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG) compl_final(); #endif } break; } } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " %s font is unloaded. => CURRENT NUM OF XFONTS %d\n", xfont->file, num_xfonts); #endif unload_xfont(xfont); free(xfont); } } /* --- static variables --- */ static int compose_dec_special_font; /* --- global functions --- */ void ui_compose_dec_special_font(void) { compose_dec_special_font = 1; } #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG) void ui_font_use_fontconfig(void) { use_fontconfig = 1; } #endif ui_font_t *ui_font_new(Display *display, vt_font_t id, int size_attr, ui_type_engine_t type_engine, ui_font_present_t font_present, const char *fontname, u_int fontsize, u_int col_width, int use_medium_for_bold, u_int letter_space /* Ignored for now. */ ) { ef_charset_t cs; char *font_file; char *decsp_id = NULL; u_int percent; ui_font_t *font; vt_font_t orig_id = id; #ifdef USE_FREETYPE u_int format; #endif u_int cols; int is_aa; cs = FONT_CS(id); #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG) if (use_fontconfig) { FcPattern *pattern; FcValue val; int is_bold; int is_italic; char *p; #ifdef USE_WIN32API init_fontconfig(); #endif if (!(pattern = parse_font_name(fontname, &is_bold, &is_italic, &percent, cs))) { return NULL; } if (FcPatternGet(pattern, FC_FILE, 0, &val) != FcResultMatch) { FcPatternDestroy(pattern); return NULL; } if ((font_file = alloca(strlen(val.u.s) + 1))) { strcpy(font_file, val.u.s); } /* For 'format = fontsize | (id & (FONT_BOLD | FONT_ITALIC))' below */ if ((p = strcasestr(font_file, "bold")) && strchr(p, '/') == NULL && strchr(p, '\\') == NULL) { id &= ~FONT_BOLD; /* XXX e.g. Inconsolata-Bold.ttf => Don't call FT_Outline_Embolden(). */ } else if (is_bold) { id |= FONT_BOLD; } if ((p = strcasestr(font_file, "italic")) && strchr(p, '/') == NULL && strchr(p, '\\') == NULL) { id &= ~FONT_ITALIC; /* XXX */ } else if (is_italic) { id |= FONT_ITALIC; } FcPatternDestroy(pattern); } else #endif if (!fontname) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Font file is not specified.\n"); #endif if (cs == DEC_SPECIAL) { /* use ui_decsp_font_new() */ font_file = NULL; percent = 0; } /* * Default font on Androidis is ttf, so charsets except unicode and ISO88591 are available. * (Chars except unicode are converted to unicode in ui_window.c for freetype.) */ #ifndef __ANDROID__ else if (!IS_ISO10646_UCS4(cs) && cs != ISO8859_1_R) { return NULL; } #endif else { struct stat st; #if defined(__FreeBSD__) if (stat("/usr/local/lib/X11/fonts/local/unifont.pcf.gz", &st) == 0) { font_file = "/usr/local/lib/X11/fonts/local/unifont.pcf.gz"; percent = 100; } else { font_file = "/usr/local/lib/X11/fonts/misc/10x20.pcf.gz"; percent = 0; } #elif defined(__NetBSD__) percent = 0; if (stat("/usr/pkg/lib/X11/fonts/efont/b16.pcf.gz", &st) == 0) { font_file = "/usr/pkg/lib/X11/fonts/efont/b16.pcf.gz"; } else { font_file = "/usr/X11R7/lib/X11/fonts/misc/10x20.pcf.gz"; } #elif defined(__OpenBSD__) if (stat("/usr/X11R6/lib/X11/fonts/misc/unifont.pcf.gz", &st) == 0) { font_file = "/usr/X11R6/lib/X11/fonts/misc/unifont.pcf.gz"; percent = 100; } else { font_file = "/usr/X11R6/lib/X11/fonts/misc/10x20.pcf.gz"; percent = 0; } #elif defined(__ANDROID__) if (stat("/system/fonts/DroidSansMono.ttf", &st) == 0) { font_file = "/system/fonts/DroidSansMono.ttf"; } else { DIR* dir; struct dirent *entry; const char *cand; if ((dir = opendir("/system/fonts")) == NULL) { return NULL; } cand = NULL; while ((entry = readdir(dir))) { if (strcasestr(entry->d_name, ".tt")) { if (cand == NULL) { if ((cand = alloca(strlen(entry->d_name) + 1))) { strcpy(cand, entry->d_name); } } else if (strcasestr(entry->d_name, "Mono")) { if ((cand = alloca(strlen(entry->d_name) + 1))) { strcpy(cand, entry->d_name); } break; } } } closedir(dir); if (cand == NULL || !(font_file = alloca(14 + strlen(cand) + 1))) { return NULL; } strcpy(font_file, "/system/fonts"); font_file[13] = '/'; strcpy(font_file + 14, cand); } percent = 0; #else /* __linux__ */ if (stat("/usr/share/fonts/X11/misc/unifont.pcf.gz", &st) == 0) { font_file = "/usr/share/fonts/X11/misc/unifont.pcf.gz"; percent = 100; } else { font_file = "/usr/share/fonts/X11/misc/10x20.pcf.gz"; percent = 0; } #endif #ifndef __ANDROID__ /* XXX double drawing is used to bolden pcf font. */ if (id & FONT_BOLD) { use_medium_for_bold = 1; } #endif } } else { char *percent_str; if (!(percent_str = alloca(strlen(fontname) + 1))) { return NULL; } strcpy(percent_str, fontname); #ifdef USE_WIN32API if (percent_str[0] != '\0' && percent_str[1] == ':') { /* c:/Users/... */ font_file = percent_str; percent_str += 2; bl_str_sep(&percent_str, ":"); } else #endif { font_file = bl_str_sep(&percent_str, ":"); } if (!percent_str || !bl_str_to_uint(&percent, percent_str)) { percent = 0; } } if (cs == DEC_SPECIAL && (compose_dec_special_font || font_file == NULL || !is_pcf(font_file))) { if (!(decsp_id = alloca(6 + DIGIT_STR_LEN(u_int) + 1 + DIGIT_STR_LEN(u_int) + 1))) { return NULL; } } if (type_engine != TYPE_XCORE || !(font = calloc(1, sizeof(ui_font_t)))) { return NULL; } if (size_attr >= DOUBLE_HEIGHT_TOP) { fontsize *= 2; col_width *= 2; } #ifdef USE_FREETYPE #ifdef USE_FONTCONFIG if (use_fontconfig && dpi_for_fc > 0.0) { fontsize = DIVIDE_ROUNDINGDOWN(dpi_for_fc * fontsize, 72); } #endif format = fontsize | (id & (FONT_BOLD | FONT_ITALIC)); if (font_present & FONT_VERT_RTL) { format |= FONT_ROTATED; /* XXX Not support ROTATED and ITALIC at the same time. (see load_glyph()). */ format &= ~FONT_ITALIC; } #endif if (decsp_id) { sprintf(decsp_id, "decsp-%dx%d", col_width, fontsize); } if (!(font_present & FONT_NOAA) && display->bytes_per_pixel > 1) { is_aa = 1; } else { is_aa = 0; } if ((font->xfont = get_cached_xfont(decsp_id ? decsp_id : font_file, #ifdef USE_FREETYPE format, #else 0, #endif is_aa))) { goto xfont_loaded; } if (!(font->xfont = calloc(1, sizeof(XFontStruct)))) { free(font); return NULL; } font->display = display; if (decsp_id) { if (!ui_load_decsp_xfont(font->xfont, decsp_id)) { compose_dec_special_font = 0; free(font->xfont); free(font); if (size_attr >= DOUBLE_HEIGHT_TOP) { fontsize /= 2; col_width /= 2; } return ui_font_new(display, id, size_attr, type_engine, font_present, font_file, fontsize, col_width, use_medium_for_bold, letter_space); } } else if (!load_xfont(font->xfont, font_file, format, cs, is_aa)) { bl_msg_printf("Failed to load %s.\n", font_file); free(font->xfont); free(font); if (fontname) { if (size_attr >= DOUBLE_HEIGHT_TOP) { fontsize /= 2; col_width /= 2; } return ui_font_new(display, id, size_attr, type_engine, font_present, NULL /* Fall back to the default font */, fontsize, col_width, use_medium_for_bold, letter_space); } else { return NULL; } } if (!add_xfont_to_cache(font->xfont)) { free(font); return NULL; } xfont_loaded: /* Following is almost the same processing as xlib. */ font->id = orig_id; if (font->id & FONT_FULLWIDTH) { cols = 2; } else { cols = 1; } #ifdef USE_FREETYPE if (HAS_POSITION_INFO_BY_GLYPH(font->xfont)) { font->is_proportional = 1; } if (IS_ISCII(cs) && font->xfont->is_aa && (font->xfont->ref_count == 1 || HAS_POSITION_INFO_BY_GLYPH(font->xfont))) { /* Proportional glyph is available on ISCII alone for now. */ font->is_var_col_width = font->is_proportional = 1; if (font->xfont->ref_count == 1) { init_iscii_ft(font->xfont->face); enable_position_info_by_glyph(font->xfont); } } else #endif if (font_present & FONT_VAR_WIDTH) { /* * If you use fixed-width fonts whose width is differnet from * each other. */ font->is_var_col_width = 1; #ifdef USE_FREETYPE font->is_proportional = 1; if (font->xfont->ref_count == 1) { enable_position_info_by_glyph(font->xfont); } else if (!HAS_POSITION_INFO_BY_GLYPH(font->xfont)) { clear_glyph_cache_ft(font->xfont); enable_position_info_by_glyph(font->xfont); } #endif } if (font_present & FONT_VERTICAL) { font->is_vertical = 1; } if (use_medium_for_bold) { font->double_draw_gap = 1; } if (id & FONT_FULLWIDTH) { font->width = font->xfont->width_full; } else { font->width = font->xfont->width; } font->height = font->xfont->height; font->ascent = font->xfont->ascent; if (col_width == 0) { /* standard(usascii) font */ if (percent > 0) { u_int ch_width; if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ ch_width = DIVIDE_ROUNDING(fontsize * percent, 100); } else { ch_width = DIVIDE_ROUNDING(fontsize * percent, 200); } if (font->width != ch_width) { if (!font->is_var_col_width) { /* * If width(2) of '1' doesn't match ch_width(4) * x_off = (4-2)/2 = 1. * It means that starting position of drawing '1' is 1 * as follows. * * 0123 * +----+ * | ** | * | * | * | * | * +----+ */ if (font->width < ch_width) { font->x_off = (ch_width - font->width) / 2; } font->width = ch_width; } } } else if (font->is_vertical) { #ifdef USE_FREETYPE if (!font->xfont->face || !(font->xfont->format & FONT_ROTATED)) #endif { /* * !! Notice !! * The width of full and half character font is the same. */ font->x_off = font->width / 2; font->width *= 2; } } if (letter_space > 0) { font->width += letter_space; font->x_off += (letter_space / 2); } } else { /* not a standard(usascii) font */ /* * XXX hack * forcibly conforming non standard font width to standard font width. */ if (font->is_vertical) { /* * !! Notice !! * The width of full and half character font is the same. */ if (font->width != col_width) { bl_msg_printf( "Font(id %x) width(%d) is not matched with " "standard width(%d).\n", font->id, font->width, col_width); /* is_var_col_width is always false if is_vertical is true. */ #if 0 if (!font->is_var_col_width) #endif { if (font->width < col_width) { font->x_off = (col_width - font->width) / 2; } font->width = col_width; } } } else { if (font->width != col_width * cols) { bl_msg_printf( "Font(id %x) width(%d) is not matched with " "standard width(%d).\n", font->id, font->width, col_width * cols); if (!font->is_var_col_width) { if (font->width < col_width * cols) { font->x_off = (col_width * cols - font->width) / 2; } font->width = col_width * cols; } } } } if (size_attr == DOUBLE_WIDTH) { font->x_off += (font->width / 2); font->width *= 2; } font->size_attr = size_attr; /* * checking if font width/height/ascent member is sane. */ if (font->width == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " font width is 0.\n"); #endif /* XXX this may be inaccurate. */ font->width = DIVIDE_ROUNDINGUP(fontsize * cols, 2); } if (font->height == 0) { /* XXX this may be inaccurate. */ font->height = fontsize; } if (font->ascent == 0) { /* XXX this may be inaccurate. */ font->ascent = fontsize; } bl_msg_printf("Load %s (id %x)\n", font->xfont->file, font->id); #ifdef DEBUG bl_debug_printf(" => CURRENT NUM OF XFONTS %d\n", num_xfonts); #endif #ifdef DEBUG ui_font_dump(font); #endif return font; } void ui_font_destroy(ui_font_t *font) { xfont_unref(font->xfont); #ifdef USE_OT_LAYOUT if (font->ot_font) { otl_close(font->ot_font); } #endif free(font); } #ifdef USE_OT_LAYOUT int ui_font_has_ot_layout_table(ui_font_t *font) { #ifdef USE_FREETYPE if (font->xfont->face) { if (!font->ot_font) { if (font->ot_font_not_found) { return 0; } if (!(font->ot_font = otl_open(font->xfont->face, 0))) { font->ot_font_not_found = 1; return 0; } if (!HAS_POSITION_INFO_BY_GLYPH(font->xfont)) { clear_glyph_cache_ft(font->xfont); enable_position_info_by_glyph(font->xfont); } font->is_proportional = 1; /* font->is_var_col_width can be 0 or 1. */ } return 1; } #endif return 0; } u_int ui_convert_text_to_glyphs(ui_font_t *font, u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features) { return otl_convert_text_to_glyphs(font->ot_font, shaped, shaped_len, offsets, widths, cmapped, src, src_len, script, features, 0); } #endif u_int ui_calculate_char_width(ui_font_t *font, u_int32_t ch, ef_charset_t cs, int *draw_alone) { if (draw_alone) { *draw_alone = 0; } #if defined(USE_FREETYPE) if (font->xfont->is_aa && font->is_proportional && font->is_var_col_width) { u_char *glyph; if ((glyph = get_ft_bitmap(font->xfont, ch, #ifdef USE_OT_LAYOUT (font->use_ot_layout /* && font->ot_font */) #else 0 #endif , NULL))) { return glyph[0]; } } #endif return font->width; } /* Return written size */ size_t ui_convert_ucs4_to_utf16(u_char *dst, /* 4 bytes. Big endian. */ u_int32_t src) { if (src < 0x10000) { dst[0] = (src >> 8) & 0xff; dst[1] = src & 0xff; return 2; } else if (src < 0x110000) { /* surrogate pair */ u_char c; src -= 0x10000; c = (u_char)(src / (0x100 * 0x400)); src -= (c * 0x100 * 0x400); dst[0] = c + 0xd8; c = (u_char)(src / 0x400); src -= (c * 0x400); dst[1] = c; c = (u_char)(src / 0x100); src -= (c * 0x100); dst[2] = c + 0xdc; dst[3] = (u_char)src; return 4; } return 0; } #ifdef DEBUG void ui_font_dump(ui_font_t *font) { bl_msg_printf("Font id %x: XFont %p (width %d, height %d, ascent %d, x_off %d)", font->id, font->xfont, font->width, font->height, font->ascent, font->x_off); if (font->is_proportional) { bl_msg_printf(" (proportional)"); } if (font->is_var_col_width) { bl_msg_printf(" (var col width)"); } if (font->is_vertical) { bl_msg_printf(" (vertical)"); } if (font->double_draw_gap) { bl_msg_printf(" (double drawing)"); } bl_msg_printf("\n"); } #endif u_char *ui_get_bitmap(XFontStruct *xfont, u_char *ch, size_t len, int use_ot_layout, XFontStruct **compl_xfont) { size_t ch_idx; int16_t glyph_idx; int32_t glyph_offset; #ifdef USE_FREETYPE if (xfont->face) { return get_ft_bitmap(xfont, ef_bytes_to_int(ch, len), use_ot_layout, compl_xfont); } else #endif if (len == 1) { ch_idx = ch[0] - xfont->min_char_or_byte2; } else if (len == 2) { ch_idx = (ch[0] - xfont->min_byte1) * (xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1) + ch[1] - xfont->min_char_or_byte2; } else /* if( len == 4) */ { ch_idx = (ch[1] * 0x100 + ch[2] - xfont->min_byte1) * (xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1) + ch[3] - xfont->min_char_or_byte2; } if (ch_idx >= (xfont->max_char_or_byte2 - xfont->min_char_or_byte2 + 1)*(xfont->max_byte1 - xfont->min_byte1 + 1) || (glyph_idx = xfont->glyph_indeces[ch_idx]) == -1) { return NULL; } /* * glyph_idx should be casted to unsigned in order not to be minus * if it is over 32767. */ glyph_offset = xfont->glyph_offsets[(u_int16_t)glyph_idx]; #if 0 bl_debug_printf(BL_DEBUG_TAG " chindex %d glindex %d glyph offset %d\n", ch_idx, glyph_idx, glyph_offset); #endif return xfont->glyphs + glyph_offset; } /* For mlterm-libvte */ void ui_font_set_dpi_for_fc(double dpi) { #ifdef USE_FONTCONFIG dpi_for_fc = dpi; #endif } mlterm-3.8.9/uitoolkit/fb/ui_font.h010064400017600000144000000012211356600660700157640ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef ___UI_FONT_H__ #define ___UI_FONT_H__ #include "../ui_font.h" u_char *ui_get_bitmap(XFontStruct *xfont, u_char *ch, size_t len, int use_ot_layout, XFontStruct **compl_xfont); #define ui_get_bitmap_line(xfont, bitmap, offset_bytes, bitmap_line) \ ((bitmap) && \ memcmp(((bitmap_line) = (bitmap) + (offset_bytes)), "\x0\x0\x0", \ (xfont)->glyph_width_bytes) != 0) /* x & 7 == x % 8 */ #define ui_get_bitmap_cell(bitmap_line, x) ((bitmap_line)[(x) / 8] & (1 << (8 - ((x)&7) - 1))) #endif mlterm-3.8.9/uitoolkit/fb/ui_gc.c010064400017600000144000000006351356600660700154120ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "../ui_gc.h" #include /* --- global functions --- */ ui_gc_t *ui_gc_new(Display *display, Drawable drawable) { return NULL; } void ui_gc_destroy(ui_gc_t *gc) {} void ui_gc_set_fg_color(ui_gc_t *gc, u_long fg_color) {} void ui_gc_set_bg_color(ui_gc_t *gc, u_long bg_color) {} void ui_gc_set_fid(ui_gc_t *gc, Font fid) {} mlterm-3.8.9/uitoolkit/fb/ui_imagelib.c010064400017600000144000000472101356600660700165720ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef NO_IMAGE #include "../ui_imagelib.h" #include /* sprintf */ #include /* write , STDIN_FILENO */ #if !defined(USE_WIN32API) && !defined(__ANDROID__) #include /* waitpid */ #endif #ifdef DLOPEN_LIBM #include /* dynamically loading pow */ #else #include /* pow */ #endif #include #include #include /* BL_LIBEXECDIR */ #include "ui_display.h" /* ui_cmap_get_closest_color */ /* Trailing "/" is appended in value_table_refresh(). */ #ifndef LIBMDIR #define LIBMDIR "/lib" #endif #if 1 #define BUILTIN_SIXEL #endif #ifdef USE_GRF #define BPP_PSEUDO 2 #else #define BPP_PSEUDO 1 #endif /* --- static functions --- */ static void value_table_refresh(u_char *value_table, /* 256 bytes */ ui_picture_modifier_t *mod) { int i, tmp; double real_gamma, real_brightness, real_contrast; static double (*pow_func)(double, double); real_gamma = (double)(mod->gamma) / 100; real_contrast = (double)(mod->contrast) / 100; real_brightness = (double)(mod->brightness) / 100; if (!pow_func) { #ifdef DLOPEN_LIBM bl_dl_handle_t handle; if ((!(handle = bl_dl_open(LIBMDIR "/", "m")) && !(handle = bl_dl_open("", "m"))) || !(pow_func = bl_dl_func_symbol(handle, "pow"))) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to load pow in libm.so\n"); #endif if (handle) { bl_dl_close(handle); } /* * gamma, contrast and brightness options are ignored. * (alpha option still survives.) */ for (i = 0; i < 256; i++) { value_table[i] = i; } return; } bl_dl_close_at_exit(handle); #else /* DLOPEN_LIBM */ pow_func = pow; #endif /* DLOPEN_LIBM */ } for (i = 0; i < 256; i++) { tmp = real_contrast * (255 * (*pow_func)(((double)i + 0.5) / 255, real_gamma) - 128) + 128 * real_brightness; if (tmp >= 255) { break; } else if (tmp < 0) { value_table[i] = 0; } else { value_table[i] = tmp; } } for (; i < 256; i++) { value_table[i] = 255; } } static void modify_pixmap(Display *display, Pixmap pixmap, ui_picture_modifier_t *pic_mod, u_int depth) { u_char *value_table; u_int32_t *src; u_char *dst; u_int num_pixels; u_int count; u_char r, g, b; u_long pixel; if (!ui_picture_modifier_is_normal(pic_mod) && (value_table = alloca(256))) { value_table_refresh(value_table, pic_mod); } else if (display->bytes_per_pixel == 4 && /* RRGGBB */ display->rgbinfo.r_offset == 16 && display->rgbinfo.g_offset == 8 && display->rgbinfo.b_offset == 0) { return; } else { value_table = NULL; } src = dst = pixmap->image; num_pixels = pixmap->width * pixmap->height; for (count = 0; count < num_pixels; count++) { pixel = *(src++); r = (pixel >> 16) & 0xff; g = (pixel >> 8) & 0xff; b = pixel & 0xff; if (value_table) { r = (value_table[r] * (255 - pic_mod->alpha) + pic_mod->blend_red * pic_mod->alpha) / 255; g = (value_table[g] * (255 - pic_mod->alpha) + pic_mod->blend_green * pic_mod->alpha) / 255; b = (value_table[b] * (255 - pic_mod->alpha) + pic_mod->blend_blue * pic_mod->alpha) / 255; } if (ui_cmap_get_closest_color(&pixel, r, g, b)) { #ifdef USE_GRF *((u_int16_t *)dst) = pixel; dst += 2; #else *(dst++) = pixel; #endif } else { pixel = RGB_TO_PIXEL(r, g, b, display->rgbinfo) | (depth == 32 ? (pixel & 0xff000000) : 0); if (display->bytes_per_pixel == 2) { *((u_int16_t *)dst) = pixel; dst += 2; } else /* if( display->bytes_per_pixel == 4) */ { *((u_int32_t *)dst) = pixel; dst += 4; } } } if (display->bytes_per_pixel < 4) { void *p; if ((p = realloc(pixmap->image, pixmap->width * pixmap->height * display->bytes_per_pixel))) { pixmap->image = p; } } } #ifdef BUILTIN_SIXEL #include #include #include /* SSIZE_MAX */ /* * This function resizes the sixel image to the specified size and shrink * pixmap->image. * It frees pixmap->image in failure. * Call resize_sixel() after load_sixel_from_file() because it returns at least * 1024*1024 pixels memory even if the actual image size is less than 1024*1024. */ static int resize_sixel(Pixmap pixmap, u_int width, u_int height, u_int bytes_per_pixel) { void *p; size_t line_len; size_t old_line_len; size_t image_len; size_t old_image_len; u_char *dst; u_char *src; int y; u_int min_height; p = NULL; if ((width == 0 || width == pixmap->width) && (height == 0 || height == pixmap->height)) { goto end; } if (width > SSIZE_MAX / bytes_per_pixel / height) { goto error; } old_line_len = pixmap->width * bytes_per_pixel; line_len = width * bytes_per_pixel; image_len = line_len * height; old_image_len = old_line_len * pixmap->height; if (image_len > old_image_len) { if (!(p = realloc(pixmap->image, image_len))) { goto error; } pixmap->image = p; } /* Tiling */ min_height = BL_MIN(height, pixmap->height); if (width > pixmap->width) { size_t surplus; u_int num_copy; u_int count; u_char *dst_next; y = min_height - 1; src = pixmap->image + old_line_len * y; dst = pixmap->image + line_len * y; surplus = line_len % old_line_len; num_copy = line_len / old_line_len - 1; for (; y >= 0; y--) { dst_next = memmove(dst, src, old_line_len); for (count = num_copy; count > 0; count--) { memcpy((dst_next += old_line_len), dst, old_line_len); } memcpy(dst_next + old_line_len, dst, surplus); dst -= line_len; src -= old_line_len; } } else if (width < pixmap->width) { src = pixmap->image + old_line_len; dst = pixmap->image + line_len; for (y = 1; y < min_height; y++) { memmove(dst, src, old_line_len); dst += line_len; src += old_line_len; } } if (height > pixmap->height) { y = pixmap->height; src = pixmap->image; dst = src + line_len * y; for (; y < height; y++) { memcpy(dst, src, line_len); dst += line_len; src += line_len; } } bl_msg_printf("Resize sixel from %dx%d to %dx%d\n", pixmap->width, pixmap->height, width, height); pixmap->width = width; pixmap->height = height; end: /* Always realloate pixmap->image according to its width, height and * bytes_per_pixel. */ if (!p && (p = realloc(pixmap->image, pixmap->width * pixmap->height * bytes_per_pixel))) { pixmap->image = p; } return 1; error: free(pixmap->image); return 0; } #define CARD_HEAD_SIZE 0 #include "../../common/c_sixel.c" /* For old machines (not to use mlimgloader) */ #if (defined(__NetBSD__) || defined(__OpenBSD__)) && !defined(USE_GRF) #define SIXEL_1BPP #include "../../common/c_sixel.c" #undef SIXEL_1BPP /* depth should be checked by the caller. */ static int load_sixel_with_mask_from_data_1bpp(char *file_data, u_int width, u_int height, Pixmap *pixmap, PixmapMask *mask) { int x; int y; u_char *src; #if 0 u_char *dst; #endif if (!(*pixmap = calloc(1, sizeof(**pixmap)))) { return 0; } if (!((*pixmap)->image = load_sixel_from_data_1bpp(file_data, &(*pixmap)->width, &(*pixmap)->height)) || /* resize_sixel() frees pixmap->image in failure. */ !resize_sixel(*pixmap, width, height, 1)) { free(*pixmap); return 0; } src = (*pixmap)->image; #if 0 if (mask && (dst = *mask = calloc(1, (*pixmap)->width * (*pixmap)->height))) { int has_tp; has_tp = 0; for (y = 0; y < (*pixmap)->height; y++) { for (x = 0; x < (*pixmap)->width; x++) { if (*src >= 0x80) { *dst = 1; /* clear opaque mark */ *src &= 0x7f; } else { has_tp = 1; } src++; dst++; } } if (!has_tp) { free(*mask); *mask = None; } } else { for (y = 0; y < (*pixmap)->height; y++) { for (x = 0; x < (*pixmap)->width; x++) { /* clear opaque mark */ *(src++) &= 0x7f; } } } #else { u_char bg_color; u_char *p; if (mask) { *mask = None; } bg_color = 0; p = src; /* Guess the current screen background color. */ for (y = 0; y < (*pixmap)->height; y++) { for (x = 0; x < (*pixmap)->width; x++) { if (*p >= 0x80) { bg_color = (((*p) & 0x7f) == 1) ? 0 : 1; break; } p++; } } for (y = 0; y < (*pixmap)->height; y++) { for (x = 0; x < (*pixmap)->width; x++) { if (*src >= 0x80) { /* clear opaque mark */ *(src++) &= 0x7f; } else { /* replace transparent pixel by the background color */ *(src++) = bg_color; } } } } #endif return 1; } #endif #endif /* BUILTIN_SIXEL */ #define SIXEL_SHAREPALETTE #include "../../common/c_sixel.c" #undef SIXEL_SHAREPALETTE #if defined(USE_WIN32API) #include static int exec_mlimgloader(char *path, u_int width, u_int height, int keep_aspect, Pixmap *pixmap) { HANDLE input_write; HANDLE input_read_tmp; HANDLE input_read; SECURITY_ATTRIBUTES sa; PROCESS_INFORMATION pi; STARTUPINFO si; char *cmd_line; DWORD len; ssize_t size; u_int32_t tmp; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; if (!CreatePipe(&input_read_tmp, &input_write, &sa, 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreatePipe() failed.\n"); #endif return 0; } if (!DuplicateHandle(GetCurrentProcess(), input_read_tmp, GetCurrentProcess(), &input_read /* Address of new handle. */, 0, FALSE /* Make it uninheritable. */, DUPLICATE_SAME_ACCESS)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " DuplicateHandle() failed.\n"); #endif CloseHandle(input_read_tmp); goto error1; } CloseHandle(input_read_tmp); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES | STARTF_FORCEOFFFEEDBACK; si.hStdOutput = input_write; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.hStdError = GetStdHandle(STD_ERROR_HANDLE); /* * Use this if you want to hide the child: * si.wShowWindow = SW_HIDE; * Note that dwFlags must include STARTF_USESHOWWINDOW if you want to * use the wShowWindow flags. */ if ((cmd_line = alloca(23 + DIGIT_STR_LEN(u_int) * 2 + strlen(path) + 1)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " alloca failed.\n"); #endif goto error1; } sprintf(cmd_line, "%s 0 %d %d %s stdout%s", "mlimgloader.exe", width, height, path, keep_aspect ? " -a" : ""); if (!CreateProcess("mlimgloader.exe", cmd_line, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " CreateProcess() failed.\n"); #endif goto error1; } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); CloseHandle(input_write); if (!(*pixmap = calloc(1, sizeof(**pixmap)))) { goto error2; } if (!ReadFile(input_read, &tmp, sizeof(u_int32_t), &len, NULL) || len != sizeof(u_int32_t)) { goto error2; } size = ((*pixmap)->width = tmp) * sizeof(u_int32_t); if (!ReadFile(input_read, &tmp, sizeof(u_int32_t), &len, NULL) || len != sizeof(u_int32_t)) { goto error2; } size *= ((*pixmap)->height = tmp); if (!((*pixmap)->image = malloc(size))) { goto error2; } else { u_char *p; p = (*pixmap)->image; do { if (!ReadFile(input_read, p, size, &len, NULL)) { free((*pixmap)->image); goto error2; } p += len; } while ((size -= len) > 0); } CloseHandle(input_read); return 1; error1: CloseHandle(input_write); CloseHandle(input_read); return 0; error2: free(*pixmap); CloseHandle(input_read); return 0; } #elif defined(__ANDROID__) static int exec_mlimgloader(char *path, u_int width, u_int height, int keep_aspect, Pixmap *pixmap) { if (!(*pixmap = calloc(1, sizeof(**pixmap)))) { return 0; } (*pixmap)->width = width; (*pixmap)->height = height; if (!((*pixmap)->image = ui_display_get_bitmap(path, &(*pixmap)->width, &(*pixmap)->height))) { free(*pixmap); return 0; } return 1; } #else static int exec_mlimgloader(char *path, u_int width, u_int height, int keep_aspect, Pixmap *pixmap) { pid_t pid; int fds[2]; ssize_t size; u_int32_t tmp; if (pipe(fds) == -1) { return 0; } pid = fork(); if (pid == -1) { close(fds[0]); close(fds[0]); return 0; } if (pid == 0) { /* child process */ char *args[8]; char width_str[DIGIT_STR_LEN(u_int) + 1]; char height_str[DIGIT_STR_LEN(u_int) + 1]; args[0] = BL_LIBEXECDIR("mlterm") "/mlimgloader"; args[1] = "0"; sprintf(width_str, "%u", width); args[2] = width_str; sprintf(height_str, "%u", height); args[3] = height_str; args[4] = path; args[5] = "stdout"; if (keep_aspect) { args[6] = "-a"; args[7] = NULL; } else { args[6] = NULL; } close(fds[0]); if (dup2(fds[1], STDOUT_FILENO) != -1) { execv(args[0], args); } bl_msg_printf("Failed to exec %s.\n", args[0]); exit(1); } close(fds[1]); if (!(*pixmap = calloc(1, sizeof(**pixmap)))) { goto error; } if (read(fds[0], &tmp, sizeof(u_int32_t)) != sizeof(u_int32_t)) { goto error; } size = ((*pixmap)->width = tmp) * sizeof(u_int32_t); if (read(fds[0], &tmp, sizeof(u_int32_t)) != sizeof(u_int32_t)) { goto error; } size *= ((*pixmap)->height = tmp); if (!((*pixmap)->image = malloc(size))) { goto error; } else { u_char *p; ssize_t n_rd; p = (*pixmap)->image; while ((n_rd = read(fds[0], p, size)) > 0) { p += n_rd; size -= n_rd; } if (size > 0) { goto error; } } close(fds[0]); /* bl_pty_fork() in vt_pty_unix_new() may block without this in startup. */ #if 1 waitpid(pid, NULL, 0); #endif return 1; error: #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to load %s\n", path); #endif if (*pixmap) { free((*pixmap)->image); free(*pixmap); } close(fds[0]); return 0; } #endif static int load_file(Display *display, char *path, u_int width, u_int height, int keep_aspect, ui_picture_modifier_t *pic_mod, u_int depth, Pixmap *pixmap, PixmapMask *mask) { if (!path || !*path) { return 0; } #ifdef BUILTIN_SIXEL if (strcasecmp(path + strlen(path) - 4, ".six") == 0) { char *file_data; if (!(file_data = read_sixel_file(path))) { return 0; } /* For old machines */ #if (defined(__NetBSD__) || defined(__OpenBSD__)) && !defined(USE_GRF) if (depth == 1) { /* pic_mod is ignored. */ if (load_sixel_with_mask_from_data_1bpp(file_data, width, height, pixmap, mask)) { free(file_data); return 1; } } else #endif if ( /* For old machines and Android (not to use mlimgloader) */ #if !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && \ (!defined(__FreeBSD__) || !defined(PC98)) width == 0 && height == 0 && #endif (*pixmap = calloc(1, sizeof(**pixmap)))) { #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE u_int32_t *sixel_cmap; if (ui_display_is_changeable_cmap()) { goto skip_sharepalette; } #endif if (depth <= 8) { if (ui_picture_modifier_is_normal(pic_mod) /* see modify_pixmap() */) { if (((*pixmap)->image = load_sixel_from_data_sharepalette(file_data, &(*pixmap)->width, &(*pixmap)->height)) && resize_sixel(*pixmap, width, height, BPP_PSEUDO)) { if (mask) { *mask = NULL; } free(file_data); goto loaded_nomodify; } } bl_msg_printf("Use closest colors for %s.\n", path); } #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE skip_sharepalette: if (!(sixel_cmap = custom_palette) && (sixel_cmap = alloca(sizeof(*sixel_cmap) * (SIXEL_PALETTE_SIZE + 1)))) { sixel_cmap[SIXEL_PALETTE_SIZE] = 0; /* No active palette */ custom_palette = sixel_cmap; } #endif if (((*pixmap)->image = load_sixel_from_data(file_data, &(*pixmap)->width, &(*pixmap)->height)) && /* resize_sixel() frees pixmap->image in failure. */ resize_sixel(*pixmap, width, height, 4)) { #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE if (sixel_cmap) { /* see set_wall_picture() in ui_screen.c */ ui_display_set_cmap(sixel_cmap, sixel_cmap[SIXEL_PALETTE_SIZE]); } #endif free(file_data); goto loaded; } else { free(*pixmap); } } free(file_data); } #endif /* BUILTIN_SIXEL */ if (!exec_mlimgloader(path, width, height, keep_aspect, pixmap)) { return 0; } loaded: if (mask) { u_char *dst; if ((dst = *mask = calloc(1, (*pixmap)->width * (*pixmap)->height))) { int x; int y; int has_tp; u_int32_t *src; has_tp = 0; src = (u_int32_t *)(*pixmap)->image; for (y = 0; y < (*pixmap)->height; y++) { for (x = 0; x < (*pixmap)->width; x++) { if (*(src++) >= 0x80000000) { *dst = 1; } else { has_tp = 1; } dst++; } } if (!has_tp) { free(*mask); *mask = None; } } } modify_pixmap(display, *pixmap, pic_mod, depth); loaded_nomodify: #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " %s(w %d h %d) is loaded%s.\n", path, (*pixmap)->width, (*pixmap)->height, (mask && *mask) ? " (has mask)" : ""); #endif return 1; } /* --- global functions --- */ void ui_imagelib_display_opened(Display *display) {} void ui_imagelib_display_closed(Display *display) {} Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, ui_picture_modifier_t *pic_mod) { Pixmap pixmap; #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE ui_display_enable_to_change_cmap(1); #endif if (!load_file(win->disp->display, path, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win), 0, pic_mod, win->disp->depth, &pixmap, NULL)) { pixmap = None; } #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE ui_display_enable_to_change_cmap(0); #endif return pixmap; } int ui_imagelib_root_pixmap_available(Display *display) { return 0; } Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modifier_t *pic_mod) { return None; } int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, int keep_aspect) { if (cardinal) { return 0; } if (!load_file(disp->display, path, *width, *height, keep_aspect, NULL, disp->depth, pixmap, mask)) { return 0; } if (*width == 0 || *height == 0 || keep_aspect) { *width = (*pixmap)->width; *height = (*pixmap)->height; } return 1; } void ui_destroy_image(Display *display, Pixmap pixmap) { free(pixmap->image); free(pixmap); } void ui_destroy_mask(Display *display, PixmapMask mask /* can be NULL */) { if (mask) { free(mask); } } #endif /* NO_IMAGE */ mlterm-3.8.9/uitoolkit/fb/ui_selection_encoding.c012075500017600000144000000000001356600660700265102../xlib/ui_selection_encoding.custar kenusersmlterm-3.8.9/uitoolkit/fb/ui_virtual_kbd.h010064400017600000144000000006071356600660700173330ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_VIRTUAL_KBD_H__ #define __UI_VIRTUAL_KBD_H__ #include "ui_display.h" #include "../ui_window.h" int ui_virtual_kbd_hide(void); int ui_is_virtual_kbd_event(ui_display_t *disp, XButtonEvent *bev); int ui_virtual_kbd_read(XKeyEvent *kev, XButtonEvent *bev); ui_window_t *ui_is_virtual_kbd_area(int y); #endif mlterm-3.8.9/uitoolkit/ui_color_manager.h010064400017600000144000000045641356600660700172540ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_COLOR_MANAGER_H__ #define __UI_COLOR_MANAGER_H__ #include #include "ui_color.h" #include "ui_color_cache.h" typedef struct ui_color_manager { /* normal or faded color cache */ ui_color_cache_t *color_cache; ui_color_cache_t *alt_color_cache; /* for fg, bg, cursor_fg and cursor_bg */ struct sys_color { ui_color_t xcolor; char *name; } sys_colors[10]; u_int8_t alpha; int8_t is_reversed; } ui_color_manager_t; ui_color_manager_t *ui_color_manager_new(ui_display_t *disp, char *fg_color, char *bg_color, char *cursor_fg_color, char *cursor_bg_color, char *bd_color, char *ul_color, char *bl_color, char *rv_color, char *it_color, char *co_color); void ui_color_manager_destroy(ui_color_manager_t *color_man); int ui_color_manager_set_fg_color(ui_color_manager_t *color_man, char *name); int ui_color_manager_set_bg_color(ui_color_manager_t *color_man, char *name); int ui_color_manager_set_cursor_fg_color(ui_color_manager_t *color_man, char *name); int ui_color_manager_set_cursor_bg_color(ui_color_manager_t *color_man, char *name); int ui_color_manager_set_alt_color(ui_color_manager_t *color_man, vt_color_t color, char *name); char *ui_color_manager_get_fg_color(ui_color_manager_t *color_man); char *ui_color_manager_get_bg_color(ui_color_manager_t *color_man); char *ui_color_manager_get_cursor_fg_color(ui_color_manager_t *color_man); char *ui_color_manager_get_cursor_bg_color(ui_color_manager_t *color_man); char *ui_color_manager_get_alt_color(ui_color_manager_t *color_man, vt_color_t color); ui_color_t *ui_get_xcolor(ui_color_manager_t *color_man, vt_color_t color); int ui_color_manager_fade(ui_color_manager_t *color_man, u_int fade_ratio); int ui_color_manager_unfade(ui_color_manager_t *color_man); int ui_color_manager_reverse_video(ui_color_manager_t *color_man); int ui_color_manager_restore_video(ui_color_manager_t *color_man); int ui_color_manager_adjust_cursor_fg_color(ui_color_manager_t *color_man); int ui_color_manager_adjust_cursor_bg_color(ui_color_manager_t *color_man); void ui_color_manager_reload(ui_color_manager_t *color_man); int ui_change_true_transbg_alpha(ui_color_manager_t *color_man, u_int8_t alpha); #endif mlterm-3.8.9/uitoolkit/ui_connect_dialog.h010064400017600000144000000007041356600660700174040ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_CONNECT_DIALOG_H__ #define __UI_CONNECT_DIALOG_H__ #include "ui.h" /* * *uri is always non-NULL if this function returns 1. * *uri is always NULL if this functions returns 0. */ int ui_connect_dialog(char **uri, char **pass, char **exec_cmd, char **privkey, int *x11_fwd, char *display_name, Window parent_window, char *default_server); #endif mlterm-3.8.9/uitoolkit/ui_display.h010064400017600000144000000062361356600660700161070ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_DISPLAY_H__ #define __UI_DISPLAY_H__ #include /* u_int */ #include "ui.h" #include "ui_gc.h" #define XC_nil 1000 /* Defined in ui_window.h */ typedef struct ui_window *ui_window_ptr_t; typedef struct ui_modifier_mapping { u_long serial; XModifierKeymap *map; } ui_modifier_mapping_t; typedef struct ui_display { /* * Public(read only) */ Display *display; /* Don't change position, which pixmap_engine depends on. */ int screen; /* DefaultScreen */ char *name; Window my_window; /* DefaultRootWindow */ #ifdef USE_XLIB /* Only one visual, colormap or depth is permitted per display. */ Visual *visual; Colormap colormap; #endif u_int depth; ui_gc_t *gc; u_int width; u_int height; /* * Private */ ui_window_ptr_t *roots; u_int num_roots; ui_window_ptr_t selection_owner; ui_modifier_mapping_t modmap; #ifdef CHANGEABLE_CURSOR Cursor cursors[3]; #endif } ui_display_t; ui_display_t *ui_display_open(char *disp_name, u_int depth); void ui_display_close(ui_display_t *disp); void ui_display_close_all(void); ui_display_t **ui_get_opened_displays(u_int *num); int ui_display_fd(ui_display_t *disp); int ui_display_show_root(ui_display_t *disp, ui_window_ptr_t root, int x, int y, int hint, char *app_name, Window parent_window); int ui_display_remove_root(ui_display_t *disp, ui_window_ptr_t root); void ui_display_idling(ui_display_t *disp); int ui_display_receive_next_event(ui_display_t *disp); #ifndef NEED_DISPLAY_SYNC_EVERY_TIME #define ui_display_sync(disp) (0) #elif defined(USE_WIN32GUI) #define ui_display_sync(disp) ui_display_receive_next_event(disp) #else void ui_display_sync(ui_display_t *disp); #endif /* * Folloing functions called from ui_window.c */ int ui_display_own_selection(ui_display_t *disp, ui_window_ptr_t win); int ui_display_clear_selection(ui_display_t *disp, ui_window_ptr_t win); XModifierKeymap *ui_display_get_modifier_mapping(ui_display_t *disp); void ui_display_update_modifier_mapping(ui_display_t *disp, u_int serial); XID ui_display_get_group_leader(ui_display_t *disp); #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE void ui_display_set_use_ansi_colors(int use); #else #define ui_display_set_use_ansi_colors(use) (0) #endif #ifdef PSEUDO_COLOR_DISPLAY int ui_display_reset_cmap(void); #else #define ui_display_reset_cmap() (0) #endif #ifdef ROTATABLE_DISPLAY void ui_display_rotate(int rotate); #ifndef MANAGE_ROOT_WINDOWS_BY_MYSELF void ui_display_logical_to_physical_coordinates(ui_display_t *disp, int *x, int *y); #endif #endif #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF void ui_display_reset_input_method_window(void); #endif #ifdef USE_CONSOLE #include void ui_display_set_char_encoding(ui_display_t *disp, vt_char_encoding_t encoding); #ifdef USE_LIBSIXEL void ui_display_set_sixel_colors(ui_display_t *disp, const char *colors); #else #define ui_display_set_sixel_colors(disp, colors) (0) #endif void ui_display_set_default_cell_size(u_int width, u_int height); #endif #ifdef USE_WIN32API void ui_display_trigger_pty_read(void); #endif #endif mlterm-3.8.9/uitoolkit/ui_dnd.h010064400017600000144000000003501356600660700151760ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ /* * Drag and Drop stuff. */ #ifndef __UI_DND_H__ #define __UI_DND_H__ #include "ui_window.h" int ui_dnd_filter_event(XEvent *event, ui_window_t *win); #endif mlterm-3.8.9/uitoolkit/ui_draw_str.c010064400017600000144000001136711356600660700162640ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_draw_str.h" #include /* alloca */ #include #ifndef NO_IMAGE #include "ui_picture.h" #define INLINEPIC_ID(glyph) (((glyph) >> PICTURE_POS_BITS) & (MAX_INLINE_PICTURES - 1)) #define INLINEPIC_POS(glyph) ((glyph) & ((1 << PICTURE_POS_BITS) - 1)) #endif #if 0 #define PERF_DEBUG #endif /* --- static functions --- */ static u_int calculate_char_width(ui_font_t *font, u_int code, ef_charset_t cs, vt_char_t *comb, u_int comb_size, int *draw_alone) { u_int width; width = ui_calculate_char_width(font, code, cs, draw_alone); if (cs == ISO10646_UCS4_1_V) { int w; for (; comb_size > 0; comb_size--, comb++) { #ifdef DEBUG if (vt_char_cs(comb) != ISO10646_UCS4_1_V) { bl_debug_printf(BL_DEBUG_TAG " %x cs is unexpectedly" " combined to ISO10646_UCS4_1_V.\n"); continue; } #endif if ((w = vt_char_get_offset(comb) + (int)vt_char_get_width(comb)) > (int)width) { width = w; } } } return width; } #ifndef USE_CONSOLE static void draw_line(ui_window_t *window, ui_color_t *color, int is_vertical, int line_style, int x, int y, u_int width, u_int height, u_int ascent, int top_margin) { u_int w; u_int h; int x2; int y2; if (is_vertical) { w = 1; h = height; if (line_style == LS_UNDERLINE_DOUBLE) { x2 = x + 2; y2 = y; } else { w += ((ascent - top_margin) / 16); if (line_style == LS_CROSSED_OUT) { x += ((width - 1) / 2); } else if (line_style == LS_OVERLINE) { x += (width - (width >= 2 ? 2 : 1)); } } } else { w = width; h = 1; if (line_style == LS_UNDERLINE_DOUBLE) { x2 = x; if (ascent + 2 >= height) { y2 = y + height - 1; y = y2 - 2; } else { y += ascent; y2 = y + 2; } } else { h += ((ascent - top_margin) / 16); if (line_style == LS_CROSSED_OUT) { y += ((height + 1) / 2); } else if (line_style == LS_OVERLINE) { /* do nothing */ } else { y += ascent; } } } ui_window_fill_with(window, color, x, y, w, h); if (line_style == LS_UNDERLINE_DOUBLE) { ui_window_fill_with(window, color, x2, y2, w, h); } } #endif #ifndef NO_IMAGE static int draw_picture(ui_window_t *window, u_int32_t *glyphs, u_int num_glyphs, int dst_x, int dst_y, u_int ch_width, u_int line_height, ui_color_t *bg_xcolor) { u_int count; ui_inline_picture_t *cur_pic; u_int num_rows; int src_x; int src_y; u_int src_width; u_int src_height; u_int dst_width; int need_clear; int is_end; cur_pic = NULL; is_end = 0; for (count = 0; count < num_glyphs; count++) { ui_inline_picture_t *pic; int pos; int x; u_int w; if (!(pic = ui_get_inline_picture(INLINEPIC_ID(glyphs[count])))) { continue; } /* * XXX * pic->col_width isn't used in this function, so it can be * removed in the future. */ if (pic != cur_pic) { num_rows = (pic->height + pic->line_height - 1) / pic->line_height; } pos = INLINEPIC_POS(glyphs[count]); x = (pos / num_rows) * ch_width; if (x + ch_width > pic->width) { w = pic->width > x ? pic->width - x : 0; } else { w = ch_width; } if (count == 0) { goto new_picture; } else if (w > 0 && pic == cur_pic && src_x + src_width == x) { if (!need_clear && w < ch_width) { if (!bg_xcolor) { ui_window_clear(window, dst_x + dst_width, dst_y, ch_width, line_height); } else { ui_window_fill_with(window, bg_xcolor, dst_x + dst_width, dst_y, ch_width, line_height); } } src_width += w; dst_width += ch_width; if (count + 1 < num_glyphs) { continue; } is_end = 1; } if (need_clear > 0) { if (!bg_xcolor) { ui_window_clear(window, dst_x, dst_y, dst_width, line_height); } else { ui_window_fill_with(window, bg_xcolor, dst_x, dst_y, dst_width, line_height); } } if (src_width > 0 && src_height > 0 #ifndef INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS && cur_pic->disp == window->disp #endif ) { #ifdef __DEBUG bl_debug_printf("Drawing picture at %d %d (pix %p mask %p x %d y %d w %d h %d)\n", dst_x, dst_y, cur_pic->pixmap, cur_pic->mask, src_x, src_y, src_width, src_height); #endif ui_window_copy_area(window, cur_pic->pixmap, cur_pic->mask, src_x, src_y, src_width, src_height, dst_x, dst_y); } if (is_end) { return 1; } dst_x += dst_width; new_picture: src_y = (pos % num_rows) * line_height; src_x = x; dst_width = ch_width; cur_pic = pic; need_clear = 0; if (cur_pic->mask) { need_clear = 1; } if (src_y + line_height > pic->height) { need_clear = 1; src_height = pic->height > src_y ? pic->height - src_y : 0; } else { src_height = line_height; } if (strstr(cur_pic->file_path, "mlterm/animx") && cur_pic->next_frame >= 0) { /* Don't clear if cur_pic is 2nd or later GIF Animation frame. */ need_clear = -1; } if ((src_width = w) < ch_width && !need_clear) { if (!bg_xcolor) { ui_window_clear(window, dst_x, dst_y, ch_width, line_height); } else { ui_window_fill_with(window, bg_xcolor, dst_x, dst_y, ch_width, line_height); } } } if (need_clear > 0) { if (!bg_xcolor) { ui_window_clear(window, dst_x, dst_y, dst_width, line_height); } else { ui_window_fill_with(window, bg_xcolor, dst_x, dst_y, dst_width, line_height); } } #ifdef __DEBUG bl_debug_printf("Drawing picture at %d %d (pix %p mask %p x %d y %d w %d h %d)\n", dst_x, dst_y, cur_pic->pixmap, cur_pic->mask, src_x, src_y, src_width, src_height); #endif if (src_width > 0 && src_height > 0 #ifndef INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS && cur_pic->disp == window->disp #endif ) { ui_window_copy_area(window, cur_pic->pixmap, cur_pic->mask, src_x, src_y, src_width, src_height, dst_x, dst_y); } return 1; } #endif #ifndef USE_CONSOLE static int get_drcs_bitmap(char *glyph, u_int width, int x, int y) { return (glyph[(y / 6) * (width + 1) + x] - '?') & (1 << (y % 6)); } static int draw_drcs(ui_window_t *window, char **glyphs, u_int num_glyphs, int x, int y, u_int ch_width, u_int line_height, ui_color_t *fg_xcolor, int size_attr) { int y_off = 0; if (size_attr >= DOUBLE_HEIGHT_TOP) { if (size_attr == DOUBLE_HEIGHT_BOTTOM) { y_off = line_height; } line_height *= 2; } for (; y_off < line_height; y_off++) { u_int w; int x_off_sum; /* x_off for all glyphs */ int x_off; /* x_off for each glyph */ char *glyph; u_int glyph_width; u_int glyph_height; u_int smpl_width; u_int smpl_height; w = 0; for (x_off_sum = 0; x_off_sum < ch_width * num_glyphs; x_off_sum++) { int left_x; int top_y; int hit; int n_smpl; int smpl_x; int smpl_y; if ((x_off = x_off_sum % ch_width) == 0) { glyph = glyphs[x_off_sum / ch_width]; glyph_width = glyph[0]; glyph_height = glyph[1]; glyph += 2; if ((smpl_width = glyph_width / ch_width + 1) >= 3) { smpl_width = 2; } if ((smpl_height = glyph_height / line_height + 1) >= 3) { smpl_height = 2; } } left_x = (x_off * glyph_width * 10 / ch_width + 5) / 10 - smpl_width / 2; top_y = (y_off * glyph_height * 10 / line_height + 5) / 10 - smpl_height / 2; /* * If top_y < 0 or top_y >= glyph_height, w is always 0 * regardless of content of glyph. */ if (top_y < 0) { top_y = 0; } else if (top_y >= glyph_height) { top_y = glyph_height - 1; } #if 0 bl_debug_printf(BL_DEBUG_TAG "x_off %d: center x %f -> %d\n", x_off, (double)(x_off * glyph_width) / (double)ch_width, left_x + smpl_width / 2); bl_debug_printf(BL_DEBUG_TAG "y_off %d: center y %f -> %d\n", y_off, (double)(y_off * glyph_height) / (double)line_height, top_y + smpl_height / 2); #endif hit = n_smpl = 0; for (smpl_y = 0; smpl_y < smpl_height; smpl_y++) { for (smpl_x = 0; smpl_x < smpl_width; smpl_x++) { if (0 <= left_x + smpl_x && left_x + smpl_x < glyph_width && 0 <= top_y + smpl_y && top_y + smpl_y < glyph_height) { if (get_drcs_bitmap(glyph, glyph_width, left_x + smpl_x, top_y + smpl_y)) { hit++; } n_smpl++; } } } if (n_smpl <= hit * 2) { w++; if (x_off_sum + 1 == ch_width * num_glyphs) { /* for x_off - w */ x_off_sum++; } else { continue; } } else if (w == 0) { continue; } if (size_attr >= DOUBLE_HEIGHT_TOP) { int exp_y; if (size_attr == DOUBLE_HEIGHT_TOP) { if (y_off >= line_height / 2) { return 1; } exp_y = y + y_off; } else { exp_y = y + y_off - line_height / 2; } ui_window_fill_with(window, fg_xcolor, x + x_off_sum - w, exp_y, w, 1); } else { ui_window_fill_with(window, fg_xcolor, x + x_off_sum - w, y + y_off, w, 1); } w = 0; } } return 1; } #endif static int get_state(ef_charset_t ch_cs, u_int32_t ch_code, vt_char_t *comb_chars, u_int32_t *pic_glyph, char **drcs_glyph, int *draw_alone) { #ifndef NO_IMAGE if (comb_chars && vt_char_cs(comb_chars) == PICTURE_CHARSET) { *draw_alone = 0; /* forcibly set 0 regardless of uifont. */ *pic_glyph = vt_char_code(comb_chars) | (vt_char_picture_id(comb_chars) << PICTURE_POS_BITS); *drcs_glyph = NULL; return 4; } else #endif { *pic_glyph = 0; if ((*drcs_glyph = vt_drcs_get_glyph(ch_cs, ch_code))) { *draw_alone = 0; /* forcibly set 0 regardless of uifont. */ return 3; } else { if (comb_chars) { *draw_alone = 1; } if (ch_cs == DEC_SPECIAL) { return 1; } else { return 0; } } } } #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO) static void fc_draw_combining_chars(ui_window_t *window, ui_font_manager_t *font_man, ui_color_t *xcolor, /* fg color */ vt_char_t *chars, u_int size, int x, int y) { u_int count; u_int32_t ch_code; ef_charset_t ch_cs; ui_font_t *uifont; for (count = 0; count < size; count++) { if (vt_char_is_zerowidth(&chars[count])) { continue; } ch_code = vt_char_code(&chars[count]); ch_cs = vt_char_cs(&chars[count]); uifont = ui_get_font(font_man, vt_char_font(&chars[count])); if (ch_cs == DEC_SPECIAL) { u_char c; c = ch_code; ui_window_draw_decsp_string(window, uifont, xcolor, x, y, &c, 1); } /* ISCII characters never have combined ones. */ else if (ch_cs == US_ASCII || ch_cs == ISO8859_1_R /* || IS_ISCII(ch_cs) */) { u_char c; c = ch_code; ui_window_ft_draw_string8(window, uifont, xcolor, x, y, &c, 1); } else { /* FcChar32 */ u_int32_t ucs4; if (ch_cs == ISO10646_UCS4_1_V) { ui_window_ft_draw_string32(window, uifont, xcolor, x + vt_char_get_offset(&chars[count]), y, &ch_code, 1); } else if ((ucs4 = ui_convert_to_xft_ucs4(ch_code, ch_cs))) { ui_window_ft_draw_string32(window, uifont, xcolor, x, y, &ucs4, 1); } } } } static int fc_draw_str(ui_window_t *window, ui_font_manager_t *font_man, ui_color_manager_t *color_man, u_int *updated_width, vt_char_t *chars, u_int num_chars, int x, int y, u_int height, u_int ascent, int top_margin, int hide_underline, int underline_offset) { int count; int start_draw; int end_of_str; u_int current_width; /* FcChar8 */ u_int8_t *str8; /* FcChar32 */ u_int32_t *str32; u_int str_len; u_int32_t ch_code; u_int ch_width; ef_charset_t ch_cs; int state; ui_font_t *uifont; vt_font_t font; vt_color_t fg_color; vt_color_t bg_color; int line_style; vt_char_t *comb_chars; u_int comb_size; int draw_alone; u_int32_t pic_glyph; u_int32_t *pic_glyphs; char *drcs_glyph; char **drcs_glyphs; int next_state; ui_font_t *next_uifont; vt_font_t next_font; vt_color_t next_fg_color; vt_color_t next_bg_color; int next_line_style; vt_char_t *next_comb_chars; u_int next_comb_size; u_int next_ch_width; int next_draw_alone; #ifdef PERF_DEBUG int draw_count = 0; #endif if (num_chars == 0) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " input chars length is 0(ui_window_draw_str).\n"); #endif return 1; } start_draw = 0; end_of_str = 0; count = 0; while (vt_char_is_zerowidth(&chars[count])) { if (++count >= num_chars) { return 1; } } ch_code = vt_char_code(&chars[count]); uifont = ui_get_font(font_man, (font = vt_char_font(&chars[count]))); ch_cs = FONT_CS(font); comb_chars = vt_get_combining_chars(&chars[count], &comb_size); ch_width = calculate_char_width(uifont, ch_code, ch_cs, comb_chars, comb_size, &draw_alone); if ((current_width = x + ch_width) > window->width || y + height > window->height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " draw string outside screen. (x %d w %d y %d h %d)\n", x, ch_width, y, height); #endif return 0; } if ((state = get_state(ch_cs, ch_code, comb_chars, &pic_glyph, &drcs_glyph, &draw_alone)) == 0 && ch_cs != US_ASCII && ch_cs != ISO8859_1_R && !IS_ISCII(ch_cs)) { state = 2; } fg_color = vt_char_fg_color(&chars[count]); bg_color = vt_char_bg_color(&chars[count]); line_style = vt_char_line_style(&chars[count]); if (!(str8 = str32 = pic_glyphs = drcs_glyphs = alloca(BL_MAX(sizeof(*str8), BL_MAX(sizeof(*str32), BL_MAX(sizeof(*pic_glyphs), sizeof(*drcs_glyphs)))) * num_chars))) { return 0; } str_len = 0; while (1) { if (state <= 1) { str8[str_len++] = ch_code; } else if (state >= 3) { if (drcs_glyph) { drcs_glyphs[str_len++] = drcs_glyph; } else /* if( pic_glyph) */ { pic_glyphs[str_len++] = pic_glyph; } } else /* if( state == 2) */ { u_int32_t ucs4; if (!(ucs4 = ui_convert_to_xft_ucs4(ch_code, ch_cs))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " strange character 0x%x, ignored.\n", ch_code); #endif } else { str32[str_len++] = ucs4; } } /* * next character. */ do { if (++count >= num_chars) { start_draw = 1; end_of_str = 1; break; } } while (vt_char_is_zerowidth(&chars[count])); if (!end_of_str) { ch_code = vt_char_code(&chars[count]); next_uifont = ui_get_font(font_man, (next_font = vt_char_font(&chars[count]))); ch_cs = FONT_CS(next_font); next_fg_color = vt_char_fg_color(&chars[count]); next_bg_color = vt_char_bg_color(&chars[count]); next_line_style = vt_char_line_style(&chars[count]); next_comb_chars = vt_get_combining_chars(&chars[count], &next_comb_size); next_ch_width = calculate_char_width(next_uifont, ch_code, ch_cs, next_comb_chars, next_comb_size, &next_draw_alone); if ((next_state = get_state(ch_cs, ch_code, next_comb_chars, &pic_glyph, &drcs_glyph, &next_draw_alone)) == 0 && ch_cs != US_ASCII && ch_cs != ISO8859_1_R && !IS_ISCII(ch_cs)) { next_state = 2; } if (current_width + next_ch_width > window->width) { start_draw = 1; end_of_str = 1; } /* * !! Notice !! * next_uifont != uifont doesn't necessarily detect change of 'state' * (for example, same Unicode font is used for both US_ASCII and * other half-width unicode characters) and 'bold'(ui_get_font() * might substitute normal fonts for bold ones), 'next_state' and * 'font & FONT_BOLD' is necessary. */ else if (next_uifont != uifont || next_fg_color != fg_color || next_bg_color != bg_color || next_line_style != line_style || /* If line_style > 0, line is drawn one by one in vertical mode. */ (line_style && uifont->is_vertical) || state != next_state || draw_alone || next_draw_alone || /* FONT_BOLD flag is not the same. */ ((font ^ next_font) & FONT_BOLD)) { start_draw = 1; } else { start_draw = 0; } } if (start_draw) { /* * status is changed. */ ui_color_t *fg_xcolor; ui_color_t *bg_xcolor; #ifdef PERF_DEBUG draw_count++; #endif bg_xcolor = ui_get_xcolor(color_man, bg_color); #ifndef NO_IMAGE if (state == 4) { draw_picture(window, pic_glyphs, str_len, x, y, ch_width, height, bg_color == VT_BG_COLOR ? NULL : bg_xcolor); goto end_draw; } #endif fg_xcolor = ui_get_xcolor(color_man, fg_color); /* * clearing background */ if (bg_color == VT_BG_COLOR) { if (updated_width) { ui_window_clear(window, x, y, current_width - x, height); } } else { ui_window_fill_with(window, bg_xcolor, x, y, current_width - x, height); } /* * drawing string */ if (fg_color == bg_color) { /* don't draw it */ } else if (state == 0) { ui_window_ft_draw_string8(window, uifont, fg_xcolor, x, y + ascent, str8, str_len); } else if (state == 1) { ui_window_draw_decsp_string(window, uifont, fg_xcolor, x, y + ascent, str8, str_len); } else if (state == 2) { ui_window_ft_draw_string32(window, uifont, fg_xcolor, x, y + ascent, str32, str_len); } else /* if( state == 3) */ { draw_drcs(window, drcs_glyphs, str_len, x, y, ch_width, height, fg_xcolor, font_man->size_attr); } if (comb_chars) { /* * 'current_width' is for some thai fonts which * automatically draw combining chars. * e.g.) * -thai-fixed-medium-r-normal--14-100-100-100-m-70-tis620.2529-1 * (distributed by ZzzThai * http://zzzthai.fedu.uec.ac.jp/ZzzThai/) * win32 unicode font. */ #if 0 fc_draw_combining_chars(window, font_man, fg_xcolor, comb_chars, comb_size, current_width, y + ascent); #else fc_draw_combining_chars(window, font_man, fg_xcolor, comb_chars, comb_size, current_width - ch_width, y + ascent); #endif } if (line_style) { if ((line_style & LS_UNDERLINE) && !hide_underline) { draw_line(window, fg_xcolor, uifont->is_vertical, line_style & LS_UNDERLINE, x, y, current_width - x, height, ascent + underline_offset, top_margin); } if (line_style & LS_CROSSED_OUT) { draw_line(window, fg_xcolor, uifont->is_vertical, LS_CROSSED_OUT, x, y, current_width - x, height, ascent, top_margin); } if (line_style & LS_OVERLINE) { draw_line(window, fg_xcolor, uifont->is_vertical, LS_OVERLINE, x, y, current_width - x, height, ascent, top_margin); } } end_draw: start_draw = 0; x = current_width; str_len = 0; } if (end_of_str) { break; } line_style = next_line_style; uifont = next_uifont; font = next_font; fg_color = next_fg_color; bg_color = next_bg_color; state = next_state; draw_alone = next_draw_alone; comb_chars = next_comb_chars; comb_size = next_comb_size; current_width += (ch_width = next_ch_width); } if (updated_width != NULL) { *updated_width = current_width; } #ifdef PERF_DEBUG bl_debug_printf(" drawing %d times in a line.\n", draw_count); #endif return 1; } #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) #ifndef USE_CONSOLE static int xcore_draw_combining_chars(ui_window_t *window, ui_font_manager_t *font_man, ui_color_t *xcolor, /* fg color */ vt_char_t *chars, u_int size, int x, int y) { u_int count; u_int32_t ch_code; ef_charset_t ch_cs; ui_font_t *uifont; int x_off; for (count = 0; count < size; count++) { if (vt_char_is_zerowidth(&chars[count])) { continue; } ch_code = vt_char_code(&chars[count]); ch_cs = vt_char_cs(&chars[count]); uifont = ui_get_font(font_man, vt_char_font(&chars[count])); if (ch_cs == DEC_SPECIAL) { u_char c; c = ch_code; ui_window_draw_decsp_string(window, uifont, xcolor, x, y, &c, 1); } else { if (ch_cs == ISO10646_UCS4_1_V) { x_off = vt_char_get_offset(&chars[count]); } else { x_off = 0; } if (ch_code < 0x100) { u_char c; c = ch_code; ui_window_draw_string(window, uifont, xcolor, x + x_off, y, &c, 1); } else { /* UCS4 */ /* [2] is for surroage pair. */ XChar2b xch[2]; u_int len; if (IS_ISO10646_UCS4(ch_cs)) { if ((len = ui_convert_ucs4_to_utf16(xch, ch_code) / 2) == 0) { continue; } } else { xch[0].byte1 = (ch_code >> 8) & 0xff; xch[0].byte2 = ch_code & 0xff; len = 1; } ui_window_draw_string16(window, uifont, xcolor, x, y, xch, len); } } } return 1; } #endif static int xcore_draw_str(ui_window_t *window, ui_font_manager_t *font_man, ui_color_manager_t *color_man, u_int *updated_width, vt_char_t *chars, u_int num_chars, int x, int y, u_int height, u_int ascent, int top_margin, int hide_underline, int underline_offset) { int count; int start_draw; int end_of_str; u_int current_width; u_char *str; XChar2b *str2b; u_int str_len; u_int32_t ch_code; ef_charset_t ch_cs; int state; /* 0(8bit),1(decsp),2(16bit) */ vt_char_t *comb_chars; u_int comb_size; u_int ch_width; ui_font_t *uifont; vt_font_t font; vt_color_t fg_color; vt_color_t bg_color; int line_style; int draw_alone; u_int32_t pic_glyph; u_int32_t *pic_glyphs; char *drcs_glyph; char **drcs_glyphs; int next_state; vt_char_t *next_comb_chars; u_int next_comb_size; u_int next_ch_width; ui_font_t *next_uifont; vt_font_t next_font; vt_color_t next_fg_color; vt_color_t next_bg_color; int next_line_style; int next_draw_alone; #ifdef PERF_DEBUG int draw_count = 0; #endif if (num_chars == 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " input chars length is 0(ui_window_draw_str).\n"); #endif return 1; } count = 0; while (vt_char_is_zerowidth(&chars[count])) { if (++count >= num_chars) { return 1; } } start_draw = 0; end_of_str = 0; ch_code = vt_char_code(&chars[count]); uifont = ui_get_font(font_man, (font = vt_char_font(&chars[count]))); ch_cs = FONT_CS(font); comb_chars = vt_get_combining_chars(&chars[count], &comb_size); ch_width = calculate_char_width(uifont, ch_code, ch_cs, comb_chars, comb_size, &draw_alone); if ((current_width = x + ch_width) > window->width || y + height > window->height) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " draw string outside screen. (x %d w %d y %d h %d)\n", x, ch_width, y, height); #endif return 0; } if ((state = get_state(ch_cs, ch_code, comb_chars, &pic_glyph, &drcs_glyph, &draw_alone)) == 0 && ch_code >= 0x100) { state = 2; } fg_color = vt_char_fg_color(&chars[count]); bg_color = vt_char_bg_color(&chars[count]); line_style = vt_char_line_style(&chars[count]); if (!(str2b = str = pic_glyphs = drcs_glyphs = /* '* 2' is for UTF16 surrogate pair. */ alloca(BL_MAX(sizeof(*str2b) * 2, BL_MAX(sizeof(*str), BL_MAX(sizeof(*pic_glyphs), sizeof(*drcs_glyphs)))) * num_chars))) { return 0; } str_len = 0; while (1) { if (state <= 1) { str[str_len++] = ch_code; } else if (state >= 3) { if (pic_glyph) { pic_glyphs[str_len++] = pic_glyph; } else /* if (drcs_glyph) */ { drcs_glyphs[str_len++] = drcs_glyph; } } else if (!IS_ISO10646_UCS4(ch_cs)) { str2b[str_len].byte1 = (ch_code >> 8) & 0xff; str2b[str_len].byte2 = ch_code & 0xff; str_len++; } else { /* UCS4 */ str_len += (ui_convert_ucs4_to_utf16(str2b + str_len, ch_code) / 2); } /* * next character. */ do { if (++count >= num_chars) { start_draw = 1; end_of_str = 1; break; } } while (vt_char_is_zerowidth(&chars[count])); if (!end_of_str) { ch_code = vt_char_code(&chars[count]); next_uifont = ui_get_font(font_man, (next_font = vt_char_font(&chars[count]))); ch_cs = FONT_CS(next_font); next_fg_color = vt_char_fg_color(&chars[count]); next_bg_color = vt_char_bg_color(&chars[count]); next_line_style = vt_char_line_style(&chars[count]); next_comb_chars = vt_get_combining_chars(&chars[count], &next_comb_size); next_ch_width = calculate_char_width(next_uifont, ch_code, ch_cs, next_comb_chars, next_comb_size, &next_draw_alone); if ((next_state = get_state(ch_cs, ch_code, next_comb_chars, &pic_glyph, &drcs_glyph, &next_draw_alone)) == 0 && ch_code >= 0x100) { next_state = 2; } if (current_width + next_ch_width > window->width) { start_draw = 1; end_of_str = 1; } /* * !! Notice !! * next_uifont != uifont doesn't necessarily detect change of 'state' * (for example, same Unicode font is used for both US_ASCII and * other half-width unicode characters) and 'bold'(ui_get_font() * might substitute normal fonts for bold ones), 'next_state' and * 'font & FONT_BOLD' is necessary. */ else if (next_uifont != uifont || next_fg_color != fg_color || next_bg_color != bg_color || next_line_style != line_style || /* If line_style > 0, line is drawn one by one in vertical mode. */ (line_style && uifont->is_vertical) || next_state != state || draw_alone || next_draw_alone || /* FONT_BOLD flag is not the same */ ((font ^ next_font) & FONT_BOLD)) { start_draw = 1; } else { start_draw = 0; } } if (start_draw) { /* * status is changed. */ ui_color_t *fg_xcolor; ui_color_t *bg_xcolor; #ifdef PERF_DEBUG draw_count++; #endif #ifdef DRAW_SCREEN_IN_PIXELS if (ui_window_has_wall_picture(window) && bg_color == VT_BG_COLOR) { bg_xcolor = NULL; } else #endif { bg_xcolor = ui_get_xcolor(color_man, bg_color); } #ifndef NO_IMAGE if (state == 4) { draw_picture(window, pic_glyphs, str_len, x, y, ch_width, height, bg_color == VT_BG_COLOR ? NULL : bg_xcolor); goto end_draw; } #endif fg_xcolor = ui_get_xcolor(color_man, fg_color); #ifdef USE_CONSOLE /* XXX DRCS (state == 3) is ignored */ if (state < 3) { u_int comb_count; for (comb_count = 0; comb_count < comb_size; comb_count++) { u_int comb_code; comb_code = vt_char_code(&comb_chars[comb_count]); if (state <= 1) { str[str_len++] = comb_code; } else if (!IS_ISO10646_UCS4(ch_cs)) { str2b[str_len].byte1 = (comb_code >> 8) & 0xff; str2b[str_len].byte2 = comb_code & 0xff; str_len++; } else { /* UCS4 */ str_len += (ui_convert_ucs4_to_utf16(str2b + str_len, comb_code) / 2); } } /* XXX Wall picture is overwritten by bg_xcolor. */ if (state == 2) { ui_window_console_draw_string16(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str2b, str_len, line_style); } else if (state == 1) { ui_window_console_draw_decsp_string(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str, str_len, line_style); } else /* if( state == 0) */ { ui_window_console_draw_string(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str, str_len, line_style); } } #else /* !USE_CONSOLE */ #ifdef USE_SDL2 if (uifont->height != height || state == 3 || (uifont->is_proportional && ui_window_has_wall_picture(window))) { if (bg_color == VT_BG_COLOR) { ui_window_clear(window, x, y, current_width - x, height); } else { ui_window_fill_with(window, bg_xcolor, x, y, current_width - x, height); } } if (state == 2) { ui_window_draw_image_string16(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str2b, str_len); } else if (state == 1) { ui_window_draw_decsp_image_string(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str, str_len); } else if(state == 0) { ui_window_draw_image_string(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str, str_len); } else /* if( state == 3) */ { draw_drcs(window, drcs_glyphs, str_len, x, y, ch_width, height, fg_xcolor, font_man->size_attr); } #else /* !USE_SDL2 */ #ifndef NO_DRAW_IMAGE_STRING if ( #ifdef DRAW_SCREEN_IN_PIXELS #ifdef USE_FREETYPE /* * ISCII or ISO10646_UCS4_1_V * (see #ifdef USE_FREETYPE #endif in draw_string() in ui_window.c) */ (uifont->is_proportional && ui_window_has_wall_picture(window)) || #endif /* draw_alone || */ /* draw_alone is always false on framebuffer. */ #else /* DRAW_SCREEN_IN_PIXELS */ #if defined(USE_WIN32GUI) && defined(USE_OT_LAYOUT) /* * U+2022 is ambiguous and should be drawn one by one, but * ui_calculate_char_width() can't tell it as ambigous if * use_ot_layout is true because ch_code is glyph index. */ (uifont->use_ot_layout /* && uifont->ot_font */) || #endif (ui_window_has_wall_picture(window) && bg_color == VT_BG_COLOR) || draw_alone || #endif /* DRAW_SCREEN_IN_PIXELS */ uifont->height != height || state == 3) #endif /* NO_DRAW_IMAGE_STRING */ { if (bg_color == VT_BG_COLOR) { ui_window_clear(window, x, y, current_width - x, height); } else { ui_window_fill_with(window, bg_xcolor, x, y, current_width - x, height); } if (fg_color == bg_color) { /* don't draw it */ } else if (state == 2) { ui_window_draw_string16(window, uifont, fg_xcolor, x, y + ascent, str2b, str_len); } else if (state == 1) { ui_window_draw_decsp_string(window, uifont, fg_xcolor, x, y + ascent, str, str_len); } else if (state == 0) { ui_window_draw_string(window, uifont, fg_xcolor, x, y + ascent, str, str_len); } else /* if( state == 3) */ { draw_drcs(window, drcs_glyphs, str_len, x, y, ch_width, height, fg_xcolor, font_man->size_attr); } } #ifndef NO_DRAW_IMAGE_STRING else { if (state == 2) { ui_window_draw_image_string16(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str2b, str_len); } else if (state == 1) { ui_window_draw_decsp_image_string(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str, str_len); } else /* if( state == 0) */ { ui_window_draw_image_string(window, uifont, fg_xcolor, bg_xcolor, x, y + ascent, str, str_len); } } #endif #endif /* USE_SDL2 */ if (comb_chars) { xcore_draw_combining_chars(window, font_man, fg_xcolor, comb_chars, comb_size, /* * 'current_width' is for some thai fonts which automatically * draw combining chars. * e.g.) * -thai-fixed-medium-r-normal--14-100-100-100-m-70-tis620.2529-1 * (distributed by ZzzThai http://zzzthai.fedu.uec.ac.jp/ZzzThai/) * win32 unicode font. */ #if 0 current_width #else current_width - ch_width #endif , y + ascent); } if (line_style) { if ((line_style & LS_UNDERLINE) && !hide_underline) { draw_line(window, fg_xcolor, uifont->is_vertical, line_style & LS_UNDERLINE, x, y, current_width - x, height, ascent + underline_offset, top_margin); } if (line_style & LS_CROSSED_OUT) { draw_line(window, fg_xcolor, uifont->is_vertical, LS_CROSSED_OUT, x, y, current_width - x, height, ascent, top_margin); } if (line_style & LS_OVERLINE) { draw_line(window, fg_xcolor, uifont->is_vertical, LS_OVERLINE, x, y, current_width - x, height, ascent, top_margin); } } #endif /* USE_CONSOLE */ end_draw: start_draw = 0; x = current_width; str_len = 0; } if (end_of_str) { break; } uifont = next_uifont; font = next_font; fg_color = next_fg_color; bg_color = next_bg_color; line_style = next_line_style; state = next_state; draw_alone = next_draw_alone; comb_chars = next_comb_chars; comb_size = next_comb_size; current_width += (ch_width = next_ch_width); } if (updated_width != NULL) { *updated_width = current_width; } #ifdef PERF_DEBUG bl_debug_printf(" drawing %d times in a line.\n", draw_count); #endif return 1; } #endif /* --- global functions --- */ int ui_draw_str(ui_window_t *window, ui_font_manager_t *font_man, ui_color_manager_t *color_man, vt_char_t *chars, u_int num_chars, int x, int y, u_int height, u_int ascent, int top_margin, int hide_underline, int underline_offset) { u_int updated_width; int ret; #ifdef __DEBUG bl_debug_printf("Draw %d characters.\n", num_chars); #endif if (font_man->size_attr >= DOUBLE_HEIGHT_TOP) { ui_window_set_clip(window, x, y, window->width - x, height); ascent = height - (height - ascent) * 2; if (font_man->size_attr == DOUBLE_HEIGHT_TOP) { ascent += height; } } switch (ui_get_type_engine(font_man)) { default: ret = 0; break; #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO) case TYPE_XFT: case TYPE_CAIRO: ret = fc_draw_str(window, font_man, color_man, &updated_width, chars, num_chars, x, y, height, ascent, top_margin, hide_underline, underline_offset); break; #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) case TYPE_XCORE: ret = xcore_draw_str(window, font_man, color_man, &updated_width, chars, num_chars, x, y, height, ascent, top_margin, hide_underline, underline_offset); break; #endif } if (font_man->size_attr >= DOUBLE_HEIGHT_TOP) { ui_window_unset_clip(window); } return ret; } int ui_draw_str_to_eol(ui_window_t *window, ui_font_manager_t *font_man, ui_color_manager_t *color_man, vt_char_t *chars, u_int num_chars, int x, int y, u_int height, u_int ascent, int top_margin, int hide_underline, int underline_offset) { u_int updated_width; int ret; #ifdef __DEBUG bl_debug_printf("Draw %d characters to eol.\n", num_chars); #endif if (font_man->size_attr >= DOUBLE_HEIGHT_TOP) { ui_window_set_clip(window, x, y, window->width - x, height); ascent = height - (height - ascent) * 2; if (font_man->size_attr == DOUBLE_HEIGHT_TOP) { ascent += height; } } switch (ui_get_type_engine(font_man)) { default: ret = 0; break; #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO) case TYPE_XFT: case TYPE_CAIRO: ui_window_clear(window, x, y, window->width - x, height); ret = fc_draw_str( window, font_man, color_man, NULL /* NULL disables ui_window_clear() in fc_draw_str() */, chars, num_chars, x, y, height, ascent, top_margin, hide_underline, underline_offset); break; #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) case TYPE_XCORE: ret = xcore_draw_str(window, font_man, color_man, &updated_width, chars, num_chars, x, y, height, ascent, top_margin, hide_underline, underline_offset); if (updated_width < window->width) { ui_window_clear(window, updated_width, y, window->width - updated_width, height); } break; #endif } if (font_man->size_attr >= DOUBLE_HEIGHT_TOP) { ui_window_unset_clip(window); } return ret; } u_int ui_calculate_vtchar_width(ui_font_t *font, vt_char_t *ch, int *draw_alone) { ef_charset_t cs; vt_char_t *comb; u_int comb_size; if ((cs = FONT_CS(font->id)) == ISO10646_UCS4_1_V) { comb = vt_get_combining_chars(ch, &comb_size); } else { comb = NULL; comb_size = 0; } return calculate_char_width(font, vt_char_code(ch), cs, comb, comb_size, draw_alone); } mlterm-3.8.9/uitoolkit/ui_draw_str.h010064400017600000144000000015721356600660700162650ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_DRAW_STR_H__ #define __UI_DRAW_STR_H__ #include #include "ui_window.h" #include "ui_font_manager.h" #include "ui_color_manager.h" int ui_draw_str(ui_window_t *window, ui_font_manager_t *font_man, ui_color_manager_t *color_man, vt_char_t *chars, u_int num_chars, int x, int y, u_int height, u_int ascent, int top_margin, int hide_underline, int underline_offset); int ui_draw_str_to_eol(ui_window_t *window, ui_font_manager_t *font_man, ui_color_manager_t *color_man, vt_char_t *chars, u_int num_chars, int x, int y, u_int height, u_int ascent, int top_margin, int hide_underline, int underline_offset); u_int ui_calculate_vtchar_width(ui_font_t *font, vt_char_t *ch, int *draw_alone); #endif mlterm-3.8.9/uitoolkit/ui_emoji.c010064400017600000144000000041561356600660700155370ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_emoji.h" #include #include #include #include #include #include #include /* --- static variables --- */ static char *emoji_path; static int emoji_path_type = -1; /* -1: not checked, 0: not exist, 1: dir, 2: font file */ /* --- global functions --- */ void ui_emoji_set_path(const char *path) { struct stat st; free(emoji_path); if (*path == '\0' || stat(path, &st) != 0) { emoji_path = NULL; emoji_path_type = 0; } if (st.st_mode & S_IFDIR) { emoji_path_type = 1; } else { emoji_path_type = 2; } emoji_path = strdup(path); } char *ui_emoji_get_path(u_int32_t code1, u_int32_t code2) { char *file_path; struct stat st; if (emoji_path_type == 0) { return NULL; } if (emoji_path) { /* emoji_path_type == 1 | 2 */ if (!(file_path = malloc(strlen(emoji_path) + 5 + DIGIT_STR_LEN(u_int32_t) * 2 + 1))) { return NULL; } if (code2 > 0) { sprintf(file_path, "%s/%x-%x", emoji_path, code1, code2); } else { sprintf(file_path, "%s/%x", emoji_path, code1); } if (emoji_path_type == 2) { return file_path; } strcat(file_path, ".gif"); } else { if (!(file_path = alloca(18 + DIGIT_STR_LEN(u_int32_t) * 2 + 1))) { return NULL; } if (code2 > 0) { sprintf(file_path, "mlterm/emoji/%x-%x.gif", code1, code2); } else { sprintf(file_path, "mlterm/emoji/%x.gif", code1); } if (!(file_path = bl_get_user_rc_path(file_path))) { return NULL; } } if (stat(file_path, &st) != 0) { strcpy(file_path + strlen(file_path) - 3, "png"); if (stat(file_path, &st) != 0) { if (emoji_path_type == -1) { char *p = strrchr(file_path, '/'); /* always returns non-NULL value */ *p = '\0'; if (stat(file_path, &st) == 0) { emoji_path_type = 1; } else { emoji_path_type = 0; } } free(file_path); return NULL; } } return file_path; } mlterm-3.8.9/uitoolkit/ui_emoji.h010064400017600000144000000003051356600660700155340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include void ui_emoji_set_path(const char *path); char *ui_emoji_get_path(u_int32_t code1, u_int32_t code2); mlterm-3.8.9/uitoolkit/ui_gc.h010064400017600000144000000016311356600660700150250ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_GC_H__ #define __UI_GC_H__ #include /* u_int */ #include "ui.h" typedef struct ui_gc { #ifndef USE_GC int gc; /* dummy */ #else Display *display; GC gc; u_long fg_color; /* alpha bits are always 0 in win32. */ u_long bg_color; /* alpha bits are always 0 in win32. */ Font fid; #ifdef USE_WIN32GUI HPEN pen; HBRUSH brush; #else PixmapMask mask; #endif #endif /* USE_GC */ } ui_gc_t; ui_gc_t *ui_gc_new(Display *display, Drawable drawable); void ui_gc_destroy(ui_gc_t *gc); void ui_gc_set_fg_color(ui_gc_t *gc, u_long fg_color); void ui_gc_set_bg_color(ui_gc_t *gc, u_long bg_color); void ui_gc_set_fid(ui_gc_t *gc, Font fid); #ifdef USE_WIN32GUI void ui_set_gc(ui_gc_t *gc, GC _gc); HPEN ui_gc_set_pen(ui_gc_t *gc, HPEN pen); HBRUSH ui_gc_set_brush(ui_gc_t *gc, HBRUSH brush); #endif #endif mlterm-3.8.9/uitoolkit/ui_event_source.c010064400017600000144000000220221356600660700171250ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_event_source.h" #include /* USE_WIN32API */ #ifndef USE_WIN32API #include /* memset/memcpy */ #include /* timeval */ #include /* select */ #include /* bl_file_set_cloexec */ #endif #include #include /* realloc/free */ #include /* u_int */ #include #include "ui_display.h" #include "ui_screen_manager.h" #if 0 #define __DEBUG #endif #ifdef USE_BEOS void beos_lock(void); void beos_unlock(void); #endif /* --- static variables --- */ #ifndef USE_WIN32API static struct { int fd; void (*handler)(void); } * additional_fds; static u_int num_additional_fds; #endif /* --- static functions --- */ #ifndef NO_DISPLAY_FD static void receive_next_event(void) { u_int count; vt_term_t **terms; u_int num_terms; int xfd; int ptyfd; int maxfd; int ret; fd_set read_fds; struct timeval tval; int is_sending_data = 0; ui_display_t **displays; u_int num_displays; #ifdef USE_LIBSSH2 int *xssh_fds; u_int num_xssh_fds; num_xssh_fds = vt_pty_ssh_get_x11_fds(&xssh_fds); #endif num_terms = vt_get_all_terms(&terms); #ifdef USE_BEOS beos_lock(); #endif while (1) { /* on Linux tv_usec,tv_sec members are zero cleared after select() */ #ifdef KEY_REPEAT_BY_MYSELF static int display_idling_wait = 4; tval.tv_usec = 25000; /* 0.025 sec */ #else tval.tv_usec = 100000; /* 0.1 sec */ #endif tval.tv_sec = 0; #ifdef USE_LIBSSH2 if (vt_pty_ssh_poll(&read_fds) > 0) { /* * Call vt_pty_ssh_send_recv_x11() and vt_term_parse_vt100_sequence() * instead of 'break' here because 'break' here suppresses * checking ui_display etc if use_local_echo option which * stops receive_bytes in vt_term_parse_vt100_sequence() is enabled. */ for (count = num_xssh_fds; count > 0; count--) { vt_pty_ssh_send_recv_x11( count - 1, xssh_fds[count - 1] >= 0 && FD_ISSET(xssh_fds[count - 1], &read_fds)); } for (count = 0; count < num_terms; count++) { ptyfd = vt_term_get_master_fd(terms[count]); #ifdef OPEN_PTY_ASYNC if (ptyfd >= 0) #endif { if (FD_ISSET(ptyfd, &read_fds)) { vt_term_parse_vt100_sequence(terms[count]); } } } } #endif maxfd = -1; FD_ZERO(&read_fds); #ifdef USE_LIBSSH2 for (count = 0; count < num_xssh_fds; count++) { if (xssh_fds[count] >= 0) { FD_SET(xssh_fds[count], &read_fds); if (xssh_fds[count] > maxfd) { maxfd = xssh_fds[count]; } } } #endif displays = ui_get_opened_displays(&num_displays); for (count = 0; count < num_displays; count++) { #ifdef NEED_DISPLAY_SYNC_EVERY_TIME /* * Need to read pending events and to flush events in * output buffer on X11 before waiting in select(). */ ui_display_sync(displays[count]); #endif xfd = ui_display_fd(displays[count]); FD_SET(xfd, &read_fds); if (xfd > maxfd) { maxfd = xfd; } } for (count = 0; count < num_terms; count++) { ptyfd = vt_term_get_master_fd(terms[count]); #ifdef OPEN_PTY_ASYNC if (ptyfd >= 0) #endif { FD_SET(ptyfd, &read_fds); if (ptyfd > maxfd) { maxfd = ptyfd; } if (vt_term_is_sending_data(terms[count])) { tval.tv_usec = 0; is_sending_data = 1; vt_term_parse_vt100_sequence(terms[count]); } } } for (count = 0; count < num_additional_fds; count++) { if (additional_fds[count].fd >= 0) { FD_SET(additional_fds[count].fd, &read_fds); if (additional_fds[count].fd > maxfd) { maxfd = additional_fds[count].fd; } } } #ifdef USE_BEOS beos_unlock(); #endif #ifdef __HAIKU__ if (vt_check_sig_child()) { return; } else #endif if ((ret = select(maxfd + 1, &read_fds, NULL, NULL, &tval)) != 0) { if (ret < 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " error happened in select.\n"); #endif return; } break; } #ifdef USE_BEOS /* UI thread might create a new vt_term by pressing Ctrl+F1 key and so on. */ num_terms = vt_get_all_terms(&terms); beos_lock(); #endif if (is_sending_data) { is_sending_data = 0; continue; } #ifdef KEY_REPEAT_BY_MYSELF /* ui_display_idling() is called every 0.1 sec. */ if (--display_idling_wait > 0) { goto additional_minus_fds; } display_idling_wait = 4; #endif for (count = 0; count < num_displays; count++) { ui_display_idling(displays[count]); } #ifdef KEY_REPEAT_BY_MYSELF additional_minus_fds: #endif /* * additional_fds.handler (-> update_preedit_text -> cand_screen->destroy) of * ibus may destroy ui_display on wayland. */ for (count = 0; count < num_additional_fds; count++) { if (additional_fds[count].fd < 0) { (*additional_fds[count].handler)(); } } } #ifdef USE_BEOS /* UI thread might create a new vt_term by pressing Ctrl+F1 key and so on. */ num_terms = vt_get_all_terms(&terms); beos_lock(); #endif /* * Processing order should be as follows. * * X Window -> PTY -> additional_fds */ for (count = 0; count < num_displays; count++) { if (FD_ISSET(ui_display_fd(displays[count]), &read_fds)) { ui_display_receive_next_event(displays[count]); /* XXX displays pointer may be changed (realloced) */ displays = ui_get_opened_displays(&num_displays); } } #ifdef USE_LIBSSH2 /* * vt_pty_ssh_send_recv_x11() should be called before * vt_term_parse_vt100_sequence() where xssh_fds can be destroyed. */ for (count = num_xssh_fds; count > 0; count--) { vt_pty_ssh_send_recv_x11(count - 1, xssh_fds[count - 1] >= 0 && FD_ISSET(xssh_fds[count - 1], &read_fds)); } #endif for (count = 0; count < num_terms; count++) { ptyfd = vt_term_get_master_fd(terms[count]); #ifdef OPEN_PTY_ASYNC if (ptyfd >= 0) #endif { if (FD_ISSET(ptyfd, &read_fds)) { vt_term_parse_vt100_sequence(terms[count]); } } } for (count = 0; count < num_additional_fds; count++) { if (additional_fds[count].fd >= 0) { if (FD_ISSET(additional_fds[count].fd, &read_fds)) { (*additional_fds[count].handler)(); } } } #ifdef USE_BEOS beos_unlock(); #endif } #endif /* --- global functions --- */ void ui_event_source_init(void) { #ifdef USE_WIN32API vt_pty_ssh_set_pty_read_trigger(ui_display_trigger_pty_read); vt_pty_mosh_set_pty_read_trigger(ui_display_trigger_pty_read); #endif } void ui_event_source_final(void) { #ifndef NO_DISPLAY_FD free(additional_fds); #endif } int ui_event_source_process(void) { #ifdef NO_DISPLAY_FD u_int num_displays; ui_display_t **displays; vt_term_t **terms; u_int num_terms; int *xssh_fds; u_int count; displays = ui_get_opened_displays(&num_displays); for (count = 0; count < num_displays; count++) { ui_display_receive_next_event(displays[count]); } #else receive_next_event(); #endif vt_close_dead_terms(); #ifdef NO_DISPLAY_FD /* * XXX * If pty is closed after vt_close_dead_terms() ... */ #ifdef USE_LIBSSH2 for (count = vt_pty_ssh_get_x11_fds(&xssh_fds); count > 0; count--) { vt_pty_ssh_send_recv_x11(count - 1, 1); } #endif num_terms = vt_get_all_terms(&terms); for (count = 0; count < num_terms; count++) { vt_term_parse_vt100_sequence(terms[count]); if (vt_term_is_sending_data(terms[count])) { ui_display_trigger_pty_read(); } } #ifndef USE_WIN32API for (count = 0; count < num_additional_fds; count++) { (*additional_fds[count].handler)(); } #endif #endif ui_close_dead_screens(); if (ui_get_all_screens(NULL) == 0) { return 0; } return 1; } /* * fd >= 0 -> Normal file descriptor. handler is invoked if fd is ready. * fd < 0 -> Special ID. handler is invoked at interval of 0.1 sec. */ int ui_event_source_add_fd(int fd, void (*handler)(void)) { #ifndef USE_WIN32API void *p; if (!handler) { return 0; } if ((p = realloc(additional_fds, sizeof(*additional_fds) * (num_additional_fds + 1))) == NULL) { return 0; } additional_fds = p; additional_fds[num_additional_fds].fd = fd; additional_fds[num_additional_fds++].handler = handler; if (fd >= 0) { bl_file_set_cloexec(fd); } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " %d is added to additional fds.\n", fd); #endif return 1; #else /* NO_DISPLAY_FD */ return 0; #endif /* NO_DISPLAY_FD */ } void ui_event_source_remove_fd(int fd) { #ifndef USE_WIN32API u_int count; for (count = 0; count < num_additional_fds; count++) { if (additional_fds[count].fd == fd) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Additional fd %d is removed.\n", fd); #endif additional_fds[count] = additional_fds[--num_additional_fds]; return; } } #endif /* NO_DISPLAY_FD */ } mlterm-3.8.9/uitoolkit/ui_event_source.h010064400017600000144000000005251356600660700171360ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_EVENT_SOURCE_H__ #define __UI_EVENT_SOURCE_H__ void ui_event_source_init(void); void ui_event_source_final(void); int ui_event_source_process(void); int ui_event_source_add_fd(int fd, void (*handler)(void)); void ui_event_source_remove_fd(int fd); #endif mlterm-3.8.9/uitoolkit/ui_font.h010064400017600000144000000077111356600660700154070ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_FONT_H__ #define __UI_FONT_H__ /* X11/Xlib.h must be included ahead of Xft.h on XFree86-4.0.x or before. */ #include "ui.h" #include /* u_int */ #include #include "ui_type_engine.h" #define FONT_VERTICAL (FONT_VERT_LTR|FONT_VERT_RTL) typedef enum ui_font_present { FONT_VERT_LTR = 0x1, /* == VERT_LTR */ FONT_VERT_RTL = 0x2, /* == VERT_RTL */ FONT_VAR_WIDTH = 0x4, FONT_AA = 0x8, FONT_NOAA = 0x10, /* Don't specify with FONT_AA */ } ui_font_present_t; typedef struct _XftFont *xft_font_ptr_t; typedef struct _cairo_scaled_font *cairo_scaled_font_ptr_t; typedef struct _FcCharSet *fc_charset_ptr_t; typedef struct _FcPattern *fc_pattern_ptr_t; /* defined in xlib/ui_decsp_font.h */ typedef struct ui_decsp_font *ui_decsp_font_ptr_t; typedef struct ui_font { /* * Private */ Display *display; /* * Public(readonly) */ vt_font_t id; #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) xft_font_ptr_t xft_font; #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) cairo_scaled_font_ptr_t cairo_font; struct { fc_charset_ptr_t charset; void *next; } * compl_fonts; fc_pattern_ptr_t pattern; #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) XFontStruct *xfont; #endif ui_decsp_font_ptr_t decsp_font; #ifdef USE_OT_LAYOUT /* ot_font == NULL and use_ot_layout == true is possible in ISO10646_UCS4_1_V * font. */ void *ot_font; int8_t ot_font_not_found; int8_t use_ot_layout; #endif /* * These members are never zero. */ u_int8_t width; u_int8_t height; u_int8_t ascent; /* This is not zero only when is_proportional is true and xfont is set. */ int8_t x_off; /* * If is_var_col_width is false and is_proportional is true, * characters are drawn one by one. (see {xft_}draw_str()) */ int8_t is_var_col_width; int8_t is_proportional; int8_t is_vertical; int8_t double_draw_gap; int8_t size_attr; } ui_font_t; void ui_compose_dec_special_font(void); #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG) void ui_font_use_fontconfig(void); #endif ui_font_t *ui_font_new(Display *display, vt_font_t id, int size_attr, ui_type_engine_t type_engine, ui_font_present_t font_present, const char *fontname, u_int fontsize, u_int col_width, int use_medium_for_bold, u_int letter_space); void ui_font_destroy(ui_font_t *font); int ui_font_load_xft_font(ui_font_t *font, char *fontname, u_int fontsize, u_int col_width, int use_medium_for_bold); int ui_font_load_xfont(ui_font_t *font, char *fontname, u_int fontsize, u_int col_width, int use_medium_for_bold); u_int ui_calculate_char_width(ui_font_t *font, u_int32_t ch, ef_charset_t cs, int *draw_alone); int ui_font_has_ot_layout_table(ui_font_t *font); u_int ui_convert_text_to_glyphs(ui_font_t *font, u_int32_t *shaped, u_int shaped_len, int8_t *offsets, u_int8_t *widths, u_int32_t *cmapped, u_int32_t *src, u_int src_len, const char *script, const char *features); #ifdef USE_XLIB char **ui_font_get_encoding_names(ef_charset_t cs); #else #define ui_font_get_encoding_names(cs) (0) #endif #if defined(USE_XLIB) || defined(USE_WAYLAND) /* For mlterm-libvte */ void ui_font_set_dpi_for_fc(double dpi); #endif #ifdef SUPPORT_POINT_SIZE_FONT void ui_font_use_point_size(int use); #else #define ui_font_use_point_size(bool) (0) #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO) void ui_use_cp932_ucs_for_xft(void); u_int32_t ui_convert_to_xft_ucs4(u_int32_t ch, ef_charset_t cs); #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) size_t ui_convert_ucs4_to_utf16(u_char *utf16, u_int32_t ucs4); #endif #ifdef DEBUG void ui_font_dump(ui_font_t *font); #endif #endif mlterm-3.8.9/uitoolkit/ui_font_cache.c010064400017600000144000000247461356600660700165340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_font_cache.h" #include /* sprintf */ #include /* DIGIT_STR_LEN */ /* --- static variables --- */ static ui_font_cache_t **font_caches; static u_int num_caches; static int leftward_double_drawing; /* --- static functions --- */ #ifdef DEBUG static void dump_cached_fonts(ui_font_cache_t *font_cache) { u_int count; u_int size; BL_PAIR(ui_font) * f_array; bl_debug_printf(BL_DEBUG_TAG " cached fonts info\n"); bl_map_get_pairs_array(font_cache->uifont_table, f_array, size); for (count = 0; count < size; count++) { if (f_array[count]->value != NULL) { ui_font_dump(f_array[count]->value); } } } #endif /* * Call this function after init all members except font_table */ static int init_usascii_font(ui_font_cache_t *font_cache) { return (font_cache->usascii_font = ui_font_cache_get_font( font_cache, NORMAL_FONT_OF(font_cache->usascii_font_cs))) != NULL; } static BL_MAP(ui_font) uifont_table_new(void) { BL_MAP(ui_font) uifont_table; bl_map_new_with_size(vt_font_t, ui_font_t*, uifont_table, bl_map_hash_int, bl_map_compare_int, 16); return uifont_table; } static void uifont_table_destroy(BL_MAP(ui_font) uifont_table, ui_font_t *exception) { u_int count; u_int size; BL_PAIR(ui_font) * f_array; bl_map_get_pairs_array(uifont_table, f_array, size); for (count = 0; count < size; count++) { if (f_array[count]->value != NULL && f_array[count]->value != exception) { ui_font_destroy(f_array[count]->value); } } bl_map_destroy(uifont_table); } #ifdef USE_XLIB static char *get_font_name_list_for_fontset(ui_font_cache_t *font_cache) { char *font_name_list; char *p; size_t list_len; if (font_cache->font_config->type_engine != TYPE_XCORE) { ui_font_config_t *font_config; if ((font_config = ui_acquire_font_config( TYPE_XCORE, font_cache->font_config->font_present & ~FONT_AA)) == NULL) { font_name_list = NULL; } else { font_name_list = ui_get_config_font_names_all(font_config, font_cache->font_size); ui_release_font_config(font_config); } } else { font_name_list = ui_get_config_font_names_all(font_cache->font_config, font_cache->font_size); } if (font_name_list) { list_len = strlen(font_name_list); } else { list_len = 0; } if ((p = malloc(list_len + 29 + DIGIT_STR_LEN(font_cache->font_size) + 1)) == NULL) { return font_name_list; } if (font_name_list) { sprintf(p, "%s,-*-*-medium-r-*-*-%d-*-*-*-*-*", font_name_list, font_cache->font_size); free(font_name_list); } else { sprintf(p, "-*-*-medium-r-*-*-%d-*-*-*-*-*", font_cache->font_size); } return p; } #endif /* --- global functions --- */ void ui_set_use_leftward_double_drawing(int use) { if (num_caches > 0) { bl_msg_printf("Unable to change leftward_double_drawing option.\n"); } else { leftward_double_drawing = use; } } ui_font_cache_t *ui_acquire_font_cache(Display *display, u_int font_size, ef_charset_t usascii_font_cs, ui_font_config_t *font_config, u_int letter_space) { int count; ui_font_cache_t *font_cache; void *p; for (count = 0; count < num_caches; count++) { if (font_caches[count]->display == display && font_caches[count]->font_size == font_size && font_caches[count]->usascii_font_cs == usascii_font_cs && font_caches[count]->font_config == font_config && font_caches[count]->letter_space == letter_space) { font_caches[count]->ref_count++; return font_caches[count]; } } if ((p = realloc(font_caches, sizeof(ui_font_cache_t*) * (num_caches + 1))) == NULL) { return NULL; } font_caches = p; if ((font_cache = malloc(sizeof(ui_font_cache_t))) == NULL) { return NULL; } font_cache->font_config = font_config; font_cache->uifont_table = uifont_table_new(); font_cache->display = display; font_cache->font_size = font_size; font_cache->usascii_font_cs = usascii_font_cs; font_cache->letter_space = letter_space; font_cache->ref_count = 1; font_cache->prev_cache.font = 0; font_cache->prev_cache.uifont = NULL; if (!init_usascii_font(font_cache)) { uifont_table_destroy(font_cache->uifont_table, NULL); free(font_cache); return NULL; } return font_caches[num_caches++] = font_cache; } void ui_release_font_cache(ui_font_cache_t *font_cache) { int count; if (--font_cache->ref_count > 0) { return; } for (count = 0; count < num_caches; count++) { if (font_caches[count] == font_cache) { font_caches[count] = font_caches[--num_caches]; uifont_table_destroy(font_cache->uifont_table, NULL); free(font_cache); if (num_caches == 0) { free(font_caches); font_caches = NULL; } return; } } } void ui_font_cache_unload(ui_font_cache_t *font_cache) { ui_font_t *prev_usascii_font; /* * Discarding existing cache. */ uifont_table_destroy(font_cache->uifont_table, font_cache->usascii_font); prev_usascii_font = font_cache->usascii_font; font_cache->usascii_font = NULL; font_cache->prev_cache.font = 0; font_cache->prev_cache.uifont = NULL; /* * Creating new cache. */ font_cache->uifont_table = uifont_table_new(); if (!init_usascii_font(font_cache)) { int result; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " ui_font_cache_unload() failed. Use old usascii font.\n"); #endif font_cache->usascii_font = prev_usascii_font; bl_map_set(result, font_cache->uifont_table, NORMAL_FONT_OF(font_cache->usascii_font_cs), prev_usascii_font); } else { ui_font_destroy(prev_usascii_font); } } void ui_font_cache_unload_all(void) { u_int count; for (count = 0; count < num_caches; count++) { ui_font_cache_unload(font_caches[count]); } } ui_font_t *ui_font_cache_get_font(ui_font_cache_t *font_cache, vt_font_t font) { ui_font_present_t font_present; vt_font_t font_for_config; int result; ui_font_t *uifont; BL_PAIR(ui_font) fn_pair; char *fontname; int use_medium_for_bold; u_int col_width; int size_attr; font_present = font_cache->font_config->font_present; if (FONT_CS(font) == US_ASCII) { font &= ~US_ASCII; font |= font_cache->usascii_font_cs; font_for_config = font; } else { font_for_config = font; if (FONT_CS(font) == ISO10646_UCS4_1_V) { font_present |= FONT_VAR_WIDTH; font_for_config &= ~ISO10646_UCS4_1_V; font_for_config |= ISO10646_UCS4_1; } } if (font_cache->prev_cache.uifont && font_cache->prev_cache.font == font) { return font_cache->prev_cache.uifont; } bl_map_get(font_cache->uifont_table, font, fn_pair); if (fn_pair) { return fn_pair->value; } if (font == NORMAL_FONT_OF(font_cache->usascii_font_cs)) { col_width = 0; } else { col_width = font_cache->usascii_font->width; } use_medium_for_bold = 0; if ((fontname = ui_get_config_font_name(font_cache->font_config, font_cache->font_size, font_for_config)) == NULL) { vt_font_t next_font; int scalable; next_font = font_for_config; #ifndef TYPE_XCORE_SCALABLE if (font_cache->font_config->type_engine == TYPE_XCORE) { /* * If the type engine doesn't support scalable fonts, * medium weight font (drawn doubly) is used for bold. */ scalable = 0; } else #endif { /* * If the type engine supports scalable fonts, * the face of medium weight / r slant font is used * for bold and italic. */ scalable = 1; } while (next_font & (FONT_BOLD | FONT_ITALIC)) { if (next_font & FONT_BOLD) { next_font &= ~FONT_BOLD; } else /* if(next_font & FONT_ITALIC) */ { if (!scalable) { break; } next_font &= ~FONT_ITALIC; } if ((fontname = ui_get_config_font_name(font_cache->font_config, font_cache->font_size, next_font))) { if ((font & FONT_BOLD) && !scalable) { use_medium_for_bold = 1; } goto found; } } } found: size_attr = SIZE_ATTR_OF(font); if ((uifont = ui_font_new(font_cache->display, NO_SIZE_ATTR(font), size_attr, font_cache->font_config->type_engine, font_present, fontname, font_cache->font_size, col_width, use_medium_for_bold, font_cache->letter_space)) || (size_attr && (uifont = ui_font_new(font_cache->display, NORMAL_FONT_OF(font_cache->usascii_font_cs), size_attr, font_cache->font_config->type_engine, font_present, fontname, font_cache->font_size, col_width, use_medium_for_bold, font_cache->letter_space)))) { if (uifont->double_draw_gap && leftward_double_drawing) { uifont->double_draw_gap = -1; } } #ifdef DEBUG else { bl_warn_printf(BL_DEBUG_TAG " font for id %x doesn't exist.\n", font); } #endif free(fontname); /* * If this font doesn't exist, NULL(which indicates it) is cached. */ bl_map_set(result, font_cache->uifont_table, font, uifont); font_cache->prev_cache.font = font; font_cache->prev_cache.uifont = uifont; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Font %x for id %x was cached.%s\n", uifont, font, use_medium_for_bold ? "(medium font is used for bold.)" : ""); #endif return uifont; } XFontSet ui_font_cache_get_fontset(ui_font_cache_t *font_cache) { #if defined(USE_XLIB) XFontSet fontset; char *list_str; char **missing; int miss_num; char *def_str; if ((list_str = get_font_name_list_for_fontset(font_cache)) == NULL) { return None; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " font set list -> %s\n", list_str); #endif fontset = XCreateFontSet(font_cache->display, list_str, &missing, &miss_num, &def_str); free(list_str); #ifdef DEBUG if (miss_num) { int count; bl_warn_printf(BL_DEBUG_TAG " missing charsets ...\n"); for (count = 0; count < miss_num; count++) { bl_msg_printf(" %s\n", missing[count]); } } #endif XFreeStringList(missing); return fontset; #elif defined(USE_WIN32GUI) static LOGFONT logfont; ZeroMemory(&logfont, sizeof(logfont)); GetObject(font_cache->usascii_font->xfont->fid, sizeof(logfont), &logfont); return &logfont; #else return None; #endif } mlterm-3.8.9/uitoolkit/ui_font_cache.h010064400017600000144000000024041356600660700165240ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_FONT_CACHE_H__ #define __UI_FONT_CACHE_H__ #include "ui.h" #include #include #include #include "ui_font_config.h" BL_MAP_TYPEDEF(ui_font, vt_font_t, ui_font_t *); typedef struct ui_font_cache { /* * Public(readonly) */ Display *display; u_int font_size; ef_charset_t usascii_font_cs; ui_font_config_t *font_config; u_int8_t letter_space; ui_font_t *usascii_font; /* * Private */ BL_MAP(ui_font) uifont_table; struct { vt_font_t font; ui_font_t *uifont; } prev_cache; u_int ref_count; } ui_font_cache_t; void ui_set_use_leftward_double_drawing(int use); ui_font_cache_t *ui_acquire_font_cache(Display *display, u_int font_size, ef_charset_t usascii_font_cs, ui_font_config_t *font_config, u_int letter_space); void ui_release_font_cache(ui_font_cache_t *font_cache); void ui_font_cache_unload(ui_font_cache_t *font_cache); void ui_font_cache_unload_all(void); ui_font_t *ui_font_cache_get_font(ui_font_cache_t *font_cache, vt_font_t font); XFontSet ui_font_cache_get_fontset(ui_font_cache_t *font_cache); #endif mlterm-3.8.9/uitoolkit/ui_font_config.c010064400017600000144000000776771356600660700167510ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_font_config.h" #include /* memset */ #include /* malloc */ #include /* strdup */ #include /* DIGIT_STR_LEN */ #include #include #include #include #include /* vt_parse_unicode_area */ #define DEFAULT_FONT 0x1ff /* MAX_CHARSET */ #if 0 #define __DEBUG #endif typedef struct cs_table { char *name; ef_charset_t cs; } cs_table_t; typedef struct custom_cache { const char *file; char *key; char *value; } custom_cache_t; /* --- static variables --- */ #if defined(USE_FRAMEBUFFER) || defined(USE_CONSOLE) || defined(USE_WAYLAND) || defined(USE_SDL2) #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG) static int use_aafont; #define FONT_FILE (use_aafont ? aafont_file + 7 : "font") #define VFONT_FILE (use_aafont ? vaafont_file + 7 : "vfont") #define TFONT_FILE (use_aafont ? taafont_file + 7 : "tfont") #else #define FONT_FILE "font" #define VFONT_FILE "vfont" #define TFONT_FILE "tfont" #endif static char *font_file = "mlterm/font-fb"; static char *vfont_file = "mlterm/vfont-fb"; static char *tfont_file = "mlterm/tfont-fb"; #else #define FONT_FILE (font_file + 7) #define VFONT_FILE (vfont_file + 7) #define TFONT_FILE (tfont_file + 7) static char *font_file = "mlterm/font"; static char *vfont_file = "mlterm/vfont"; static char *tfont_file = "mlterm/tfont"; #endif static char *aafont_file = "mlterm/aafont"; static char *vaafont_file = "mlterm/vaafont"; static char *taafont_file = "mlterm/taafont"; /* * If this table is changed, ui_font.c:cs_info_table and mc_font.c:cs_info_table * shoule be also changed. */ static cs_table_t cs_table[] = { {"ISO10646_UCS4_1", ISO10646_UCS4_1}, {"DEC_SPECIAL", DEC_SPECIAL}, {"ISO8859_1", ISO8859_1_R}, {"ISO8859_2", ISO8859_2_R}, {"ISO8859_3", ISO8859_3_R}, {"ISO8859_4", ISO8859_4_R}, {"ISO8859_5", ISO8859_5_R}, {"ISO8859_6", ISO8859_6_R}, {"ISO8859_7", ISO8859_7_R}, {"ISO8859_8", ISO8859_8_R}, {"ISO8859_9", ISO8859_9_R}, {"ISO8859_10", ISO8859_10_R}, {"TIS620", TIS620_2533}, {"ISO8859_13", ISO8859_13_R}, {"ISO8859_14", ISO8859_14_R}, {"ISO8859_15", ISO8859_15_R}, {"ISO8859_16", ISO8859_16_R}, {"TCVN5712", TCVN5712_3_1993}, {"ISCII_ASSAMESE", ISCII_ASSAMESE}, {"ISCII_BENGALI", ISCII_BENGALI}, {"ISCII_GUJARATI", ISCII_GUJARATI}, {"ISCII_HINDI", ISCII_HINDI}, {"ISCII_KANNADA", ISCII_KANNADA}, {"ISCII_MALAYALAM", ISCII_MALAYALAM}, {"ISCII_ORIYA", ISCII_ORIYA}, {"ISCII_PUNJABI", ISCII_PUNJABI}, {"ISCII_TAMIL", ISCII_TAMIL}, {"ISCII_TELUGU", ISCII_TELUGU}, {"VISCII", VISCII}, {"KOI8_R", KOI8_R}, {"KOI8_U", KOI8_U}, #if 0 /* * Koi8_t and georgian_ps charsets can be shown by unicode font only. */ {"KOI8_T", KOI8_T}, {"GEORGIAN_PS", GEORGIAN_PS}, #endif #ifdef USE_WIN32GUI {"CP1250", CP1250}, {"CP1251", CP1251}, {"CP1252", CP1252}, {"CP1253", CP1253}, {"CP1254", CP1254}, {"CP1255", CP1255}, {"CP1256", CP1256}, {"CP1257", CP1257}, {"CP1258", CP1258}, #endif {"JISX0201_KATA", JISX0201_KATA}, {"JISX0201_ROMAN", JISX0201_ROMAN}, {"JISX0208_1978", JISC6226_1978}, {"JISC6226_1978", JISC6226_1978}, {"JISX0208_1983", JISX0208_1983}, {"JISX0208_1990", JISX0208_1990}, {"JISX0212_1990", JISX0212_1990}, {"JISX0213_2000_1", JISX0213_2000_1}, {"JISX0213_2000_2", JISX0213_2000_2}, {"KSC5601_1987", KSC5601_1987}, {"KSX1001_1997", KSC5601_1987}, #if 0 /* * XXX * UHC and JOHAB fonts are not used at the present time. * see vt_vt100_parser.c:vt_parse_vt100_sequence(). */ {"UHC", UHC}, {"JOHAB", JOHAB}, #endif {"GB2312_80", GB2312_80}, {"GBK", GBK}, {"BIG5", BIG5}, {"HKSCS", HKSCS}, {"CNS11643_1992_1", CNS11643_1992_1}, {"CNS11643_1992_2", CNS11643_1992_2}, {"CNS11643_1992_3", CNS11643_1992_3}, {"CNS11643_1992_4", CNS11643_1992_4}, {"CNS11643_1992_5", CNS11643_1992_5}, {"CNS11643_1992_6", CNS11643_1992_6}, {"CNS11643_1992_7", CNS11643_1992_7}, }; static ui_font_config_t **font_configs; static u_int num_configs; /* * These will be leaked unless change_custom_cache( ... , "") deletes them. * change_custom_cache( ... , "") is called only from save_conf, which means * that they are deleted when all of them are saved to ~/.mlterm/(vt)(aa)font * file. */ static custom_cache_t *custom_cache; static u_int num_customs; /* --- static functions --- */ static BL_PAIR(ui_font_name) get_font_name_pair(BL_MAP(ui_font_name) table, vt_font_t font) { BL_PAIR(ui_font_name) pair; bl_map_get(table, font, pair); return pair; } static BL_PAIR(ui_font_name) * get_font_name_pairs_array(u_int *size, BL_MAP(ui_font_name) table) { BL_PAIR(ui_font_name) * array; bl_map_get_pairs_array(table, array, *size); return array; } static int set_font_name_to_table(BL_MAP(ui_font_name) table, vt_font_t font, char *fontname) { int result; bl_map_set(result, table, font, fontname); return result; } static vt_font_t parse_key(const char *key) { int count; size_t key_len; ef_charset_t cs; vt_font_t font; key_len = strlen(key); if (key_len >= 7 && strncmp(key, "DEFAULT", 7) == 0) { if (key_len >= 8) { bl_warn_printf("Illegal charset for font: %s.\n", key); return UNKNOWN_CS; } font = DEFAULT_FONT; goto check_style; } if (key_len >= 3 && strncmp(key, "U+", 2) == 0) { u_int min; u_int max; if (vt_parse_unicode_area(key, &min, &max) && (font = vt_get_unicode_area_font(min, max)) != UNKNOWN_CS) { goto check_style; } else { return UNKNOWN_CS; } } for (count = 0; count < sizeof(cs_table) / sizeof(cs_table[0]); count++) { size_t nlen; nlen = strlen(cs_table[count].name); if (key_len >= nlen && strncmp(cs_table[count].name, key, nlen) == 0 && (key[nlen] == '\0' || /* "_BOLD" or "_FULLWIDTH" is trailing */ key[nlen] == '_')) { cs = cs_table[count].cs; break; } } if (count == sizeof(cs_table) / sizeof(cs_table[0])) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " %s is not valid charset.\n", key); #endif return UNKNOWN_CS; } font = NORMAL_FONT_OF(cs); if (!(font & FONT_FULLWIDTH) && (strstr(key, "_BIWIDTH") || /* XXX compat with 3.2.2 or before. */ strstr(key, "_FULLWIDTH"))) { font |= FONT_FULLWIDTH; } check_style: if (strstr(key, "_BOLD")) { font |= FONT_BOLD; } if (strstr(key, "_ITALIC")) { font |= FONT_ITALIC; } return font; } static void parse_value(char **font_name, /* if value is "" or illegal format, not changed. */ char *value /* Don't specify NULL. */ ) { #if 1 /* XXX Compat with old format (3.6.3 or before): [size],[font name] */ char *p; if ('0' <= *value && *value <= '9' && (p = strchr(value, ','))) { value = p + 1; } #endif *font_name = value; } /* * * 1: Valid "%d" or no '%' is found. * 0: Invalid '%' is found. */ static int is_valid_font_format(const char *format) { char *p; if ((p = strchr(format, '%'))) { /* force to be '%d' */ if (p[1] != 'd') { return 0; } /* '%' can happen only once at most */ if (p != strrchr(format, '%')) { return 0; } } return 1; } /* * * 0: Not changed(including the case of failure). * 1: Succeeded. */ static int customize_font_name(ui_font_config_t *font_config, vt_font_t font, const char *fontname) { BL_PAIR(ui_font_name) pair; if (is_valid_font_format(fontname) == 0) { bl_msg_printf("%s is invalid format for font name.\n"); return 0; } if ((pair = get_font_name_pair(font_config->font_name_table, font))) { if (*fontname == '\0') { int result; /* Curent setting in font_config is removed. */ free(pair->value); bl_map_erase_simple(result, font_config->font_name_table, font); } else if (strcmp(pair->value, fontname) != 0) { char *value; if ((value = strdup(fontname)) == NULL) { return 0; } free(pair->value); pair->value = value; } else { /* If new fontname is the same as current one, nothing is done. */ return 0; } } else { char *value; if (*fontname == '\0' || (value = strdup(fontname)) == NULL) { return 0; } set_font_name_to_table(font_config->font_name_table, font, value); } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Set %x font => fontname %s.\n", font, fontname); #endif return 1; } static int parse_conf(ui_font_config_t *font_config, const char *key, const char *value /* value = "" or ";" => Reset font name. */ ) { vt_font_t font; char *font_name; if ((font = parse_key(key)) == UNKNOWN_CS || (font_name = alloca(strlen(value) + 1)) == NULL) { return 0; } strcpy(font_name, value); /* * XXX * Compat with old formats (3.6.3 or before): [default font name];[font size],[font name];... */ #if 1 { const char *p = value; while ((p = strchr(p, ';'))) { p++; if (('0' <= *p && *p <= '9') || *p == '\0') { font_name[p - value - 1] = '\0'; break; } } } #endif parse_value(&font_name, font_name); customize_font_name(font_config, font, font_name); return 1; } static int apply_custom_cache(ui_font_config_t *font_config, const char *filename) { u_int count; for (count = 0; count < num_customs; count++) { if (filename == custom_cache[count].file) { #ifdef __DEBUG bl_debug_printf("Appling customization %s=%s\n", custom_cache[count].key, custom_cache[count].value); #endif parse_conf(font_config, custom_cache[count].key, custom_cache[count].value); } } return 1; } static int read_conf(ui_font_config_t *font_config, const char *filename) { bl_file_t *from; char *key; char *value; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " read_conf( %s)\n", filename); #endif if (!(from = bl_file_open(filename, "r"))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " %s couldn't be opened.\n", filename); #endif return 0; } while (bl_conf_io_read(from, &key, &value)) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Read line from %s => %s = %s\n", filename, key, value); #endif parse_conf(font_config, key, value); } bl_file_close(from); return 1; } static int read_all_conf(ui_font_config_t *font_config, const char *changed_font_file /* If this function is * called after a font * file is * changed, specify it * here to avoid re-read * font files. * Otherwise specify * NULL. */ ) { char *font_rcfile; char *font_rcfile2; /* prior to font_rcfile */ char *rcpath; #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG) if (use_aafont) #else /* '>= XFT' means XFT or Cairo */ if (font_config->type_engine >= TYPE_XFT) #endif { font_rcfile = aafont_file; switch (font_config->font_present & ~FONT_AA) { default: font_rcfile2 = NULL; break; case FONT_VAR_WIDTH: font_rcfile2 = vaafont_file; break; case FONT_VERTICAL: font_rcfile2 = taafont_file; break; } } else { font_rcfile = font_file; switch (font_config->font_present & ~FONT_AA) { default: font_rcfile2 = NULL; break; case FONT_VAR_WIDTH: font_rcfile2 = vfont_file; break; case FONT_VERTICAL: font_rcfile2 = tfont_file; break; } } if (!changed_font_file) { if ((rcpath = bl_get_sys_rc_path(font_rcfile))) { read_conf(font_config, rcpath); free(rcpath); } } if (!changed_font_file || changed_font_file == font_rcfile) { if ((rcpath = bl_get_user_rc_path(font_rcfile))) { read_conf(font_config, rcpath); free(rcpath); } } apply_custom_cache(font_config, font_rcfile); if (font_rcfile2) { if (!changed_font_file) { if ((rcpath = bl_get_sys_rc_path(font_rcfile2))) { read_conf(font_config, rcpath); free(rcpath); } } if ((rcpath = bl_get_user_rc_path(font_rcfile2))) { read_conf(font_config, rcpath); free(rcpath); } apply_custom_cache(font_config, font_rcfile2); } return 1; } static int change_custom_cache(const char *file, const char *key, const char *value) { void *p; u_int count; for (count = 0; count < num_customs; count++) { if (custom_cache[count].file == file && strcmp(custom_cache[count].key, key) == 0) { if (*value) { /* replace */ char *p; if (strcmp(custom_cache[count].value, value) == 0) { /* not changed */ return 0; } if ((p = strdup(value))) { free(custom_cache[count].value); custom_cache[count].value = p; } } else { /* remove */ free(custom_cache[count].key); free(custom_cache[count].value); custom_cache[count] = custom_cache[--num_customs]; if (num_customs == 0) { free(custom_cache); custom_cache = NULL; #ifdef __DEBUG bl_debug_printf("Custom cache is completely freed.\n"); #endif } } return 1; } } /* #if 1 => Don't remove font settings read from *font files in ~/.mlterm */ #if 0 if (*value == '\0') { return 0; } #endif if ((p = realloc(custom_cache, sizeof(custom_cache_t) * (num_customs + 1))) == NULL) { return 0; } custom_cache = p; if ((custom_cache[num_customs].key = strdup(key)) == NULL) { return 0; } if ((custom_cache[num_customs].value = strdup(value)) == NULL) { free(custom_cache[num_customs].key); return 0; } custom_cache[num_customs++].file = file; #ifdef __DEBUG bl_debug_printf("%s=%s is newly added to custom cache.\n", key, value); #endif return 1; } static int write_conf(char *path, /* Can be destroyed in this function. */ const char *key, const char *value) { bl_conf_write_t *conf; if (!(conf = bl_conf_write_open(path))) { return 0; } bl_conf_io_write(conf, key, value); bl_conf_write_close(conf); return 1; } static int save_conf(const char *file, const char *key, char *value /* Includes multiple entries. Destroyed in this function. */ ) { char *path; int ret; if ((path = bl_get_user_rc_path(file)) == NULL) { return 0; } if ((ret = write_conf(path, key, value))) { /* Remove from custom_cache */ change_custom_cache(file, key, ""); } free(path); return ret; } static ui_font_config_t *find_font_config(ui_type_engine_t type_engine, ui_font_present_t font_present) { if (font_configs) { u_int count; for (count = 0; count < num_configs; count++) { if (font_configs[count]->font_present == font_present && font_configs[count]->type_engine == type_engine) { return font_configs[count]; } } } return NULL; } static u_int match_font_configs(ui_font_config_t **matched_configs, u_int max_size, /* must be over 0. */ int is_xcore, ui_font_present_t present_mask) { u_int count; u_int size; size = 0; for (count = 0; count < num_configs; count++) { if ( #if !defined(USE_FREETYPE) || !defined(USE_FONTCONFIG) (is_xcore ? font_configs[count]->type_engine == TYPE_XCORE : /* '>= XFT' means XFT or Cairo */ font_configs[count]->type_engine >= TYPE_XFT) && #endif (present_mask ? (font_configs[count]->font_present & present_mask) : 1)) { matched_configs[size++] = font_configs[count]; if (size >= max_size) { break; } } } return size; } static ui_font_config_t *create_shared_font_config(ui_type_engine_t type_engine, ui_font_present_t font_present) { u_int count; for (count = 0; count < num_configs; count++) { if ((type_engine == TYPE_XCORE ? font_configs[count]->type_engine == TYPE_XCORE : /* '>= XFT' means XFT or Cairo */ font_configs[count]->type_engine >= TYPE_XFT) && ((font_configs[count]->font_present & ~FONT_AA) == (font_present & ~FONT_AA))) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Found sharable font_config.\n"); #endif ui_font_config_t *font_config; if ((font_config = malloc(sizeof(ui_font_config_t))) == NULL) { return NULL; } font_config->type_engine = type_engine; font_config->font_present = font_present; font_config->font_name_table = font_configs[count]->font_name_table; font_config->ref_count = 0; return font_config; } } return NULL; } static void new_table(ui_font_config_t *font_config) { bl_map_new_with_size(vt_font_t, char *, font_config->font_name_table, bl_map_hash_int, bl_map_compare_int, 16); } static void destroy_table(ui_font_config_t *font_config) { u_int count; u_int size; BL_PAIR(ui_font_name) * fn_array; fn_array = get_font_name_pairs_array(&size, font_config->font_name_table); for (count = 0; count < size; count++) { free(fn_array[count]->value); } bl_map_destroy(font_config->font_name_table); } /* --- global functions --- */ #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG) int ui_use_aafont(void) { if (num_configs > 0 || use_aafont) { return 0; } use_aafont = 1; ui_font_use_fontconfig(); return 1; } int ui_is_using_aafont(void) { return use_aafont; } #endif ui_font_config_t *ui_acquire_font_config(ui_type_engine_t type_engine, ui_font_present_t font_present) { ui_font_config_t *font_config; void *p; if ((font_config = find_font_config(type_engine, font_present))) { font_config->ref_count++; return font_config; } if ((p = realloc(font_configs, sizeof(ui_font_config_t *) * (num_configs + 1))) == NULL) { return NULL; } font_configs = p; if ((font_config = create_shared_font_config(type_engine, font_present)) == NULL) { if ((font_config = ui_font_config_new(type_engine, font_present)) == NULL || !read_all_conf(font_config, NULL)) { return NULL; } } font_config->ref_count++; return font_configs[num_configs++] = font_config; } void ui_release_font_config(ui_font_config_t *font_config) { u_int count; int has_share; int found; if (--font_config->ref_count > 0) { return; } has_share = 0; found = 0; count = 0; while (count < num_configs) { if (font_configs[count] == font_config) { font_configs[count] = font_configs[--num_configs]; found = 1; continue; } else if ((font_config->type_engine == TYPE_XCORE ? font_configs[count]->type_engine == TYPE_XCORE : /* '>= XFT' means XFT or Cairo */ font_configs[count]->type_engine >= TYPE_XFT) && ((font_configs[count]->font_present & ~FONT_AA) == (font_config->font_present & ~FONT_AA))) { has_share = 1; } count++; } if (!found) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " font_config is not found in font_configs.\n"); #endif return; } if (has_share /* && num_configs > 0 */) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Sharable font_config exists.\n"); #endif free(font_config); return; } ui_font_config_destroy(font_config); if (num_configs == 0) { free(font_configs); font_configs = NULL; } } ui_font_config_t *ui_font_config_new(ui_type_engine_t type_engine, ui_font_present_t font_present) { ui_font_config_t *font_config; if ((font_config = malloc(sizeof(ui_font_config_t))) == NULL) { return NULL; } new_table(font_config); font_config->type_engine = type_engine; font_config->font_present = font_present; font_config->ref_count = 0; return font_config; } void ui_font_config_destroy(ui_font_config_t *font_config) { destroy_table(font_config); free(font_config); } /* * 0 => customization is failed. * -1 => customization is succeeded but saving is failed. * 1 => succeeded. */ int ui_customize_font_file(const char *file, /* if null, use "mlterm/font" file. */ char *key, /* charset name */ char *value, /* font list */ int save) { /* * Max number of target font_config is 6. * [file == aafont_file] * TYPE_XFT, TYPE_XFT & FONT_VAR_WIDTH , TYPE_XFT & FONT_VERTICAL , TYPE_XFT & * FONT_AA , * TYPE_XFT & FONT_VAR_WIDTH & FONT_AA , TYPE_XFT & FONT_VERTICAL & FONT_AA */ ui_font_config_t *targets[6]; u_int num_targets; u_int count; int ret; if (file == NULL || #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG) strcmp(file, "font") == 0 #else strcmp(file, FONT_FILE) == 0 #endif ) { file = font_file; num_targets = match_font_configs(targets, 6, /* is xcore */ 1, 0); } else if (strcmp(file, aafont_file + 7) == 0) { file = aafont_file; num_targets = match_font_configs(targets, 6, /* is not xcore */ 0, 0); } else if (strcmp(file, VFONT_FILE) == 0) { file = vfont_file; num_targets = match_font_configs(targets, 6, /* is xcore */ 1, FONT_VAR_WIDTH); } else if (strcmp(file, TFONT_FILE) == 0) { file = tfont_file; num_targets = match_font_configs(targets, 6, /* is xcore */ 1, FONT_VERTICAL); } else if (strcmp(file, vaafont_file + 7) == 0) { file = vaafont_file; num_targets = match_font_configs(targets, 6, /* is not xcore */ 0, FONT_VAR_WIDTH); } else if (strcmp(file, taafont_file + 7) == 0) { file = taafont_file; num_targets = match_font_configs(targets, 6, /* is not xcore */ 0, FONT_VERTICAL); } else { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " font file %s is not found.\n", file); #endif return 0; } #ifdef __DEBUG if (num_targets) { bl_debug_printf("customize font file %s %s %s\n", file, key, value); } else { bl_debug_printf("customize font file %s %s %s(not changed in run time)\n", file, key, value); } #endif if (change_custom_cache(file, key, value)) { if (*value == '\0') { /* remove */ for (count = 0; count < num_targets; count++) { /* * reset font_name_table * * ~/.mlterm/font: ISO10646_UCS4_1=a * => mlcc font ISO10646_UCS4_1 b * => mlcc font ISO10646_UCS4_1 "" (results in ISO10646_UCS4_1=a) */ destroy_table(targets[count]); new_table(targets[count]); read_all_conf(targets[count], NULL); } return 1; } else { ret = 1; for (count = 0; count < num_targets; count++) { read_all_conf(targets[count], file); } } } else { ret = 0; } if (save && !save_conf(file, key, value)) { return ret ? -1 : 0; } else { return ret; } } char *ui_get_config_font_name(ui_font_config_t *font_config, u_int font_size, vt_font_t font) { vt_font_t cand_font; BL_PAIR(ui_font_name) pair; char *font_name; char *encoding; size_t encoding_len; int has_percentd; #ifdef USE_XLIB static char *orig_style[] = {"-medium-", "-r-", "-medium-r-"}; static char *new_style[] = {"-bold-", "-i-", "-bold-i-"}; #endif if (UNICODE_AREA(font)) { font &= ~FONT_FULLWIDTH; } encoding = NULL; cand_font = NO_SIZE_ATTR(font); while (!(pair = get_font_name_pair(font_config->font_name_table, cand_font))) { #ifdef USE_XLIB int idx; if (font_config->type_engine == TYPE_XCORE) { if ((idx = FONT_STYLE_INDEX(font)) >= 0 && ((pair = get_font_name_pair(font_config->font_name_table, FONT_CS(cand_font))) && (font_name = bl_str_replace(pair->value, orig_style[idx], new_style[idx])))) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Set font %s for %x\n", font_name, font); #endif set_font_name_to_table(font_config->font_name_table, cand_font, font_name); continue; } } else #endif { if (cand_font & FONT_STYLES) { cand_font &= ~FONT_STYLES; continue; } } if (cand_font & FONT_FULLWIDTH) { cand_font &= ~FONT_FULLWIDTH; } else if (FONT_CS(cand_font) != DEFAULT_FONT) { cand_font = DEFAULT_FONT; } else { return NULL; } } #ifdef USE_XLIB if (font_config->type_engine == TYPE_XCORE && FONT_CS(cand_font) == DEFAULT_FONT && /* encoding is appended if font_name is XLFD (not alias name). */ (strchr(pair->value, '*') || strchr(pair->value, '-'))) { char **names; if ((names = ui_font_get_encoding_names(FONT_CS(font))) && names[0]) { encoding = names[0]; } } #endif #if 1 if (*(pair->value) == '&' && /* XXX font variable is overwritten. */ (font = parse_key(pair->value + 1)) != UNKNOWN_CS) { /* * XXX (Undocumented) * * JISX0213_2000_1 = &JISX0208_1983 in font configuration files. * => try to get a font name of JISX0208_1983 instead of * JISX0213_2000_1 recursively. */ return ui_get_config_font_name(font_config, font_size, font); } #endif /* * If pair->value is valid format or not is checked by is_valid_font_format() * in customize_font_name(). * So all you have to do here is strchr( ... , '%') alone. */ if (strchr(pair->value, '%')) { has_percentd = 1; } else if (encoding == NULL) { return strdup(pair->value); } else { has_percentd = 0; } if (!(font_name = malloc(strlen(pair->value) + /* -2 is for "%d" */ (has_percentd ? DIGIT_STR_LEN(font_size) - 2 : 0) + (encoding_len = encoding ? strlen(encoding) : 0) + 1))) { return NULL; } if (has_percentd) { sprintf(font_name, pair->value, font_size); } else { strcpy(font_name, pair->value); } if (encoding) { char *percent; if ((percent = strchr(font_name, ':'))) { /* -*-:200 -> -*-iso8859-1:200 */ memmove(percent + encoding_len, percent, strlen(percent) + 1); memcpy(percent, encoding, encoding_len); } else { strcat(font_name, encoding); } } return font_name; } char *ui_get_config_font_name2(const char *file, /* can be NULL */ u_int font_size, char *font_cs) { vt_font_t font; ui_font_config_t *font_config; ui_type_engine_t engine; ui_font_present_t present; char *font_name; if (file == NULL || strcmp(file, FONT_FILE) == 0) { engine = TYPE_XCORE; present = 0; } #if !defined(USE_FREETYPE) || !defined(USE_FONTCONFIG) else if (strcmp(file, aafont_file + 7) == 0) { engine = TYPE_XFT; /* * font_config::font_name_table is shared with * font_configs whose difference is only FONT_AA. */ present = 0; } else if (strcmp(file, vaafont_file + 7) == 0) { engine = TYPE_XFT; present = FONT_VAR_WIDTH; } else if (strcmp(file, taafont_file + 7) == 0) { engine = TYPE_XFT; present = FONT_VERTICAL; } #endif else if (strcmp(file, VFONT_FILE) == 0) { engine = TYPE_XCORE; present = FONT_VAR_WIDTH; } else if (strcmp(file, TFONT_FILE) == 0) { engine = TYPE_XCORE; present = FONT_VERTICAL; } else { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " font file %s is not found.\n", file); #endif return NULL; } if ((font_config = ui_acquire_font_config(engine, present)) == NULL) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " ui_font_config_t is not found.\n"); #endif return NULL; } if ((font = parse_key(font_cs)) == UNKNOWN_CS) { return NULL; } font_name = ui_get_config_font_name(font_config, font_size, font); ui_release_font_config(font_config); return font_name; } char *ui_get_config_font_names_all(ui_font_config_t *font_config, u_int font_size) { BL_PAIR(ui_font_name) * array; u_int size; char *font_name_list; size_t list_len; char *p; u_int count; array = get_font_name_pairs_array(&size, font_config->font_name_table); if (size == 0) { return NULL; } list_len = 0; for (count = 0; count < size; count++) { list_len += (strlen(array[count]->value) - 2 + DIGIT_STR_LEN(font_size) + 1); } if ((font_name_list = malloc(list_len)) == NULL) { return NULL; } p = font_name_list; for (count = 0; count < size; count++) { /* * XXX * Ignore DEFAULT_FONT setting because it doesn't have encoding name. */ if (FONT_CS(array[count]->key) != DEFAULT_FONT) { sprintf(p, array[count]->value, font_size); p += strlen(p); *(p++) = ','; } } if (p > font_name_list) { --p; } *p = '\0'; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Font list is %s\n", font_name_list); #endif return font_name_list; } char *ui_font_config_dump(ui_font_config_t *font_config) { BL_PAIR(ui_font_name) * array; u_int size; char *font_name_list; size_t list_len; char *p; u_int count; array = get_font_name_pairs_array(&size, font_config->font_name_table); if (size == 0) { return "No font settings"; } list_len = 0; for (count = 0; count < size; count++) { list_len += (4 /* CSI2J */ + 15 /* ISO10646_UCS4_1, U+10FFFF-10FFFF */ + 12 /* _BOLD_ITALIC */ + 10 /* _FULLWIDTH */ + 1 /* = */ + strlen(array[count]->value) + 2 /* \r\n or \0 */); } if ((font_name_list = malloc(list_len)) == NULL) { return "No font settings"; } strcpy(font_name_list, "\x1b[2J"); p = font_name_list + 4; for (count = 0; count < size; count++) { if (FONT_CS(array[count]->key) == DEFAULT_FONT) { strcpy(p, "DEFAULT"); p += 7; } else { u_int count2; for (count2 = 0; count2 < sizeof(cs_table) / sizeof(cs_table[0]); count2++) { if (FONT_CS(array[count]->key) == cs_table[count2].cs) { int min; int max; if (vt_get_unicode_area(array[count]->key, &min, &max)) { sprintf(p, "U+%x-%x", min, max); } else { strcpy(p, cs_table[count2].name); } p += strlen(p); goto next_step; } } continue; } next_step: if (array[count]->key & FONT_BOLD) { strcpy(p, "_BOLD"); p += 5; } if (array[count]->key & FONT_ITALIC) { strcpy(p, "_ITALIC"); p += 7; } if (array[count]->key & FONT_FULLWIDTH) { strcpy(p, "_FULLWIDTH"); p += 10; } sprintf(p, "=%s", array[count]->value); p += strlen(p); *(p++) = '\r'; *(p++) = '\n'; } *(p - 2) = '\0'; return font_name_list; } char *ui_get_charset_name(ef_charset_t cs) { int count; for (count = 0; count < sizeof(cs_table) / sizeof(cs_table[0]); count++) { if (cs_table[count].cs == cs) { return cs_table[count].name; } } return NULL; } #ifdef BL_DEBUG #include void TEST_ui_font_config(void) { #ifdef USE_XLIB ui_font_config_t *font_config; char *value; font_config = ui_font_config_new(TYPE_XCORE, 0); customize_font_name(font_config, ISO8859_1_R, "-hoge-medium-r-fuga-"); value = ui_get_config_font_name(font_config, 12, ISO8859_1_R | FONT_BOLD); assert(strcmp("-hoge-bold-r-fuga-", value) == 0); free(value); value = ui_get_config_font_name(font_config, 12, ISO8859_1_R | FONT_ITALIC); assert(strcmp("-hoge-medium-i-fuga-", value) == 0); free(value); value = ui_get_config_font_name(font_config, 12, ISO8859_1_R | FONT_BOLD | FONT_ITALIC); assert(strcmp("-hoge-bold-i-fuga-", value) == 0); free(value); ui_font_config_destroy(font_config); bl_msg_printf("PASS ui_font_config test.\n"); #endif } #endif mlterm-3.8.9/uitoolkit/ui_font_config.h010064400017600000144000000027271356600660700167360ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_FONT_CONFIG_H__ #define __UI_FONT_CONFIG_H__ #include #include #include "ui_font.h" BL_MAP_TYPEDEF(ui_font_name, vt_font_t, char *); typedef struct ui_font_config { /* Public(readonly) */ ui_type_engine_t type_engine; ui_font_present_t font_present; /* * Private * font_configs whose difference is only FONT_AA share these members. */ BL_MAP(ui_font_name) font_name_table; u_int ref_count; } ui_font_config_t; #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG) int ui_use_aafont(void); int ui_is_using_aafont(void); #endif ui_font_config_t *ui_acquire_font_config(ui_type_engine_t type_engine, ui_font_present_t font_present); void ui_release_font_config(ui_font_config_t *font_config); ui_font_config_t *ui_font_config_new(ui_type_engine_t type_engine, ui_font_present_t font_present); void ui_font_config_destroy(ui_font_config_t *font_config); int ui_customize_font_file(const char *file, char *key, char *value, int save); char *ui_get_config_font_name(ui_font_config_t *font_config, u_int font_size, vt_font_t font); char *ui_get_config_font_name2(const char *file, u_int font_size, char *font_cs); char *ui_get_config_font_names_all(ui_font_config_t *font_config, u_int font_size); char *ui_font_config_dump(ui_font_config_t *font_config); char *ui_get_charset_name(ef_charset_t cs); #endif mlterm-3.8.9/uitoolkit/ui_font_manager.c010064400017600000144000000310201356600660700170620ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_font_manager.h" #include /* strcat */ #include /* sprintf */ #include /* malloc/alloca */ #include /* DIGIT_STR_LEN */ #if 0 #define __DEBUG #endif typedef struct encoding_to_cs_table { u_int16_t encoding; /* vt_char_encoding_t */ u_int16_t cs; /* ef_charset_t */ } encoding_to_cs_table_t; /* --- static variables --- */ /* * !!! Notice !!! * The order should be the same as vt_char_encoding_t. * US_ASCII font for encodings after VT_UTF8 is ISO8859_1_R. (see * ui_get_usascii_font_cs()) */ static encoding_to_cs_table_t usascii_font_cs_table[] = { {VT_ISO8859_1, ISO8859_1_R}, {VT_ISO8859_2, ISO8859_2_R}, {VT_ISO8859_3, ISO8859_3_R}, {VT_ISO8859_4, ISO8859_4_R}, {VT_ISO8859_5, ISO8859_5_R}, {VT_ISO8859_6, ISO8859_6_R}, {VT_ISO8859_7, ISO8859_7_R}, {VT_ISO8859_8, ISO8859_8_R}, {VT_ISO8859_9, ISO8859_9_R}, {VT_ISO8859_10, ISO8859_10_R}, {VT_TIS620, TIS620_2533}, {VT_ISO8859_13, ISO8859_13_R}, {VT_ISO8859_14, ISO8859_14_R}, {VT_ISO8859_15, ISO8859_15_R}, {VT_ISO8859_16, ISO8859_16_R}, {VT_TCVN5712, TCVN5712_3_1993}, {VT_ISCII_ASSAMESE, ISO8859_1_R}, {VT_ISCII_BENGALI, ISO8859_1_R}, {VT_ISCII_GUJARATI, ISO8859_1_R}, {VT_ISCII_HINDI, ISO8859_1_R}, {VT_ISCII_KANNADA, ISO8859_1_R}, {VT_ISCII_MALAYALAM, ISO8859_1_R}, {VT_ISCII_ORIYA, ISO8859_1_R}, {VT_ISCII_PUNJABI, ISO8859_1_R}, {VT_ISCII_TELUGU, ISO8859_1_R}, {VT_VISCII, VISCII}, {VT_KOI8_R, KOI8_R}, {VT_KOI8_U, KOI8_U}, {VT_KOI8_T, KOI8_T}, {VT_GEORGIAN_PS, GEORGIAN_PS}, {VT_CP1250, CP1250}, {VT_CP1251, CP1251}, {VT_CP1252, CP1252}, {VT_CP1253, CP1253}, {VT_CP1254, CP1254}, {VT_CP1255, CP1255}, {VT_CP1256, CP1256}, {VT_CP1257, CP1257}, {VT_CP1258, CP1258}, {VT_CP874, CP874}, {VT_UTF8, ISO10646_UCS4_1}, }; static u_int min_font_size = 1; static u_int max_font_size = 10000; /* --- static functions --- */ static int change_font_cache(ui_font_manager_t *font_man, ui_font_cache_t *font_cache) { ui_release_font_cache(font_man->font_cache); font_man->font_cache = font_cache; return 1; } static void adjust_font_size(u_int *font_size) { if (*font_size > max_font_size) { bl_msg_printf("font size %d is too large. %d is used.\n", *font_size, max_font_size); *font_size = max_font_size; } else if (*font_size < min_font_size) { bl_msg_printf("font size %d is too small. %d is used.\n", *font_size, min_font_size); *font_size = min_font_size; } } /* --- global functions --- */ int ui_set_font_size_range(u_int min_fsize, u_int max_fsize) { if (min_fsize == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " min_font_size must not be 0.\n"); #endif return 0; } if (max_fsize < min_fsize) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " max_font_size %d should be larger than min_font_size %d\n", max_fsize, min_fsize); #endif return 0; } min_font_size = min_fsize; max_font_size = max_fsize; return 1; } ui_font_manager_t *ui_font_manager_new(Display *display, ui_type_engine_t type_engine, ui_font_present_t font_present, u_int font_size, ef_charset_t usascii_font_cs, u_int step_in_changing_font_size, u_int letter_space, int use_bold_font, int use_italic_font) { ui_font_manager_t *font_man; if (!(font_man = malloc(sizeof(ui_font_manager_t)))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc() failed.\n"); #endif return NULL; } adjust_font_size(&font_size); if ((!(font_man->font_config = ui_acquire_font_config(type_engine, font_present)) || !(font_man->font_cache = ui_acquire_font_cache(display, font_size, usascii_font_cs, font_man->font_config, letter_space)))) { ui_type_engine_t engine; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Could not handle %s fonts.\n", ui_get_type_engine_name(type_engine)); #endif for (engine = TYPE_XCORE;; engine++) { if (engine == type_engine) { #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG) if (font_man->font_config) { ui_release_font_config(font_man->font_config); font_man->font_config = NULL; } if (ui_use_aafont()) { /* XXX unicode_policy is not changed here unlike ui_main_config.c. */ bl_msg_printf("Try to load fonts with aafont instead of font-fb. " "Don't set char encodings except UTF-8.\n"); } else #endif { continue; } } if (font_man->font_config) { ui_release_font_config(font_man->font_config); } if (engine >= TYPE_ENGINE_MAX) { free(font_man); return NULL; } if ((font_man->font_config = ui_acquire_font_config(engine, font_present)) && (font_man->font_cache = ui_acquire_font_cache(display, font_size, usascii_font_cs, font_man->font_config, letter_space))) { break; } } bl_msg_printf("Fall back to %s.\n", ui_get_type_engine_name(engine)); } if (max_font_size - min_font_size >= step_in_changing_font_size) { font_man->step_in_changing_font_size = step_in_changing_font_size; } else { font_man->step_in_changing_font_size = max_font_size - min_font_size; } font_man->use_bold_font = use_bold_font; font_man->use_italic_font = use_italic_font; font_man->size_attr = 0; #ifdef USE_OT_LAYOUT font_man->use_ot_layout = 0; #endif return font_man; } void ui_font_manager_destroy(ui_font_manager_t *font_man) { ui_release_font_cache(font_man->font_cache); ui_release_font_config(font_man->font_config); font_man->font_config = NULL; free(font_man); } void ui_font_manager_set_attr(ui_font_manager_t *font_man, int size_attr, int use_ot_layout) { font_man->size_attr = size_attr; #ifdef USE_OT_LAYOUT font_man->use_ot_layout = use_ot_layout; #endif } ui_font_t *ui_get_font(ui_font_manager_t *font_man, vt_font_t font) { ui_font_t *uifont; if (!font_man->use_bold_font) { font &= ~FONT_BOLD; } if (!font_man->use_italic_font) { font &= ~FONT_ITALIC; } if (!(uifont = ui_font_cache_get_font(font_man->font_cache, SIZE_ATTR_FONT(font, font_man->size_attr)))) { uifont = font_man->font_cache->usascii_font; } #ifdef USE_OT_LAYOUT if (FONT_CS(font) == ISO10646_UCS4_1_V) { uifont->use_ot_layout = 1; } else { uifont->use_ot_layout = font_man->use_ot_layout; } #endif return uifont; } int ui_font_manager_usascii_font_cs_changed(ui_font_manager_t *font_man, ef_charset_t usascii_font_cs) { ui_font_cache_t *font_cache; if (usascii_font_cs == font_man->font_cache->usascii_font_cs) { return 0; } if ((font_cache = ui_acquire_font_cache( font_man->font_cache->display, font_man->font_cache->font_size, usascii_font_cs, font_man->font_config, font_man->font_cache->letter_space)) == NULL) { return 0; } change_font_cache(font_man, font_cache); return 1; } /* * Return 1 if font present is successfully changed. * Return 0 if not changed. */ int ui_change_font_present(ui_font_manager_t *font_man, ui_type_engine_t type_engine, ui_font_present_t font_present) { ui_font_config_t *font_config; ui_font_cache_t *font_cache; #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO) /* * FONT_AA is effective in xft or cairo, so following hack is necessary in * xlib. */ if ((type_engine == TYPE_XCORE) && (font_man->font_config->font_present & FONT_AA)) { font_present &= ~FONT_AA; } else if ((font_present & FONT_AA) && font_man->font_config->type_engine == TYPE_XCORE && type_engine == TYPE_XCORE) { #if !defined(USE_TYPE_XFT) && defined(USE_TYPE_CAIRO) type_engine = TYPE_CAIRO; #else type_engine = TYPE_XFT; #endif } #endif if (font_present == font_man->font_config->font_present && type_engine == font_man->font_config->type_engine) { /* Same as current settings. */ return 0; } if ((font_config = ui_acquire_font_config(type_engine, font_present)) == NULL) { return 0; } if ((font_cache = ui_acquire_font_cache( font_man->font_cache->display, font_man->font_cache->font_size, font_man->font_cache->usascii_font_cs, font_config, font_man->font_cache->letter_space)) == NULL) { ui_release_font_config(font_config); return 0; } change_font_cache(font_man, font_cache); ui_release_font_config(font_man->font_config); font_man->font_config = font_config; return 1; } ui_type_engine_t ui_get_type_engine(ui_font_manager_t *font_man) { return font_man->font_config->type_engine; } ui_font_present_t ui_get_font_present(ui_font_manager_t *font_man) { return font_man->font_config->font_present; } int ui_change_font_size(ui_font_manager_t *font_man, u_int font_size) { ui_font_cache_t *font_cache; adjust_font_size(&font_size); if (font_size == font_man->font_cache->font_size) { /* not changed (pretending to succeed) */ return 1; } if (font_size < min_font_size || max_font_size < font_size) { return 0; } if ((font_cache = ui_acquire_font_cache( font_man->font_cache->display, font_size, font_man->font_cache->usascii_font_cs, font_man->font_config, font_man->font_cache->letter_space)) == NULL) { return 0; } change_font_cache(font_man, font_cache); return 1; } int ui_larger_font(ui_font_manager_t *font_man) { u_int font_size; ui_font_cache_t *font_cache; if (font_man->font_cache->font_size + font_man->step_in_changing_font_size > max_font_size) { font_size = min_font_size; } else { font_size = font_man->font_cache->font_size + font_man->step_in_changing_font_size; } if ((font_cache = ui_acquire_font_cache( font_man->font_cache->display, font_size, font_man->font_cache->usascii_font_cs, font_man->font_config, font_man->font_cache->letter_space)) == NULL) { return 0; } change_font_cache(font_man, font_cache); return 1; } int ui_smaller_font(ui_font_manager_t *font_man) { u_int font_size; ui_font_cache_t *font_cache; if (font_man->font_cache->font_size < min_font_size + font_man->step_in_changing_font_size) { font_size = max_font_size; } else { font_size = font_man->font_cache->font_size - font_man->step_in_changing_font_size; } if ((font_cache = ui_acquire_font_cache( font_man->font_cache->display, font_size, font_man->font_cache->usascii_font_cs, font_man->font_config, font_man->font_cache->letter_space)) == NULL) { return 0; } change_font_cache(font_man, font_cache); return 1; } u_int ui_get_font_size(ui_font_manager_t *font_man) { return font_man->font_cache->font_size; } int ui_set_letter_space(ui_font_manager_t *font_man, u_int letter_space) { ui_font_cache_t *font_cache; if (font_man->font_cache->letter_space == letter_space) { return 0; } if ((font_cache = ui_acquire_font_cache(font_man->font_cache->display, font_man->font_cache->font_size, font_man->font_cache->usascii_font_cs, font_man->font_config, letter_space)) == NULL) { return 0; } change_font_cache(font_man, font_cache); return 1; } int ui_set_use_bold_font(ui_font_manager_t *font_man, int use_bold_font) { if (font_man->use_bold_font == use_bold_font) { return 0; } font_man->use_bold_font = use_bold_font; return 1; } int ui_set_use_italic_font(ui_font_manager_t *font_man, int use_italic_font) { if (font_man->use_italic_font == use_italic_font) { return 0; } font_man->use_italic_font = use_italic_font; return 1; } ef_charset_t ui_get_usascii_font_cs(vt_char_encoding_t encoding) { if (encoding < 0 || sizeof(usascii_font_cs_table) / sizeof(usascii_font_cs_table[0]) <= encoding) { return ISO8859_1_R; } #ifdef DEBUG else if (encoding != usascii_font_cs_table[encoding].encoding) { bl_warn_printf(BL_DEBUG_TAG " %x is illegal encoding.\n", encoding); return ISO8859_1_R; } #endif else { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " us ascii font is %x cs\n", usascii_font_cs_table[encoding].cs); #endif return usascii_font_cs_table[encoding].cs; } } mlterm-3.8.9/uitoolkit/ui_font_manager.h010064400017600000144000000053111356600660700170730ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_FONT_MANAGER_H__ #define __UI_FONT_MANAGER_H__ #include "ui.h" #include #include #include "ui_font_cache.h" typedef struct ui_font_manager { ui_font_cache_t *font_cache; ui_font_config_t *font_config; u_int8_t step_in_changing_font_size; int8_t use_bold_font; int8_t use_italic_font; int8_t size_attr; #ifdef USE_OT_LAYOUT int8_t use_ot_layout; #endif } ui_font_manager_t; int ui_set_font_size_range(u_int min_font_size, u_int max_font_size); ui_font_manager_t *ui_font_manager_new(Display *display, ui_type_engine_t type_engine, ui_font_present_t font_present, u_int font_size, ef_charset_t usascii_font_cs, u_int step_in_changing_font_size, u_int letter_space, int use_bold_font, int use_italic_font); void ui_font_manager_destroy(ui_font_manager_t *font_man); void ui_font_manager_set_attr(ui_font_manager_t *font_man, int size_attr, int use_ot_layout); ui_font_t *ui_get_font(ui_font_manager_t *font_man, vt_font_t font); #define ui_get_usascii_font(font_man) ((font_man)->font_cache->usascii_font) int ui_font_manager_usascii_font_cs_changed(ui_font_manager_t *font_man, ef_charset_t usascii_font_cs); int ui_change_font_present(ui_font_manager_t *font_man, ui_type_engine_t type_engine, ui_font_present_t font_present); ui_type_engine_t ui_get_type_engine(ui_font_manager_t *font_man); ui_font_present_t ui_get_font_present(ui_font_manager_t *font_man); int ui_change_font_size(ui_font_manager_t *font_man, u_int font_size); int ui_larger_font(ui_font_manager_t *font_man); int ui_smaller_font(ui_font_manager_t *font_man); u_int ui_get_font_size(ui_font_manager_t *font_man); int ui_set_letter_space(ui_font_manager_t *font_man, u_int letter_space); #define ui_get_letter_space(font_man) ((font_man)->font_cache->letter_space) int ui_set_use_bold_font(ui_font_manager_t *font_man, int use_bold_font); #define ui_is_using_bold_font(font_man) ((font_man)->use_bold_font) int ui_set_use_italic_font(ui_font_manager_t *font_man, int use_italic_font); #define ui_is_using_italic_font(font_man) ((font_man)->use_italic_font) #define ui_get_fontset(font_man) ui_font_cache_get_fontset((font_man)->font_cache) #define ui_get_current_usascii_font_cs(font_man) ((font_man)->font_cache->usascii_font_cs) ef_charset_t ui_get_usascii_font_cs(vt_char_encoding_t encoding); #define ui_font_manager_dump_font_config(font_man) ui_font_config_dump((font_man)->font_config) #endif mlterm-3.8.9/uitoolkit/ui_im.c010064400017600000144000000162011356600660700150330ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include /* sprintf */ #include /* malloc/alloca/free */ #include /* bl_str_sep */ #include #include #include #include "ui_im.h" #include "ui_event_source.h" #ifdef USE_IM_PLUGIN #ifndef LIBDIR #define IM_DIR "/usr/local/lib/mlterm/" #else #define IM_DIR LIBDIR "/mlterm/" #endif typedef ui_im_t *(*ui_im_new_func_t)(u_int64_t magic, vt_char_encoding_t term_encoding, ui_im_export_syms_t *syms, char *engine, u_int mod_ignore_mask); /* --- static variables --- */ static ui_im_export_syms_t im_export_syms = { vt_str_init, vt_str_destroy, vt_char_combine, vt_char_set, vt_get_char_encoding_name, vt_get_char_encoding, vt_convert_to_internal_ch, vt_isciikey_state_new, vt_isciikey_state_destroy, vt_convert_ascii_to_iscii, vt_char_encoding_parser_new, vt_char_encoding_conv_new, ui_im_candidate_screen_new, ui_im_status_screen_new, ui_event_source_add_fd, ui_event_source_remove_fd, XStringToKeysym }; #if 1 /* restroing locale which was overwritten by SCIM */ #define RESTORE_LOCALE 1 #endif /* --- static functions --- */ static void *im_dlopen(char *im_name) { char *libname; void *handle; if (!(libname = alloca(strlen(im_name) + 4))) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " alloca() failed.\n"); #endif return NULL; } sprintf(libname, "im-%s", im_name); if (!(handle = bl_dl_open(IM_DIR, libname))) { handle = bl_dl_open("", libname); } return handle; } static int dlsym_im_new_func(char *im_name, ui_im_new_func_t *func, bl_dl_handle_t *handle) { char *symname; #ifdef PLUGIN_MODULE_SUFFIX char *im_name2; #endif if (!im_name || !(symname = alloca(strlen(im_name) + 8))) { return 0; } sprintf(symname, "im_%s_new", im_name); #ifdef PLUGIN_MODULE_SUFFIX if ((im_name2 = alloca(strlen(im_name) + 3 + 1))) { sprintf(im_name2, "%s-" PLUGIN_MODULE_SUFFIX, im_name); if (!(*handle = im_dlopen(im_name2))) { #endif if (!(*handle = im_dlopen(im_name))) { return 0; } #ifdef PLUGIN_MODULE_SUFFIX } } #endif if (!(*func = (ui_im_new_func_t)bl_dl_func_symbol(*handle, symname))) { bl_dl_close(*handle); return 0; } return 1; } /* --- global functions --- */ ui_im_t *ui_im_new(ui_display_t *disp, ui_font_manager_t *font_man, ui_color_manager_t *color_man, void *vtparser, ui_im_event_listener_t *im_listener, char *input_method, u_int mod_ignore_mask) { ui_im_t *im; ui_im_new_func_t func; bl_dl_handle_t handle; char *im_name; char *im_attr; #ifdef RESTORE_LOCALE char *cur_locale; #endif if (input_method == NULL) { return NULL; } if (strcmp(input_method, "none") == 0) { return NULL; } if (strchr(input_method, ':')) { if ((im_attr = alloca(strlen(input_method) + 1)) == NULL) { return NULL; } strcpy(im_attr, input_method); if ((im_name = bl_str_sep(&im_attr, ":")) == NULL) { #ifdef DEBUG bl_error_printf("%s is illegal input method.\n", input_method); #endif return NULL; } } else { if ((im_name = alloca(strlen(input_method) + 1))) { strcpy(im_name, input_method); } im_attr = NULL; } #ifdef RESTORE_LOCALE if ((cur_locale = alloca(strlen(bl_get_locale()) + 1))) { strcpy(cur_locale, bl_get_locale()); } #endif if (!dlsym_im_new_func(im_name, &func, &handle)) { #ifdef RESTORE_LOCALE if (cur_locale) { bl_locale_init(cur_locale); } #endif bl_error_printf("%s: Could not load.\n", im_name); return NULL; } #ifdef RESTORE_LOCALE bl_locale_init(cur_locale); #endif if (!(im = (*func)(IM_API_COMPAT_CHECK_MAGIC, vt_parser_get_encoding((vt_parser_t*)vtparser), &im_export_syms, im_attr, mod_ignore_mask))) { bl_error_printf("%s: Could not open.\n", im_name); /* * Even if ibus daemon was not found, ibus_init() has been * already called in im_ibus_new(). * So if im-ibus module is unloaded here, ibus_init() * will be called again and segfault will happen when * im-ibus module is loaded next time. * Fcitx is also the same. */ if (strcmp(im_name, "ibus") != 0 && strcmp(im_name, "fcitx") != 0) { bl_dl_close(handle); } else { bl_dl_close_at_exit(handle); } return NULL; } /* * initializations for ui_im_t */ im->handle = handle; im->name = strdup(im_name); im->disp = disp; im->font_man = font_man; im->color_man = color_man; im->vtparser = vtparser; im->listener = im_listener; im->cand_screen = NULL; im->stat_screen = NULL; im->preedit.chars = NULL; im->preedit.num_chars = 0; im->preedit.filled_len = 0; im->preedit.segment_offset = 0; im->preedit.cursor_offset = UI_IM_PREEDIT_NOCURSOR; return im; } void ui_im_destroy(ui_im_t *im) { bl_dl_handle_t handle; int do_close; if (strcmp(im->name, "ibus") == 0 || strcmp(im->name, "fcitx") == 0) { do_close = 0; } else { do_close = 1; } free(im->name); if (im->cand_screen) { (*im->cand_screen->destroy)(im->cand_screen); } if (im->stat_screen) { (*im->stat_screen->destroy)(im->stat_screen); } if (im->preedit.chars) { vt_str_destroy(im->preedit.chars, im->preedit.num_chars); } handle = im->handle; (*im->destroy)(im); /* * Don't unload libim-ibus.so or libim-fcitx.so because it depends * on glib which works unexpectedly. */ if (do_close) { bl_dl_close(handle); } } void ui_im_redraw_preedit(ui_im_t *im, int is_focused) { (*im->listener->draw_preedit_str)(im->listener->self, im->preedit.chars, im->preedit.filled_len, im->preedit.cursor_offset); if (!im->cand_screen && !im->stat_screen) { return; } if (is_focused) { int x; int y; if ((*im->listener->get_spot)(im->listener->self, im->preedit.chars, im->preedit.segment_offset, &x, &y)) { if (im->stat_screen && (im->cand_screen && im->preedit.filled_len)) { (*im->stat_screen->hide)(im->stat_screen); (*im->cand_screen->show)(im->cand_screen); (*im->cand_screen->set_spot)(im->cand_screen, x, y); } else if (im->stat_screen) { (*im->stat_screen->show)(im->stat_screen); (*im->stat_screen->set_spot)(im->stat_screen, x, y); } else if (im->cand_screen && im->preedit.filled_len) { (*im->cand_screen->show)(im->cand_screen); (*im->cand_screen->set_spot)(im->cand_screen, x, y); } } } else { if (im->cand_screen) { (*im->cand_screen->hide)(im->cand_screen); } if (im->stat_screen) { (*im->stat_screen->hide)(im->stat_screen); } } } #else /* ! USE_IM_PLUGIN */ ui_im_t *ui_im_new(ui_display_t *disp, ui_font_manager_t *font_man, ui_color_manager_t *color_man, void *vtparser, ui_im_event_listener_t *im_listener, char *input_method, u_int mod_ignore_mask) { return NULL; } void ui_im_destroy(ui_im_t *im) {} void ui_im_redraw_preedit(ui_im_t *im, int is_focused) {} #endif mlterm-3.8.9/uitoolkit/ui_im.h010064400017600000144000000101751356600660700150440ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_IM_H__ #define __UI_IM_H__ #include #include #include #include "ui.h" /* KeySym, XKeyEvent */ #include "ui_im_candidate_screen.h" #include "ui_im_status_screen.h" #define UI_IM_PREEDIT_NOCURSOR -1 /* * information for the current preedit string */ typedef struct ui_im_preedit { vt_char_t *chars; u_int num_chars; /* == array size */ u_int filled_len; int segment_offset; int cursor_offset; } ui_im_preedit_t; typedef struct ui_im_event_listener { void *self; int (*get_spot)(void *, vt_char_t *, int, int *, int *); u_int (*get_line_height)(void *); int (*is_vertical)(void *); void (*draw_preedit_str)(void *, vt_char_t *, u_int, int); void (*im_changed)(void *, char *); int (*compare_key_state_with_modmap)(void *, u_int, int *, int *, int *, int *, int *, int *, int *, int *); void (*write_to_term)(void *, u_char *, size_t); #ifdef DEBUG void (*write_to_status_line)(void *, u_char *, size_t); #endif } ui_im_event_listener_t; /* * dirty hack to replace -export-dynamic option of libtool */ typedef struct ui_im_export_syms { void (*vt_str_init)(vt_char_t *, u_int); void (*vt_str_destroy)(vt_char_t *, u_int); vt_char_t *(*vt_char_combine)(vt_char_t *, u_int32_t, ef_charset_t, int, int, vt_color_t, vt_color_t, int, int, int, int, int); int (*vt_char_set)(vt_char_t *, u_int32_t, ef_charset_t cs, int, int, vt_color_t, vt_color_t, int, int, int, int, int); char *(*vt_get_char_encoding_name)(vt_char_encoding_t); vt_char_encoding_t (*vt_get_char_encoding)(const char *); int (*vt_convert_to_internal_ch)(void *, ef_char_t *); vt_isciikey_state_t (*vt_isciikey_state_new)(int); void (*vt_isciikey_state_destroy)(vt_isciikey_state_t); size_t (*vt_convert_ascii_to_iscii)(vt_isciikey_state_t, u_char *, size_t, u_char *, size_t); ef_parser_t *(*vt_char_encoding_parser_new)(vt_char_encoding_t); ef_conv_t *(*vt_char_encoding_conv_new)(vt_char_encoding_t); ui_im_candidate_screen_t *(*ui_im_candidate_screen_new)(ui_display_t *, ui_font_manager_t *, ui_color_manager_t *, void *, int, int, u_int, int, int); ui_im_status_screen_t *(*ui_im_status_screen_new)(ui_display_t *, ui_font_manager_t *, ui_color_manager_t *, void *, int, u_int, int, int); int (*ui_event_source_add_fd)(int, void (*handler)(void)); void (*ui_event_source_remove_fd)(int); KeySym (*XStringToKeysym)(char *); } ui_im_export_syms_t; /* * input method module object */ typedef struct ui_im { bl_dl_handle_t handle; char *name; ui_display_t *disp; ui_font_manager_t *font_man; ui_color_manager_t *color_man; void *vtparser; ui_im_event_listener_t *listener; ui_im_candidate_screen_t *cand_screen; ui_im_status_screen_t *stat_screen; ui_im_preedit_t preedit; /* * methods */ void (*destroy)(struct ui_im *); /* Return 1 if key event to be processed is still left. */ int (*key_event)(struct ui_im *, u_char, KeySym, XKeyEvent *); /* Return 1 if switching is succeeded. */ int (*switch_mode)(struct ui_im *); /* Return 1 if input method is active. */ int (*is_active)(struct ui_im *); void (*focused)(struct ui_im *); void (*unfocused)(struct ui_im *); } ui_im_t; ui_im_t *ui_im_new(ui_display_t *disp, ui_font_manager_t *font_man, ui_color_manager_t *color_man, void *vtparser, ui_im_event_listener_t *im_listener, char *input_method, u_int mod_ignore_mask); void ui_im_destroy(ui_im_t *xim); void ui_im_redraw_preedit(ui_im_t *im, int is_focused); #define IM_API_VERSION 0x0a #define IM_API_COMPAT_CHECK_MAGIC \ (((IM_API_VERSION & 0x0f) << 28) | ((sizeof(ui_im_t) & 0xff) << 20) | \ ((sizeof(ui_im_export_syms_t) & 0xff) << 12) | (sizeof(ui_im_candidate_screen_t) & 0xfff)) #endif mlterm-3.8.9/uitoolkit/ui_im_candidate_screen.c010064400017600000144000000637301356600660700203770ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_im_candidate_screen.h" #ifdef USE_IM_PLUGIN #include #include #include #include #include "ui_draw_str.h" #ifdef USE_CONSOLE #define MARGIN 0 #define LINE_SPACE 0 #else #define MARGIN 3 #define LINE_SPACE 2 #endif #define VISIBLE_INDEX(n, p, i, t, l) \ do { \ (t) = ((i) / p) * p; \ (l) = (t) + p - 1; \ if ((l) > (n)-1) { \ (l) = (n)-1; \ } \ } while (0) /* * calculate max number of digits */ #define NUM_OF_DIGITS(n, d) \ do { \ u_int d2 = (d); \ (n) = 1; \ while (((d2) /= 10)) { \ (n)++; \ } \ } while (0) #define INVALID_INDEX (cand_screen->num_candidates) #ifdef USE_WAYLAND #define DISPLAY(cand_screen) ((cand_screen)->window.disp->display->parent) #else #define DISPLAY(cand_screen) ((cand_screen)->window.disp) #endif /* --- static variables --- */ /* --- static functions --- */ static int free_candidates(ui_im_candidate_t *candidates, u_int num_candidates) { ui_im_candidate_t *c; int i; if (candidates == NULL || num_candidates == 0) { return 1; } for (i = 0, c = candidates; i < num_candidates; i++, c++) { vt_str_destroy(c->chars, c->num_chars); c->filled_len = 0; c->num_chars = 0; } free(candidates); return 1; } static u_int candidate_width(ui_font_manager_t *font_man, ui_im_candidate_t *candidate) { u_int width; int i; if (candidate->chars == NULL || candidate->filled_len == 0) { return 0; } width = 0; ui_font_manager_set_attr(font_man, 0, 0); for (i = 0; i < candidate->filled_len; i++) { ui_font_t *font; font = ui_get_font(font_man, vt_char_font(&candidate->chars[i])); width += ui_calculate_char_width(font, vt_char_code(&candidate->chars[i]), vt_char_cs(&candidate->chars[i]), NULL); } return width; } static u_int max_candidate_width(ui_font_manager_t *font_man, ui_im_candidate_t *candidates, u_int num_candidates) { u_int max_width; int i; max_width = 0; for (i = 0; i < num_candidates; i++) { u_int width; width = candidate_width(font_man, &candidates[i]); if (width > max_width) { max_width = width; } } return max_width; } static u_int total_candidate_width(ui_font_manager_t *font_man, ui_im_candidate_t *candidates, u_int to, u_int from) { u_int total_width; int i; total_width = 0; for (i = to; i <= from; i++) { total_width += candidate_width(font_man, &candidates[i]); } return total_width; } static void adjust_window_position_by_size(ui_im_candidate_screen_t *cand_screen, int *x, int *y) { #ifdef USE_WAYLAND if (ACTUAL_WIDTH(&cand_screen->window) > DISPLAY(cand_screen)->width) { /* do nothing */ } else #endif if (*x + ACTUAL_WIDTH(&cand_screen->window) > DISPLAY(cand_screen)->width) { if (cand_screen->is_vertical_term) { /* ui_im_candidate_screen doesn't know column width. */ *x -= (ACTUAL_WIDTH(&cand_screen->window) + cand_screen->line_height); } else { *x = DISPLAY(cand_screen)->width - ACTUAL_WIDTH(&cand_screen->window); } } #ifdef USE_WAYLAND if (ACTUAL_HEIGHT(&cand_screen->window) > DISPLAY(cand_screen)->height) { /* do nothing */ } else #endif if (*y + ACTUAL_HEIGHT(&cand_screen->window) > DISPLAY(cand_screen)->height) { *y -= ACTUAL_HEIGHT(&cand_screen->window); if (!cand_screen->is_vertical_term) { *y -= cand_screen->line_height; } } } static void resize(ui_im_candidate_screen_t *cand_screen, u_int width, u_int height) { if (ui_window_resize(&cand_screen->window, width, height, 0)) { int x; int y; x = cand_screen->x; y = cand_screen->y; adjust_window_position_by_size(cand_screen, &x, &y); if (x != cand_screen->window.x || y != cand_screen->window.y) { ui_window_move(&cand_screen->window, x, y); } #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF /* resized but position is not changed. */ ui_display_reset_input_method_window(); ui_window_draw_rect_frame(&cand_screen->window, -MARGIN, -MARGIN, cand_screen->window.width + MARGIN - 1, cand_screen->window.height + MARGIN - 1); #endif } } static void draw_str(ui_im_candidate_screen_t *cand_screen, vt_char_t *str, u_int len, int x, int row, u_int font_height, u_int font_ascent, int to_eol) { (to_eol ? ui_draw_str_to_eol : ui_draw_str)( &cand_screen->window, cand_screen->font_man, cand_screen->color_man, str, len, x, (font_height + LINE_SPACE) * row, font_height + LINE_SPACE, font_ascent + LINE_SPACE / 2, LINE_SPACE / 2, 1 /* no need to draw underline */, 0); } #define MAX_NUM_OF_DIGITS 4 /* max is 9999. enough? */ static void draw_screen_vertical(ui_im_candidate_screen_t *cand_screen, u_int top, u_int last, u_int draw_index, int do_resize) { ui_font_t *font; u_int i; u_int num_digits; u_int win_width; u_int win_height; vt_char_t *p; if (cand_screen->num_candidates > cand_screen->num_per_window) { NUM_OF_DIGITS(num_digits, cand_screen->num_per_window); } else { NUM_OF_DIGITS(num_digits, last); } /* * resize window */ /* * width : [digit] + [space] + [max_candidate_width] * or width of "index/total" * height: ([ascii height] + [line space]) x (num_per_window + 1) * or ([ascii height] + [line space)] x num_candidates * +-------------------+ * |1 cand0 |\ * |2 cand1 | \ * |3 cand2 | | * |4 cand3 | | * |5 cand4 | |-- num_per_window * |6 cand5 | | * |7 cand6 | | * |8 cand7 | | * |9 widest candidate| / * |10 cand9 |/ * | index/total |--> show if total > num_per_window * +-------------------+ */ font = ui_get_usascii_font(cand_screen->font_man); if (do_resize) { u_int width; u_int num; /* width of window */ win_width = font->width * (num_digits + 1); win_width += max_candidate_width(cand_screen->font_man, &cand_screen->candidates[top], last - top + 1); NUM_OF_DIGITS(num, cand_screen->num_candidates); if ((width = (num * 2 + 1) * font->width) > win_width) { win_width = width; } /* height of window */ if (cand_screen->num_candidates > cand_screen->num_per_window) { win_height = (font->height + LINE_SPACE) * (cand_screen->num_per_window + 1); } else { win_height = (font->height + LINE_SPACE) * cand_screen->num_candidates; } resize(cand_screen, win_width, win_height); } else { win_width = cand_screen->window.width; win_height = cand_screen->window.height; } /* * digits and candidates */ #ifdef DEBUG if (num_digits > MAX_NUM_OF_DIGITS) { bl_warn_printf(BL_DEBUG_TAG " num_digits %d is too large.\n", num_digits); return; } #endif if (draw_index != INVALID_INDEX) { i = draw_index; last = draw_index; } else { i = top; } for (; i <= last; i++) { u_char digit[MAX_NUM_OF_DIGITS + 1]; vt_char_t digit_str[MAX_NUM_OF_DIGITS + 1]; int j; /* * digits * +----------+ * |1 cand0 | * ^^ */ if (cand_screen->candidates[i].info) { char byte2; byte2 = (cand_screen->candidates[i].info >> 8) & 0xff; if (num_digits > 2) { num_digits = 2; } bl_snprintf(digit, MAX_NUM_OF_DIGITS + 1, "%c%c ", cand_screen->candidates[i].info & 0xff, byte2 ? byte2 : ' '); } else { bl_snprintf(digit, MAX_NUM_OF_DIGITS + 1, "%i ", i - top + 1); } p = digit_str; for (j = 0; j < num_digits + 1; j++) { vt_char_init(p); vt_char_set(p++, digit[j], US_ASCII, 0, 0, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0); } draw_str(cand_screen, digit_str, num_digits + 1, 0, i - top, font->height, font->ascent, 0); vt_str_final(digit_str, num_digits + 1); /* * candidate * +----------+ * |1 cand0 | * ^^^^^ */ draw_str(cand_screen, cand_screen->candidates[i].chars, cand_screen->candidates[i].filled_len, font->width * (num_digits + 1), i - top, font->height, font->ascent, 1); } if (draw_index != INVALID_INDEX) { return; } /* * |7 cand6 | * |8 last candidate| * | |\ * | | }-- clear this area * | |/ * +----------------+ */ if (cand_screen->num_candidates > cand_screen->num_per_window && last - top < cand_screen->num_per_window) { u_int y; y = (font->height + LINE_SPACE) * (last - top + 1); ui_window_clear(&cand_screen->window, 0, y, win_width, win_height - y - 1); } /* * |8 cand7 | * |9 cand8 | * |10 cand9 | * | index/total | <-- draw this * +-------------+ */ if (cand_screen->num_candidates > cand_screen->num_per_window) { u_char navi[MAX_NUM_OF_DIGITS * 2 + 4]; vt_char_t navi_str[MAX_NUM_OF_DIGITS * 2 + 4]; u_int width; size_t len; int x; #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF ui_window_clear(&cand_screen->window, 0, (font->height + LINE_SPACE) * cand_screen->num_per_window + LINE_SPACE, win_width, font->height); #endif len = bl_snprintf(navi, MAX_NUM_OF_DIGITS * 2 + 2, "%d/%d", cand_screen->index + 1, cand_screen->num_candidates); width = len * font->width; x = (win_width - width) / 2; /* centering */ p = navi_str; for (i = 0; i < len; i++) { vt_char_init(p); vt_char_set(p++, navi[i], US_ASCII, 0, 0, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0); } draw_str(cand_screen, navi_str, len, x, cand_screen->num_per_window, font->height, font->ascent, 0); vt_str_final(navi_str, len); } } static void draw_screen_horizontal(ui_im_candidate_screen_t *cand_screen, u_int top, u_int last, u_int draw_index, int do_resize) { ui_font_t *font; u_int win_width; u_int win_height; u_int i; int x = 0; u_int num_digits; u_char digit[MAX_NUM_OF_DIGITS + 1]; vt_char_t digit_str[MAX_NUM_OF_DIGITS + 1]; vt_char_t *p; /* * resize window */ /* * +-------------------------------------+ * |1:cand0 2:cand1 3:cand4 ... 10:cand9 | * +-------------------------------------+ */ font = ui_get_usascii_font(cand_screen->font_man); if (do_resize) { /* width of window */ win_width = 0; for (i = top; i <= last; i++) { if (cand_screen->candidates[i].info) { if (((cand_screen->candidates[i].info >> 8) & 0xff) != 0) { num_digits = 2; } else { num_digits = 1; } } else { NUM_OF_DIGITS(num_digits, i); } win_width += font->width * (num_digits + 2); } win_width += total_candidate_width(cand_screen->font_man, cand_screen->candidates, top, last); /* height of window */ win_height = font->height + LINE_SPACE; resize(cand_screen, win_width, win_height); } else { win_width = cand_screen->window.width; win_height = cand_screen->window.height; } for (i = top; i <= last; i++) { int j; /* * digits * +--------------- * |1:cand0 2:cand1 * ^^ */ NUM_OF_DIGITS(num_digits, i); if (cand_screen->candidates[i].info) { char byte2; if ((byte2 = (cand_screen->candidates[i].info >> 8) & 0xff) != 0) { num_digits = 2; bl_snprintf(digit, MAX_NUM_OF_DIGITS + 1, "%c%c.", cand_screen->candidates[i].info, byte2); } else { num_digits = 1; bl_snprintf(digit, MAX_NUM_OF_DIGITS + 1, "%c.", cand_screen->candidates[i].info); } } else { bl_snprintf(digit, MAX_NUM_OF_DIGITS + 1, "%i.", i - top + 1); } p = digit_str; for (j = 0; j < num_digits + 1; j++) { vt_char_init(p); vt_char_set(p++, digit[j], US_ASCII, 0, 0, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0); } if (draw_index != INVALID_INDEX) { if (i < draw_index) { x += (font->width * (num_digits + 2) + candidate_width(cand_screen->font_man, &cand_screen->candidates[i])); continue; } else /* if( i == draw_index) */ { last = draw_index; } } draw_str(cand_screen, digit_str, num_digits + 1, x, 0, font->height, font->ascent, 0); x += font->width * (num_digits + 1); vt_str_final(digit_str, num_digits + 1); /* * candidate * +--------------- * |1:cand0 2:cand2 * ^^^^^ */ draw_str(cand_screen, cand_screen->candidates[i].chars, cand_screen->candidates[i].filled_len, x, 0, font->height, font->ascent, 0); x += candidate_width(cand_screen->font_man, &cand_screen->candidates[i]); /* * +--------------- * |1:cand0 2:cand2 * ^ */ ui_window_clear(&cand_screen->window, x, LINE_SPACE / 2, font->width, win_height - LINE_SPACE); x += font->width; } } static void draw_screen(ui_im_candidate_screen_t *cand_screen, u_int old_index, int do_resize) { u_int top; u_int last; VISIBLE_INDEX(cand_screen->num_candidates, cand_screen->num_per_window, cand_screen->index, top, last); if (old_index != cand_screen->index && old_index != INVALID_INDEX) { u_int old_top; u_int old_last; VISIBLE_INDEX(cand_screen->num_candidates, cand_screen->num_per_window, old_index, old_top, old_last); if (old_top == top && old_last == last) { if (cand_screen->is_vertical_direction) { draw_screen_vertical(cand_screen, top, last, old_index, 0); draw_screen_vertical(cand_screen, top, last, cand_screen->index, 0); } else { draw_screen_horizontal(cand_screen, top, last, old_index, 0); draw_screen_horizontal(cand_screen, top, last, cand_screen->index, 0); } goto end; } } if (cand_screen->is_vertical_direction) { draw_screen_vertical(cand_screen, top, last, INVALID_INDEX, do_resize); } else { draw_screen_horizontal(cand_screen, top, last, INVALID_INDEX, do_resize); } end: ui_window_flush(&cand_screen->window); } static void adjust_window_x_position(ui_im_candidate_screen_t *cand_screen, int *x) { u_int top; u_int last; u_int num_digits; if (cand_screen->is_vertical_term) { return; } VISIBLE_INDEX(cand_screen->num_candidates, cand_screen->num_per_window, cand_screen->index, top, last); if (cand_screen->is_vertical_direction) { if (cand_screen->num_candidates > cand_screen->num_per_window) { NUM_OF_DIGITS(num_digits, cand_screen->num_per_window); } else { NUM_OF_DIGITS(num_digits, last); } } else { num_digits = 1; } if (num_digits) { *x -= (ui_get_usascii_font(cand_screen->font_man)->width * (num_digits + 1) + MARGIN); if (*x < 0) { *x = 0; } } } /* * methods of ui_im_candidate_screen_t */ static void destroy(ui_im_candidate_screen_t *cand_screen) { free_candidates(cand_screen->candidates, cand_screen->num_candidates); ui_display_remove_root(cand_screen->window.disp, &cand_screen->window); #ifdef USE_REAL_VERTICAL_FONT if (cand_screen->is_vertical_term) { ui_font_manager_destroy(cand_screen->font_man); } #endif free(cand_screen); } static void show(ui_im_candidate_screen_t *cand_screen) { ui_window_map(&cand_screen->window); } static void hide(ui_im_candidate_screen_t *cand_screen) { ui_window_unmap(&cand_screen->window); } static int set_spot(ui_im_candidate_screen_t *cand_screen, int x, int y) { adjust_window_x_position(cand_screen, &x); cand_screen->x = x; cand_screen->y = y; adjust_window_position_by_size(cand_screen, &x, &y); if (cand_screen->window.x != x || cand_screen->window.y != y) { ui_window_move(&cand_screen->window, x, y); return 1; } else { return 0; } } static int init_candidates(ui_im_candidate_screen_t *cand_screen, u_int num_candidates, u_int num_per_window) { if (cand_screen->candidates) { free_candidates(cand_screen->candidates, cand_screen->num_candidates); cand_screen->candidates = NULL; } cand_screen->num_candidates = num_candidates; cand_screen->num_per_window = num_per_window; /* allocate candidates(ui_im_candidate_t) array */ if ((cand_screen->candidates = calloc(sizeof(ui_im_candidate_t), cand_screen->num_candidates)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " calloc failed.\n"); #endif cand_screen->num_candidates = 0; cand_screen->num_per_window = 0; return 0; } cand_screen->index = 0; cand_screen->need_redraw = 1; return 1; } static int set_candidate(ui_im_candidate_screen_t *cand_screen, ef_parser_t *parser, u_char *str, u_int index /* 16bit: info, 16bit: index */ ) { int count = 0; ef_char_t ch; vt_char_t *p; u_short info; info = index >> 16; index &= 0xFF; if (index >= cand_screen->num_candidates) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " index of candidates is too large number " "[num_candidates: %d, index: %d]\n", cand_screen->num_candidates, index); #endif return 0; } cand_screen->candidates[index].info = info; /* * count number of characters to allocate candidates[index].chars */ (*parser->init)(parser); (*parser->set_str)(parser, str, strlen(str)); while ((*parser->next_char)(parser, &ch)) { count++; } if (cand_screen->candidates[index].chars) { vt_str_destroy(cand_screen->candidates[index].chars, cand_screen->candidates[index].num_chars); cand_screen->candidates[index].filled_len = 0; } if (!(cand_screen->candidates[index].chars = vt_str_new(count))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_str_new() failed.\n"); #endif cand_screen->candidates[index].num_chars = 0; return 0; } cand_screen->candidates[index].num_chars = count; /* * im encoding -> term encoding */ (*parser->init)(parser); (*parser->set_str)(parser, str, strlen(str)); p = cand_screen->candidates[index].chars; vt_str_init(p, cand_screen->candidates[index].num_chars); while ((*parser->next_char)(parser, &ch)) { int is_fullwidth = 0; int is_comb = 0; if (vt_convert_to_internal_ch(cand_screen->vtparser, &ch) <= 0) { continue; } if (ch.property & EF_FULLWIDTH) { is_fullwidth = 1; } else if (ch.property & EF_AWIDTH) { /* TODO: check col_size_of_width_a */ is_fullwidth = 1; } if (ch.property & EF_COMBINING) { is_comb = 1; if (vt_char_combine(p - 1, ef_char_to_int(&ch), ch.cs, is_fullwidth, is_comb, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0)) { continue; } /* * if combining failed , char is normally appended. */ } vt_char_set(p, ef_char_to_int(&ch), ch.cs, is_fullwidth, is_comb, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0); p++; cand_screen->candidates[index].filled_len++; } cand_screen->need_redraw = 1; return 1; } static int select_candidate(ui_im_candidate_screen_t *cand_screen, u_int index) { ui_im_candidate_t *cand; u_int i; u_int old_index; if (index >= cand_screen->num_candidates) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Selected index [%d] is larger than number of candidates [%d].\n", index, cand_screen->num_candidates); #endif return 0; } cand = &cand_screen->candidates[cand_screen->index]; if (cand->chars) { for (i = 0; i < cand->filled_len; i++) { vt_char_set_fg_color(&cand->chars[i], VT_FG_COLOR); vt_char_set_bg_color(&cand->chars[i], VT_BG_COLOR); } } cand = &cand_screen->candidates[index]; if (cand->chars) { for (i = 0; i < cand->filled_len; i++) { vt_char_set_fg_color(&cand->chars[i], VT_BG_COLOR); vt_char_set_bg_color(&cand->chars[i], VT_FG_COLOR); } } if (cand_screen->need_redraw) { old_index = INVALID_INDEX; cand_screen->need_redraw = 0; } else { old_index = cand_screen->index; } cand_screen->index = index; draw_screen(cand_screen, old_index, 1); return 1; } /* * callbacks of ui_window events */ static void window_realized(ui_window_t *win) { ui_im_candidate_screen_t *cand_screen; cand_screen = (ui_im_candidate_screen_t *)win; ui_window_set_type_engine(&cand_screen->window, ui_get_type_engine(cand_screen->font_man)); ui_window_set_fg_color(win, ui_get_xcolor(cand_screen->color_man, VT_FG_COLOR)); ui_window_set_bg_color(win, ui_get_xcolor(cand_screen->color_man, VT_BG_COLOR)); ui_window_set_override_redirect(&cand_screen->window, 1); } static void window_exposed(ui_window_t *win, int x, int y, u_int width, u_int height) { ui_im_candidate_screen_t *cand_screen; cand_screen = (ui_im_candidate_screen_t *)win; if (cand_screen->num_candidates > 0) { draw_screen(cand_screen, INVALID_INDEX, 0); } cand_screen->need_redraw = 0; /* draw border (margin area has been already cleared in ui_window.c) */ ui_window_draw_rect_frame(win, -MARGIN, -MARGIN, win->width + MARGIN - 1, win->height + MARGIN - 1); } static void button_pressed(ui_window_t *win, XButtonEvent *event, int click_num) { ui_im_candidate_screen_t *cand_screen; u_int index; u_int top; u_int last; cand_screen = (ui_im_candidate_screen_t *)win; if (event->button != 1) { return; } if (!cand_screen->listener.selected) { return; } VISIBLE_INDEX(cand_screen->num_candidates, cand_screen->num_per_window, cand_screen->index, top, last); index = event->y / (ui_get_usascii_font(cand_screen->font_man)->height + LINE_SPACE); index += top; if (!select_candidate(cand_screen, index)) { return; } (*cand_screen->listener.selected)(cand_screen->listener.self, index); } /* --- global functions --- */ ui_im_candidate_screen_t *ui_im_candidate_screen_new(ui_display_t *disp, ui_font_manager_t *font_man, ui_color_manager_t *color_man, void *vtparser, int is_vertical_term, int is_vertical_direction, u_int line_height_of_screen, int x, int y) { ui_im_candidate_screen_t *cand_screen; if ((cand_screen = calloc(1, sizeof(ui_im_candidate_screen_t))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc failed.\n"); #endif return NULL; } #ifdef USE_REAL_VERTICAL_FONT if (is_vertical_term) { cand_screen->font_man = ui_font_manager_new(disp->display, ui_get_type_engine(font_man), ui_get_font_present(font_man) & ~FONT_VERTICAL, ui_get_font_size(font_man), ui_get_current_usascii_font_cs(font_man), font_man->step_in_changing_font_size, ui_get_letter_space(font_man), ui_is_using_bold_font(font_man), ui_is_using_italic_font(font_man)); } else #endif { cand_screen->font_man = font_man; } cand_screen->color_man = color_man; cand_screen->vtparser = vtparser; cand_screen->x = x; cand_screen->y = y; cand_screen->line_height = line_height_of_screen; cand_screen->is_vertical_term = is_vertical_term; cand_screen->is_vertical_direction = is_vertical_direction; if (!ui_window_init(&cand_screen->window, MARGIN * 2, MARGIN * 2, MARGIN * 2, MARGIN * 2, 0, 0, MARGIN, MARGIN, /* ceate_gc */ 1, 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ui_window_init failed.\n"); #endif goto error; } ui_window_add_event_mask(&cand_screen->window, ButtonPressMask | ButtonReleaseMask); /* * +------------+ * | ui_window.c | --- window events ---> +-------------------------+ * +------------+ | ui_im_candidate_screen.c | * +------------+ ----- methods ------> +-------------------------+ * | im plugin | <---- callbacks ------ * +------------+ */ /* callbacks for window events */ cand_screen->window.window_realized = window_realized; #if 0 cand_screen->window.window_finalized = window_finalized; #endif cand_screen->window.window_exposed = window_exposed; #if 0 cand_screen->window.button_released = button_released; #endif cand_screen->window.button_pressed = button_pressed; #if 0 cand_screen->window.button_press_continued = button_press_continued; cand_screen->window.window_destroyed = window_destroyed; cand_screen->window.mapping_notify = mapping_notify; #endif /* methods of ui_im_candidate_screen_t */ cand_screen->destroy = destroy; cand_screen->show = show; cand_screen->hide = hide; cand_screen->set_spot = set_spot; cand_screen->init = init_candidates; cand_screen->set = set_candidate; cand_screen->select = select_candidate; if (!ui_display_show_root(disp, &cand_screen->window, x, y, XValue | YValue, "mlterm-candidate-window", 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ui_display_show_root() failed.\n"); #endif goto error; } return cand_screen; error: free(cand_screen); return NULL; } #else /* ! USE_IM_PLUGIN */ ui_im_candidate_screen_t *ui_im_candidate_screen_new( ui_display_t *disp, ui_font_manager_t *font_man, ui_color_manager_t *color_man, void *vtparser, int is_vertical_term, int is_vertical_direction, u_int line_height_of_screen, int x, int y) { return NULL; } #endif mlterm-3.8.9/uitoolkit/ui_im_candidate_screen.h010064400017600000144000000046221356600660700203770ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_IM_CANDIDATE_SCREEN_H__ #define __UI_IM_CANDIDATE_SCREEN_H__ #include #include "ui_window.h" #include "ui_display.h" #include "ui_font_manager.h" #include "ui_color_manager.h" typedef struct ui_im_candidate { u_short info; /* to store misc. info from IM plugins */ vt_char_t *chars; u_int num_chars; /* == array size */ u_int filled_len; } ui_im_candidate_t; typedef struct ui_im_candidate_event_listener { void *self; void (*selected)(void *p, u_int index); } ui_im_candidate_event_listener_t; typedef struct ui_im_candidate_screen { ui_window_t window; ui_font_manager_t *font_man; /* same as attached screen */ ui_color_manager_t *color_man; /* same as attached screen */ void *vtparser; /* same as attached screen */ ui_im_candidate_t *candidates; u_int num_candidates; /* == array size */ u_int num_per_window; u_int index; /* current selected index of candidates */ int x; /* not adjusted by window size */ int y; /* not adjusted by window size */ u_int line_height; /* line height of attaced screen */ int8_t is_vertical_term; int8_t is_vertical_direction; int8_t need_redraw; /* ui_im_candidate_screen.c -> im plugins */ ui_im_candidate_event_listener_t listener; /* * methods for ui_im_candidate_screen_t which is called from im */ void (*destroy)(struct ui_im_candidate_screen *); void (*show)(struct ui_im_candidate_screen *); void (*hide)(struct ui_im_candidate_screen *); int (*set_spot)(struct ui_im_candidate_screen *, int, int); int (*init)(struct ui_im_candidate_screen *, u_int, u_int); int (*set)(struct ui_im_candidate_screen *, ef_parser_t *, u_char *, u_int); int (*select)(struct ui_im_candidate_screen *cand_screen, u_int); } ui_im_candidate_screen_t; ui_im_candidate_screen_t *ui_im_candidate_screen_new(ui_display_t *disp, ui_font_manager_t *font_man, ui_color_manager_t *color_man, void *vtparser, int is_vertical_term, int is_vertical_direction, u_int line_height_of_screen, int x, int y); #endif mlterm-3.8.9/uitoolkit/ui_im_status_screen.c010064400017600000144000000344671356600660700200130ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_im_status_screen.h" #ifdef USE_IM_PLUGIN #ifdef USE_SDL2 #define USE_STATUS_LINE #endif #ifndef USE_STATUS_LINE #include #include #include #include "ui_draw_str.h" #ifdef USE_CONSOLE #define MARGIN 0 #define LINE_SPACE 0 #else #define MARGIN 3 #define LINE_SPACE 2 #endif #ifdef USE_WAYLAND #define DISPLAY(stat_screen) ((stat_screen)->window.disp->display->parent) #else #define DISPLAY(stat_screen) ((stat_screen)->window.disp) #endif /* --- static functions --- */ static void adjust_window_position_by_size(ui_im_status_screen_t *stat_screen, int *x, int *y) { #ifdef USE_WAYLAND if (ACTUAL_HEIGHT(&stat_screen->window) > DISPLAY(stat_screen)->height) { /* do nothing */ } else #endif if (*y + ACTUAL_HEIGHT(&stat_screen->window) > DISPLAY(stat_screen)->height) { *y -= ACTUAL_HEIGHT(&stat_screen->window); if (!stat_screen->is_vertical) { *y -= stat_screen->line_height; } } #ifdef USE_WAYLAND if (ACTUAL_WIDTH(&stat_screen->window) > DISPLAY(stat_screen)->width) { /* do nothing */ } else #endif if (*x + ACTUAL_WIDTH(&stat_screen->window) > DISPLAY(stat_screen)->width) { if (stat_screen->is_vertical) { /* ui_im_stat_screen doesn't know column width. */ *x -= (ACTUAL_WIDTH(&stat_screen->window) + stat_screen->line_height); } else { *x = DISPLAY(stat_screen)->width - ACTUAL_WIDTH(&stat_screen->window); } } } #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF static void reset_screen(ui_window_t *win) { ui_display_reset_input_method_window(); ui_window_draw_rect_frame(win, -MARGIN, -MARGIN, win->width + MARGIN - 1, win->height + MARGIN - 1); } #endif static int is_nl(vt_char_t *ch) { return vt_char_cs(ch) == US_ASCII && vt_char_code(ch) == '\n'; } static void draw_screen(ui_im_status_screen_t *stat_screen, int do_resize, int modified_beg /* for canna */ ) { #define MAX_ROWS ((sizeof(stat_screen->head_indexes) / sizeof(stat_screen->head_indexes[0])) - 1) ui_font_t *font; u_int line_height; int *heads; u_int i; ui_font_manager_set_attr(stat_screen->font_man, 0, 0); font = ui_get_usascii_font(stat_screen->font_man); line_height = font->height + LINE_SPACE; heads = stat_screen->head_indexes; /* * resize window */ /* width of window */ if (do_resize) { u_int max_width; u_int tmp_max_width; u_int width; u_int rows; /* The minimum width of normal display is regarded as 640. */ if ((max_width = DISPLAY(stat_screen)->width / 2) < 320) { max_width = 320; } tmp_max_width = 0; width = 0; heads[0] = 0; rows = 1; for (i = 0; i < stat_screen->filled_len; i++) { if (is_nl(&stat_screen->chars[i]) && rows < MAX_ROWS - 1) { if (rows == 1 || tmp_max_width < width) { tmp_max_width = width; } heads[rows++] = i + 1; width = 0; } else { u_int ch_width; ch_width = ui_calculate_char_width( ui_get_font(stat_screen->font_man, vt_char_font(&stat_screen->chars[i])), vt_char_code(&stat_screen->chars[i]), vt_char_cs(&stat_screen->chars[i]), NULL); if (width + ch_width > max_width) { if (rows == 1 || tmp_max_width < width) { tmp_max_width = width; } heads[rows++] = i; if (rows == MAX_ROWS) { /* Characters after max_width at the last line are never shown. */ break; } width = ch_width; } else { width += ch_width; } } } if (width < tmp_max_width) { width = tmp_max_width; } /* for following 'heads[i + 1] - heads[i]' */ heads[rows] = stat_screen->filled_len; if (ui_window_resize(&stat_screen->window, width, line_height * rows, 0)) { int x; int y; x = stat_screen->x; y = stat_screen->y; adjust_window_position_by_size(stat_screen, &x, &y); if (stat_screen->window.x != x || stat_screen->window.y != y) { ui_window_move(&stat_screen->window, x, y); } #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF reset_screen(&stat_screen->window); #endif modified_beg = 0; } } for (i = 0; heads[i] < stat_screen->filled_len; i++) { if (heads[i + 1] > modified_beg) { u_int len; len = heads[i + 1] - heads[i]; if (is_nl(&stat_screen->chars[heads[i + 1] - 1])) { len--; } ui_draw_str_to_eol(&stat_screen->window, stat_screen->font_man, stat_screen->color_man, stat_screen->chars + heads[i], len, 0, line_height * i, line_height, font->ascent + LINE_SPACE / 2, LINE_SPACE / 2, 1 /* no need to draw underline */, 0); } } ui_window_flush(&stat_screen->window); } /* * methods of ui_im_status_screen_t */ static void destroy(ui_im_status_screen_t *stat_screen) { ui_display_remove_root(stat_screen->window.disp, &stat_screen->window); if (stat_screen->chars) { vt_str_destroy(stat_screen->chars, stat_screen->num_chars); } #ifdef USE_REAL_VERTICAL_FONT if (stat_screen->is_vertical) { ui_font_manager_destroy(stat_screen->font_man); } #endif free(stat_screen); } static void show(ui_im_status_screen_t *stat_screen) { ui_window_map(&stat_screen->window); } static void hide(ui_im_status_screen_t *stat_screen) { ui_window_unmap(&stat_screen->window); } static int set_spot(ui_im_status_screen_t *stat_screen, int x, int y) { stat_screen->x = x; stat_screen->y = y; adjust_window_position_by_size(stat_screen, &x, &y); if (stat_screen->window.x != x || stat_screen->window.y != y) { ui_window_move(&stat_screen->window, x, y); #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF reset_screen(&stat_screen->window); draw_screen(stat_screen, 0, 0); #endif return 1; } else { return 0; } } static int set(ui_im_status_screen_t *stat_screen, ef_parser_t *parser, u_char *str) { int count; ef_char_t ch; vt_char_t *p; vt_char_t *old_chars; u_int old_num_chars; u_int old_filled_len; int modified_beg; /* * count number of characters to allocate status[index].chars */ (*parser->init)(parser); (*parser->set_str)(parser, str, strlen(str)); for (count = 0; (*parser->next_char)(parser, &ch); count++) ; old_chars = stat_screen->chars; old_num_chars = stat_screen->num_chars; old_filled_len = stat_screen->filled_len; if (!(stat_screen->chars = vt_str_new(count))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " vt_str_new() failed.\n"); #endif return 0; } stat_screen->num_chars = count; stat_screen->filled_len = 0; /* * u_char -> vt_char_t */ (*parser->init)(parser); (*parser->set_str)(parser, str, strlen(str)); p = stat_screen->chars; vt_str_init(p, stat_screen->num_chars); while ((*parser->next_char)(parser, &ch)) { int is_fullwidth = 0; int is_comb = 0; /* -1 (== control sequence) is permitted for \n. */ if (!vt_convert_to_internal_ch(stat_screen->vtparser, &ch)) { continue; } if (ch.property & EF_FULLWIDTH) { is_fullwidth = 1; } else if (ch.property & EF_AWIDTH) { /* TODO: check col_size_of_width_a */ is_fullwidth = 1; } if (is_comb) { if (vt_char_combine(p - 1, ef_char_to_int(&ch), ch.cs, is_fullwidth, is_comb, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0)) { continue; } /* * if combining failed , char is normally appended. */ } if (vt_is_msb_set(ch.cs)) { SET_MSB(ch.ch[0]); } vt_char_set(p, ef_char_to_int(&ch), ch.cs, is_fullwidth, is_comb, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0); p++; stat_screen->filled_len++; } for (modified_beg = 0; modified_beg < stat_screen->filled_len && modified_beg < old_filled_len && vt_char_code_equal(old_chars + modified_beg, stat_screen->chars + modified_beg); modified_beg++) ; if (old_chars) { vt_str_destroy(old_chars, old_num_chars); } if (modified_beg < old_filled_len || old_filled_len != stat_screen->filled_len) { draw_screen(stat_screen, 1, modified_beg); } return 1; } /* * callbacks of ui_window events */ static void window_realized(ui_window_t *win) { ui_im_status_screen_t *stat_screen; stat_screen = (ui_im_status_screen_t *)win; ui_window_set_type_engine(&stat_screen->window, ui_get_type_engine(stat_screen->font_man)); ui_window_set_fg_color(win, ui_get_xcolor(stat_screen->color_man, VT_FG_COLOR)); ui_window_set_bg_color(win, ui_get_xcolor(stat_screen->color_man, VT_BG_COLOR)); ui_window_set_override_redirect(&stat_screen->window, 1); } static void window_exposed(ui_window_t *win, int x, int y, u_int width, u_int height) { draw_screen((ui_im_status_screen_t *)win, 0, 0); /* draw border (margin area has been already cleared in ui_window.c) */ ui_window_draw_rect_frame(win, -MARGIN, -MARGIN, win->width + MARGIN - 1, win->height + MARGIN - 1); } /* --- global functions --- */ ui_im_status_screen_t *ui_im_status_screen_new(ui_display_t *disp, ui_font_manager_t *font_man, ui_color_manager_t *color_man, void *vtparser, int is_vertical, u_int line_height, int x, int y) { ui_im_status_screen_t *stat_screen; if ((stat_screen = calloc(1, sizeof(ui_im_status_screen_t))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc failed.\n"); #endif return NULL; } #ifdef USE_REAL_VERTICAL_FONT if (is_vertical) { stat_screen->font_man = ui_font_manager_new(disp->display, ui_get_type_engine(font_man), ui_get_font_present(font_man) & ~FONT_VERTICAL, ui_get_font_size(font_man), ui_get_current_usascii_font_cs(font_man), font_man->step_in_changing_font_size, ui_get_letter_space(font_man), ui_is_using_bold_font(font_man), ui_is_using_italic_font(font_man)); } else #endif { stat_screen->font_man = font_man; } stat_screen->color_man = color_man; stat_screen->vtparser = vtparser; stat_screen->x = x; stat_screen->y = y; stat_screen->line_height = line_height; stat_screen->is_vertical = is_vertical; if (!ui_window_init(&stat_screen->window, MARGIN * 2, MARGIN * 2, MARGIN * 2, MARGIN * 2, 0, 0, MARGIN, MARGIN, /* ceate_gc */ 1, 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ui_window_init failed.\n"); #endif goto error; } /* * +------------+ * | ui_window.c | --- window events ---> +----------------------+ * +------------+ | ui_im_status_screen.c | * +------------+ +----------------------+ * | im plugin | <------ methods ------ * +------------+ */ /* callbacks for window events */ stat_screen->window.window_realized = window_realized; #if 0 stat_screen->window.window_finalized = window_finalized; #endif stat_screen->window.window_exposed = window_exposed; /* methods of ui_im_status_screen_t */ stat_screen->destroy = destroy; stat_screen->show = show; stat_screen->hide = hide; stat_screen->set_spot = set_spot; stat_screen->set = set; if (!ui_display_show_root(disp, &stat_screen->window, x, y, XValue | YValue, "mlterm-status-window", 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ui_display_show_root() failed.\n"); #endif goto error; } return stat_screen; error: free(stat_screen); return NULL; } #else /* USE_STATUS_LINE */ #include #include /* --- static functions --- */ static void destroy(ui_im_status_screen_t *stat_screen) { vt_parser_write_loopback(stat_screen->vtparser, "\x1b[0$~", 5); free(stat_screen); } static void show(ui_im_status_screen_t *stat_screen) {} static void hide(ui_im_status_screen_t *stat_screen) { vt_parser_write_loopback(stat_screen->vtparser, "\x1b[0$~", 5); } static int set_spot(ui_im_status_screen_t *stat_screen, int x, int y) { return 1; } static void replace_char(char *str, char orig, char new) { char *p; for (p = str; *p; p++) { if (*p == orig) { *p = new; } } } static int set(ui_im_status_screen_t *stat_screen, ef_parser_t *parser, u_char *str) { u_char *seq; size_t len = strlen(str); if ((seq = alloca(27 + len))) { replace_char(str, '\n', ' '); memcpy(seq, "\x1b[2$~\x1b[1$}\x1b[?7l\x1b[2J\x1b[H", 22); memcpy(seq + 22, str, len); memcpy(seq + 22 + len, "\x1b[0$}", 5); vt_parser_write_loopback(stat_screen->vtparser, seq, 27 + len); } return 1; } /* --- global functions --- */ ui_im_status_screen_t *ui_im_status_screen_new(ui_display_t *disp, ui_font_manager_t *font_man, ui_color_manager_t *color_man, void *vtparser, int is_vertical, u_int line_height, int x, int y) { ui_im_status_screen_t *stat_screen; if ((stat_screen = calloc(1, sizeof(ui_im_status_screen_t))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc failed.\n"); #endif return NULL; } stat_screen->font_man = font_man; stat_screen->color_man = color_man; stat_screen->vtparser = vtparser; stat_screen->x = x; stat_screen->y = y; stat_screen->line_height = line_height; stat_screen->is_vertical = is_vertical; /* methods of ui_im_status_screen_t */ stat_screen->destroy = destroy; stat_screen->show = show; stat_screen->hide = hide; stat_screen->set_spot = set_spot; stat_screen->set = set; return stat_screen; } #endif /* USE_STATUS_LINE */ #else /* ! USE_IM_PLUGIN */ ui_im_status_screen_t *ui_im_status_screen_new(ui_display_t *disp, ui_font_manager_t *font_man, ui_color_manager_t *color_man, void *vtparser, int is_vertical, u_int line_height, int x, int y) { return NULL; } #endif mlterm-3.8.9/uitoolkit/ui_im_status_screen.h010064400017600000144000000030001356600660700177730ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_IM_STATUS_SCREEN_H__ #define __UI_IM_STATUS_SCREEN_H__ #include #include "ui_window.h" #include "ui_display.h" #include "ui_font_manager.h" #include "ui_color_manager.h" typedef struct ui_im_status_screen { ui_window_t window; ui_font_manager_t *font_man; /* is the same as attached screen */ ui_color_manager_t *color_man; /* is the same as attached screen */ void *vtparser; /* is the same as attached screen */ vt_char_t *chars; u_int num_chars; /* == array size */ u_int filled_len; int x; /* not adjusted by window size */ int y; /* not adjusted by window size */ u_int line_height; /* line height of attaced screen */ int is_vertical; /* * methods of ui_im_status_screen_t which is called from im */ void (*destroy)(struct ui_im_status_screen *); void (*show)(struct ui_im_status_screen *); void (*hide)(struct ui_im_status_screen *); int (*set_spot)(struct ui_im_status_screen *, int, int); int (*set)(struct ui_im_status_screen *, ef_parser_t *, u_char *); int head_indexes[15]; /* 14 lines (13 candidates and N/N) + 1 */ } ui_im_status_screen_t; ui_im_status_screen_t *ui_im_status_screen_new(ui_display_t *disp, ui_font_manager_t *font_man, ui_color_manager_t *color_man, void *vtparser, int is_vertical, u_int line_height, int x, int y); #endif mlterm-3.8.9/uitoolkit/ui_imagelib.h010064400017600000144000000021501356600660700162020ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_IMAGELIB_H__ #define __UI_IMAGELIB_H__ #include "ui_window.h" #include "ui_picture.h" typedef struct _GdkPixbuf* GdkPixbufPtr; void ui_imagelib_display_opened(Display *disp); void ui_imagelib_display_closed(Display *disp); Pixmap ui_imagelib_load_file_for_background(ui_window_t *win, char *path, ui_picture_modifier_t *pic_mod); Pixmap ui_imagelib_get_transparent_background(ui_window_t *win, ui_picture_modifier_t *pic_mod); int ui_imagelib_load_file(ui_display_t *disp, char *path, u_int32_t **cardinal, Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height, int keep_aspect); Pixmap ui_imagelib_pixbuf_to_pixmap(ui_window_t *win, ui_picture_modifier_t *pic_mod, GdkPixbufPtr pixbuf); void ui_destroy_image(Display *display, Pixmap pixmap); #ifdef USE_XLIB #define ui_destroy_mask(display, mask) ((mask) ? ui_destroy_image(display, mask) : 0) #else void ui_destroy_mask(Display *display, PixmapMask mask); #endif #endif mlterm-3.8.9/uitoolkit/ui_layout.c010064400017600000144000001364501356600660700157540ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_layout.h" #include /* u_int */ #include #ifdef USE_BEOS void view_reset_uiwindow(ui_window_t *uiwindow); #endif #ifdef USE_CONSOLE static u_int dummy_arg; #define SEPARATOR_WIDTH ui_get_opened_displays(&dummy_arg)[0]->display->col_width #define SEPARATOR_HEIGHT ui_get_opened_displays(&dummy_arg)[0]->display->line_height #else #define SEPARATOR_WIDTH 1 #define SEPARATOR_HEIGHT 1 #endif #define SCROLLBAR_WIDTH(scrollbar) (ACTUAL_WIDTH(&(scrollbar).window) + SEPARATOR_WIDTH) #define HAS_MULTI_CHILDREN(layout) ((layout)->term.next[0] || (layout)->term.next[1]) /* --- static variables --- */ static void (*orig_window_focused)(ui_window_t *); static void (*orig_xterm_set_window_name)(void *, u_char *); static void (*orig_xterm_set_icon_name)(void *, u_char *); /* --- static functions --- */ static void update_title(ui_screen_t *screen) { ui_set_window_name(&screen->window, vt_term_window_name(screen->term)); ui_set_icon_name(&screen->window, vt_term_icon_name(screen->term)); } static void window_focused(ui_window_t *win) { ui_layout_t *layout = (ui_layout_t*)win->parent; (*orig_window_focused)(win); if (HAS_MULTI_CHILDREN(layout)) { /* * If two screens in layout and one of them is removed, update_title() is * not called here. It is called at the end of ui_layout_remove_child(). */ update_title((ui_screen_t*)win); } } static void xterm_set_window_name(void *p, u_char *name) { ui_window_t *win = p; ui_layout_t *layout = (ui_layout_t*)win->parent; if (!HAS_MULTI_CHILDREN(layout) || win->inputtable > 0) { (*orig_xterm_set_window_name)(p, name); } } static void xterm_set_icon_name(void *p, u_char *name) { ui_window_t *win = p; ui_layout_t *layout = (ui_layout_t*)win->parent; if (!HAS_MULTI_CHILDREN(layout) || win->inputtable > 0) { (*orig_xterm_set_icon_name)(p, name); } } static u_int modify_separator(u_int separator, u_int total, u_int next_min, u_int unit, u_int fixed, u_int margin) { u_int surplus; int dont_round_up; if (total < separator + margin + next_min) { #if 0 separator = total - next_min - margin; #else separator = total / 2; #endif dont_round_up = 1; } else { dont_round_up = 0; } if ((surplus = (separator - fixed) % unit) > 0) { if (!dont_round_up && surplus > unit / 2) { separator += (unit - surplus); } else if (separator - fixed > surplus) { separator -= surplus; } else { separator = fixed + unit; } } return separator; } static void reset_layout(struct terminal *term, int x, int y, u_int width, u_int height) { u_int child_width; u_int child_height; int screen_moved; int screen_resized; if (term->separator_x > 0) { term->separator_x = child_width = modify_separator( term->separator_x, width, term->next[0]->screen->window.hmargin * 2 + ui_col_width(term->next[0]->screen) + (term->next[0]->sb_mode != SBM_NONE ? SCROLLBAR_WIDTH(term->next[0]->scrollbar) : 0), ui_col_width(term->screen), term->screen->window.hmargin * 2 + (term->sb_mode != SBM_NONE ? SCROLLBAR_WIDTH(term->scrollbar) : 0), SEPARATOR_WIDTH); } else { child_width = width; } if (term->separator_y > 0) { term->separator_y = child_height = modify_separator( term->separator_y, height, term->next[1]->screen->window.vmargin * 2 + ui_line_height(term->next[1]->screen), ui_line_height(term->screen), term->screen->window.vmargin * 2, SEPARATOR_HEIGHT); } else { child_height = height; } if (term->sb_mode != SBM_NONE) { int sep_x; int sb_moved; int sb_resized; if (term->sb_mode == SBM_RIGHT) { screen_moved = ui_window_move(&term->screen->window, x, y); sb_moved = ui_window_move(&term->scrollbar.window, x + child_width - ACTUAL_WIDTH(&term->scrollbar.window), y); sep_x = x + child_width - SCROLLBAR_WIDTH(term->scrollbar); } else { screen_moved = ui_window_move(&term->screen->window, x + SCROLLBAR_WIDTH(term->scrollbar), y); sb_moved = ui_window_move(&term->scrollbar.window, x, y); sep_x = x + ACTUAL_WIDTH(&term->scrollbar.window); } /* * The order of resizing: ui_scrollbar_t -> ui_screen_t * * ui_window_resize_with_margin(screen) may call ui_scrollbar_line_is_added() * which redraws screen by ui_window_update(), so you should resize ui_scrollbar_t * before ui_screen_t. */ sb_resized = ui_window_resize_with_margin(&term->scrollbar.window, ACTUAL_WIDTH(&term->scrollbar.window), child_height, NOTIFY_TO_MYSELF); screen_resized = ui_window_resize_with_margin(&term->screen->window, child_width - SCROLLBAR_WIDTH(term->scrollbar), child_height, NOTIFY_TO_MYSELF); #ifdef MANAGE_SUB_WINDOWS_BY_MYSELF ui_window_fill_with(&UI_SCREEN_TO_LAYOUT(term->screen)->window, &UI_SCREEN_TO_LAYOUT(term->screen)->window.fg_color, sep_x, y, SEPARATOR_WIDTH, child_height); #else if ( #ifdef USE_WIN32GUI /* * Scrollbar 3 isn't clearly redrawn without this. * * 1 2 3 * +-+------------+-+-----+-+----+ * | |$ hresize_sc| |$ | |$ | * | |reen +1 | | | | | * | | | | | | | */ sb_moved #else sb_moved && !sb_resized && UI_SCREEN_TO_LAYOUT(term->screen)->bg_pic #endif ) { ui_window_update_all(&term->scrollbar.window); } #endif } else { screen_moved = ui_window_move(&term->screen->window, x, y); screen_resized = ui_window_resize_with_margin(&term->screen->window, child_width, child_height, NOTIFY_TO_MYSELF); } #ifndef MANAGE_SUB_WINDOWS_BY_MYSELF if ( #ifdef USE_QUARTZ /* ui_window_move() clears screen in true transparency on MacOSX/Cocoa. */ term->screen->color_man->alpha < 255 || #endif (screen_moved && !screen_resized && UI_SCREEN_TO_LAYOUT(term->screen)->bg_pic)) { ui_window_update_all(&term->screen->window); } #endif if (term->yfirst) { if (term->next[1] && term->separator_y > 0) { reset_layout(term->next[1], x, y + term->separator_y + SEPARATOR_HEIGHT, width, height - term->separator_y - SEPARATOR_HEIGHT); #ifdef MANAGE_SUB_WINDOWS_BY_MYSELF ui_window_fill_with(&UI_SCREEN_TO_LAYOUT(term->screen)->window, &UI_SCREEN_TO_LAYOUT(term->screen)->window.fg_color, x, y + term->separator_y, width, SEPARATOR_HEIGHT); #endif } if (term->next[0] && term->separator_x > 0) { reset_layout(term->next[0], x + term->separator_x + SEPARATOR_WIDTH, y, width - term->separator_x - SEPARATOR_WIDTH, child_height); #ifdef MANAGE_SUB_WINDOWS_BY_MYSELF ui_window_fill_with(&UI_SCREEN_TO_LAYOUT(term->screen)->window, &UI_SCREEN_TO_LAYOUT(term->screen)->window.fg_color, x + term->separator_x, y, SEPARATOR_WIDTH, child_height); #endif } } else { if (term->next[0] && term->separator_x > 0) { reset_layout(term->next[0], x + term->separator_x + SEPARATOR_WIDTH, y, width - term->separator_x - SEPARATOR_WIDTH, height); #ifdef MANAGE_SUB_WINDOWS_BY_MYSELF ui_window_fill_with(&UI_SCREEN_TO_LAYOUT(term->screen)->window, &UI_SCREEN_TO_LAYOUT(term->screen)->window.fg_color, x + term->separator_x, y, SEPARATOR_WIDTH, height); #endif } if (term->next[1] && term->separator_y > 0) { reset_layout(term->next[1], x, y + term->separator_y + SEPARATOR_HEIGHT, child_width, height - term->separator_y - SEPARATOR_HEIGHT); #ifdef MANAGE_SUB_WINDOWS_BY_MYSELF ui_window_fill_with(&UI_SCREEN_TO_LAYOUT(term->screen)->window, &UI_SCREEN_TO_LAYOUT(term->screen)->window.fg_color, x, y + term->separator_y, child_width, SEPARATOR_HEIGHT); #endif } } } static struct terminal *search_term(struct terminal *term, ui_screen_t *screen) { struct terminal *hit; if (term->screen == screen) { return term; } if ((term->next[0] && (hit = search_term(term->next[0], screen))) || (term->next[1] && (hit = search_term(term->next[1], screen)))) { return hit; } return NULL; } static struct terminal *search_parent_term(struct terminal *term, struct terminal *child) { struct terminal *parent; if (term->next[0] == child || term->next[1] == child) { return term; } if ((term->next[0] && (parent = search_parent_term(term->next[0], child))) || (term->next[1] && (parent = search_parent_term(term->next[1], child)))) { return parent; } return NULL; } static ui_screen_t *search_next_screen(struct terminal *term, ui_screen_t *screen, int *found) { ui_screen_t *hit; int idx; int count; if (term->screen == screen) { *found = 1; } if (term->yfirst) { idx = 0; } else { idx = 1; } for (count = 0; count < 2; count++) { if (term->next[idx]) { if (*found) { return term->next[idx]->screen; } else if ((hit = search_next_screen(term->next[idx], screen, found))) { return hit; } } idx = !idx; } return NULL; } static ui_screen_t *search_prev_screen(struct terminal *term, ui_screen_t *screen, ui_screen_t **prev) { int idx; int count; if (*prev && term->screen == screen) { return *prev; } *prev = term->screen; if (term->yfirst) { idx = 0; } else { idx = 1; } for (count = 0; count < 2; count++) { if (term->next[idx] && search_prev_screen(term->next[idx], screen, prev)) { return *prev; } idx = !idx; } return NULL; } static struct terminal *get_current_term(struct terminal *term) { struct terminal *current; if (term->screen->window.inputtable > 0) { return term; } if ((term->next[0] && (current = get_current_term(term->next[0]))) || (term->next[1] && (current = get_current_term(term->next[1])))) { return current; } return NULL; } static ui_window_t *get_current_window(ui_layout_t *layout) { struct terminal *term; if ((term = get_current_term(&layout->term))) { return &term->screen->window; } else { return &layout->term.screen->window; } } static u_int get_separator_x(ui_screen_t *screen, u_int sb_width, u_int percent /* < 100 */ ) { u_int width; u_int fixed_width; u_int sep_x; width = screen->window.width; fixed_width = screen->window.hmargin * 2 + sb_width; sep_x = (width + fixed_width) * percent / 100; if (sep_x < fixed_width + ui_col_width(screen)) { return 0; } #ifdef PSEUDO_COLOR_DISPLAY if (screen->window.disp->display->pixels_per_byte > 1) { return sep_x - sep_x % screen->window.disp->display->pixels_per_byte - SEPARATOR_WIDTH; } else #endif { return sep_x - (sep_x - fixed_width) % ui_col_width(screen); } } static u_int get_separator_y(ui_screen_t *screen, u_int percent /* < 100 */ ) { u_int height; u_int fixed_height; u_int sep_y; height = screen->window.height; fixed_height = screen->window.vmargin * 2; sep_y = (height + fixed_height) * percent / 100; if (sep_y < fixed_height + ui_line_height(screen)) { return 0; } return sep_y - (sep_y - fixed_height) % ui_line_height(screen); } /* * callbacks of ui_window_t events. */ static void window_finalized(ui_window_t *win) { ui_layout_t *layout; layout = (ui_layout_t *)win; ui_layout_destroy(layout); } #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE static void reload_color_cache(struct terminal *term, int do_unload) { ui_screen_reload_color_cache(term->screen, do_unload); if (term->next[0]) { reload_color_cache(term->next[0], 0); } if (term->next[1]) { reload_color_cache(term->next[1], 0); } } #endif static void window_resized(ui_window_t *win) { ui_layout_t *layout; ui_picture_t *pic; layout = (ui_layout_t *)win; if (layout->bg_pic && (pic = ui_acquire_bg_picture(&layout->window, &layout->pic_mod, layout->pic_file_path))) { ui_window_set_wall_picture(&layout->window, pic->pixmap, 0); ui_release_picture(layout->bg_pic); layout->bg_pic = pic; #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE if (layout->window.disp->depth == 4 && strstr(layout->pic_file_path, "six")) { /* * Color pallette of ui_display can be changed by ui_acquire_bg_picture(). * (see ui_display_set_cmap() called from fb/ui_imagelib.c.) */ reload_color_cache(&layout->term, 1); } #endif } reset_layout(&layout->term, 0, 0, win->width, win->height); } static void child_window_resized(ui_window_t *win, ui_window_t *child) { ui_layout_t *layout; u_int actual_width; layout = (ui_layout_t *)win; if (HAS_MULTI_CHILDREN(layout)) { reset_layout(&layout->term, 0, 0, layout->window.width, layout->window.height); return; } if (&layout->term.screen->window == child) { if (layout->term.sb_mode == SBM_NONE) { actual_width = ACTUAL_WIDTH(child); } else { actual_width = ACTUAL_WIDTH(child) + ACTUAL_WIDTH(&layout->term.scrollbar.window) + SEPARATOR_WIDTH; } ui_window_resize_with_margin(&layout->window, actual_width, ACTUAL_HEIGHT(child), NOTIFY_TO_NONE); ui_window_resize_with_margin(&layout->term.scrollbar.window, ACTUAL_WIDTH(&layout->term.scrollbar.window), ACTUAL_HEIGHT(child), NOTIFY_TO_MYSELF); if (layout->term.sb_mode == SBM_RIGHT) { ui_window_move(&layout->term.scrollbar.window, ACTUAL_WIDTH(&layout->term.screen->window) + SEPARATOR_WIDTH, 0); } } else if (&layout->term.scrollbar.window == child) { if (layout->term.sb_mode == SBM_NONE) { return; } ui_window_resize_with_margin( &layout->window, ACTUAL_WIDTH(child) + ACTUAL_WIDTH(&layout->term.screen->window) + SEPARATOR_WIDTH, ACTUAL_HEIGHT(child), NOTIFY_TO_NONE); if (layout->term.sb_mode == SBM_LEFT) { ui_window_move(&layout->term.screen->window, ACTUAL_WIDTH(&layout->term.scrollbar.window) + SEPARATOR_WIDTH, 0); } } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " illegal child. this event should be invoken only by screen.\n"); #endif } } static void window_exposed(ui_window_t *win, int x, int y, u_int width, u_int height) { ui_window_fill_with(win, &((ui_layout_t *)win)->term.screen->window.fg_color, x, y, width, height); } static void key_pressed(ui_window_t *win, XKeyEvent *event) { ui_layout_t *layout; ui_window_t *child; layout = (ui_layout_t *)win; child = get_current_window(layout); /* key_pressed of ui_screen_t can be NULL. (see xterm_lock_keyboard in ui_screen.c) */ if (child->key_pressed) { /* dispatch to screen */ (*child->key_pressed)(child, event); } } static void utf_selection_notified(ui_window_t *win, u_char *buf, size_t len) { ui_layout_t *layout; ui_window_t *child; layout = (ui_layout_t *)win; child = get_current_window(layout); /* dispatch to screen */ (*child->utf_selection_notified)(child, buf, len); } static void xct_selection_notified(ui_window_t *win, u_char *buf, size_t len) { ui_layout_t *layout; ui_window_t *child; layout = (ui_layout_t *)win; child = get_current_window(layout); /* dispatch to screen */ (*child->xct_selection_notified)(child, buf, len); } #ifndef DISABLE_XDND static void set_xdnd_config(ui_window_t *win, char *dev, char *buf, char *value) { ui_layout_t *layout; ui_window_t *child; layout = (ui_layout_t *)win; child = get_current_window(layout); /* dispatch to screen */ (*child->set_xdnd_config)(child, dev, buf, value); } #endif static void window_destroyed_intern(struct terminal *term) { if (term->next[0]) { window_destroyed_intern(term->next[0]); } if (term->next[1]) { window_destroyed_intern(term->next[1]); } /* dispatch to screen */ (*term->screen->window.window_destroyed)(&term->screen->window); } static void window_destroyed(ui_window_t *win) { ui_layout_t *layout; layout = (ui_layout_t *)win; window_destroyed_intern(&layout->term); } #ifndef USE_QUARTZ static void change_sb_mode_intern(struct terminal *term, ui_sb_mode_t new_mode, int dynamic_change); static void check_scrollbar_visible(struct terminal *term) { if (term->autohide_scrollbar && term->sb_mode == SBM_RIGHT) { if (term->scrollbar.window.button_is_pressing) { term->idling_count = 0; } else if (++term->idling_count == 30) { term->idling_count = 0; change_sb_mode_intern(term, SBM_NONE, 1); } } if (term->next[0]) { check_scrollbar_visible(term->next[0]); } if (term->next[1]) { check_scrollbar_visible(term->next[1]); } } static void window_idling(ui_window_t *win) { ui_layout_t *layout; layout = (ui_layout_t *)win; check_scrollbar_visible(&layout->term); } #endif #if 0 /* * Overriding methods of ui_scrollbar_t. */ static void sb_key_pressed(ui_window_t *win, XKeyEvent *event) { struct terminal term; ui_screen_t **screen; screen = ((void *)win) - (((void *)&term.scrollbar) - ((void *)&term.screen)); /* dispatch to screen */ (*(*screen)->window.key_pressed)(&(*screen)->window, event); } #endif /* * Overriding methods of vt_screen_listener_t of ui_screen_t. */ static void line_scrolled_out(void *p /* must be ui_screen_t(, or child of ui_layout_t) */ ) { ui_layout_t *layout; struct terminal *term; layout = UI_SCREEN_TO_LAYOUT((ui_screen_t *)p); (*layout->line_scrolled_out)(p); if ((term = search_term(&layout->term, p))) { if (vt_term_log_size_is_unlimited(((ui_screen_t *)p)->term)) { ui_scrollbar_set_num_log_lines(&term->scrollbar, vt_term_get_log_size(((ui_screen_t *)p)->term)); } ui_scrollbar_line_is_added(&term->scrollbar); } } /* * callbacks of ui_sb_event_listener_t events. */ static int screen_scroll_to(void *p, int row) { struct terminal *term; term = p; ui_screen_scroll_to(term->screen, row); return 1; } static int screen_scroll_upward(void *p, u_int size) { struct terminal *term; term = p; ui_screen_scroll_upward(term->screen, size); return 1; } static int screen_scroll_downward(void *p, u_int size) { struct terminal *term; term = p; ui_screen_scroll_downward(term->screen, size); return 1; } static int screen_is_static(void *p) { struct terminal *term; term = p; if (vt_term_is_backscrolling(term->screen->term) == BSM_STATIC) { return 1; } else { return 0; } } /* * callbacks of ui_screen_scroll_event_listener_t events. */ static void bs_mode_exited(void *p) { struct terminal *term; term = p; ui_scrollbar_reset(&term->scrollbar); } static void scrolled_upward(void *p, u_int size) { struct terminal *term; term = p; ui_scrollbar_move_downward(&term->scrollbar, size); } static void scrolled_downward(void *p, u_int size) { struct terminal *term; term = p; ui_scrollbar_move_upward(&term->scrollbar, size); } static void scrolled_to(void *p, int row) { struct terminal *term; term = p; ui_scrollbar_move(&term->scrollbar, row); } static void log_size_changed(void *p, u_int log_size) { struct terminal *term; term = p; ui_scrollbar_set_num_log_lines(&term->scrollbar, log_size); } static void line_height_changed(void *p, u_int line_height) { struct terminal *term; term = p; ui_scrollbar_set_line_height(&term->scrollbar, line_height); } static void change_fg_color(void *p, char *color) { struct terminal *term; term = p; ui_scrollbar_set_fg_color(&term->scrollbar, color); } static char *get_fg_color(void *p) { struct terminal *term; term = p; return term->scrollbar.fg_color; } static void change_bg_color(void *p, char *color) { struct terminal *term; term = p; ui_scrollbar_set_bg_color(&term->scrollbar, color); } static char *get_bg_color(void *p) { struct terminal *term; term = p; return term->scrollbar.bg_color; } static void change_view(void *p, char *name) { struct terminal *term; term = p; ui_scrollbar_change_view(&term->scrollbar, name); } static char *get_view_name(void *p) { struct terminal *term; term = p; return term->scrollbar.view_name; } static void transparent_state_changed(void *p, int is_transparent, ui_picture_modifier_t *pic_mod) { struct terminal *term; term = p; if (is_transparent == 1) { ui_scrollbar_set_transparent(&term->scrollbar, pic_mod, 1); } else { ui_scrollbar_unset_transparent(&term->scrollbar); } } static ui_sb_mode_t sb_mode(void *p) { struct terminal *term; term = p; if (term->autohide_scrollbar) { return SBM_AUTOHIDE; } else { return term->sb_mode; } } static void screen_color_changed(void *p) { ui_layout_t *layout; layout = UI_SCREEN_TO_LAYOUT(((struct terminal *)p)->screen); if (&layout->term == p) { ui_window_set_fg_color(&layout->window, &layout->term.screen->window.fg_color); ui_window_set_bg_color(&layout->window, &layout->term.screen->window.bg_color); } } static u_int total_width(struct terminal *term) { u_int width; width = ACTUAL_WIDTH(&term->screen->window); if (term->sb_mode != SBM_NONE) { width += (ACTUAL_WIDTH(&term->scrollbar.window) + SEPARATOR_WIDTH); } if (term->separator_x > 0 && term->next[0]) { width += (total_width(term->next[0]) + SEPARATOR_WIDTH); } return width; } static u_int total_height(struct terminal *term) { u_int height; height = ACTUAL_HEIGHT(&term->screen->window); if (term->separator_y > 0 && term->next[1]) { height += (total_height(term->next[1]) + SEPARATOR_HEIGHT); } return height; } static void clear_hint_size(struct terminal *term) { int count; for (count = 0; count < 2; count++) { if (term->next[count]) { clear_hint_size(term->next[count]); } } term->screen->window.sizehint_flag = 0; term->scrollbar.window.sizehint_flag = 0; } static void total_hint_width(struct terminal *term, u_int *width) { if (term->sb_mode != SBM_NONE) { *width += SEPARATOR_WIDTH; } if (term->next[0]) { *width += SEPARATOR_WIDTH; total_hint_width(term->next[0], width); } if (term->next[1]) { clear_hint_size(term->next[1]); } term->screen->window.sizehint_flag = SIZEHINT_WIDTH; term->scrollbar.window.sizehint_flag = SIZEHINT_WIDTH; } static void total_hint_height(struct terminal *term, u_int *height) { if (term->next[0]) { clear_hint_size(term->next[0]); } if (term->next[1]) { *height += SEPARATOR_HEIGHT; total_hint_height(term->next[1], height); } term->screen->window.sizehint_flag = SIZEHINT_HEIGHT; term->scrollbar.window.sizehint_flag = 0; } static void total_hint_size(struct terminal *term, u_int *width, u_int *height) { if (term->sb_mode != SBM_NONE) { *width += SEPARATOR_WIDTH; } if (term->next[0]) { *width += SEPARATOR_WIDTH; total_hint_width(term->next[0], width); } if (term->next[1]) { *height += SEPARATOR_HEIGHT; total_hint_height(term->next[1], height); } term->screen->window.sizehint_flag = SIZEHINT_HEIGHT|SIZEHINT_WIDTH; term->scrollbar.window.sizehint_flag = SIZEHINT_WIDTH; } static void update_normal_hints(ui_layout_t *layout) { u_int min_width = 0; u_int min_height = 0; total_hint_size(&layout->term, &min_width, &min_height); ui_window_set_normal_hints(&layout->window, min_width, min_height, 0, 0); } #ifndef USE_QUARTZ static int need_idling_event(struct terminal *term) { if (!term->autohide_scrollbar && (!term->next[0] || !need_idling_event(term->next[0])) && (!term->next[1] || !need_idling_event(term->next[1]))) { return 0; } else { return 1; } } #endif static void change_sb_mode_intern(struct terminal *term, ui_sb_mode_t new_mode, int dynamic_change) { ui_layout_t *layout; ui_sb_mode_t old_mode; layout = UI_SCREEN_TO_LAYOUT(term->screen); if (new_mode == SBM_AUTOHIDE) { if (term->autohide_scrollbar) { return; } new_mode = SBM_NONE; term->autohide_scrollbar = 1; ui_window_add_event_mask(&term->screen->window, PointerMotionMask); #ifndef USE_QUARTZ layout->window.idling = window_idling; #endif } else if (!dynamic_change) { term->autohide_scrollbar = 0; ui_window_remove_event_mask(&term->screen->window, PointerMotionMask); (*term->screen->xterm_listener.set_mouse_report)(term->screen->xterm_listener.self); #ifndef USE_QUARTZ if (!need_idling_event(&layout->term)) { layout->window.idling = NULL; } #endif } if ((old_mode = term->sb_mode) == new_mode) { return; } /* * term->sb_mode should be changed before ui_window_unmap/ui_window_map * for framebuffer. (see fb/ui_window.c) */ term->sb_mode = new_mode; if (new_mode == SBM_NONE) { ui_window_unmap(&term->scrollbar.window); } #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF else if (old_mode == SBM_NONE) { /* scrollbar's height may have been changed. */ ui_window_resize_with_margin(&term->scrollbar.window, ACTUAL_WIDTH(&term->scrollbar.window), ACTUAL_HEIGHT(&term->screen->window), NOTIFY_TO_MYSELF); /* Don't call ui_window_map() because scrollbar's position may be * inappropriate. */ term->scrollbar.window.is_mapped = 1; term->scrollbar.window.x = -1; /* To redraw scrollbar in ui_window_move() */ if (new_mode == SBM_LEFT) { /* Shrink window size before ui_window_move() in reset_layout(). */ ui_window_resize_with_margin(&term->screen->window, ACTUAL_WIDTH(&term->screen->window) - SCROLLBAR_WIDTH(term->scrollbar), ACTUAL_HEIGHT(&term->screen->window), 0); } } reset_layout(&layout->term, 0, 0, layout->window.width, layout->window.height); if (new_mode == SBM_NONE) { /* Window size was enlarged but not exposed. */ (*term->screen->window.window_exposed)( &term->screen->window, ACTUAL_WIDTH(&term->screen->window) - SCROLLBAR_WIDTH(term->scrollbar), 0, SCROLLBAR_WIDTH(term->scrollbar), ACTUAL_HEIGHT(&term->screen->window)); } #else else if (old_mode == SBM_NONE) { ui_window_map(&term->scrollbar.window); #ifdef MANAGE_SUB_WINDOWS_BY_MYSELF /* To show hidden scrollbar whose size and position aren't changed. (for wayland) */ term->scrollbar.window.x = -1; /* To redraw scrollbar in ui_window_move() */ #endif } else { goto noresize; } if (term->screen->window.x + ACTUAL_WIDTH(&term->screen->window) + (old_mode != SBM_NONE ? SCROLLBAR_WIDTH(term->scrollbar) : 0) >= ACTUAL_WIDTH(&layout->window)) { /* This should be called before ui_window_resize(&layout->window) */ update_normal_hints(layout); if (ui_window_resize(&layout->window, total_width(&layout->term), total_height(&layout->term), NOTIFY_TO_MYSELF)) { return; } } noresize: reset_layout(&layout->term, 0, 0, layout->window.width, layout->window.height); #endif update_normal_hints(layout); } static void change_sb_mode(void *p, ui_sb_mode_t new_mode) { change_sb_mode_intern(p, new_mode, 0); } static void term_changed(void *p, u_int log_size, u_int logged_lines) { struct terminal *term; term = p; ui_scrollbar_set_num_log_lines(&term->scrollbar, log_size); ui_scrollbar_set_num_filled_log_lines(&term->scrollbar, logged_lines); } static void screen_pointer_motion(ui_window_t *win, XMotionEvent *event) { struct terminal *term; ui_layout_t *layout; layout = UI_SCREEN_TO_LAYOUT((ui_screen_t *)win); (*layout->pointer_motion)(win, event); term = search_term(&layout->term, (ui_screen_t *)win); if (term->autohide_scrollbar) { ui_sb_mode_t mode; if (((int)win->width) - 2 <= event->x && 0 <= event->y && event->y < win->height) { if (term->scrollbar.window.is_mapped) { return; } mode = SBM_RIGHT; } else { if (!term->scrollbar.window.is_mapped) { return; } mode = SBM_NONE; } change_sb_mode_intern(term, mode, 1); } } static void destroy_term(struct terminal *term) { ui_scrollbar_final(&term->scrollbar); if (term->next[0]) { destroy_term(term->next[0]); free(term->next[0]); } if (term->next[1]) { destroy_term(term->next[1]); free(term->next[1]); } } static void destroy_screen_bg_pic(ui_screen_t *screen) { free(screen->pic_file_path); screen->pic_file_path = NULL; ui_release_picture(screen->bg_pic); screen->bg_pic = NULL; } static void destroy_layout_bg_pic(ui_layout_t *layout) { free(layout->pic_file_path); layout->pic_file_path = NULL; ui_release_picture(layout->bg_pic); layout->bg_pic = NULL; } static void save_screen_bg_pic(ui_layout_t *layout) { /* layout->bg_pic has been already set. */ ui_release_picture(layout->term.screen->bg_pic); layout->term.screen->bg_pic = NULL; layout->pic_file_path = layout->term.screen->pic_file_path; layout->term.screen->pic_file_path = NULL; layout->pic_mod = layout->term.screen->pic_mod; } static void restore_screen_bg_pic(ui_layout_t *layout) { layout->term.screen->pic_file_path = layout->pic_file_path; layout->pic_file_path = NULL; layout->term.screen->bg_pic = layout->bg_pic; layout->bg_pic = NULL; layout->term.screen->pic_mod = layout->pic_mod; } /* --- global functions --- */ ui_layout_t *ui_layout_new(ui_screen_t *screen, char *view_name, char *fg_color, char *bg_color, ui_sb_mode_t mode, u_int hmargin, u_int vmargin) { ui_layout_t *layout; u_int actual_width; u_int min_width; int screen_x; int sb_x; int sb_map; if ((layout = calloc(1, sizeof(ui_layout_t))) == NULL) { return NULL; } /* * event callbacks. */ layout->term.sb_listener.self = &layout->term; layout->term.sb_listener.screen_scroll_to = screen_scroll_to; layout->term.sb_listener.screen_scroll_upward = screen_scroll_upward; layout->term.sb_listener.screen_scroll_downward = screen_scroll_downward; layout->term.sb_listener.screen_is_static = screen_is_static; if (ui_scrollbar_init( &layout->term.scrollbar, &layout->term.sb_listener, view_name, fg_color, bg_color, ACTUAL_HEIGHT(&screen->window), ui_line_height(screen), vt_term_get_log_size(screen->term), vt_term_get_num_logged_lines(screen->term), screen->window.is_transparent, ui_screen_get_picture_modifier(screen)) == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ui_scrollbar_init() failed.\n"); #endif goto error; } #if 0 layout->term.scrollbar.window.key_pressed = sb_key_pressed; #endif layout->term.screen = screen; /* * event callbacks. */ layout->term.screen_scroll_listener.self = &layout->term; layout->term.screen_scroll_listener.bs_mode_entered = NULL; layout->term.screen_scroll_listener.bs_mode_exited = bs_mode_exited; layout->term.screen_scroll_listener.scrolled_upward = scrolled_upward; layout->term.screen_scroll_listener.scrolled_downward = scrolled_downward; layout->term.screen_scroll_listener.scrolled_to = scrolled_to; layout->term.screen_scroll_listener.log_size_changed = log_size_changed; layout->term.screen_scroll_listener.line_height_changed = line_height_changed; layout->term.screen_scroll_listener.change_fg_color = change_fg_color; layout->term.screen_scroll_listener.fg_color = get_fg_color; layout->term.screen_scroll_listener.change_bg_color = change_bg_color; layout->term.screen_scroll_listener.bg_color = get_bg_color; layout->term.screen_scroll_listener.change_view = change_view; layout->term.screen_scroll_listener.view_name = get_view_name; layout->term.screen_scroll_listener.transparent_state_changed = transparent_state_changed; layout->term.screen_scroll_listener.sb_mode = sb_mode; layout->term.screen_scroll_listener.change_sb_mode = change_sb_mode; layout->term.screen_scroll_listener.term_changed = term_changed; layout->term.screen_scroll_listener.screen_color_changed = screen_color_changed; ui_set_screen_scroll_listener(screen, &layout->term.screen_scroll_listener); layout->line_scrolled_out = screen->screen_listener.line_scrolled_out; screen->screen_listener.line_scrolled_out = line_scrolled_out; if (mode == SBM_AUTOHIDE) { layout->term.sb_mode = SBM_NONE; layout->term.autohide_scrollbar = 1; } else { layout->term.sb_mode = mode; } layout->pointer_motion = screen->window.pointer_motion; screen->window.pointer_motion = screen_pointer_motion; if (layout->term.sb_mode == SBM_NONE) { actual_width = ACTUAL_WIDTH(&screen->window); min_width = 0; } else { actual_width = ACTUAL_WIDTH(&screen->window) + SCROLLBAR_WIDTH(layout->term.scrollbar); min_width = SEPARATOR_WIDTH; } if (ui_window_init(&layout->window, actual_width, ACTUAL_HEIGHT(&screen->window), min_width, 0, 0, 0, hmargin, vmargin, 0, 0) == 0) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ui_window_init() failed.\n"); #endif goto error; } if (layout->term.sb_mode == SBM_RIGHT) { screen_x = 0; sb_x = ACTUAL_WIDTH(&screen->window) + SEPARATOR_WIDTH; sb_map = 1; } else if (layout->term.sb_mode == SBM_LEFT) { screen_x = ACTUAL_WIDTH(&layout->term.scrollbar.window) + SEPARATOR_WIDTH; sb_x = 0; sb_map = 1; } else /* if( layout->term.sb_mode == SBM_NONE) */ { screen_x = sb_x = 0; /* overlaying scrollbar window */ sb_map = 0; } orig_window_focused = screen->window.window_focused; orig_xterm_set_window_name = screen->xterm_listener.set_window_name; orig_xterm_set_icon_name = screen->xterm_listener.set_icon_name; screen->window.window_focused = window_focused; screen->xterm_listener.set_window_name = xterm_set_window_name; screen->xterm_listener.set_icon_name = xterm_set_icon_name; if (!ui_window_add_child(&layout->window, &layout->term.scrollbar.window, sb_x, 0, sb_map) || !ui_window_add_child(&layout->window, &screen->window, screen_x, 0, 1)) { goto error; } /* * event call backs. */ ui_window_add_event_mask(&layout->window, KeyPressMask); layout->window.window_finalized = window_finalized; layout->window.window_resized = window_resized; layout->window.child_window_resized = child_window_resized; layout->window.window_exposed = window_exposed; layout->window.key_pressed = key_pressed; layout->window.utf_selection_notified = utf_selection_notified; layout->window.xct_selection_notified = xct_selection_notified; layout->window.window_destroyed = window_destroyed; #ifndef DISABLE_XDND layout->window.set_xdnd_config = set_xdnd_config; #endif if (layout->term.autohide_scrollbar) { #ifndef USE_QUARTZ layout->window.idling = window_idling; #endif ui_window_add_event_mask(&screen->window, PointerMotionMask); } return layout; error: free(layout); return NULL; } void ui_layout_destroy(ui_layout_t *layout) { if (layout->bg_pic) { destroy_layout_bg_pic(layout); } destroy_term(&layout->term); free(layout); } int ui_layout_add_child(ui_layout_t *layout, ui_screen_t *screen, int horizontal, const char *sep_str /* "XX%" or "XX" */ ) { struct terminal *next; struct terminal *term; u_int sep = 50; int is_percent = 1; if (sep_str) { char *p; if ((p = strchr(sep_str, '%'))) { if (!bl_str_n_to_uint(&sep, sep_str, p - sep_str) || sep >= 100 || sep == 0) { return 0; } } else { if (!bl_str_to_uint(&sep, sep_str) || sep == 0) { return 0; } is_percent = 0; } } if (!(next = calloc(1, sizeof(struct terminal)))) { return 0; } if (!(term = get_current_term(&layout->term))) { term = &layout->term; } if (horizontal) { u_int orig_separator_x; u_int sb_width; orig_separator_x = term->separator_x; if (term->sb_mode != SBM_NONE) { sb_width = SCROLLBAR_WIDTH(term->scrollbar); } else { sb_width = 0; } if (is_percent ? ((term->separator_x = get_separator_x(term->screen, sb_width, sep)) == 0) : ((term->separator_x = screen->window.hmargin * 2 + ui_col_width(term->screen) * sep + sb_width) >= ACTUAL_WIDTH(&term->screen->window) + sb_width)) { term->separator_x = orig_separator_x; free(next); return 0; } next->next[0] = term->next[0]; term->next[0] = next; if (orig_separator_x > 0) { next->separator_x = orig_separator_x - term->separator_x; } } else { u_int orig_separator_y; orig_separator_y = term->separator_y; if (is_percent ? ((term->separator_y = get_separator_y(term->screen, sep)) == 0) : ((term->separator_y = screen->window.vmargin * 2 + ui_line_height(term->screen) * sep) >= ACTUAL_HEIGHT(&term->screen->window))) { term->separator_y = orig_separator_y; free(next); return 0; } if (term->separator_x == 0) { term->yfirst = 1; } next->next[1] = term->next[1]; term->next[1] = next; if (orig_separator_y > 0) { next->separator_y = orig_separator_y - term->separator_y; } } next->sb_listener = term->sb_listener; next->sb_listener.self = next; ui_scrollbar_init( &next->scrollbar, &next->sb_listener, term->scrollbar.view_name, term->scrollbar.fg_color, term->scrollbar.bg_color, ACTUAL_HEIGHT(&screen->window), ui_line_height(screen), vt_term_get_log_size(screen->term), vt_term_get_num_logged_lines(screen->term), screen->window.is_transparent, ui_screen_get_picture_modifier(screen)); #if 0 next->scrollbar.window.key_pressed = sb_key_pressed; #endif ui_window_add_child(&layout->window, &next->scrollbar.window, 0, 0, 0); ui_window_show(&next->scrollbar.window, 0); next->screen_scroll_listener = term->screen_scroll_listener; next->screen_scroll_listener.self = next; next->screen = screen; ui_set_screen_scroll_listener(screen, &next->screen_scroll_listener); screen->screen_listener.line_scrolled_out = line_scrolled_out; screen->window.window_focused = window_focused; screen->xterm_listener.set_window_name = xterm_set_window_name; screen->xterm_listener.set_icon_name = xterm_set_icon_name; ui_window_add_child(&layout->window, &screen->window, 0, 0, 0); if (screen->pic_file_path) { destroy_screen_bg_pic(screen); } ui_window_show(&screen->window, 0); if (!ui_window_has_wall_picture(&layout->window) && layout->term.screen->pic_file_path) { if ((layout->bg_pic = ui_acquire_bg_picture(&layout->window, &layout->term.screen->pic_mod, layout->term.screen->pic_file_path))) { save_screen_bg_pic(layout); ui_window_set_wall_picture(&layout->window, layout->bg_pic->pixmap, 0); #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE if (layout->window.disp->depth == 4 && strstr(layout->pic_file_path, "six")) { /* * Color pallette of ui_display can be changed by * ui_acquire_bg_picture(). * (see ui_display_set_cmap() called from fb/ui_imagelib.c.) */ reload_color_cache(&layout->term, 1); } #endif } } next->sb_mode = term->sb_mode; if ((next->autohide_scrollbar = term->autohide_scrollbar)) { ui_window_add_event_mask(&screen->window, PointerMotionMask); } screen->window.pointer_motion = screen_pointer_motion; reset_layout(&layout->term, 0, 0, layout->window.width, layout->window.height); if (term->sb_mode != SBM_NONE) { ui_window_map(&next->scrollbar.window); } ui_window_map(&screen->window); ui_window_set_input_focus(&term->screen->window); update_normal_hints(layout); return 1; } int ui_layout_remove_child(ui_layout_t *layout, ui_screen_t *screen) { struct terminal *term; int idx2; #ifndef MANAGE_SUB_WINDOWS_BY_MYSELF u_int w_surplus; u_int h_surplus; #endif if (!HAS_MULTI_CHILDREN(layout)) { return 0; } term = search_term(&layout->term, screen); ui_scrollbar_final(&term->scrollbar); ui_window_unmap(&term->scrollbar.window); ui_window_final(&term->scrollbar.window); if (term->yfirst) { idx2 = 0; } else { idx2 = 1; } if (!term->next[idx2]) { idx2 = !idx2; } if (term == &layout->term) { struct terminal *next; if (idx2 == 0) { if (term->separator_y > 0) { term->next[0]->separator_y = term->separator_y; } } else { if (term->separator_x > 0) { term->next[1]->separator_x = term->separator_x; } } term->next[idx2]->yfirst = term->yfirst; next = term->next[idx2]; if (term->next[!idx2]) { struct terminal *parent; int empty_idx; /* Search from 'next' for a term whose child is NULL. */ parent = search_parent_term(next, NULL); if (parent->next[!idx2] == NULL) { empty_idx = !idx2; } else { empty_idx = idx2; } parent->next[empty_idx] = term->next[!idx2]; if (empty_idx == 0) { parent->separator_x = get_separator_x(parent->screen, parent->sb_mode == SBM_NONE ? 0 : SCROLLBAR_WIDTH(parent->scrollbar), 100); } else { parent->separator_y = get_separator_y(parent->screen, 100); } } *term = *next; term->screen_scroll_listener.self = term; ui_set_screen_scroll_listener(term->screen, &term->screen_scroll_listener); term->sb_listener.self = term; term->scrollbar.sb_listener = &term->sb_listener; #ifndef USE_QUARTZ term->scrollbar.view->win = &term->scrollbar.window; #ifdef USE_BEOS view_reset_uiwindow(&term->scrollbar.window); #endif #endif term = next; } else { struct terminal *parent; int idx; parent = search_parent_term(&layout->term, term); if (parent->next[0] == term) { idx = 0; } else { idx = 1; } if (term->next[idx2]) { if (idx2 == 0) { if (term->separator_y > 0) { term->next[0]->separator_y = term->separator_y; } } else { if (term->separator_x > 0) { term->next[1]->separator_x = term->separator_x; } } term->next[idx2]->yfirst = term->yfirst; parent->next[idx] = term->next[idx2]; if (term->next[!idx2]) { parent = search_parent_term(parent->next[idx], NULL); if (parent->next[!idx2] == NULL) { parent->next[!idx2] = term->next[!idx2]; } else { parent->next[idx2] = term->next[!idx2]; } } } else { parent->next[idx] = NULL; if (idx == 0) { parent->separator_x = 0; } else { parent->separator_y = 0; } } } ui_window_remove_child(&layout->window, &term->scrollbar.window); ui_window_remove_child(&layout->window, &screen->window); ui_window_unmap(&screen->window); if (layout->bg_pic && !HAS_MULTI_CHILDREN(layout)) { restore_screen_bg_pic(layout); ui_window_unset_wall_picture(&layout->window, 0); } #ifndef MANAGE_SUB_WINDOWS_BY_MYSELF if (!HAS_MULTI_CHILDREN(layout)) { w_surplus = (layout->window.width - layout->term.screen->window.hmargin * 2 - (layout->term.sb_mode != SBM_NONE ? SCROLLBAR_WIDTH(layout->term.scrollbar) : 0)) % ui_col_width(layout->term.screen); h_surplus = (layout->window.height - layout->term.screen->window.vmargin * 2) % ui_line_height(layout->term.screen); } else { w_surplus = h_surplus = 0; } if (w_surplus > 0 || h_surplus > 0) { ui_window_resize(&layout->window, layout->window.width - w_surplus, layout->window.height - h_surplus, NOTIFY_TO_MYSELF); } else #endif { reset_layout(&layout->term, 0, 0, layout->window.width, layout->window.height); } update_normal_hints(layout); #ifndef MANAGE_SUB_WINDOWS_BY_MYSELF if (ui_screen_attached(screen)) { /* Revert the size of vt_term to the original one. */ ui_window_resize_with_margin( &screen->window, ACTUAL_WIDTH(&layout->window) - (term->sb_mode != SBM_NONE ? SCROLLBAR_WIDTH(term->scrollbar) : 0), ACTUAL_HEIGHT(&layout->window), NOTIFY_TO_MYSELF); } #endif free(term); ui_window_set_input_focus(&layout->term.screen->window); /* See window_focused() above */ if (!HAS_MULTI_CHILDREN(layout)) { update_title(layout->term.screen); } #ifndef USE_QUARTZ if (layout->window.idling && !need_idling_event(&layout->term)) { layout->window.idling = NULL; } #endif return 1; } int ui_layout_switch_screen(ui_layout_t *layout, int prev) { ui_screen_t *screen; if (!HAS_MULTI_CHILDREN(layout)) { return 0; } if (prev) { screen = NULL; search_prev_screen(&layout->term, (ui_screen_t *)get_current_window(layout), &screen); } else { int found = 0; if (!(screen = search_next_screen(&layout->term, (ui_screen_t *)get_current_window(layout), &found))) { screen = layout->term.screen; } } ui_window_set_input_focus(&screen->window); return 1; } int ui_layout_resize(ui_layout_t *layout, ui_screen_t *screen, int horizontal, const char *size_str /* "N", "+N", "-N" or "N%" */) { struct terminal *term; struct terminal *child = NULL; int size; int is_percent; char *p; if ((p = strchr(size_str, '%'))) { if (!bl_str_n_to_int(&size, size_str, p - size_str) || size <= 0) { return 0; } is_percent = 1; } else { if (!bl_str_to_int(&size, *size_str == '+' ? size_str + 1: size_str) || size == 0) { return 0; } is_percent = 0; } if (!(term = search_term(&layout->term, screen))) { term = &layout->term; } if (horizontal) { if (is_percent) { if (term->separator_x > 0) { term->separator_x = total_width(term) * size / 100; } } else { int step; if (*size_str == '+' || *size_str == '-') { step = size; } else { step = size - vt_term_get_cols(screen->term); } while (term->separator_x == 0) { if (!(term = search_parent_term(&layout->term, (child = term)))) { return 0; } } if (term->next[0] == child) { step = -step; } step *= ui_col_width(term->screen); if (step < 0 && term->separator_x < abs(step)) { return 0; } term->separator_x += step; } } else { if (is_percent) { if (term->separator_y > 0) { term->separator_y = total_height(term) * size / 100; } } else { int step; if (*size_str == '+' || *size_str == '-') { step = size; } else { step = size - vt_term_get_rows(screen->term); } while (term->separator_y == 0) { if (!(term = search_parent_term(&layout->term, (child = term)))) { return 0; } } if (term->next[1] == child) { step = -step; } step *= ui_line_height(term->screen); if (step < 0 && term->separator_y < abs(step)) { return 0; } term->separator_y += step; } } reset_layout(&layout->term, 0, 0, layout->window.width, layout->window.height); return 1; } mlterm-3.8.9/uitoolkit/ui_layout.h010064400017600000144000000032031356600660700157460ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_LAYOUT_H__ #define __UI_LAYOUT_H__ #include /* int8_t */ #include "ui_screen.h" #include "ui_scrollbar.h" #include "ui_color_manager.h" #define UI_SCREEN_TO_LAYOUT(screen) ((ui_layout_t *)(screen)->window.parent) typedef struct ui_layout { ui_window_t window; struct terminal { ui_scrollbar_t scrollbar; ui_screen_t *screen; ui_sb_mode_t sb_mode; ui_scrollbar_event_listener_t sb_listener; ui_screen_scroll_event_listener_t screen_scroll_listener; u_int16_t separator_x; u_int16_t separator_y; int yfirst; int8_t autohide_scrollbar; int8_t idling_count; /* 0: right, 1: down */ struct terminal *next[2]; } term; char *pic_file_path; ui_picture_modifier_t pic_mod; ui_picture_t *bg_pic; void (*line_scrolled_out)(void *); void (*pointer_motion)(ui_window_t *, XMotionEvent *); } ui_layout_t; ui_layout_t *ui_layout_new(ui_screen_t *screen, char *view_name, char *fg_color, char *bg_color, ui_sb_mode_t mode, u_int hmargin, u_int vmargin); void ui_layout_destroy(ui_layout_t *layout); int ui_layout_add_child(ui_layout_t *layout, ui_screen_t *screen, int horizontal, const char *percent); int ui_layout_remove_child(ui_layout_t *layout, ui_screen_t *screen); int ui_layout_switch_screen(ui_layout_t *layout, int prev); int ui_layout_resize(ui_layout_t *layout, ui_screen_t *screen, int horizontal, const char *size); #define ui_layout_has_one_child(layout) \ ((layout)->term.next[0] == NULL && ((layout)->term.next[1]) == NULL) #endif mlterm-3.8.9/uitoolkit/ui_main_config.c010064400017600000144000001371551356600660700167130ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_main_config.h" #include #include /* malloc/realloc */ #include /* bl_str_to_uint */ #include /* bl_get_lang */ #include #include /* BL_INT_TO_STR */ #include /* bl_setenv */ #include #include "ui_selection_encoding.h" #include "ui_emoji.h" #if defined(__ANDROID__) || defined(USE_QUARTZ) || defined(USE_WIN32API) /* Shrink unused memory */ #define bl_conf_add_opt(conf, a, b, c, d, e) bl_conf_add_opt(conf, a, b, c, d, "") #endif /* --- static variables --- */ #ifdef USE_WAYLAND static char *default_display = "wayland-0"; #else static char *default_display = ""; #endif /* --- static functions --- */ static vt_char_encoding_t get_encoding(const char *value, int *is_auto_encoding /* overwritten only if auto encoding */ ) { vt_char_encoding_t encoding; if (!value) { /* goto "auto" */ } else if ((encoding = vt_get_char_encoding(value)) == VT_UNKNOWN_ENCODING) { bl_msg_printf("Use auto detected encoding instead of %s(unsupported).\n", value); } else { return encoding; } encoding = vt_get_char_encoding("auto"); if (is_auto_encoding) { *is_auto_encoding = 1; } return encoding; } /* --- global functions --- */ void ui_prepare_for_main_config(bl_conf_t *conf) { char *rcpath; if ((rcpath = bl_get_sys_rc_path("mlterm/main"))) { bl_conf_read(conf, rcpath); free(rcpath); } if ((rcpath = bl_get_user_rc_path("mlterm/main"))) { bl_conf_read(conf, rcpath); free(rcpath); } bl_conf_add_opt(conf, '#', "initstr", 0, "init_str", "initial string sent to pty"); bl_conf_add_opt(conf, '$', "mc", 0, "click_interval", "click interval(milisecond) [250]"); bl_conf_add_opt(conf, '%', "logseq", 1, "logging_vt_seq", "enable logging vt100 sequence [false]"); #ifdef USE_XLIB bl_conf_add_opt(conf, '&', "borderless", 1, "borderless", "override redirect [false]"); bl_conf_add_opt(conf, '*', "type", 0, "type_engine", "type engine " #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) "[cairo]" #elif !defined(USE_TYPE_XCORE) && defined(USE_TYPE_XFT) "[xft]" #else "[xcore]" #endif ); #endif bl_conf_add_opt(conf, '1', "wscr", 0, "screen_width_ratio", "screen width in percent against font width [100]"); #if 1 /* BACKWARD COMPAT (3.8.2 or before) */ bl_conf_add_opt(conf, '2', "hscr", 0, "screen_height_ratio", "screen height in percent against font height [100]"); #endif #ifndef NO_IMAGE bl_conf_add_opt(conf, '3', "contrast", 0, "contrast", "contrast of background image in percent [100]"); bl_conf_add_opt(conf, '4', "gamma", 0, "gamma", "gamma of background image in percent [100]"); #endif bl_conf_add_opt(conf, '5', "big5bug", 1, "big5_buggy", "manage buggy Big5 CTEXT in XFree86 4.1 or earlier [false]"); bl_conf_add_opt(conf, '6', "stbs", 1, "static_backscroll_mode", "screen is static under backscroll mode [false]"); bl_conf_add_opt(conf, '7', "bel", 0, "bel_mode", "bel (0x07) mode (none/sound/visual) [sound]"); bl_conf_add_opt(conf, '8', "88591", 1, "iso88591_font_for_usascii", "use ISO-8859-1 font for ASCII part of any encoding [false]"); bl_conf_add_opt(conf, '9', "crfg", 0, "cursor_fg_color", "cursor foreground color"); bl_conf_add_opt(conf, '0', "crbg", 0, "cursor_bg_color", "cursor background color"); #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO) || \ defined(USE_FREETYPE) || defined(USE_WIN32GUI) bl_conf_add_opt(conf, 'A', "aa", 1, "use_anti_alias", "forcibly use anti alias font by using Xft or cairo"); #endif bl_conf_add_opt(conf, 'B', "sbbg", 0, "sb_bg_color", "scrollbar background color"); #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_FRIBIDI) || defined(USE_IND) || \ defined(USE_OT_LAYOUT) bl_conf_add_opt(conf, 'C', "ctl", 1, "use_ctl", "use complex text layouting [true]"); #endif bl_conf_add_opt(conf, 'E', "km", 0, "encoding", "character encoding (AUTO/ISO-8859-*/EUC-*/UTF-8/...) [AUTO]"); bl_conf_add_opt(conf, 'F', "sbfg", 0, "sb_fg_color", "scrollbar foreground color"); bl_conf_add_opt(conf, 'G', "vertical", 0, "vertical_mode", "vertical mode (none/cjk/mongol) [none]"); #ifndef NO_IMAGE bl_conf_add_opt(conf, 'H', "bright", 0, "brightness", "brightness of background image in percent [100]"); #endif #ifdef USE_XLIB bl_conf_add_opt(conf, 'I', "icon", 0, "icon_name", "icon name"); #endif bl_conf_add_opt(conf, 'J', "dyncomb", 1, "use_dynamic_comb", "use dynamic combining [false]"); bl_conf_add_opt(conf, 'K', "metakey", 0, "mod_meta_key", "meta key [none]"); bl_conf_add_opt(conf, 'L', "ls", 1, "use_login_shell", "turn on login shell [false]"); bl_conf_add_opt(conf, 'M', "im", 0, "input_method", "input method (xim/kbd/uim/m17nlib/scim/ibus/fcitx/canna/wnn/skk/iiimf/none) [xim]"); bl_conf_add_opt(conf, 'N', "name", 0, "app_name", "application name"); bl_conf_add_opt(conf, 'O', "sbmod", 0, "scrollbar_mode", "scrollbar mode (none/left/right/autohide) [none]"); bl_conf_add_opt(conf, 'P', "clip", 1, "use_clipboard", "use CLIPBOARD (not only PRIMARY) selection [true]"); bl_conf_add_opt(conf, 'Q', "vcur", 1, "use_vertical_cursor", "rearrange cursor key for vertical mode [true]"); bl_conf_add_opt(conf, 'S', "sbview", 0, "scrollbar_view_name", "scrollbar view name (simple/sample/...) [simple]"); bl_conf_add_opt(conf, 'T', "title", 0, "title", "title name"); bl_conf_add_opt(conf, 'U', "viaucs", 1, "receive_string_via_ucs", "process received (pasted) strings via Unicode [false]"); bl_conf_add_opt(conf, 'V', "varwidth", 1, "use_variable_column_width", "variable column width (for proportional/ISCII) [false]"); bl_conf_add_opt(conf, 'W', "sep", 0, "word_separators", "word-separating characters for double-click [,.:;/@]"); bl_conf_add_opt(conf, 'X', "alpha", 0, "alpha", "alpha blending for translucent [255]"); bl_conf_add_opt(conf, 'Z', "multicol", 1, "use_multi_column_char", "fullwidth character occupies two logical columns [true]"); bl_conf_add_opt(conf, 'a', "ac", 0, "col_size_of_width_a", "columns for Unicode \"EastAsianAmbiguous\" character [1]"); bl_conf_add_opt(conf, 'b', "bg", 0, "bg_color", "background color"); #if defined(USE_XLIB) || defined(USE_CONSOLE) || defined(USE_WAYLAND) bl_conf_add_opt(conf, 'd', "display", 0, "display", "X server to connect"); #endif bl_conf_add_opt(conf, 'f', "fg", 0, "fg_color", "foreground color"); bl_conf_add_opt(conf, 'g', "geometry", 0, "geometry", "size (in characters) and position [80x24]"); bl_conf_add_opt(conf, 'k', "meta", 0, "mod_meta_mode", "mode in pressing meta key (none/esc/8bit) [8bit]"); bl_conf_add_opt(conf, 'l', "sl", 0, "logsize", "number of backlog (scrolled lines to save) [" BL_INT_TO_STR(VT_LOG_SIZE_UNIT) "]"); bl_conf_add_opt(conf, 'm', "comb", 1, "use_combining", "use combining characters [true]"); bl_conf_add_opt(conf, 'n', "noucsfont", 1, "not_use_unicode_font", "use non-Unicode fonts even in UTF-8 mode [false]"); bl_conf_add_opt(conf, 'o', "lsp", 0, "line_space", "extra space between lines in pixels [0]"); #ifndef NO_IMAGE bl_conf_add_opt(conf, 'p', "pic", 0, "wall_picture", "path for wallpaper (background) image"); #endif bl_conf_add_opt(conf, 'q', "extkey", 1, "use_extended_scroll_shortcut", "use extended scroll shortcut keys [false]"); bl_conf_add_opt(conf, 'r', "fade", 0, "fade_ratio", "fade ratio in percent when window unfocued [100]"); bl_conf_add_opt(conf, 's', "mdi", 1, "use_mdi", "use multiple document interface [true]"); #if 1 bl_conf_add_opt(conf, '\0', "sb", 1, "use_scrollbar", "use scrollbar [true]"); #endif bl_conf_add_opt(conf, 't', "transbg", 1, "use_transbg", "use transparent background [false]"); bl_conf_add_opt(conf, 'u', "onlyucsfont", 1, "only_use_unicode_font", "use a Unicode font even in non-UTF-8 modes [false]"); bl_conf_add_opt(conf, 'w', "fontsize", 0, "fontsize", "font size in pixels [16]"); bl_conf_add_opt(conf, 'x', "tw", 0, "tabsize", "tab width in columns [8]"); bl_conf_add_opt(conf, 'y', "term", 0, "termtype", "terminal type for TERM variable [xterm]"); bl_conf_add_opt(conf, 'z', "largesmall", 0, "step_in_changing_font_size", "step in changing font size in GUI configurator [1]"); bl_conf_add_opt(conf, '\0', "bdfont", 1, "use_bold_font", "use bold fonts [true]"); bl_conf_add_opt(conf, '\0', "itfont", 1, "use_italic_font", "use italic fonts [true]"); bl_conf_add_opt(conf, '\0', "iconpath", 0, "icon_path", "path to an imagefile to be use as an window icon"); #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_FRIBIDI) bl_conf_add_opt(conf, '\0', "bimode", 0, "bidi_mode", "bidi mode [normal]"); bl_conf_add_opt(conf, '\0', "bisep", 0, "bidi_separators", "Separator characters to render bidi text"); #endif bl_conf_add_opt(conf, '\0', "parent", 0, "parent_window", "parent window"); bl_conf_add_opt(conf, '\0', "bd", 0, "bd_color", "Color to use to display bold characters (equivalent to colorBD)"); bl_conf_add_opt(conf, '\0', "ul", 0, "ul_color", "Color to use to display underlined characters (equivalent to colorUL)"); bl_conf_add_opt(conf, '\0', "bl", 0, "bl_color", "Color to use to display blinking characters (equivalent to colorBL)"); bl_conf_add_opt(conf, '\0', "rv", 0, "rv_color", "Color to use to display reverse characters (equivalent to colorRV)"); bl_conf_add_opt(conf, '\0', "it", 0, "it_color", "Color to use to display italic characters"); bl_conf_add_opt(conf, '\0', "co", 0, "co_color", "Color to use to display crossed-out characters"); bl_conf_add_opt(conf, '\0', "noul", 1, "hide_underline", "Don't draw underline [false]"); bl_conf_add_opt(conf, '\0', "ulpos", 0, "underline_offset", "underline position [0]"); bl_conf_add_opt(conf, '\0', "blpos", 0, "baseline_offset", "baseline position [0]"); #ifdef USE_OT_LAYOUT bl_conf_add_opt(conf, '\0', "otl", 1, "use_ot_layout", "OpenType shape [false]"); bl_conf_add_opt(conf, '\0', "ost", 0, "ot_script", "Script of glyph subsutitution [latn]"); bl_conf_add_opt(conf, '\0', "oft", 0, "ot_features", "Features of glyph subsutitution [liga,clig,dlig,hlig,rlig]"); #endif #if defined(USE_WIN32API) || defined(USE_LIBSSH2) bl_conf_add_opt(conf, '\0', "serv", 0, "default_server", "connecting server by default"); bl_conf_add_opt(conf, '\0', "dialog", 1, "always_show_dialog", "always show dialog to input server address, password and so on [false]"); bl_conf_add_opt(conf, '\0', "pubkey", 0, "ssh_public_key", "ssh public key file " #ifdef USE_WIN32API "[%HOMEPATH%\\mlterm\\id_rsa.pub]" #else "[~/.ssh/id_rsa.pub]" #endif ); bl_conf_add_opt(conf, '\0', "privkey", 0, "ssh_private_key", "ssh private key file " #ifdef USE_WIN32API "[%HOMEPATH%\\mlterm\\id_rsa]" #else "[~/.ssh/id_rsa]" #endif ); bl_conf_add_opt(conf, '\0', "ciphlist", 0, "cipher_list", "preferred cipher list"); bl_conf_add_opt(conf, '\0', "x11", 1, "ssh_x11_forwarding", "allow x11 forwarding [false]"); bl_conf_add_opt(conf, '\0', "scp", 1, "allow_scp", "allow scp [false]"); bl_conf_add_opt(conf, '\0', "rcn", 1, "ssh_auto_reconnect", "reconnect to ssh server automatically[false]"); #endif bl_conf_add_opt(conf, '\0', "csp", 0, "letter_space", "extra space between letters in pixels [0]"); bl_conf_add_opt(conf, '\0', "osc52", 1, "allow_osc52", "allow access to clipboard by OSC 52 sequence [false]"); bl_conf_add_opt(conf, '\0', "blink", 1, "blink_cursor", "blink cursor [false]"); bl_conf_add_opt(conf, '\0', "border", 0, "inner_border", "inner border [2]"); bl_conf_add_opt(conf, '\0', "lborder", 0, "layout_inner_border", "inner border of layout manager [0]"); #ifndef __ANDROID__ bl_conf_add_opt(conf, '\0', "restart", 1, "auto_restart", "restart mlterm automatically if an error like segv happens. [true]"); #endif bl_conf_add_opt(conf, '\0', "logmsg", 1, "logging_msg", "output messages to ~/.mlterm/msg.log [true]"); bl_conf_add_opt(conf, '\0', "loecho", 1, "use_local_echo", "use local echo [false]"); bl_conf_add_opt(conf, '\0', "altbuf", 1, "use_alt_buffer", "use alternative buffer. [true]"); bl_conf_add_opt(conf, '\0', "colors", 1, "use_ansi_colors", "recognize ANSI color change escape sequences. [true]"); bl_conf_add_opt(conf, '\0', "exitbs", 1, "exit_backscroll_by_pty", "exit backscroll mode on receiving data from pty. [false]"); bl_conf_add_opt(conf, '\0', "shortcut", 1, "allow_change_shortcut", "allow dynamic change of shortcut keys. [false]"); bl_conf_add_opt(conf, '\0', "boxdraw", 0, "box_drawing_font", "force unicode or decsp font for box-drawing characters. [noconv]"); bl_conf_add_opt(conf, '\0', "urgent", 1, "use_urgent_bell", "draw the user's attention when making a bell sound. [false]"); bl_conf_add_opt(conf, '\0', "locale", 0, "locale", "set locale"); bl_conf_add_opt(conf, '\0', "ucsnoconv", 0, "unicode_noconv_areas", "use unicode fonts partially regardless of -n option"); bl_conf_add_opt(conf, '\0', "fullwidth", 0, "unicode_full_width_areas", "force full width regardless of EastAsianWidth.txt"); bl_conf_add_opt(conf, '\0', "halfwidth", 0, "unicode_half_width_areas", "force half width regardless of EastAsianWidth.txt"); bl_conf_add_opt(conf, '\0', "ade", 0, "auto_detect_encodings", "encodings detected automatically"); bl_conf_add_opt(conf, '\0', "auto", 1, "use_auto_detect", "detect character encoding automatically"); bl_conf_add_opt(conf, '\0', "ldd", 1, "leftward_double_drawing", "embold glyphs by drawing doubly at 1 pixel leftward " "instead of rightward"); bl_conf_add_opt(conf, '\0', "working-directory", 0, "working_directory", "working directory"); bl_conf_add_opt(conf, '\0', "seqfmt", 0, "vt_seq_format", "format of logging vt100 sequence. [raw]"); bl_conf_add_opt(conf, '\0', "uriword", 1, "regard_uri_as_word", "select uri by double-clicking it [false]"); bl_conf_add_opt(conf, '\0', "vtcolor", 0, "vt_color_mode", "vt color mode [high]"); bl_conf_add_opt(conf, '\0', "da1", 0, "primary_da", "primary device attributes string " #ifndef NO_IMAGE "[63;1;2;3;4;7;29]" #else "[63;1;2;7;29]" #endif ); bl_conf_add_opt(conf, '\0', "da2", 0, "secondary_da", "secondary device attributes string [24;279;0]"); bl_conf_add_opt(conf, '\0', "metaprefix", 0, "mod_meta_prefix", "prefix characters in pressing meta key if mod_meta_mode = esc"); #ifdef USE_GRF bl_conf_add_opt(conf, '\0', "multivram", 1, "separate_wall_picture", "draw wall picture on another vram. (available on 4bpp) [true]"); #endif #ifdef ROTATABLE_DISPLAY bl_conf_add_opt(conf, '\0', "rotate", 0, "rotate_display", "rotate display. [none]"); #endif #ifdef USE_CONSOLE bl_conf_add_opt(conf, '\0', "ckm", 0, "console_encoding", "character encoding of console [none]"); bl_conf_add_opt(conf, '\0', "csc", 0, "console_sixel_colors", "the number of sixel colors of console [16]"); bl_conf_add_opt(conf, '\0', "csz", 0, "default_cell_size", "default cell size [8,16]"); #endif #if defined(__ANDROID__) && defined(USE_LIBSSH2) bl_conf_add_opt(conf, '\0', "slp", 1, "start_with_local_pty", "start mlterm with local pty instead of ssh connection [false]"); #endif bl_conf_add_opt(conf, '\0', "trim", 1, "trim_trailing_newline_in_pasting", "trim trailing newline in pasting text. [false]"); bl_conf_add_opt(conf, '\0', "bc", 1, "broadcast", "broadcast input characters to all ptys [false]"); bl_conf_add_opt(conf, '\0', "ibc", 1, "ignore_broadcasted_chars", "ignore broadcasted characters [false]"); bl_conf_add_opt(conf, '\0', "emoji", 0, "emoji_path", "emoji directory or file path [~/.mlterm/emoji]"); bl_conf_add_opt(conf, '\0', "lew", 0, "local_echo_wait", "time (msec) to keep local echo mode [250]"); bl_conf_add_opt(conf, '\0', "sr", 1, "scroll_on_resizing", "scroll screen on resizing [false]"); bl_conf_add_opt(conf, '\0', "recvdir", 0, "receive_directory", "directory to save received files [~/.mlterm/recv]"); #ifdef USE_IM_CURSOR_COLOR bl_conf_add_opt(conf, '\0', "imcolor", 0, "im_cursor_color", "cursor color when input method is activated. [false]"); #endif bl_conf_set_end_opt(conf, 'e', NULL, "exec_cmd", "execute external command"); } void ui_main_config_init(ui_main_config_t *main_config, bl_conf_t *conf, int argc, char **argv) { char *value; char *invalid_msg = "%s=%s is invalid.\n"; memset(main_config, 0, sizeof(ui_main_config_t)); if ((value = bl_conf_get_value(conf, "locale"))) { bl_locale_init(value); } /* * xlib: "-d :0.0" etc. * console: "-d client:fd" * wayland: "-d wayland-0" */ #if defined(USE_XLIB) || defined(USE_CONSOLE) || defined(USE_WAYLAND) if (!(value = bl_conf_get_value(conf, "display")) || !(main_config->disp_name = strdup(value))) #endif { main_config->disp_name = default_display; #ifdef USE_XLIB /* In case of starting mlterm with "-j genuine" option without X server. */ if (getenv("DISPLAY") == NULL) { bl_setenv("DISPLAY", ":0", 0); } #endif } if ((value = bl_conf_get_value(conf, "fontsize")) == NULL) { main_config->font_size = 16; } else if (!bl_str_to_uint(&main_config->font_size, value)) { bl_msg_printf(invalid_msg, "fontsize", value); /* default value is used. */ main_config->font_size = 16; } if ((value = bl_conf_get_value(conf, "app_name"))) { main_config->app_name = strdup(value); } if ((value = bl_conf_get_value(conf, "title"))) { main_config->title = strdup(value); } #ifdef USE_XLIB if ((value = bl_conf_get_value(conf, "icon_name"))) { main_config->icon_name = strdup(value); } #endif /* BACKWARD COMPAT (3.1.7 or before) */ #if 1 if ((value = bl_conf_get_value(conf, "conf_menu_path_1"))) { main_config->shortcut_strs[0] = malloc(5 + strlen(value) + 2 + 1); sprintf(main_config->shortcut_strs[0], "\"menu:%s\"", value); } if ((value = bl_conf_get_value(conf, "conf_menu_path_2"))) { main_config->shortcut_strs[1] = malloc(5 + strlen(value) + 2 + 1); sprintf(main_config->shortcut_strs[1], "\"menu:%s\"", value); } if ((value = bl_conf_get_value(conf, "conf_menu_path_3"))) { main_config->shortcut_strs[2] = malloc(5 + strlen(value) + 2 + 1); sprintf(main_config->shortcut_strs[2], "\"menu:%s\"", value); } if ((value = bl_conf_get_value(conf, "button3_behavior")) && /* menu1,menu2,menu3,xterm values are ignored. */ strncmp(value, "menu", 4) != 0) { main_config->shortcut_strs[3] = malloc(7 + strlen(value) + 2 + 1); /* XXX "abc" should be "exesel:\"abc\"" but it's not supported. */ sprintf(main_config->shortcut_strs[3], "\"exesel:%s\"", value); } #endif if ((value = bl_conf_get_value(conf, "scrollbar_view_name"))) { main_config->scrollbar_view_name = strdup(value); } main_config->use_char_combining = 1; if ((value = bl_conf_get_value(conf, "use_combining"))) { if (strcmp(value, "false") == 0) { main_config->use_char_combining = 0; } } if ((value = bl_conf_get_value(conf, "use_dynamic_comb"))) { if (strcmp(value, "true") == 0) { main_config->use_dynamic_comb = 1; } } if ((value = bl_conf_get_value(conf, "logging_vt_seq"))) { if (strcmp(value, "true") == 0) { main_config->logging_vt_seq = 1; } } if ((value = bl_conf_get_value(conf, "vt_seq_format"))) { vt_set_use_ttyrec_format(strcmp(value, "ttyrec") == 0); } if ((value = bl_conf_get_value(conf, "logging_msg")) && strcmp(value, "false") == 0) { bl_set_msg_log_file_name(NULL); } else { bl_set_msg_log_file_name("mlterm/msg.log"); } main_config->step_in_changing_font_size = 1; if ((value = bl_conf_get_value(conf, "step_in_changing_font_size"))) { u_int size; if (bl_str_to_uint(&size, value)) { main_config->step_in_changing_font_size = size; } else { bl_msg_printf(invalid_msg, "step_in_changing_font_size", value); } } #ifdef USE_XLIB #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_CAIRO) main_config->type_engine = TYPE_CAIRO; #elif !defined(USE_TYPE_XCORE) && defined(USE_TYPE_XFT) main_config->type_engine = TYPE_XFT; #else main_config->type_engine = TYPE_XCORE; #endif if ((value = bl_conf_get_value(conf, "type_engine"))) { main_config->type_engine = ui_get_type_engine_by_name(value); } #else main_config->type_engine = TYPE_XCORE; #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO) || \ defined(USE_FREETYPE) || defined(USE_WIN32GUI) if ((value = bl_conf_get_value(conf, "use_anti_alias"))) { if (strcmp(value, "true") == 0) { main_config->font_present |= FONT_AA; if (main_config->type_engine == TYPE_XCORE) { /* forcibly use xft or cairo */ #if defined(USE_TYPE_XFT) && !defined(USE_TYPE_CAIRO) main_config->type_engine = TYPE_XFT; #else main_config->type_engine = TYPE_CAIRO; #endif } } else if (strcmp(value, "false") == 0) { main_config->font_present |= FONT_NOAA; } } #endif if ((value = bl_conf_get_value(conf, "use_variable_column_width"))) { if (strcmp(value, "true") == 0) { main_config->font_present |= FONT_VAR_WIDTH; } } if ((value = bl_conf_get_value(conf, "vertical_mode"))) { if ((main_config->vertical_mode = vt_get_vertical_mode(value))) { main_config->font_present |= main_config->vertical_mode; } } if ((value = bl_conf_get_value(conf, "fg_color"))) { main_config->fg_color = strdup(value); } if ((value = bl_conf_get_value(conf, "bg_color"))) { main_config->bg_color = strdup(value); } if ((value = bl_conf_get_value(conf, "cursor_fg_color"))) { main_config->cursor_fg_color = strdup(value); } if ((value = bl_conf_get_value(conf, "cursor_bg_color"))) { main_config->cursor_bg_color = strdup(value); } main_config->alt_color_mode = 0; if ((value = bl_conf_get_value(conf, "bd_color"))) { main_config->bd_color = strdup(value); main_config->alt_color_mode |= ALT_COLOR_BOLD; } if ((value = bl_conf_get_value(conf, "ul_color"))) { main_config->ul_color = strdup(value); main_config->alt_color_mode |= ALT_COLOR_UNDERLINE; } if ((value = bl_conf_get_value(conf, "bl_color"))) { main_config->ul_color = strdup(value); main_config->alt_color_mode |= ALT_COLOR_BLINKING; } if ((value = bl_conf_get_value(conf, "rv_color"))) { main_config->rv_color = strdup(value); main_config->alt_color_mode |= ALT_COLOR_REVERSE; } if ((value = bl_conf_get_value(conf, "it_color"))) { main_config->it_color = strdup(value); main_config->alt_color_mode |= ALT_COLOR_ITALIC; } if ((value = bl_conf_get_value(conf, "co_color"))) { main_config->ul_color = strdup(value); main_config->alt_color_mode |= ALT_COLOR_CROSSED_OUT; } if ((value = bl_conf_get_value(conf, "sb_fg_color"))) { main_config->sb_fg_color = strdup(value); } if ((value = bl_conf_get_value(conf, "sb_bg_color"))) { main_config->sb_bg_color = strdup(value); } if ((value = bl_conf_get_value(conf, "termtype"))) { main_config->term_type = strdup(value); } else { main_config->term_type = strdup("xterm"); } #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF /* * The pty is always resized to fit the display size. * Don't use 80x24 for the default value because the screen is not drawn * correctly on startup if the display size / the us-ascii font size is * 80x24 by chance. */ main_config->cols = 1; main_config->rows = 1; #else main_config->cols = 80; main_config->rows = 24; if ((value = bl_conf_get_value(conf, "geometry"))) { /* * For each value not found, the argument is left unchanged. * (see man XParseGeometry(3)) */ main_config->geom_hint = XParseGeometry(value, &main_config->x, &main_config->y, &main_config->cols, &main_config->rows); if (main_config->cols == 0 || main_config->rows == 0) { bl_msg_printf("geometry option %s is illegal.\n", value); main_config->cols = 80; main_config->rows = 24; } } #endif main_config->screen_width_ratio = 100; #if 1 /* BACKWARD COMPAT (3.8.2 or before) */ if ((value = bl_conf_get_value(conf, "screen_height_ratio"))) { u_int ratio; if (bl_str_to_uint(&ratio, value) && ratio) { main_config->screen_width_ratio = ratio; } } #endif if ((value = bl_conf_get_value(conf, "screen_width_ratio"))) { u_int ratio; if (bl_str_to_uint(&ratio, value) && ratio) { main_config->screen_width_ratio = ratio; } else { bl_msg_printf(invalid_msg, "screen_width_ratio", value); } } main_config->use_multi_col_char = 1; if ((value = bl_conf_get_value(conf, "use_multi_column_char"))) { if (strcmp(value, "false") == 0) { main_config->use_multi_col_char = 0; } } if ((value = bl_conf_get_value(conf, "line_space"))) { int size; if (bl_str_to_int(&size, value)) { main_config->line_space = size; } else { bl_msg_printf(invalid_msg, "line_space", value); } } if ((value = bl_conf_get_value(conf, "letter_space"))) { u_int size; if (bl_str_to_uint(&size, value)) { main_config->letter_space = size; } else { bl_msg_printf(invalid_msg, "letter_space", value); } } main_config->num_log_lines = VT_LOG_SIZE_UNIT; main_config->unlimit_log_size = 0; if ((value = bl_conf_get_value(conf, "logsize"))) { u_int size; if (strcmp(value, "unlimited") == 0) { main_config->unlimit_log_size = 1; } else if (bl_str_to_uint(&size, value)) { main_config->num_log_lines = size; } else { bl_msg_printf(invalid_msg, "logsize", value); } } main_config->tab_size = 8; if ((value = bl_conf_get_value(conf, "tabsize"))) { u_int size; if (bl_str_to_uint(&size, value)) { main_config->tab_size = size; } else { bl_msg_printf(invalid_msg, "tabsize", value); } } #if defined(__APPLE__) || defined(USE_BEOS) main_config->use_login_shell = 1; #else main_config->use_login_shell = 0; #endif if ((value = bl_conf_get_value(conf, "use_login_shell"))) { if (strcmp(value, "true") == 0) { main_config->use_login_shell = 1; } } if ((value = bl_conf_get_value(conf, "big5_buggy"))) { int flag = true_or_false(value); if (flag != -1) { ui_set_big5_selection_buggy(flag); } } main_config->use_mdi = 1; #if !defined(USE_QUARTZ) && !defined(USE_BEOS) if ((value = bl_conf_get_value(conf, "use_mdi"))) { if (strcmp(value, "false") == 0) { main_config->use_mdi = 0; } } #endif #if defined(USE_CONSOLE) || defined(COCOA_TOUCH) main_config->sb_mode = SBM_NONE; #else if ((value = bl_conf_get_value(conf, "scrollbar_mode"))) { main_config->sb_mode = ui_get_sb_mode_by_name(value); } else { /* XXX Backward compatibility with 3.4.5 or before */ #if 1 if ((value = bl_conf_get_value(conf, "use_scrollbar"))) { main_config->sb_mode = (strcmp(value, "true") == 0 ? SBM_LEFT : SBM_NONE); } else #endif { main_config->sb_mode = SBM_LEFT; } } #endif if ((value = bl_conf_get_value(conf, "iso88591_font_for_usascii"))) { if (strcmp(value, "true") == 0) { main_config->iso88591_font_for_usascii = 1; } } if ((value = bl_conf_get_value(conf, "not_use_unicode_font"))) { if (strcmp(value, "true") == 0) { main_config->unicode_policy = NOT_USE_UNICODE_FONT; } } if ((value = bl_conf_get_value(conf, "unicode_noconv_areas"))) { vt_set_unicode_noconv_areas(value); } if ((value = bl_conf_get_value(conf, "unicode_full_width_areas"))) { vt_set_full_width_areas(value); } if ((value = bl_conf_get_value(conf, "unicode_half_width_areas"))) { vt_set_half_width_areas(value); } if ((value = bl_conf_get_value(conf, "only_use_unicode_font"))) { if (strcmp(value, "true") == 0) { if (main_config->unicode_policy == NOT_USE_UNICODE_FONT) { bl_msg_printf( "only_use_unicode_font and not_use_unicode_font options " "cannot be used at the same time.\n"); /* default values are used */ main_config->unicode_policy = 0; } else { main_config->unicode_policy = ONLY_USE_UNICODE_FONT; } } } #ifdef FORCE_UNICODE else { main_config->unicode_policy = ONLY_USE_UNICODE_FONT; } #endif if ((value = bl_conf_get_value(conf, "box_drawing_font"))) { if (strcmp(value, "decsp") == 0) { main_config->unicode_policy |= NOT_USE_UNICODE_BOXDRAW_FONT; } else if (strcmp(value, "unicode") == 0) { main_config->unicode_policy |= ONLY_USE_UNICODE_BOXDRAW_FONT; } } #ifdef FORCE_UNICODE else { main_config->unicode_policy |= ONLY_USE_UNICODE_BOXDRAW_FONT; } #endif if ((value = bl_conf_get_value(conf, "receive_string_via_ucs"))) { if (strcmp(value, "true") == 0) { main_config->receive_string_via_ucs = 1; } } /* "zh" and "ko" ? */ if (strcmp(bl_get_lang(), "ja") == 0 #ifdef USE_WIN32API || strcmp(bl_get_lang(), "Japanese") == 0 #endif ) { main_config->col_size_of_width_a = 2; } else { main_config->col_size_of_width_a = 1; } if ((value = bl_conf_get_value(conf, "col_size_of_width_a"))) { u_int col_size_of_width_a; if (bl_str_to_uint(&col_size_of_width_a, value)) { main_config->col_size_of_width_a = col_size_of_width_a; } else { bl_msg_printf(invalid_msg, "col_size_of_width_a", value); } } if ((value = bl_conf_get_value(conf, "wall_picture"))) { if (*value != '\0') { main_config->pic_file_path = strdup(value); } } if ((value = bl_conf_get_value(conf, "use_transbg"))) { if (strcmp(value, "true") == 0) { main_config->use_transbg = 1; } } if (main_config->pic_file_path && main_config->use_transbg) { bl_msg_printf( "wall picture and transparent background cannot be used at the same " "time.\n"); /* using wall picture */ main_config->use_transbg = 0; } main_config->brightness = 100; if ((value = bl_conf_get_value(conf, "brightness"))) { u_int brightness; if (bl_str_to_uint(&brightness, value)) { main_config->brightness = brightness; } else { bl_msg_printf(invalid_msg, "brightness", value); } } main_config->contrast = 100; if ((value = bl_conf_get_value(conf, "contrast"))) { u_int contrast; if (bl_str_to_uint(&contrast, value)) { main_config->contrast = contrast; } else { bl_msg_printf(invalid_msg, "contrast", value); } } main_config->gamma = 100; if ((value = bl_conf_get_value(conf, "gamma"))) { u_int gamma; if (bl_str_to_uint(&gamma, value)) { main_config->gamma = gamma; } else { bl_msg_printf(invalid_msg, "gamma", value); } } main_config->alpha = 255; if ((value = bl_conf_get_value(conf, "alpha"))) { u_int alpha; if (bl_str_to_uint(&alpha, value)) { main_config->alpha = alpha; } else { bl_msg_printf(invalid_msg, "alpha", value); } } main_config->fade_ratio = 100; if ((value = bl_conf_get_value(conf, "fade_ratio"))) { u_int fade_ratio; if (bl_str_to_uint(&fade_ratio, value) && fade_ratio <= 100) { main_config->fade_ratio = fade_ratio; } else { bl_msg_printf(invalid_msg, "fade_ratio", value); } } main_config->encoding = get_encoding(bl_conf_get_value(conf, "encoding"), &main_config->is_auto_encoding); #ifdef USE_CONSOLE ui_display_set_char_encoding(NULL, get_encoding(bl_conf_get_value(conf, "console_encoding"), NULL)); if ((value = bl_conf_get_value(conf, "console_sixel_colors"))) { ui_display_set_sixel_colors(NULL, value); } if ((value = bl_conf_get_value(conf, "cell_size"))) { u_int width; u_int height; if (sscanf(value, "%d,%d", &width, &height) == 2) { ui_display_set_default_cell_size(width, height); } } #endif #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_FRIBIDI) || defined(USE_IND) || \ defined(USE_OT_LAYOUT) main_config->use_ctl = 1; if ((value = bl_conf_get_value(conf, "use_ctl"))) { if (strcmp(value, "false") == 0) { /* * If use_ot_layout is true, use_ctl = true forcibly. * See processing "use_ot_layout" option. */ main_config->use_ctl = 0; } } #endif main_config->bidi_mode = BIDI_NORMAL_MODE; #if !defined(NO_DYNAMIC_LOAD_CTL) || defined(USE_FRIBIDI) if ((value = bl_conf_get_value(conf, "bidi_mode"))) { #if 1 /* Compat with 3.3.6 or before. */ if (strcmp(value, "cmd_l") == 0) { main_config->bidi_mode = BIDI_ALWAYS_LEFT; main_config->bidi_separators = strdup(" "); } else if (strcmp(value, "cmd_r") == 0) { main_config->bidi_mode = BIDI_ALWAYS_RIGHT; main_config->bidi_separators = strdup(" "); } else #endif { main_config->bidi_mode = vt_get_bidi_mode(value); } } if ((value = bl_conf_get_value(conf, "bidi_separators"))) { free(main_config->bidi_separators); main_config->bidi_separators = strdup(value); } #endif /* If value is "none" or not is also checked in ui_screen.c */ if ((value = bl_conf_get_value(conf, "mod_meta_key")) && strcmp(value, "none") != 0) { main_config->mod_meta_key = strdup(value); } if ((value = bl_conf_get_value(conf, "mod_meta_mode"))) { main_config->mod_meta_mode = ui_get_mod_meta_mode_by_name(value); } else { main_config->mod_meta_mode = MOD_META_SET_MSB; } if ((value = bl_conf_get_value(conf, "bel_mode"))) { main_config->bel_mode = ui_get_bel_mode_by_name(value); } else { main_config->bel_mode = BEL_SOUND; } if ((value = bl_conf_get_value(conf, "use_urgent_bell"))) { int flag = true_or_false(value); if (flag != -1) { ui_set_use_urgent_bell(flag); } } main_config->use_vertical_cursor = 1; if ((value = bl_conf_get_value(conf, "use_vertical_cursor"))) { if (strcmp(value, "false") == 0) { main_config->use_vertical_cursor = 0; } } if ((value = bl_conf_get_value(conf, "use_extended_scroll_shortcut"))) { if (strcmp(value, "true") == 0) { main_config->use_extended_scroll_shortcut = 1; } } #ifdef USE_XLIB if ((value = bl_conf_get_value(conf, "borderless"))) { if (strcmp(value, "true") == 0) { main_config->borderless = 1; } } #endif main_config->bs_mode = BSM_DEFAULT; if ((value = bl_conf_get_value(conf, "static_backscroll_mode"))) { if (strcmp(value, "true") == 0) { main_config->bs_mode = BSM_STATIC; } } if ((value = bl_conf_get_value(conf, "exit_backscroll_by_pty"))) { int flag = true_or_false(value); if (flag != -1) { ui_exit_backscroll_by_pty(flag); } } if ((value = bl_conf_get_value(conf, "allow_change_shortcut"))) { int flag = true_or_false(value); if (flag != -1) { ui_allow_change_shortcut(flag); } } if ((value = bl_conf_get_value(conf, "icon_path"))) { main_config->icon_path = strdup(value); } if ((value = bl_conf_get_value(conf, "input_method"))) { main_config->input_method = strdup(value); } else { #ifdef USE_WAYLAND main_config->input_method = strdup("ibus"); #else main_config->input_method = strdup("xim"); #endif } if ((value = bl_conf_get_value(conf, "init_str"))) { if ((main_config->init_str = malloc(strlen(value) + 1))) { char *p1; char *p2; p1 = value; p2 = main_config->init_str; while (*p1) { if (*p1 == '\\') { p1++; if (*p1 == '\0') { break; } else if (*p1 == 'n') { *(p2++) = '\n'; } else if (*p1 == 'r') { *(p2++) = '\r'; } else if (*p1 == 't') { *(p2++) = '\t'; } else if (*p1 == 'e') { *(p2++) = '\033'; } else { *(p2++) = *p1; } } else { *(p2++) = *p1; } p1++; } *p2 = '\0'; } } if ((value = bl_conf_get_value(conf, "parent_window"))) { u_int parent_window; if (bl_str_to_uint(&parent_window, value)) { main_config->parent_window = parent_window; } else { bl_msg_printf(invalid_msg, "parent_window", value); } } #if defined(USE_WIN32API) || defined(USE_LIBSSH2) if ((value = bl_conf_get_value(conf, "default_server")) && *value) { main_config->default_server = strdup(value); } if ((value = bl_conf_get_value(conf, "always_show_dialog"))) { if (strcmp(value, "true") == 0) { main_config->show_dialog = 1; } } #endif #ifdef USE_LIBSSH2 if ((value = bl_conf_get_value(conf, "ssh_public_key"))) { main_config->public_key = strdup(value); } if ((value = bl_conf_get_value(conf, "ssh_private_key"))) { main_config->private_key = strdup(value); } if ((value = bl_conf_get_value(conf, "cipher_list"))) { vt_pty_ssh_set_cipher_list(strdup(value)); } if ((value = bl_conf_get_value(conf, "ssh_x11_forwarding"))) { if (strcmp(value, "true") == 0) { main_config->use_x11_forwarding = 1; } } if ((value = bl_conf_get_value(conf, "allow_scp"))) { int flag = true_or_false(value); if (flag != -1) { vt_set_use_scp_full(flag); } } if ((value = bl_conf_get_value(conf, "ssh_auto_reconnect"))) { int flag = true_or_false(value); if (flag != -1) { vt_pty_ssh_set_use_auto_reconnect(flag); } } #endif if ((value = bl_conf_get_value(conf, "allow_osc52"))) { if (strcmp(value, "true") == 0) { main_config->allow_osc52 = 1; } } if ((value = bl_conf_get_value(conf, "blink_cursor"))) { if (strcmp(value, "true") == 0) { main_config->blink_cursor = 1; } } main_config->hmargin = main_config->vmargin = 2; if ((value = bl_conf_get_value(conf, "inner_border"))) { u_int hmargin; u_int vmargin; /* 640x480 => (640-224*2)x(480-224*2) => 192x32 on framebuffer. */ if (sscanf(value, "%d,%d", &hmargin, &vmargin) == 2) { if (hmargin <= 224 && vmargin <= 224) { main_config->hmargin = hmargin; main_config->vmargin = vmargin; } } else if (bl_str_to_uint(&hmargin, value) && hmargin <= 224) { main_config->hmargin = main_config->vmargin = hmargin; } } main_config->layout_hmargin = main_config->layout_vmargin = 0; if ((value = bl_conf_get_value(conf, "layout_inner_border"))) { u_int hmargin; u_int vmargin; /* 640x480 => (640-224*2)x(480-224*2) => 192x32 on framebuffer. */ if (sscanf(value, "%d,%d", &hmargin, &vmargin) == 2) { if (hmargin <= 224 && vmargin <= 224) { main_config->layout_hmargin = hmargin; main_config->layout_vmargin = vmargin; } } else if (bl_str_to_uint(&hmargin, value) && hmargin <= 224) { main_config->layout_hmargin = main_config->layout_vmargin = hmargin; } } main_config->use_bold_font = 1; if ((value = bl_conf_get_value(conf, "use_bold_font"))) { if (strcmp(value, "false") == 0) { main_config->use_bold_font = 0; } } main_config->use_italic_font = 1; if ((value = bl_conf_get_value(conf, "use_italic_font"))) { if (strcmp(value, "false") == 0) { main_config->use_italic_font = 0; } } if ((value = bl_conf_get_value(conf, "hide_underline"))) { if (strcmp(value, "true") == 0) { main_config->hide_underline = 1; } } if ((value = bl_conf_get_value(conf, "underline_offset"))) { int size; if (bl_str_to_int(&size, value)) { main_config->underline_offset = size; } else { bl_msg_printf(invalid_msg, "underline_offset", value); } } if ((value = bl_conf_get_value(conf, "baseline_offset"))) { int size; if (bl_str_to_int(&size, value)) { main_config->baseline_offset = size; } else { bl_msg_printf(invalid_msg, "baseline_offset", value); } } if ((value = bl_conf_get_value(conf, "word_separators"))) { vt_set_word_separators(value); } if ((value = bl_conf_get_value(conf, "regard_uri_as_word"))) { int flag = true_or_false(value); if (flag != -1) { vt_set_regard_uri_as_word(flag); } } if ((value = bl_conf_get_value(conf, "use_clipboard"))) { int flag = true_or_false(value); if (flag != -1) { ui_set_use_clipboard_selection(flag); } } #ifndef __ANDROID__ if (!(value = bl_conf_get_value(conf, "auto_restart")) || strcmp(value, "false") != 0) { vt_set_auto_restart_cmd(bl_get_prog_path()); } #endif if ((value = bl_conf_get_value(conf, "use_local_echo"))) { if (strcmp(value, "true") == 0) { main_config->use_local_echo = 1; } } if ((value = bl_conf_get_value(conf, "local_echo_wait"))) { u_int msec; if (bl_str_to_uint(&msec, value)) { vt_set_local_echo_wait(msec); } } if ((value = bl_conf_get_value(conf, "click_interval"))) { int interval; if (bl_str_to_int(&interval, value)) { ui_set_click_interval(interval); } else { bl_msg_printf(invalid_msg, "click_interval", value); } } if ((value = bl_conf_get_value(conf, "use_alt_buffer"))) { int flag = true_or_false(value); if (flag != -1) { vt_set_use_alt_buffer(flag); } } main_config->use_ansi_colors = 1; if ((value = bl_conf_get_value(conf, "use_ansi_colors"))) { if (strcmp(value, "false") == 0) { main_config->use_ansi_colors = 0; } ui_display_set_use_ansi_colors(main_config->use_ansi_colors); } if ((value = bl_conf_get_value(conf, "auto_detect_encodings"))) { vt_set_auto_detect_encodings(value); } if ((value = bl_conf_get_value(conf, "use_auto_detect"))) { if (strcmp(value, "true") == 0) { main_config->use_auto_detect = 1; } } if ((value = bl_conf_get_value(conf, "leftward_double_drawing"))) { int flag = true_or_false(value); if (flag != -1) { ui_set_use_leftward_double_drawing(flag); } } if ((value = bl_conf_get_value(conf, "working_directory"))) { main_config->work_dir = strdup(value); } if ((value = bl_conf_get_value(conf, "vt_color_mode"))) { vt_set_color_mode(value); } if ((value = bl_conf_get_value(conf, "primary_da"))) { vt_set_primary_da(value); } if ((value = bl_conf_get_value(conf, "secondary_da"))) { vt_set_secondary_da(value); } if ((value = bl_conf_get_value(conf, "mod_meta_prefix"))) { ui_set_mod_meta_prefix(bl_str_unescape(value)); } #ifdef USE_OT_LAYOUT main_config->use_ot_layout = 0; if ((value = bl_conf_get_value(conf, "use_ot_layout"))) { if (strcmp(value, "true") == 0) { main_config->use_ot_layout = 1; if (!main_config->use_ctl) { bl_msg_printf("Set use_ctl=true forcibly."); main_config->use_ctl = 1; } } } if ((value = bl_conf_get_value(conf, "ot_script"))) { vt_set_ot_layout_attr(value, OT_SCRIPT); } if ((value = bl_conf_get_value(conf, "ot_features"))) { vt_set_ot_layout_attr(value, OT_FEATURES); } #endif #ifdef USE_GRF if ((value = bl_conf_get_value(conf, "separate_wall_picture"))) { extern int separate_wall_picture; int flag = true_or_false(value); if (flag != -1) { separate_wall_picture = flag; } } #endif #ifdef ROTATABLE_DISPLAY if ((value = bl_conf_get_value(conf, "rotate_display"))) { ui_display_rotate(strcmp(value, "right") == 0 ? 1 : (strcmp(value, "left") == 0 ? -1 : 0)); } #endif #if defined(__ANDROID__) && defined(USE_LIBSSH2) if ((value = bl_conf_get_value(conf, "start_with_local_pty"))) { int flag = true_or_false(value); if (flag != -1) { start_with_local_pty = flag; } } #endif if ((value = bl_conf_get_value(conf, "trim_trailing_newline_in_pasting"))) { int flag = true_or_false(value); if (flag != -1) { ui_set_trim_trailing_newline_in_pasting(flag); } } if ((value = bl_conf_get_value(conf, "broadcast"))) { int flag = true_or_false(value); if (flag != -1) { vt_set_broadcasting(flag); } } if ((value = bl_conf_get_value(conf, "ignore_broadcasted_chars"))) { if (strcmp(value, "true") == 0) { main_config->ignore_broadcasted_chars = 1; } } if ((value = bl_conf_get_value(conf, "emoji_path"))) { ui_emoji_set_path(value); } if ((value = bl_conf_get_value(conf, "scroll_on_resizing"))) { int flag = true_or_false(value); if (flag != -1) { vt_set_scroll_on_resizing(flag); } } if ((value = bl_conf_get_value(conf, "receive_directory"))) { vt_set_recv_dir(value); } #ifdef USE_IM_CURSOR_COLOR if ((value = bl_conf_get_value(conf, "im_cursor_color"))) { if (*value) { ui_set_im_cursor_color(value); } } #endif if ((value = bl_conf_get_value(conf, "exec_cmd"))) { if (strcmp(value, "true") == 0) { if ((main_config->cmd_argv = malloc(sizeof(char *) * (argc + 1)))) { /* * !! Notice !! * cmd_path and strings in cmd_argv vector should be allocated * by the caller. */ main_config->cmd_path = argv[0]; memcpy(&main_config->cmd_argv[0], argv, sizeof(char *) * argc); main_config->cmd_argv[argc] = NULL; } } else { u_int argc; argc = bl_count_char_in_str(value, ' ') + 1; if ((main_config->cmd_argv = malloc(sizeof(char *) * (argc + 1) + strlen(value) + 1))) { value = strcpy(main_config->cmd_argv + argc + 1, value); bl_arg_str_to_array(main_config->cmd_argv, &argc, value); main_config->cmd_path = main_config->cmd_argv[0]; } } } } void ui_main_config_final(ui_main_config_t *main_config) { if (main_config->disp_name != default_display) { free(main_config->disp_name); } free(main_config->app_name); free(main_config->title); free(main_config->icon_name); free(main_config->term_type); free(main_config->scrollbar_view_name); free(main_config->pic_file_path); free(main_config->shortcut_strs[0]); free(main_config->shortcut_strs[1]); free(main_config->shortcut_strs[2]); free(main_config->shortcut_strs[3]); free(main_config->fg_color); free(main_config->bg_color); free(main_config->cursor_fg_color); free(main_config->cursor_bg_color); free(main_config->bd_color); free(main_config->it_color); free(main_config->ul_color); free(main_config->bl_color); free(main_config->co_color); free(main_config->sb_fg_color); free(main_config->sb_bg_color); free(main_config->mod_meta_key); free(main_config->icon_path); free(main_config->input_method); free(main_config->init_str); free(main_config->bidi_separators); #if defined(USE_WIN32API) || defined(USE_LIBSSH2) free(main_config->default_server); #endif #ifdef USE_LIBSSH2 free(main_config->public_key); free(main_config->private_key); #endif free(main_config->work_dir); free(main_config->cmd_argv); } mlterm-3.8.9/uitoolkit/ui_main_config.h010064400017600000144000000056151356600660700167130ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_MAIN_CONFIG_H__ #define __UI_MAIN_CONFIG_H__ #include #include #include #include "ui_layout.h" typedef struct ui_main_config { /* * Public (read only) */ int x; int y; int geom_hint; u_int cols; u_int rows; u_int font_size; u_int tab_size; u_int screen_width_ratio; u_int num_log_lines; ui_mod_meta_mode_t mod_meta_mode; ui_bel_mode_t bel_mode; ui_sb_mode_t sb_mode; vt_char_encoding_t encoding; int is_auto_encoding; ui_type_engine_t type_engine; ui_font_present_t font_present; vt_bidi_mode_t bidi_mode; vt_vertical_mode_t vertical_mode; vt_bs_mode_t bs_mode; vt_unicode_policy_t unicode_policy; vt_alt_color_mode_t alt_color_mode; u_int parent_window; char *disp_name; char *app_name; char *title; char *icon_name; char *term_type; char *scrollbar_view_name; char *pic_file_path; /* BACKWARD COMPAT (3.1.7 or before) */ #if 1 char *shortcut_strs[4]; #endif char *fg_color; char *bg_color; char *cursor_fg_color; char *cursor_bg_color; char *bd_color; char *ul_color; char *bl_color; char *rv_color; char *it_color; char *co_color; char *sb_fg_color; char *sb_bg_color; char *mod_meta_key; char *icon_path; char *input_method; char *init_str; char *bidi_separators; #if defined(USE_WIN32API) || defined(USE_LIBSSH2) char *default_server; #endif #ifdef USE_LIBSSH2 char *public_key; char *private_key; #endif char *work_dir; char *cmd_path; char **cmd_argv; u_int16_t brightness; u_int16_t contrast; u_int16_t gamma; u_int8_t col_size_of_width_a; u_int8_t step_in_changing_font_size; u_int8_t alpha; u_int8_t fade_ratio; int8_t line_space; u_int8_t letter_space; int8_t use_mdi; int8_t use_login_shell; int8_t use_ctl; int8_t iso88591_font_for_usascii; int8_t receive_string_via_ucs; int8_t use_transbg; int8_t use_char_combining; int8_t use_multi_col_char; int8_t use_vertical_cursor; int8_t use_extended_scroll_shortcut; int8_t borderless; int8_t use_dynamic_comb; int8_t logging_vt_seq; int8_t allow_osc52; int8_t blink_cursor; u_int8_t hmargin; u_int8_t vmargin; u_int8_t layout_hmargin; u_int8_t layout_vmargin; int8_t hide_underline; int8_t underline_offset; int8_t baseline_offset; int8_t use_bold_font; int8_t use_italic_font; int8_t use_local_echo; int8_t use_x11_forwarding; int8_t use_auto_detect; int8_t unlimit_log_size; int8_t use_ot_layout; int8_t ignore_broadcasted_chars; int8_t use_ansi_colors; #if defined(USE_WIN32API) || defined(USE_LIBSSH2) int8_t show_dialog; #endif } ui_main_config_t; void ui_prepare_for_main_config(bl_conf_t *conf); void ui_main_config_init(ui_main_config_t *main_config, bl_conf_t *conf, int argc, char **argv); void ui_main_config_final(ui_main_config_t *main_config); #endif mlterm-3.8.9/uitoolkit/ui_mod_meta_mode.c010064400017600000144000000014641356600660700172240ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_mod_meta_mode.h" #include /* strcmp */ /* --- static variables --- */ /* Order of this table must be same as ui_mod_meta_mode_t. */ static char *mod_meta_mode_name_table[] = { "none", "esc", "8bit", }; /* --- global functions --- */ ui_mod_meta_mode_t ui_get_mod_meta_mode_by_name(char *name) { ui_mod_meta_mode_t mode; for (mode = 0; mode < MOD_META_MODE_MAX; mode++) { if (strcmp(mod_meta_mode_name_table[mode], name) == 0) { return mode; } } /* default value */ return MOD_META_NONE; } char *ui_get_mod_meta_mode_name(ui_mod_meta_mode_t mode) { if (mode < 0 || MOD_META_MODE_MAX <= mode) { /* default value */ mode = MOD_META_NONE; } return mod_meta_mode_name_table[mode]; } mlterm-3.8.9/uitoolkit/ui_mod_meta_mode.h010064400017600000144000000006211356600660700172230ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_MOD_META_MODE_H__ #define __UI_MOD_META_MODE_H__ typedef enum ui_mod_meta_mode { MOD_META_NONE = 0x0, MOD_META_OUTPUT_ESC, MOD_META_SET_MSB, MOD_META_MODE_MAX } ui_mod_meta_mode_t; ui_mod_meta_mode_t ui_get_mod_meta_mode_by_name(char *name); char *ui_get_mod_meta_mode_name(ui_mod_meta_mode_t mode); #endif mlterm-3.8.9/uitoolkit/ui_picture.c010064400017600000144000000661041356600660700161100ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef NO_IMAGE #include "ui_picture.h" #include /* unlink */ #include /* system */ #include #include #include #include /* strdup */ #include /* malloc */ #include /* DIGIT_STR_LEN */ #include /* bl_get_user_rc_path */ #ifdef HAVE_WINDOWS_H #include /* for CreateEvent */ #endif #if defined(USE_WIN32API) #include /* _beginthreadex */ #elif defined(HAVE_PTHREAD) #include #endif #if defined(HAVE_PTHREAD) || defined(USE_WIN32API) #ifndef HAVE_WINDOWS_H #include #include #endif #endif #ifdef USE_XLIB /* HAVE_WINDOWS_H is undefined on cygwin/x11 */ #undef HAVE_WINDOWS_H #endif #include "ui_imagelib.h" #define DUMMY_PIXMAP ((Pixmap)1) #define PIXMAP_IS_ACTIVE(inline_pic) ((inline_pic).pixmap && (inline_pic).pixmap != DUMMY_PIXMAP) #if 0 #define __DEBUG #endif typedef struct inline_pic_args { int idx; #ifdef HAVE_WINDOWS_H HANDLE ev; #else int ev; #endif int keep_aspect; } inline_pic_args_t; /* --- static varaibles --- */ static ui_picture_t **pics; static u_int num_pics; static ui_icon_picture_t **icon_pics; static u_int num_icon_pics; static ui_inline_picture_t *inline_pics; static u_int num_inline_pics; static u_int num_anims; static int need_cleanup; /* --- static functions --- */ static ui_picture_t *create_picture_intern(Display *display, ui_picture_modifier_t *mod, char *file_path, u_int width, u_int height) { ui_picture_t *pic; if ((pic = malloc(sizeof(ui_picture_t))) == NULL) { return NULL; } if (mod) { if ((pic->mod = malloc(sizeof(ui_picture_modifier_t))) == NULL) { goto error1; } *pic->mod = *mod; } else { pic->mod = NULL; } if ((pic->file_path = strdup(file_path)) == NULL) { goto error2; } pic->display = display; pic->width = width; pic->height = height; return pic; error2: free(pic->mod); error1: free(pic); return NULL; } static int destroy_picture_intern(ui_picture_t *pic) { free(pic->file_path); free(pic->mod); free(pic); return 1; } static ui_picture_t *create_bg_picture(ui_window_t *win, ui_picture_modifier_t *mod, char *file_path) { ui_picture_t *pic; if (!(pic = create_picture_intern(win->disp->display, mod, file_path, ACTUAL_WIDTH(win), ACTUAL_HEIGHT(win)))) { return NULL; } if (strcmp(file_path, "root") == 0) { pic->pixmap = ui_imagelib_get_transparent_background(win, mod); } else { pic->pixmap = ui_imagelib_load_file_for_background(win, file_path, mod); } if (pic->pixmap == None) { destroy_picture_intern(pic); return NULL; } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " New pixmap %ul is created.\n", pic->pixmap); #endif pic->ref_count = 1; return pic; } static int destroy_picture(ui_picture_t *pic) { /* XXX Pixmap of "pixmap:" is managed by others, so don't free here. */ if (strncmp(pic->file_path, "pixmap:", 7) != 0) { ui_destroy_image(pic->display, pic->pixmap); } destroy_picture_intern(pic); #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " pixmap is destroyed.\n"); #endif return 1; } static ui_icon_picture_t *create_icon_picture(ui_display_t *disp, char *file_path /* Don't specify NULL. */ ) { u_int icon_size = 48; ui_icon_picture_t *pic; if ((pic = malloc(sizeof(ui_icon_picture_t))) == NULL) { return NULL; } if ((pic->file_path = strdup(file_path)) == NULL) { free(pic->file_path); return NULL; } if (!ui_imagelib_load_file(disp, file_path, &(pic->cardinal), &(pic->pixmap), &(pic->mask), &icon_size, &icon_size, 0)) { free(pic->file_path); free(pic); #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to load icon file(%s).\n", file_path); #endif return NULL; } pic->disp = disp; pic->ref_count = 1; #if 0 bl_debug_printf(BL_DEBUG_TAG " Successfully loaded icon file %s.\n", file_path); #endif return pic; } static int destroy_icon_picture(ui_icon_picture_t *pic) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s icon will be destroyed.\n", pic->file_path); #endif ui_destroy_image(pic->disp->display, pic->pixmap); ui_destroy_mask(pic->disp->display, pic->mask); free(pic->cardinal); free(pic->file_path); free(pic); return 1; } static int hash_path(char *path) { int hash; hash = 0; while (*path) { hash += *(path++); } return hash & 65535 /* 0xffff */; } static inline size_t get_anim_file_path_len(char *dir) { return strlen(dir) + 10 + 5 + DIGIT_STR_LEN(int)+1; } static int anim_file_exists(char *file_path, char *dir, int hash, int count) { struct stat st; if (count > 0) { sprintf(file_path, "%sanim%d-%d.gif", dir, hash, count); if (stat(file_path, &st) == 0) { return 1; } sprintf(file_path, "%sanimx%d-%d.gif", dir, hash, count); } else { sprintf(file_path, "%sanim%d.gif", dir, hash); } return stat(file_path, &st) == 0; } /* * XXX * This function should be called synchronously because both load_file_async() * and cleanup_inline_pictures() can call this asynchronously. */ static int destroy_inline_picture(ui_inline_picture_t *pic /* pic->pixmap mustn't be NULL. */ ) { if (pic->pixmap == DUMMY_PIXMAP) { if (strstr(pic->file_path, "mlterm/anim")) { /* GIF Animation frame */ unlink(pic->file_path); } else if (pic->disp) { /* loading async */ return 0; } } /* pic->disp can be NULL by ui_picture_display_closed() and load_file(). */ if (pic->disp) { if (pic->pixmap != DUMMY_PIXMAP) { ui_destroy_image(pic->disp->display, pic->pixmap); ui_destroy_mask(pic->disp->display, pic->mask); } pic->disp = NULL; } if (pic->file_path) { if (strcasecmp(pic->file_path + strlen(pic->file_path) - 4, ".gif") == 0 && /* If check_anim was processed, next_frame == -2. */ pic->next_frame == -1) { char *dir; char *file_path; if ((dir = bl_get_user_rc_path("mlterm/")) && (file_path = alloca(get_anim_file_path_len(dir)))) { int hash; int count; hash = hash_path(pic->file_path); for (count = 0;; count++) { if (!anim_file_exists(file_path, dir, hash, count)) { break; } unlink(file_path); } } free(dir); } free(pic->file_path); pic->file_path = NULL; } /* pixmap == None means that the inline picture is empty. */ pic->pixmap = None; /* * Don't next_frame = -1 here because ui_animate_inline_pictures() refers it * even if load_file() fails. */ if (pic->next_frame >= 0) { num_anims--; } return 1; } static void pty_closed(vt_term_t *term) { u_int count; for (count = 0; count < num_inline_pics; count++) { if (inline_pics[count].term == term && inline_pics[count].pixmap) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " destroy inline picture %d (%d)\n", count, num_inline_pics); #endif destroy_inline_picture(inline_pics + count); } } /* XXX The memory of intern_pics is not freed. */ } static void check_inline_pictures(vt_term_t *term, u_int8_t *flags, int beg, int end) { int row; vt_line_t *line; u_int count; for (row = beg; row <= end; row++) { if ((line = vt_term_get_line(term, row))) { for (count = 0; count < line->num_filled_chars; count++) { vt_char_t *ch; if ((ch = vt_get_picture_char(line->chars + count))) { int idx; idx = vt_char_picture_id(ch); do { flags[idx] = 1; idx = inline_pics[idx].next_frame; } while (idx >= 0 && flags[idx] == 0); } } } } } static void check_inline_pictures_drcs(vt_term_t *term, u_int8_t *flags) { vt_drcs_t *drcs; if ((drcs = term->parser->drcs)) { size_t count; for (count = 0; count < sizeof(drcs->fonts) / sizeof(drcs->fonts[0]); count++) { if (drcs->fonts[count] && vt_drcs_has_picture(drcs->fonts[count])) { flags[drcs->fonts[count]->pic_id] = 1; /* animation check is not necessary. */ } } } } static int cleanup_inline_pictures(vt_term_t *term) { #define THRESHOLD 48 int count; int empty_idx; u_int8_t *flags; /* * Don't cleanup unused inline pictures until the number of cached inline * pictures is THRESHOLD or more(num_inline_pics >= THRESHOLD and * need_cleanup is true). */ if (num_inline_pics < THRESHOLD || !(flags = alloca(num_inline_pics))) { if (num_inline_pics == 0) { /* XXX */ vt_term_pty_closed_event = pty_closed; } return -1; } if (!need_cleanup) { memset(flags, 1, num_inline_pics); } else { int beg; int end; vt_edit_t *orig_edit; memset(flags, 0, num_inline_pics); /* * Inline pictures in back logs except recent MAX_INLINE_PICTURES*2 lines * are destroyed in line_scrolled_out() in ui_screen.c. */ if ((beg = -vt_term_get_num_logged_lines(term)) < INLINEPIC_AVAIL_ROW) { beg = INLINEPIC_AVAIL_ROW; } end = vt_term_get_rows(term); orig_edit = term->screen->edit; check_inline_pictures(term, flags, beg, end); if (term->screen->edit == &term->screen->alt_edit) { term->screen->edit = &term->screen->normal_edit; check_inline_pictures(term, flags, 0, end); } if (term->screen->page_edits) { int count = 0; for (count = 0; count < 8 /* MAX_PAGE_ID in vt_screen.c */ ; count++) { if ((term->screen->edit = term->screen->page_edits + count) != orig_edit) { check_inline_pictures(term, flags, 0, end); } } } term->screen->edit = orig_edit; check_inline_pictures_drcs(term, flags); } empty_idx = -1; for (count = num_inline_pics - 1; count >= 0; count--) { if (inline_pics[count].pixmap == None) { /* do nothing */ } else if (!flags[count] && inline_pics[count].term == term) { /* * Don't cleanup inline pictures refered twice or more times * until num_inline_pics reaches THRESHOLD or more. */ if (inline_pics[count].weighting >= 2 && num_inline_pics < THRESHOLD + 8) { inline_pics[count].weighting /= 2; continue; } else { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " destroy inline picture %s %d (%d) \n", inline_pics[count].file_path, count, num_inline_pics); #endif if (!destroy_inline_picture(inline_pics + count)) { continue; } if (count == num_inline_pics - 1) { num_inline_pics--; /* * Don't return count because it is out * of num_inline_pics. */ continue; } } } else { continue; } if (empty_idx == -1) { if (!need_cleanup) { return count; } else { empty_idx = count; /* Continue cleaning up. */ } } } if (empty_idx == -1 && num_inline_pics >= THRESHOLD) { /* * There is no empty entry. (The number of cached inline pictures * is THRESHOLD or more.) */ need_cleanup = 1; } else { need_cleanup = 0; } return empty_idx; } static int load_file(void *p) { int idx; Pixmap pixmap; PixmapMask mask; u_int width; u_int height; idx = ((inline_pic_args_t*)p)->idx; width = inline_pics[idx].width; height = inline_pics[idx].height; if (ui_imagelib_load_file(inline_pics[idx].disp, inline_pics[idx].file_path, NULL, &pixmap, &mask, &width, &height, ((inline_pic_args_t*)p)->keep_aspect)) { if (strstr(inline_pics[idx].file_path, "mlterm/anim")) { /* GIF Animation frame */ unlink(inline_pics[idx].file_path); } /* XXX pthread_mutex_lock( &mutex) is necessary. */ inline_pics[idx].mask = mask; inline_pics[idx].width = width; inline_pics[idx].height = height; inline_pics[idx].pixmap = pixmap; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " new inline picture (%s %d %d %d %p %p) is created.\n", inline_pics[idx].file_path, idx, width, height, inline_pics[idx].pixmap, inline_pics[idx].mask); #endif return 1; } else { inline_pics[idx].disp = NULL; destroy_inline_picture(inline_pics + idx); return 0; } } #if defined(USE_WIN32API) || defined(HAVE_PTHREAD) #ifdef USE_WIN32API static u_int __stdcall #else static void* #endif load_file_async(void *p) { #ifdef HAVE_PTHREAD pthread_detach(pthread_self()); #endif load_file(p); #ifdef HAVE_WINDOWS_H if (((inline_pic_args_t*)p)->ev) { SetEvent(((inline_pic_args_t*)p)->ev); CloseHandle(((inline_pic_args_t*)p)->ev); } #else if (((inline_pic_args_t*)p)->ev != -1) { close(((inline_pic_args_t*)p)->ev); } #endif free(p); return 0; } #endif static int ensure_inline_picture(ui_display_t *disp, const char *file_path, u_int *width, /* can be 0 */ u_int *height, /* can be 0 */ u_int col_width, u_int line_height, vt_term_t *term) { int idx; if ((idx = cleanup_inline_pictures(term)) == -1) { void *p; /* XXX pthread_mutex_lock( &mutex) is necessary. */ if (num_inline_pics >= MAX_INLINE_PICTURES || !(p = realloc(inline_pics, (num_inline_pics + 1) * sizeof(*inline_pics)))) { return -1; } inline_pics = p; idx = num_inline_pics++; } inline_pics[idx].pixmap = None; /* mark as empty */ inline_pics[idx].file_path = strdup(file_path); inline_pics[idx].width = *width; inline_pics[idx].height = *height; inline_pics[idx].disp = disp; inline_pics[idx].term = term; inline_pics[idx].col_width = col_width; inline_pics[idx].line_height = line_height; inline_pics[idx].next_frame = -1; /* Don't destroy before being inserted to vt_term_t after loading async. */ inline_pics[idx].weighting = 2; return idx; } static int next_frame_pos(ui_inline_picture_t *prev, ui_inline_picture_t *next, int pos) { u_int cur_rows; u_int next_rows; int row; int col; cur_rows = (prev->height + prev->line_height - 1) / prev->line_height; next_rows = (next->height + next->line_height - 1) / next->line_height; row = pos % cur_rows; col = pos / cur_rows; if (row < next_rows && col < (next->width + next->col_width - 1) / next->col_width) { return MAKE_INLINEPIC_POS(col, row, next_rows); } else { return -1; } } /* --- global functions --- */ void ui_picture_display_opened(Display *display) { ui_imagelib_display_opened(display); } void ui_picture_display_closed(Display *display) { int count; if (num_icon_pics > 0) { for (count = num_icon_pics - 1; count >= 0; count--) { if (icon_pics[count]->disp->display == display) { destroy_icon_picture(icon_pics[count]); icon_pics[count] = icon_pics[--num_icon_pics]; } } if (num_icon_pics == 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " All cached icons were free'ed\n"); #endif free(icon_pics); icon_pics = NULL; } } for (count = 0; count < num_inline_pics; count++) { if (inline_pics[count].disp && inline_pics[count].disp->display == display) { if (PIXMAP_IS_ACTIVE(inline_pics[count])) { ui_destroy_image(display, inline_pics[count].pixmap); ui_destroy_mask(display, inline_pics[count].mask); } /* * Don't set ui_inline_picture_t::pixmap = None here because * this inline picture can still exist in vt_term_t. * * disp = NULL is for platforms where * INLINE_PICTURE_MOVABLE_BETWEEN_DISPLAYS is not defined. * (see draw_picture() in ui_draw_str.c) */ inline_pics[count].disp = NULL; } } ui_imagelib_display_closed(display); } /* * Judge whether pic_mods are equal or not. * \param a,b picture modifier * \return 1 when they are same. 0 when not. */ int ui_picture_modifiers_equal( ui_picture_modifier_t *a, /* Can be NULL (which means normal pic_mod) */ ui_picture_modifier_t *b /* Can be NULL (which means normal pic_mod) */ ) { if (a == b) { /* If a==NULL and b==NULL, return 1 */ return 1; } if (a == NULL) { a = b; b = NULL; } if (b == NULL) { /* Check if 'a' is normal or not. */ if ((a->brightness == 100) && (a->contrast == 100) && (a->gamma == 100) && (a->alpha == 0)) { return 1; } } else { if ((a->brightness == b->brightness) && (a->contrast == b->contrast) && (a->gamma == b->gamma) && (a->alpha == b->alpha) && (a->blend_red == b->blend_red) && (a->blend_green == b->blend_green) && (a->blend_blue == b->blend_blue)) { return 1; } } return 0; } ui_picture_t *ui_acquire_bg_picture(ui_window_t *win, ui_picture_modifier_t *mod, char *file_path /* "root" means transparency. */ ) { ui_picture_t **p; if (strcmp(file_path, "root") != 0) /* Transparent background is not cached. */ { u_int count; for (count = 0; count < num_pics; count++) { if (strcmp(file_path, pics[count]->file_path) == 0 && win->disp->display == pics[count]->display && ui_picture_modifiers_equal(mod, pics[count]->mod) && ACTUAL_WIDTH(win) == pics[count]->width && ACTUAL_HEIGHT(win) == pics[count]->height) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Use cached picture(%s).\n", file_path); #endif pics[count]->ref_count++; return pics[count]; } } } if ((p = realloc(pics, (num_pics + 1) * sizeof(*pics))) == NULL) { return NULL; } pics = p; if (!(pics[num_pics] = create_bg_picture(win, mod, file_path))) { if (num_pics == 0 /* pics == NULL */) { free(pics); pics = NULL; } return NULL; } return pics[num_pics++]; } void ui_release_picture(ui_picture_t *pic) { u_int count; for (count = 0; count < num_pics; count++) { if (pic == pics[count]) { if (--(pic->ref_count) == 0) { destroy_picture(pic); if (--num_pics == 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " All cached bg pictures were free'ed\n"); #endif free(pics); pics = NULL; } else { pics[count] = pics[num_pics]; } } return; } } } ui_icon_picture_t *ui_acquire_icon_picture(ui_display_t *disp, char *file_path /* Don't specify NULL. */ ) { u_int count; ui_icon_picture_t **p; for (count = 0; count < num_icon_pics; count++) { if (strcmp(file_path, icon_pics[count]->file_path) == 0 && disp == icon_pics[count]->disp) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Use cached icon(%s).\n", file_path); #endif icon_pics[count]->ref_count++; return icon_pics[count]; } } if ((p = realloc(icon_pics, (num_icon_pics + 1) * sizeof(*icon_pics))) == NULL) { return NULL; } icon_pics = p; if ((icon_pics[num_icon_pics] = create_icon_picture(disp, file_path)) == NULL) { if (num_icon_pics == 0 /* icon_pics == NULL */) { free(icon_pics); icon_pics = NULL; } return NULL; } return icon_pics[num_icon_pics++]; } void ui_release_icon_picture(ui_icon_picture_t *pic) { u_int count; for (count = 0; count < num_icon_pics; count++) { if (pic == icon_pics[count]) { if (--(pic->ref_count) == 0) { destroy_icon_picture(pic); if (--num_icon_pics == 0) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " All cached icons were free'ed\n"); #endif free(icon_pics); icon_pics = NULL; } else { icon_pics[count] = icon_pics[num_icon_pics]; } } return; } } } /* * The caller must check if file_path exists or not to avoid to call mlimgloader unnecessarily. * 'file_path' can be /foo/bar.ttf/1f400 for emoji. */ int ui_load_inline_picture(ui_display_t *disp, char *file_path, u_int *width /* can be 0 */, u_int *height /* can be 0 */, u_int col_width, u_int line_height, int keep_aspect, vt_term_t *term) { int idx; inline_pic_args_t *args; /* XXX Don't reuse ~/.mlterm/[pty name].six, [pty name].rgs and anim-*.gif */ if (!strstr(file_path, "mlterm/") || strstr(file_path, "mlterm/macro") || strstr(file_path, "mlterm/emoji/")) { for (idx = 0; idx < num_inline_pics; idx++) { if (PIXMAP_IS_ACTIVE(inline_pics[idx]) && disp == inline_pics[idx].disp && strcmp(file_path, inline_pics[idx].file_path) == 0 && term == inline_pics[idx].term && /* XXX */ (*width == 0 || *width == inline_pics[idx].width) && /* XXX */ (*height == 0 || *height == inline_pics[idx].height)) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Use cached picture(%s).\n", file_path); #endif inline_pics[idx].weighting++; if (strcasecmp(file_path + strlen(file_path) - 4, ".gif") == 0 && /* If check_anim was processed, next_frame == -2. */ inline_pics[idx].next_frame == -1) { goto check_anim; } else { goto end; } } } } if ((idx = ensure_inline_picture(disp, file_path, width, height, col_width, line_height, term)) == -1 || !(args = malloc(sizeof(inline_pic_args_t)))) { return -1; } args->idx = idx; args->keep_aspect = keep_aspect; #if defined(HAVE_PTHREAD) || defined(USE_WIN32API) if (strstr(file_path, "://")) { /* Loading a remote file asynchronously. */ #ifdef HAVE_WINDOWS_H args->ev = CreateEvent(NULL, FALSE, FALSE, NULL); #else int fds[2]; if (pipe(fds) != 0) { fds[1] = args->ev = -1; } else { args->ev = fds[0]; } #endif inline_pics[idx].pixmap = DUMMY_PIXMAP; #ifdef USE_WIN32API { HANDLE thrd; u_int tid; if ((thrd = _beginthreadex(NULL, 0, load_file_async, args, 0, &tid))) { CloseHandle(thrd); } } #else { pthread_t thrd; pthread_create(&thrd, NULL, load_file_async, args); } #endif #ifdef HAVE_WINDOWS_H if (WaitForSingleObject(args->ev, 750) != WAIT_TIMEOUT && PIXMAP_IS_ACTIVE(inline_pics[idx])) { goto check_anim; } #else if (fds[1] != -1) { fd_set read_fds; struct timeval tval; int ret; tval.tv_usec = 750000; tval.tv_sec = 0; FD_ZERO(&read_fds); FD_SET(fds[1], &read_fds); ret = select(fds[1] + 1, &read_fds, NULL, NULL, &tval); close(fds[1]); if (ret != 0 && PIXMAP_IS_ACTIVE(inline_pics[idx])) { goto check_anim; } } #endif } else #endif { int ret = load_file(args); free(args); if (ret) { goto check_anim; } } return -1; check_anim: if (strcasecmp(file_path + strlen(file_path) - 4, ".gif") == 0) { /* Animation GIF */ char *dir; /* mark checked */ inline_pics[idx].next_frame = -2; if ((dir = bl_get_user_rc_path("mlterm/")) && (file_path = alloca(get_anim_file_path_len(dir)))) { int hash; int count; int i; int prev_i; hash = hash_path(inline_pics[idx].file_path); if (anim_file_exists(file_path, dir, hash, 0)) { /* The first frame has been already loaded. */ unlink(file_path); } prev_i = idx; for (count = 1;; count++) { if (!anim_file_exists(file_path, dir, hash, count)) { break; } /* * Don't clean up because the 1st frame has not been set * to vt_term_t yet here. */ need_cleanup = 0; if ((i = ensure_inline_picture(disp, file_path, width, height, col_width, line_height, term)) >= 0 && ui_add_frame_to_animation(prev_i, i)) { inline_pics[i].pixmap = DUMMY_PIXMAP; prev_i = i; } } } free(dir); } end: *width = inline_pics[idx].width; *height = inline_pics[idx].height; return idx; } ui_inline_picture_t *ui_get_inline_picture(int idx) { if (inline_pics && idx < num_inline_pics) { return inline_pics + idx; } else { return NULL; } } int ui_add_frame_to_animation(int prev_idx, int next_idx) { ui_inline_picture_t *prev_pic; ui_inline_picture_t *next_pic; if ((prev_pic = ui_get_inline_picture(prev_idx)) && (next_pic = ui_get_inline_picture(next_idx)) && /* Animation is stopped after adding next_idx which equals to prev_pic->next_frame */ prev_pic->next_frame != next_idx && /* Don't add a picture which has been already added to an animation. */ next_pic->next_frame < 0) { if (prev_pic->next_frame < 0) { num_anims += 2; prev_pic->next_frame = next_idx; next_pic->next_frame = prev_idx; } else { num_anims++; next_pic->next_frame = prev_pic->next_frame; prev_pic->next_frame = next_idx; } return 1; } else { return 0; } } int ui_animate_inline_pictures(vt_term_t *term) { int wait; int row; vt_line_t *line; u_int num_rows; if (!num_anims) { return 0; } wait = 0; num_rows = vt_term_get_rows(term); for (row = 0; row < num_rows; row++) { if ((line = vt_term_get_line_in_screen(term, row))) { int char_index; for (char_index = 0; char_index < line->num_filled_chars; char_index++) { vt_char_t *ch; if ((ch = vt_get_picture_char(line->chars + char_index))) { int32_t pos; int idx; int next; pos = vt_char_code(ch); idx = vt_char_picture_id(ch); if ((next = inline_pics[idx].next_frame) < 0) { continue; } retry: if (inline_pics[next].pixmap == DUMMY_PIXMAP) { inline_pic_args_t args; args.idx = next; if (!load_file(&args)) { if (inline_pics[next].next_frame == idx) { inline_pics[idx].next_frame = -1; continue; } next = inline_pics[idx].next_frame = inline_pics[next].next_frame; goto retry; } /* shorten waiting time. */ wait = 2; } if ((pos = next_frame_pos(inline_pics + idx, inline_pics + next, pos)) >= 0) { vt_char_set_code(ch, pos); vt_char_set_picture_id(ch, next); vt_line_set_modified(line, char_index, char_index); if (wait == 0) { wait = 1; } } } } } } return wait; } int ui_load_tmp_picture(ui_display_t *disp, char *file_path, Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height) { *width = *height = 0; if (ui_imagelib_load_file(disp, file_path, NULL, pixmap, mask, width, height, 0)) { return 1; } else { return 0; } } void ui_destroy_tmp_picture(ui_display_t *disp, Pixmap pixmap, PixmapMask mask) { ui_destroy_image(disp->display, pixmap); ui_destroy_mask(disp->display, mask); } #endif /* NO_IMAGE */ mlterm-3.8.9/uitoolkit/ui_picture.h010064400017600000144000000061101356600660700161040ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_PICTURE_H__ #define __UI_PICTURE_H__ #include /* u_int16_t */ #include #include "ui.h" /* XA_PIXMAP */ #include "ui_window.h" typedef struct ui_picture_modifier { u_int16_t brightness; /* 0 - 65535 */ u_int16_t contrast; /* 0 - 65535 */ u_int16_t gamma; /* 0 - 65535 */ u_int8_t alpha; /* 0 - 255 */ u_int8_t blend_red; u_int8_t blend_green; u_int8_t blend_blue; } ui_picture_modifier_t; typedef struct ui_picture { Display *display; ui_picture_modifier_t *mod; char *file_path; u_int width; u_int height; Pixmap pixmap; u_int ref_count; } ui_picture_t; typedef struct ui_icon_picture { ui_display_t *disp; char *file_path; Pixmap pixmap; PixmapMask mask; u_int32_t *cardinal; u_int ref_count; } ui_icon_picture_t; typedef struct ui_inline_picture { Pixmap pixmap; PixmapMask mask; char *file_path; u_int width; u_int height; ui_display_t *disp; vt_term_t *term; u_int8_t col_width; u_int8_t line_height; int16_t next_frame; u_int16_t weighting; } ui_inline_picture_t; #define MAX_INLINE_PICTURES (1 << PICTURE_ID_BITS) #define MAKE_INLINEPIC_POS(col, row, num_rows) ((col) * (num_rows) + (row)) #define INLINEPIC_AVAIL_ROW -(MAX_INLINE_PICTURES * 2) #ifdef NO_IMAGE #define ui_picture_display_opened(display) (0) #define ui_picture_display_closed(display) (0) #define ui_picture_modifiers_equal(a, b) (0) #define ui_acquire_bg_picture(win, mod, file_path) (NULL) #define ui_release_picture(pic) (0) #define ui_acquire_icon_picture(disp, file_path) (NULL) #define ui_release_icon_picture(pic) (0) #define ui_load_inline_picture(disp, file_path, width, height, col_width, line_height, \ keep_aspect, term) (-1) #define ui_get_inline_picture(idx) (NULL) #else /* defined in c_sixel.c */ u_int32_t *ui_set_custom_sixel_palette(u_int32_t *palette); void ui_picture_display_opened(Display *display); void ui_picture_display_closed(Display *display); int ui_picture_modifiers_equal(ui_picture_modifier_t *a, ui_picture_modifier_t *b); ui_picture_t *ui_acquire_bg_picture(ui_window_t *win, ui_picture_modifier_t *mod, char *file_path); void ui_release_picture(ui_picture_t *pic); ui_icon_picture_t *ui_acquire_icon_picture(ui_display_t *disp, char *file_path); void ui_release_icon_picture(ui_icon_picture_t *pic); int ui_load_inline_picture(ui_display_t *disp, char *file_path, u_int *width, u_int *height, u_int col_width, u_int line_height, int keep_aspect, vt_term_t *term); ui_inline_picture_t *ui_get_inline_picture(int idx); int ui_add_frame_to_animation(int prev_idx, int next_idx); int ui_animate_inline_pictures(vt_term_t *term); int ui_load_tmp_picture(ui_display_t *disp, char *file_path, Pixmap *pixmap, PixmapMask *mask, u_int *width, u_int *height); void ui_destroy_tmp_picture(ui_display_t *disp, Pixmap pixmap, PixmapMask mask); #endif #define ui_picture_modifier_is_normal(pic_mod) (ui_picture_modifiers_equal((pic_mod), NULL)) #endif mlterm-3.8.9/uitoolkit/ui_sb_mode.c010064400017600000144000000014301356600660700160340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_sb_mode.h" #include #include /* u_int */ /* --- static variables --- */ /* Order of this table must be same as ui_sb_mode_t. */ static char *sb_mode_name_table[] = { "none", "left", "right", "autohide", }; /* --- global functions --- */ ui_sb_mode_t ui_get_sb_mode_by_name(char *name) { #ifndef USE_CONSOLE ui_sb_mode_t mode; for (mode = 0; mode < SBM_MAX; mode++) { if (strcmp(sb_mode_name_table[mode], name) == 0) { return mode; } } #endif /* default value */ return SBM_NONE; } char *ui_get_sb_mode_name(ui_sb_mode_t mode) { if ((u_int)mode >= SBM_MAX) { /* default value */ mode = SBM_NONE; } return sb_mode_name_table[mode]; } mlterm-3.8.9/uitoolkit/ui_sb_mode.h010064400017600000144000000005121356600660700160410ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_SB_MODE_H__ #define __UI_SB_MODE_H__ typedef enum ui_sb_mode { SBM_NONE, SBM_LEFT, SBM_RIGHT, SBM_AUTOHIDE, SBM_MAX } ui_sb_mode_t; ui_sb_mode_t ui_get_sb_mode_by_name(char *name); char *ui_get_sb_mode_name(ui_sb_mode_t mode); #endif mlterm-3.8.9/uitoolkit/ui_sb_view.h010064400017600000144000000050661356600660700161000ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ /* * !! Notice !! * This file must be kept as independent to specific systems as possible. * So types like u_xxx which may not be defined in some environments must * not be used here. */ #ifndef __UI_SB_VIEW_H__ #define __UI_SB_VIEW_H__ #include "ui.h" typedef struct ui_display *__ui_display_ptr_t; typedef struct ui_window *__ui_window_ptr_t; typedef struct ui_sb_view { Display *display; int screen; Window window; GC gc; /* If you change gc values in ui_sb_view, restore them before return. */ unsigned int height; /* * Set 1 when create ui_sb_view_t. * ui_sb_view_t of version 0 doesn't have this 'version' member, so * ui_sb_view_t->version designates ui_sb_view->get_geometry_hints actually. * It is assumed that ui_sb_view_t->version of version 0 is not 1. */ int version; void (*get_geometry_hints)(struct ui_sb_view *, unsigned int *width, unsigned int *top_margin, unsigned int *bottom_margin, int *up_button_y, unsigned int *up_button_height, int *down_button_y, unsigned int *down_button_height); void (*get_default_color)(struct ui_sb_view *, char **fg_color, char **bg_color); /* Win32: GC is None. */ void (*realized)(struct ui_sb_view *, Display *, int screen, Window, GC, unsigned int height); void (*resized)(struct ui_sb_view *, Window, unsigned int height); void (*color_changed)(struct ui_sb_view *, int); void (*destroy)(struct ui_sb_view *); /* * Win32: ui_sb_view_t::gc is set by ui_scrollbar.c before following draw_XXX * functions is called. */ /* drawing bar only. */ void (*draw_scrollbar)(struct ui_sb_view *, int bar_top_y, unsigned int bar_height); /* drawing background of bar. */ void (*draw_background)(struct ui_sb_view *, int, unsigned int); void (*draw_up_button)(struct ui_sb_view *, int); void (*draw_down_button)(struct ui_sb_view *, int); /* ui_scrollbar sets this after ui_*_sb_view_new(). */ __ui_window_ptr_t win; } ui_sb_view_t; typedef struct ui_sb_view_rc { char *key; char *value; } ui_sb_view_rc_t; typedef struct ui_sb_view_conf { char *sb_name; char *engine_name; char *dir; ui_sb_view_rc_t *rc; unsigned int rc_num; unsigned int use_count; int (*load_image)(__ui_display_ptr_t disp, char *path, /* u_int32_t */ unsigned int **cardinal, Pixmap *pixmap, Pixmap *mask, unsigned int *width, unsigned int *height); } ui_sb_view_conf_t; #endif mlterm-3.8.9/uitoolkit/ui_sb_view_factory.c010064400017600000144000000224341356600660700176200ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_sb_view_factory.h" #include /* sprintf */ #include #include /* alloca */ #include /* strdup */ #include #include #include "ui_simple_sb_view.h" #include "ui_imagelib.h" #ifndef LIBDIR #define SBLIB_DIR "/usr/local/lib/mlterm/" #else #define SBLIB_DIR LIBDIR "/mlterm/" #endif #ifndef XDATADIR #define SB_DIR "/usr/local/share/mlterm/scrollbars" #else #define SB_DIR XDATADIR "/mlterm/scrollbars" #endif typedef ui_sb_view_t* (*ui_sb_view_new_func_t)(void); typedef ui_sb_view_t* (*ui_sb_engine_new_func_t)(ui_sb_view_conf_t *conf, int is_transparent); /* --- static variables --- */ #ifdef SUPPORT_PIXMAP_ENGINE static ui_sb_view_conf_t **view_confs; static u_int num_view_confs; #endif /* --- static functions --- */ static inline ui_sb_view_t *check_version(ui_sb_view_t *view) { return view->version == 1 ? view : NULL; } static ui_sb_view_new_func_t dlsym_sb_view_new_func(const char *name, int is_transparent) { bl_dl_handle_t handle; char *symbol; u_int len; #ifdef PLUGIN_MODULE_SUFFIX char *p; if (!(p = alloca(strlen(name) + 3 + 1))) { return NULL; } sprintf(p, "%s-" PLUGIN_MODULE_SUFFIX, name); if (!(handle = bl_dl_open(SBLIB_DIR, p)) && !(handle = bl_dl_open("", p))) #else if (!(handle = bl_dl_open(SBLIB_DIR, name)) && !(handle = bl_dl_open("", name))) #endif { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " bl_dl_open(%s) failed.\n", name); #endif return NULL; } bl_dl_close_at_exit(handle); len = 27 + strlen(name) + 1; if ((symbol = alloca(len)) == NULL) { return NULL; } if (is_transparent) { sprintf(symbol, "ui_%s_transparent_sb_view_new", name); } else { sprintf(symbol, "ui_%s_sb_view_new", name); } return (ui_sb_view_new_func_t)bl_dl_func_symbol(handle, symbol); } /* * pixmap_engine is supported only if mlterm is built with -export-dynamic * option of ld * because shared library of pixmap_engine refers to ui_imagelib_load_file. */ #ifdef SUPPORT_PIXMAP_ENGINE static ui_sb_engine_new_func_t dlsym_sb_engine_new_func(const char *name) { ui_sb_engine_new_func_t func; bl_dl_handle_t handle; char *symbol; u_int len; #ifdef PLUGIN_MODULE_SUFFIX char *p; if (!(p = alloca(strlen(name) + 3 + 1))) { return NULL; } sprintf(p, "%s-" PLUGIN_MODULE_SUFFIX, name); if (!(handle = bl_dl_open(SBLIB_DIR, name)) && !(handle = bl_dl_open("", name))) #else if (!(handle = bl_dl_open(SBLIB_DIR, name)) && !(handle = bl_dl_open("", name))) #endif { return NULL; } bl_dl_close_at_exit(handle); len = 16 + strlen(name) + 1; if ((symbol = alloca(len)) == NULL) { return NULL; } sprintf(symbol, "ui_%s_sb_engine_new", name); if ((func = (ui_sb_engine_new_func_t)bl_dl_func_symbol(handle, symbol)) == NULL) { return NULL; } return func; } static ui_sb_view_conf_t *search_view_conf(const char *sb_name) { u_int count; for (count = 0; count < num_view_confs; count++) { if (strcmp(view_confs[count]->sb_name, sb_name) == 0) { return view_confs[count]; } } return NULL; } static void free_conf(ui_sb_view_conf_t *conf) { ui_sb_view_rc_t *rc; int i; free(conf->sb_name); free(conf->engine_name); free(conf->dir); for (rc = conf->rc, i = 0; i < conf->rc_num; rc++, i++) { free(rc->key); free(rc->value); } free(conf->rc); free(conf); } static ui_sb_view_conf_t *register_new_view_conf(bl_file_t *rcfile, const char *sb_name, char *rcfile_path) { ui_sb_view_conf_t *conf; char *key; char *value; int len; void *p; if ((conf = calloc(1, sizeof(ui_sb_view_conf_t))) == NULL) { return NULL; } conf->load_image = ui_imagelib_load_file; conf->sb_name = strdup(sb_name); /* remove "/rc" /foo/bar/name/rc -> /foo/bar/name */ len = strlen(rcfile_path) - 3; if ((conf->dir = malloc(sizeof(char) * (len + 1))) == NULL) { goto error; } strncpy(conf->dir, rcfile_path, len); conf->dir[len] = '\0'; while (bl_conf_io_read(rcfile, &key, &value)) { if (strcmp(key, "engine") == 0) { /* Last "engine" parameter is effective. */ free(conf->engine_name); conf->engine_name = strdup(value); } else { ui_sb_view_rc_t *p; if ((p = realloc(conf->rc, sizeof(ui_sb_view_rc_t) * (conf->rc_num + 1))) == NULL) { #ifdef __DEBUG bl_debug_printf("realloc() failed."); #endif goto error; } conf->rc = p; p = &conf->rc[conf->rc_num]; p->key = strdup(key); p->value = strdup(value); conf->rc_num++; } } if (conf->engine_name == NULL) { goto error; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "%s has been registered as new view. [dir: %s]\n", conf->sb_name, conf->dir); #endif if ((p = realloc(view_confs, sizeof(ui_sb_view_conf_t*) * (num_view_confs + 1))) == NULL) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " realloc failed.\n"); #endif goto error; } view_confs = p; view_confs[num_view_confs++] = conf; return conf; error: free_conf(conf); return NULL; } static int unregister_view_conf(ui_sb_view_conf_t *conf) { u_int count; for (count = 0; count < num_view_confs; count++) { if (view_confs[count] == conf) { free_conf(conf); view_confs[count] = view_confs[--num_view_confs]; if (num_view_confs == 0) { free(view_confs); view_confs = NULL; } } } return 1; } static ui_sb_view_conf_t *find_view_rcfile(const char *name) { ui_sb_view_conf_t *conf; bl_file_t *rcfile; char *user_dir; char *path; /* search known conf from view_conf_list */ if ((conf = search_view_conf(name))) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "%s was found in view_conf_list\n", sb_name); #endif return conf; } if (!(user_dir = bl_get_user_rc_path("mlterm/scrollbars"))) { return NULL; } if (!(path = malloc(strlen(user_dir) + strlen(name) + 5))) { free(user_dir); return NULL; } sprintf(path, "%s/%s/rc", user_dir, name); free(user_dir); if (!(rcfile = bl_file_open(path, "r"))) { void *p; if (!(p = realloc(path, strlen(SB_DIR) + strlen(name) + 5))) { free(path); return NULL; } path = p; sprintf(path, "%s/%s/rc", SB_DIR, name); if (!(rcfile = bl_file_open(path, "r"))) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "rcfile for %s could not be found\n", name); #endif free(path); return NULL; } } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG "rcfile for %s: %s\n", name, path); #endif conf = register_new_view_conf(rcfile, name, path); free(path); bl_file_close(rcfile); return conf; } #endif /* --- global functions --- */ ui_sb_view_t *ui_sb_view_new(const char *name) { ui_sb_view_new_func_t func; #ifdef SUPPORT_PIXMAP_ENGINE ui_sb_view_conf_t *conf; /* new style plugin ? (requires rcfile and engine library) */ if ((conf = find_view_rcfile(name))) { ui_sb_engine_new_func_t func_engine; if ((func_engine = dlsym_sb_engine_new_func(conf->engine_name)) == NULL) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " %s scrollbar failed.\n", name); #endif unregister_view_conf(conf); return NULL; } /* * Increment conf->use_count in func_engine(). * Decrement conf->use_count in ui_sb_view_t::destroy(). */ return check_version((*func_engine)(conf, 0)); } #endif if (strcmp(name, "simple") == 0) { return check_version(ui_simple_sb_view_new()); } else if ((func = dlsym_sb_view_new_func(name, 0)) == NULL) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " %s scrollbar failed.\n", name); #endif return NULL; } return check_version((*func)()); } ui_sb_view_t *ui_transparent_sb_view_new(const char *name) { ui_sb_view_new_func_t func; #ifdef SUPPORT_PIXMAP_ENGINE ui_sb_view_conf_t *conf; /* new style plugin? (requires an rcfile and an engine library) */ if ((conf = find_view_rcfile(name))) { ui_sb_engine_new_func_t func_engine; if ((func_engine = dlsym_sb_engine_new_func(conf->engine_name)) == NULL) { unregister_view_conf(conf); return NULL; } return check_version((*func_engine)(conf, 1)); } #endif if (strcmp(name, "simple") == 0) { return check_version(ui_simple_transparent_sb_view_new()); } else if ((func = dlsym_sb_view_new_func(name, 1)) == NULL) { return NULL; } return check_version((*func)()); } /* * This function cleans up configurations of pixmap_engine. * Call this function after ui_sb_view_t::destroy() is called. */ void ui_unload_scrollbar_view_lib(const char *name) { #ifdef SUPPORT_PIXMAP_ENGINE ui_sb_view_conf_t *conf; /* new style plugin? (requires an rcfile and an engine library) */ if ((conf = search_view_conf(name))) { /* remove unused conf */ if (conf->use_count == 0) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s(pixmap_engine) is no longer used. removing from " "view_conf_list\n", name); #endif unregister_view_conf(conf); } #ifdef __DEBUG else { bl_debug_printf(BL_DEBUG_TAG " %s(pixmap_engine) is still being used. [use_count: %d]\n", name, conf->use_count); } #endif } #endif } mlterm-3.8.9/uitoolkit/ui_sb_view_factory.h010064400017600000144000000005121356600660700176160ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_SB_VIEW_FACTORY_H__ #define __UI_SB_VIEW_FACTORY_H__ #include "ui_sb_view.h" ui_sb_view_t *ui_sb_view_new(const char *name); ui_sb_view_t *ui_transparent_sb_view_new(const char *name); void ui_unload_scrollbar_view_lib(const char *name); #endif mlterm-3.8.9/uitoolkit/ui_screen.c010064400017600000144000005740201356600660700157150ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_screen.h" #include /* sprintf */ #include /* fork/execvp */ #include /* abs */ #include #include /* alloca */ #include #include /* strdup, bl_snprintf */ #include /* DIGIT_STR_LEN */ #include /* PATH_MAX */ #include /* bl_arg_str_to_array */ #include /* bl_get_user_rc_path */ #include #include #ifdef USE_BRLAPI #include "ui_brltty.h" #endif #include "ui_xic.h" #include "ui_draw_str.h" #include "ui_selection_encoding.h" #include "ui_emoji.h" #define HAS_SYSTEM_LISTENER(screen, function) \ ((screen)->system_listener && (screen)->system_listener->function) #define HAS_SCROLL_LISTENER(screen, function) \ ((screen)->screen_scroll_listener && (screen)->screen_scroll_listener->function) #define IS_LIBVTE(screen) (!(screen)->window.parent && (screen)->window.parent_window) #define line_top_margin(screen) ((int)((screen)->line_space / 2)) #if 1 #define NL_TO_CR_IN_PAST_TEXT #endif #if 0 #define __DEBUG #endif /* * For ui_window_update() * * XXX * Note that vte.c calls ui_window_update( ... , 1), so if you change following *enums, * vte.c must be changed at the same time. */ enum { UPDATE_SCREEN = 0x1, UPDATE_CURSOR = 0x2, UPDATE_SCREEN_BLINK = 0x4, }; /* --- static variables --- */ static int exit_backscroll_by_pty; static int allow_change_shortcut; static char *mod_meta_prefix = "\x1b"; static int trim_trailing_newline_in_pasting; static ef_parser_t *vt_str_parser; /* XXX leaked */ #ifdef USE_IM_CURSOR_COLOR static char *im_cursor_color = NULL; #endif /* --- static functions --- */ #ifdef USE_OT_LAYOUT static void *ot_layout_get_ot_layout_font(vt_term_t *term, vt_font_t font) { ui_font_t *uifont; if (!term->screen->screen_listener || !(uifont = ui_get_font(((ui_screen_t *)term->screen->screen_listener->self)->font_man, font)) || !ui_font_has_ot_layout_table(uifont)) { return NULL; } return uifont; } #endif static int convert_row_to_y(ui_screen_t *screen, int row /* Should be 0 >= and <= vt_term_get_rows() */ ) { /* * !! Notice !! * assumption: line hight is always the same! */ return ui_line_height(screen) * row; } /* * If y < 0 , return 0 with *y_rest = 0. * If y > screen->window.height , return screen->window.height / line_height * with *y_rest = * y - screen->window.height. */ static int convert_y_to_row(ui_screen_t *screen, u_int *y_rest, int y) { int row; if (y < 0) { y = 0; } /* * !! Notice !! * assumption: line hight is always the same! */ if (y >= screen->height) { row = (screen->height - 1) / ui_line_height(screen); } else { row = y / ui_line_height(screen); } if (y_rest) { *y_rest = y - row *ui_line_height(screen); } return row; } static int convert_char_index_to_x( ui_screen_t *screen, vt_line_t *line, int char_index /* Should be 0 >= and <= vt_line_end_char_index() */ ) { int count; int x; ui_font_manager_set_attr(screen->font_man, line->size_attr, vt_line_has_ot_substitute_glyphs(line)); if (vt_line_is_rtl(line)) { x = screen->width; for (count = vt_line_end_char_index(line); count >= char_index; count--) { vt_char_t *ch; ch = vt_char_at(line, count); if (!vt_char_is_zerowidth(ch)) { x -= ui_calculate_vtchar_width(ui_get_font(screen->font_man, vt_char_font(ch)), ch, NULL); } } } else { /* * excluding the last char width. */ x = 0; for (count = 0; count < char_index; count++) { vt_char_t *ch; ch = vt_char_at(line, count); if (!vt_char_is_zerowidth(ch)) { x += ui_calculate_vtchar_width(ui_get_font(screen->font_man, vt_char_font(ch)), ch, NULL); } } } return x; } static int convert_char_index_to_x_with_shape(ui_screen_t *screen, vt_line_t *line, int char_index) { vt_line_t *orig; int x; orig = vt_line_shape(line); x = convert_char_index_to_x(screen, line, char_index); if (orig) { vt_line_unshape(line, orig); } return x; } /* * If x < 0, return 0 with *ui_rest = 0. * If x > screen->width, return screen->width / char_width with * *ui_rest = x - screen->width. */ static int convert_x_to_char_index(ui_screen_t *screen, vt_line_t *line, u_int *ui_rest, int x) { int count; u_int width; int end_char_index; ui_font_manager_set_attr(screen->font_man, line->size_attr, vt_line_has_ot_substitute_glyphs(line)); end_char_index = vt_line_end_char_index(line); if (vt_line_is_rtl(line)) { if (x > screen->width) { x = 0; } else { x = screen->width - x; } for (count = end_char_index; count > 0; count--) { vt_char_t *ch; ch = vt_char_at(line, count); if (vt_char_is_zerowidth(ch)) { continue; } width = ui_calculate_vtchar_width(ui_get_font(screen->font_man, vt_char_font(ch)), ch, NULL); if (x <= width) { break; } x -= width; } } else { if (x < 0) { x = 0; } for (count = 0; count < end_char_index; count++) { vt_char_t *ch; ch = vt_char_at(line, count); if (vt_char_is_zerowidth(ch)) { continue; } width = ui_calculate_vtchar_width(ui_get_font(screen->font_man, vt_char_font(ch)), ch, NULL); if (x < width) { break; } x -= width; } } if (ui_rest != NULL) { *ui_rest = x; } return count; } static int convert_x_to_char_index_with_shape(ui_screen_t *screen, vt_line_t *line, u_int *ui_rest, int x) { vt_line_t *orig; int char_index; orig = vt_line_shape(line); char_index = convert_x_to_char_index(screen, line, ui_rest, x); if (orig) { vt_line_unshape(line, orig); } return char_index; } static u_int screen_width(ui_screen_t *screen) { /* * logical cols/rows => visual width/height. */ if (vt_term_get_vertical_mode(screen->term)) { return vt_term_get_logical_rows(screen->term) * ui_col_width(screen); } else { return vt_term_get_logical_cols(screen->term) * ui_col_width(screen) * screen->screen_width_ratio / 100; } } static u_int screen_height(ui_screen_t *screen) { /* * logical cols/rows => visual width/height. */ if (vt_term_get_vertical_mode(screen->term)) { return vt_term_get_logical_cols(screen->term) * ui_line_height(screen) * screen->screen_width_ratio / 100; } else { return (vt_term_get_logical_rows(screen->term) + (vt_term_has_status_line(screen->term) ? 1 : 0)) * ui_line_height(screen); } } static int activate_xic(ui_screen_t *screen) { /* * FIXME: This function is a dirty wrapper on ui_xic_activate(). */ char *saved_ptr; char *xim_name; char *xim_locale; xim_name = xim_locale = NULL; saved_ptr = bl_str_sep(&screen->input_method, ":"); xim_name = bl_str_sep(&screen->input_method, ":"); xim_locale = bl_str_sep(&screen->input_method, ":"); ui_xic_activate(&screen->window, xim_name ? xim_name : "", xim_locale ? xim_locale : ""); if (xim_name) { *(xim_name - 1) = ':'; } if (xim_locale) { *(xim_locale - 1) = ':'; } screen->input_method = saved_ptr; return 1; } /* * drawing screen functions. */ static int draw_line(ui_screen_t *screen, vt_line_t *line, int y) { int beg_x; int ret; ret = 0; if (vt_line_is_empty(line)) { ui_window_clear(&screen->window, (beg_x = 0), y, screen->window.width, ui_line_height(screen)); ret = 1; } else { int beg_char_index; u_int num_redrawn; int is_cleared_to_end; vt_line_t *orig; ui_font_present_t present; orig = vt_line_shape(line); present = ui_get_font_present(screen->font_man); if (vt_line_is_cleared_to_end(line) || (present & FONT_VAR_WIDTH)) { is_cleared_to_end = 1; } else { is_cleared_to_end = 0; } beg_char_index = vt_line_get_beg_of_modified(line); num_redrawn = vt_line_get_num_redrawn_chars(line, is_cleared_to_end); if ((present & FONT_VAR_WIDTH) && vt_line_is_rtl(line)) { num_redrawn += beg_char_index; beg_char_index = 0; } /* don't use _with_shape function since line is already shaped */ beg_x = convert_char_index_to_x(screen, line, beg_char_index); ui_font_manager_set_attr(screen->font_man, line->size_attr, vt_line_has_ot_substitute_glyphs(line)); if (is_cleared_to_end) { if (vt_line_is_rtl(line)) { ui_window_clear(&screen->window, 0, y, beg_x, ui_line_height(screen)); if (!ui_draw_str(&screen->window, screen->font_man, screen->color_man, vt_char_at(line, beg_char_index), num_redrawn, beg_x, y, ui_line_height(screen), ui_line_ascent(screen), line_top_margin(screen), screen->hide_underline, screen->underline_offset)) { goto end; } } else { if (!ui_draw_str_to_eol(&screen->window, screen->font_man, screen->color_man, vt_char_at(line, beg_char_index), num_redrawn, beg_x, y, ui_line_height(screen), ui_line_ascent(screen), line_top_margin(screen), screen->hide_underline, screen->underline_offset)) { goto end; } } } else { if (!ui_draw_str(&screen->window, screen->font_man, screen->color_man, vt_char_at(line, beg_char_index), num_redrawn, beg_x, y, ui_line_height(screen), ui_line_ascent(screen), line_top_margin(screen), screen->hide_underline, screen->underline_offset)) { goto end; } } ret = 1; end: if (orig) { vt_line_unshape(line, orig); } } return ret; } static int xterm_im_is_active(void *p); /* * Don't call this function directly. * Call this function via highlight_cursor. */ static void draw_cursor(ui_screen_t *screen) { int row; int x; int y; vt_line_t *line; vt_line_t *orig; vt_char_t ch; vt_cursor_style_t cursor_style; int is_picture; #ifdef USE_IM_CURSOR_COLOR char *orig_cursor_bg; int cursor_bg_is_replaced = 0; #endif if (screen->is_preediting) { return; } if (!vt_term_is_visible_cursor(screen->term)) { return; } if ((row = vt_term_cursor_row_in_screen(screen->term)) == -1) { return; } y = convert_row_to_y(screen, row); if ((line = vt_term_get_cursor_line(screen->term)) == NULL || vt_line_is_empty(line)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " cursor line doesn't exist.\n"); #endif return; } orig = vt_line_shape(line); /* don't use _with_shape function since line is already shaped */ x = convert_char_index_to_x(screen, line, vt_term_cursor_char_index(screen->term)); /* * XXX * screen_width_ratio < 100 causes segfault on wayland, framebuffer and android without this. */ #if 1 if (x + ui_col_width(screen) > screen->width || y + ui_line_height(screen) > screen->height) { /* XXX screen_width_ratio option drives out the cursor outside of the screen. */ if (orig) { vt_line_unshape(line, orig); } return; } #endif cursor_style = vt_term_get_cursor_style(screen->term); vt_char_init(&ch); vt_char_copy(&ch, vt_char_at(line, vt_term_cursor_char_index(screen->term))); if (vt_get_picture_char(&ch)) { cursor_style = CS_BOX; is_picture = 1; } else { is_picture = 0; } if (cursor_style & (CS_UNDERLINE|CS_BAR|CS_BOX)) { /* do nothing */ } else if (screen->window.is_focused) { #ifdef USE_IM_CURSOR_COLOR if (im_cursor_color && xterm_im_is_active(screen)) { if ((orig_cursor_bg = ui_color_manager_get_cursor_bg_color(screen->color_man))) { orig_cursor_bg = strdup(orig_cursor_bg); } ui_color_manager_set_cursor_bg_color(screen->color_man, im_cursor_color); cursor_bg_is_replaced = 1; } #endif /* if fg/bg color should be overriden, reset ch's color to default */ if (ui_color_manager_adjust_cursor_fg_color(screen->color_man)) { /* for curosr's bg */ vt_char_set_bg_color(&ch, VT_BG_COLOR); } if (ui_color_manager_adjust_cursor_bg_color(screen->color_man)) { /* for cursor's fg */ vt_char_set_fg_color(&ch, VT_FG_COLOR); } vt_char_reverse_color(&ch); } else { /* unfocused */ cursor_style = CS_BOX; } ui_font_manager_set_attr(screen->font_man, line->size_attr, vt_line_has_ot_substitute_glyphs(line)); if (cursor_style & CS_UNDERLINE) { ui_font_t *font = ui_get_font(screen->font_man, vt_char_font(&ch)); ui_window_fill(&screen->window, x, y + ui_line_ascent(screen), ui_calculate_vtchar_width(font, &ch, NULL), 2); } else if (cursor_style & CS_BAR) { if (vt_term_cursor_is_rtl(screen->term)) { ui_font_t *font = ui_get_font(screen->font_man, vt_char_font(&ch)); ui_window_fill(&screen->window, x + ui_calculate_vtchar_width(font, &ch, NULL) - 2, y, 2, ui_line_height(screen)); } else { ui_window_fill(&screen->window, x, y, 2, ui_line_height(screen)); } } else { if (!is_picture) { ui_draw_str(&screen->window, screen->font_man, screen->color_man, &ch, 1, x, y, ui_line_height(screen), ui_line_ascent(screen), line_top_margin(screen), screen->hide_underline, screen->underline_offset); } if (cursor_style & CS_BOX) { /* is picture or unfocused */ ui_font_t *font = ui_get_font(screen->font_man, vt_char_font(&ch)); ui_window_set_fg_color(&screen->window, ui_get_xcolor(screen->color_man, vt_char_fg_color(&ch))); ui_window_draw_rect_frame(&screen->window, x, y, x + ui_calculate_vtchar_width(font, &ch, NULL) - 1, y + ui_line_height(screen) - 1); } else { /* CS_BLOCK */ ui_color_manager_adjust_cursor_fg_color(screen->color_man); ui_color_manager_adjust_cursor_bg_color(screen->color_man); #ifdef USE_IM_CURSOR_COLOR if (cursor_bg_is_replaced) { ui_color_manager_set_cursor_bg_color(screen->color_man, orig_cursor_bg); free(orig_cursor_bg); } #endif } } vt_char_final(&ch); if (orig) { vt_line_unshape(line, orig); } } static void flush_scroll_cache(ui_screen_t *screen, int scroll_actual_screen) { int scroll_cache_rows; int scroll_region_rows; if (!screen->scroll_cache_rows) { return; } /* * ui_window_scroll_*() can invoke window_exposed event internally, * and flush_scroll_cache() is called twice. * To avoid this, screen->scroll_cache_row is set 0 here before calling * ui_window_scroll_*(). * * 1) Stop processing VT100 sequence. * 2) flush_scroll_cache() (ui_screen.c) * 3) scroll_region() (ui_window.c) * - XCopyArea * 4) Start processing VT100 sequence. * 5) Stop processing VT100 sequence. * 6) ui_window_update() to redraw data modified by VT100 sequence. * 7) flush_scroll_cache() * 8) scroll_region() * - XCopyArea * - Wait and process GraphicsExpose caused by 3). * 9) flush_scroll_cache() * 10)scroll_region() <- avoid this by screen->scroll_cache_rows = 0. * - XCopyArea */ scroll_cache_rows = screen->scroll_cache_rows; screen->scroll_cache_rows = 0; if (scroll_cache_rows >= (scroll_region_rows = screen->scroll_cache_boundary_end - screen->scroll_cache_boundary_start + 1)) { return; } if (scroll_actual_screen && ui_window_is_scrollable(&screen->window)) { if (!vt_term_get_vertical_mode(screen->term)) { int beg_y; int end_y; u_int scroll_height; scroll_height = ui_line_height(screen) * abs(scroll_cache_rows); /* scroll_height < screen->height is always true. */ /* if (scroll_height < screen->height) */ { beg_y = convert_row_to_y(screen, screen->scroll_cache_boundary_start); end_y = beg_y + ui_line_height(screen) * scroll_region_rows; if (scroll_cache_rows > 0) { ui_window_scroll_upward_region(&screen->window, beg_y, end_y, scroll_height); } else { ui_window_scroll_downward_region(&screen->window, beg_y, end_y, scroll_height); } } #if 0 else { ui_window_clear_all(&screen->window); } #endif } else { int beg_x; int end_x; u_int scroll_width; scroll_width = ui_col_width(screen) * abs(scroll_cache_rows); /* scroll_width < screen->width is always true. */ /* if (scroll_width < screen->width) */ { beg_x = ui_col_width(screen) * screen->scroll_cache_boundary_start; end_x = beg_x + ui_col_width(screen) * scroll_region_rows; if (vt_term_get_vertical_mode(screen->term) & VERT_RTL) { end_x = screen->width - beg_x; beg_x = screen->width - end_x; scroll_cache_rows = -(scroll_cache_rows); } if (scroll_cache_rows > 0) { ui_window_scroll_leftward_region(&screen->window, beg_x, end_x, scroll_width); } else { ui_window_scroll_rightward_region(&screen->window, beg_x, end_x, scroll_width); } } #if 0 else { ui_window_clear_all(&screen->window); } #endif } } else { /* * setting modified mark to the lines within scroll region. * * XXX * Not regarding vertical mode. */ #if 0 if (!vt_term_get_vertical_mode(screen->term)) { } else #endif { if (scroll_cache_rows > 0) { /* * scrolling upward. */ vt_term_set_modified_lines_in_screen(screen->term, screen->scroll_cache_boundary_start, screen->scroll_cache_boundary_end - scroll_cache_rows); } else { /* * scrolling downward. */ vt_term_set_modified_lines_in_screen( screen->term, screen->scroll_cache_boundary_start + scroll_cache_rows, screen->scroll_cache_boundary_end); } } } } static void set_scroll_boundary(ui_screen_t *screen, int boundary_start, int boundary_end) { if (screen->scroll_cache_rows) { if (screen->scroll_cache_boundary_start != boundary_start || screen->scroll_cache_boundary_end != boundary_end) { flush_scroll_cache(screen, 0); } } screen->scroll_cache_boundary_start = boundary_start; screen->scroll_cache_boundary_end = boundary_end; } /* * Don't call this function except from window_exposed or update_window. * Call this function via ui_window_update. */ static void redraw_screen(ui_screen_t *screen) { int count; vt_line_t *line; int y; int line_height; #ifdef USE_BRLAPI ui_brltty_write(); #endif flush_scroll_cache(screen, 1); count = 0; while (1) { if ((line = vt_term_get_line_in_screen(screen->term, count)) == NULL) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " nothing is redrawn.\n"); #endif return; } if (vt_line_is_modified(line)) { break; } count++; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " redrawing -> line %d\n", count); #endif y = convert_row_to_y(screen, count); draw_line(screen, line, y); count++; y += (line_height = ui_line_height(screen)); while ((line = vt_term_get_line_in_screen(screen->term, count)) != NULL) { if (vt_line_is_modified(line)) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " redrawing -> line %d\n", count); #endif if (!draw_line(screen, line, y)) { break; } } #ifdef __DEBUG else { bl_debug_printf(BL_DEBUG_TAG " not redrawing -> line %d\n", count); } #endif y += line_height; count++; } vt_term_updated_all(screen->term); if (screen->im) { ui_im_redraw_preedit(screen->im, screen->window.is_focused); } } /* * Don't call this function except from window_exposed or update_window. * Call this function via ui_window_update. */ static void highlight_cursor(ui_screen_t *screen) { flush_scroll_cache(screen, 1); draw_cursor(screen); ui_xic_set_spot(&screen->window); } static void unhighlight_cursor(ui_screen_t *screen, int revert_visual) { vt_term_unhighlight_cursor(screen->term, revert_visual); } /* * {enter|exit}_backscroll_mode() and bs_XXX() functions provides backscroll *operations. * * Similar processing to bs_XXX() is done in *ui_screen_scroll_{upward|downward|to}(). */ static void enter_backscroll_mode(ui_screen_t *screen) { if (vt_term_is_backscrolling(screen->term)) { return; } vt_term_enter_backscroll_mode(screen->term); if (HAS_SCROLL_LISTENER(screen, bs_mode_entered)) { (*screen->screen_scroll_listener->bs_mode_entered)(screen->screen_scroll_listener->self); } } static void exit_backscroll_mode(ui_screen_t *screen) { if (!vt_term_is_backscrolling(screen->term)) { return; } vt_term_exit_backscroll_mode(screen->term); ui_window_update(&screen->window, UPDATE_SCREEN | UPDATE_CURSOR); if (HAS_SCROLL_LISTENER(screen, bs_mode_exited)) { (*screen->screen_scroll_listener->bs_mode_exited)(screen->screen_scroll_listener->self); } } static int bs_scroll_upward(ui_screen_t *screen, u_int size) { if (vt_term_backscroll_upward(screen->term, size)) { ui_window_update(&screen->window, UPDATE_SCREEN | UPDATE_CURSOR); if (HAS_SCROLL_LISTENER(screen, scrolled_upward)) { (*screen->screen_scroll_listener->scrolled_upward)(screen->screen_scroll_listener->self, size); } return 1; } else { return 0; } } static int bs_scroll_downward(ui_screen_t *screen, u_int size) { if (vt_term_backscroll_downward(screen->term, size)) { ui_window_update(&screen->window, UPDATE_SCREEN | UPDATE_CURSOR); if (HAS_SCROLL_LISTENER(screen, scrolled_downward)) { (*screen->screen_scroll_listener->scrolled_downward)(screen->screen_scroll_listener->self, size); } return 1; } else { return 0; } } #define bs_half_page_upward(screen) bs_scroll_upward(screen, vt_term_get_rows((screen)->term) / 2) #define bs_half_page_downward(screen) \ bs_scroll_downward(screen, vt_term_get_rows((screen)->term) / 2) #define bs_page_upward(screen) bs_scroll_upward(screen, vt_term_get_rows((screen)->term)) #define bs_page_downward(screen) bs_scroll_downward(screen, vt_term_get_rows((screen)->term)) /* * Utility function to execute both ui_restore_selected_region_color() and * ui_window_update(). */ static void restore_selected_region_color_instantly(ui_screen_t *screen) { if (ui_restore_selected_region_color(&screen->sel)) { ui_window_update(&screen->window, UPDATE_SCREEN | UPDATE_CURSOR); } } static void write_to_pty_intern(vt_term_t *term, u_char *str, /* str may be NULL */ size_t len, ef_parser_t *parser /* parser may be NULL */) { if (parser && str) { (*parser->init)(parser); (*parser->set_str)(parser, str, len); } vt_term_init_encoding_conv(term); if (parser) { u_char conv_buf[512]; size_t filled_len; #ifdef __DEBUG { size_t i; bl_debug_printf(BL_DEBUG_TAG " written str:\n"); for (i = 0; i < len; i++) { bl_msg_printf("[%.2x]", str[i]); } bl_msg_printf("=>\n"); } #endif while (!parser->is_eos) { if ((filled_len = vt_term_convert_to(term, conv_buf, sizeof(conv_buf), parser)) == 0) { break; } #ifdef __DEBUG { size_t i; for (i = 0; i < filled_len; i++) { bl_msg_printf("[%.2x]", conv_buf[i]); } } #endif vt_term_write(term, conv_buf, filled_len); } } else if (str) { #ifdef __DEBUG { size_t i; bl_debug_printf(BL_DEBUG_TAG " written str: "); for (i = 0; i < len; i++) { bl_msg_printf("%.2x", str[i]); } bl_msg_printf("\n"); } #endif vt_term_write(term, str, len); } else { return; } } static void write_to_pty(ui_screen_t *screen, u_char *str, /* str may be NULL */ size_t len, ef_parser_t *parser /* parser may be NULL */) { if (vt_term_is_broadcasting(screen->term)) { vt_term_t **terms; u_int num = vt_get_all_terms(&terms); u_int count; for (count = 0; count < num; count++) { if (vt_term_is_broadcasting(terms[count])) { write_to_pty_intern(terms[count], str, len, parser); } } } else { write_to_pty_intern(screen->term, str, len, parser); } } static int write_special_key(ui_screen_t *screen, vt_special_key_t key, int modcode, int is_numlock) { if (vt_term_is_broadcasting(screen->term)) { vt_term_t **terms; u_int num = vt_get_all_terms(&terms); u_int count; for (count = 0; count < num; count++) { if (vt_term_is_broadcasting(terms[count])) { if (!vt_term_write_special_key(terms[count], key, modcode, is_numlock)) { return 0; } } } return 1; } else { return vt_term_write_special_key(screen->term, key, modcode, is_numlock); } } static int set_wall_picture(ui_screen_t *screen) { ui_picture_t *pic; if (!screen->pic_file_path) { return 0; } if (!(pic = ui_acquire_bg_picture(&screen->window, ui_screen_get_picture_modifier(screen), screen->pic_file_path))) { bl_msg_printf("Wall picture file %s is not found.\n", screen->pic_file_path); free(screen->pic_file_path); screen->pic_file_path = NULL; ui_window_unset_wall_picture(&screen->window, 1); return 0; } #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE if (screen->window.disp->depth == 4 && strstr(screen->pic_file_path, "six")) { /* * Color pallette of ui_display can be changed by ui_acquire_bg_picture(). * (see ui_display_set_cmap() called from fb/ui_imagelib.c.) */ ui_screen_reload_color_cache(screen, 1); } #endif if (!ui_window_set_wall_picture(&screen->window, pic->pixmap, 1)) { ui_release_picture(pic); /* Because picture is loaded successfully, screen->pic_file_path retains. */ return 0; } if (screen->bg_pic) { ui_release_picture(screen->bg_pic); } screen->bg_pic = pic; return 1; } static void set_icon(ui_screen_t *screen) { ui_icon_picture_t *icon; char *path; if ((path = vt_term_icon_path(screen->term))) { if (screen->icon && strcmp(path, screen->icon->file_path) == 0) { /* Not changed. */ return; } if ((icon = ui_acquire_icon_picture(screen->window.disp, path))) { ui_window_set_icon(&screen->window, icon); } else { ui_window_remove_icon(&screen->window); } } else { if (screen->icon == NULL) { /* Not changed. */ return; } icon = NULL; ui_window_remove_icon(&screen->window); } if (screen->icon) { ui_release_icon_picture(screen->icon); } screen->icon = icon; } /* referred in update_special_visual. */ static void change_font_present(ui_screen_t *screen, ui_type_engine_t type_engine, ui_font_present_t font_present); static int update_special_visual(ui_screen_t *screen) { ui_font_present_t font_present; if (!vt_term_update_special_visual(screen->term)) { /* If special visual is not changed, following processing is not necessary. */ return 0; } font_present = ui_get_font_present(screen->font_man) & ~FONT_VERTICAL; /* Similar if-else conditions exist in vt_term_update_special_visual. */ if (vt_term_get_vertical_mode(screen->term)) { font_present |= vt_term_get_vertical_mode(screen->term); } change_font_present(screen, ui_get_type_engine(screen->font_man), font_present); return 1; } static ui_im_t *im_new(ui_screen_t *screen) { return ui_im_new(screen->window.disp, screen->font_man, screen->color_man, screen->term->parser, &screen->im_listener, screen->input_method, screen->mod_ignore_mask); } /* * callbacks of ui_window events */ #ifdef UIWINDOW_SUPPORTS_PREEDITING static void (*orig_draw_preedit_str)(void *, vt_char_t *, u_int, int); static void dummy_draw_preedit_str(void *p, vt_char_t *chars, u_int num_chars, int cursor_offset) { /* Don't set ui_screen_t::is_preediting = 0. */ } static void preedit(ui_window_t *win, const char *preedit_text, const char *cur_preedit_text) { ef_parser_t *utf8_parser; vt_term_t *term = ((ui_screen_t *)win)->term; if (vt_term_is_backscrolling(term)) { return; } if (preedit_text && cur_preedit_text && strcmp(preedit_text, cur_preedit_text) == 0) { return; } vt_term_set_config(term, "use_local_echo", "false"); if (orig_draw_preedit_str) { ((ui_screen_t*)win)->im_listener.draw_preedit_str = orig_draw_preedit_str; orig_draw_preedit_str = NULL; ((ui_screen_t*)win)->is_preediting = 0; } if (!(utf8_parser = ui_get_selection_parser(1))) { return; } (*utf8_parser->init)(utf8_parser); if (*preedit_text == '\0') { preedit_text = NULL; } else { u_char buf[128]; size_t len; /* Hide cursor */ orig_draw_preedit_str = ((ui_screen_t*)win)->im_listener.draw_preedit_str; ((ui_screen_t*)win)->im_listener.draw_preedit_str = dummy_draw_preedit_str; ((ui_screen_t*)win)->is_preediting = 1; vt_term_parse_vt100_sequence(term); vt_term_set_config(term, "use_local_echo", "true"); (*utf8_parser->set_str)(utf8_parser, preedit_text, strlen(preedit_text)); while (!utf8_parser->is_eos && (len = vt_term_convert_to(term, buf, sizeof(buf), utf8_parser)) > 0) { vt_term_preedit(term, buf, len); } } ui_window_update(win, 3); /* UPDATE_SCREEN|UPDATE_CURSOR */ } #endif static void window_realized(ui_window_t *win) { ui_screen_t *screen; char *name; screen = (ui_screen_t *)win; ui_window_set_type_engine(win, ui_get_type_engine(screen->font_man)); screen->mod_meta_mask = ui_window_get_mod_meta_mask(win, screen->mod_meta_key); screen->mod_ignore_mask = ui_window_get_mod_ignore_mask(win, NULL); if (screen->input_method) { /* XIM or other input methods? */ if (strncmp(screen->input_method, "xim", 3) == 0) { activate_xic(screen); } else { ui_xic_activate(&screen->window, "unused", ""); if (!(screen->im = im_new(screen))) { free(screen->input_method); screen->input_method = NULL; } } } ui_window_set_fg_color(win, ui_get_xcolor(screen->color_man, VT_FG_COLOR)); ui_window_set_bg_color(win, ui_get_xcolor(screen->color_man, VT_BG_COLOR)); if (HAS_SCROLL_LISTENER(screen, screen_color_changed)) { (*screen->screen_scroll_listener->screen_color_changed)(screen->screen_scroll_listener->self); } ui_get_xcolor_rgba(&screen->pic_mod.blend_red, &screen->pic_mod.blend_green, &screen->pic_mod.blend_blue, NULL, ui_get_xcolor(screen->color_man, VT_BG_COLOR)); if ((name = vt_term_window_name(screen->term))) { ui_set_window_name(&screen->window, name); } if ((name = vt_term_icon_name(screen->term))) { ui_set_icon_name(&screen->window, name); } set_icon(screen); if (screen->borderless) { ui_window_set_borderless_flag(&screen->window, 1); } /* XXX Don't load wall picture until window is resized */ #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF if (screen->window.is_mapped) #endif { set_wall_picture(screen); } } static void window_exposed(ui_window_t *win, int x, int y, u_int width, u_int height) { int beg_row; int end_row; ui_screen_t *screen; screen = (ui_screen_t *)win; if (vt_term_get_vertical_mode(screen->term)) { u_int ncols; ncols = vt_term_get_cols(screen->term); if ((beg_row = x / ui_col_width(screen)) >= ncols) { beg_row = ncols - 1; } if ((end_row = (x + width) / ui_col_width(screen) + 1) >= ncols) { end_row = ncols - 1; } if (vt_term_get_vertical_mode(screen->term) & VERT_RTL) { u_int swp; swp = ncols - beg_row - 1; beg_row = ncols - end_row - 1; end_row = swp; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " exposed [row] from %d to %d [x] from %d to %d\n", beg_row, end_row, x, x + width); #endif vt_term_set_modified_lines_in_screen(screen->term, beg_row, end_row); } else { int row; vt_line_t *line; u_int col_width; col_width = ui_col_width(screen); beg_row = convert_y_to_row(screen, NULL, y); end_row = convert_y_to_row(screen, NULL, y + height); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " exposed [row] from %d to %d [y] from %d to %d\n", beg_row, end_row, y, y + height); #endif for (row = beg_row; row <= end_row; row++) { if ((line = vt_term_get_line_in_screen(screen->term, row))) { if (vt_line_is_rtl(line)) { vt_line_set_modified_all(line); } else { int beg; int end; u_int rest; /* * Don't add rest/col_width to beg because the * character at beg can be full-width. */ beg = convert_x_to_char_index_with_shape(screen, line, &rest, x); end = convert_x_to_char_index_with_shape(screen, line, &rest, x + width); end += ((rest + col_width - 1) / col_width); vt_line_set_modified(line, beg, end); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " exposed line %d to %d [row %d]\n", beg, end, row); #endif } } } } vt_term_select_drcs(screen->term); redraw_screen(screen); if (beg_row <= vt_term_cursor_row_in_screen(screen->term) && vt_term_cursor_row_in_screen(screen->term) <= end_row) { highlight_cursor(screen); } ui_window_flush(&screen->window); } static void update_window(ui_window_t *win, int flag) { ui_screen_t *screen; screen = (ui_screen_t *)win; vt_term_select_drcs(screen->term); if (flag & UPDATE_SCREEN) { redraw_screen(screen); } else if (flag & UPDATE_SCREEN_BLINK) { vt_set_blink_chars_visible(0); redraw_screen(screen); vt_set_blink_chars_visible(1); } if (flag & UPDATE_CURSOR) { highlight_cursor(screen); } ui_window_flush(&screen->window); } static void window_resized(ui_window_t *win) { ui_screen_t *screen; u_int rows; u_int cols; u_int width; u_int height; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " window is resized => width %d height %d.\n", win->width, win->height); #endif screen = (ui_screen_t *)win; screen->autoscroll_count = 0; /* This is necessary since vt_term_t size is changed. */ ui_stop_selecting(&screen->sel); ui_restore_selected_region_color(&screen->sel); exit_backscroll_mode(screen); unhighlight_cursor(screen, 1); /* * visual width/height => logical cols/rows */ if (vt_term_get_vertical_mode(screen->term)) { height = screen->window.width; width = (screen->window.height * 100) / screen->screen_width_ratio; rows = height / ui_col_width(screen); cols = width / ui_line_height(screen); } else { width = (screen->window.width * 100) / screen->screen_width_ratio; height = screen->window.height; cols = width / ui_col_width(screen); rows = height / ui_line_height(screen); } if (vt_term_resize(screen->term, cols, rows, width, height) == 2) { /* vt_screen_resize() reverts some scrolled out lines to the main screen. */ if (HAS_SCROLL_LISTENER(screen, term_changed)) { (*screen->screen_scroll_listener->term_changed)(screen->screen_scroll_listener->self, vt_term_get_log_size(screen->term), vt_term_get_num_logged_lines(screen->term)); } } screen->width = screen_width(screen); screen->height = screen_height(screen); set_wall_picture(screen); ui_window_update(&screen->window, UPDATE_SCREEN | UPDATE_CURSOR); ui_xic_resized(&screen->window); } static void window_focused(ui_window_t *win) { ui_screen_t *screen; screen = (ui_screen_t *)win; if (screen->fade_ratio != 100) { if (ui_color_manager_unfade(screen->color_man)) { ui_window_set_fg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_FG_COLOR)); ui_window_set_bg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_BG_COLOR)); vt_term_set_modified_all_lines_in_screen(screen->term); ui_window_update(&screen->window, UPDATE_SCREEN); } } ui_window_update(&screen->window, UPDATE_CURSOR); if (screen->im) { (*screen->im->focused)(screen->im); } if (vt_term_want_focus_event(screen->term)) { write_to_pty(screen, "\x1b[I", 3, NULL); } #ifdef USE_BRLAPI ui_brltty_focus(screen->term); #endif } static void window_unfocused(ui_window_t *win) { ui_screen_t *screen; screen = (ui_screen_t *)win; /* * XXX * Unfocus event can be received in deleting window after screen->term was * destroyed. */ #if 1 if (!screen->term) { return; } #endif if (screen->fade_ratio != 100) { if (ui_color_manager_fade(screen->color_man, screen->fade_ratio)) { ui_window_set_fg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_FG_COLOR)); ui_window_set_bg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_BG_COLOR)); vt_term_set_modified_all_lines_in_screen(screen->term); ui_window_update(&screen->window, UPDATE_SCREEN); } } ui_window_update(&screen->window, UPDATE_CURSOR); if (screen->im) { (*screen->im->unfocused)(screen->im); } if (vt_term_want_focus_event(screen->term)) { write_to_pty(screen, "\x1b[O", 3, NULL); } } /* * the finalizer of ui_screen_t. * * ui_display_close or ui_display_remove_root -> ui_window_final -> *window_finalized */ static void window_finalized(ui_window_t *win) { ui_screen_destroy((ui_screen_t *)win); } static void window_destroyed(ui_window_t *win) { ui_screen_t *screen; screen = (ui_screen_t *)win; if (HAS_SYSTEM_LISTENER(screen, close_screen)) { (*screen->system_listener->close_screen)(screen->system_listener->self, screen, 1); } } static void mapping_notify(ui_window_t *win) { ui_screen_t *screen; screen = (ui_screen_t *)win; screen->mod_meta_mask = ui_window_get_mod_meta_mask(win, screen->mod_meta_key); screen->mod_ignore_mask = ui_window_get_mod_ignore_mask(win, NULL); } static size_t trim_trailing_newline_in_pasting1(u_char *str, size_t len) { if (trim_trailing_newline_in_pasting) { size_t count; for (count = len; count > 0; count--) { if (str[count - 1] == '\r' || str[count - 1] == '\n') { len--; } else { break; } } } return len; } static u_int trim_trailing_newline_in_pasting2(vt_char_t *str, u_int len) { if (trim_trailing_newline_in_pasting) { size_t count; for (count = len; count > 0; count--) { if (vt_char_code_is(&str[count - 1], '\r', US_ASCII) || vt_char_code_is(&str[count - 1], '\n', US_ASCII)) { len--; } else { break; } } } return len; } #ifdef NL_TO_CR_IN_PAST_TEXT static void convert_nl_to_cr1(u_char *str, size_t len) { size_t count; for (count = 0; count < len; count++) { if (str[count] == '\n') { str[count] = '\r'; } } } static void convert_nl_to_cr2(vt_char_t *str, u_int len) { u_int count; for (count = 0; count < len; count++) { if (vt_char_code_is(&str[count], '\n', US_ASCII)) { vt_char_set_code(&str[count], '\r'); } } } #endif static int yank_event_received(ui_screen_t *screen, Time time) { if (ui_window_is_selection_owner(&screen->window)) { u_int len; if (screen->sel.sel_str == NULL || screen->sel.sel_len == 0) { return 0; } len = trim_trailing_newline_in_pasting2(screen->sel.sel_str, screen->sel.sel_len); #ifdef NL_TO_CR_IN_PAST_TEXT /* * Convert normal newline chars to carriage return chars which are * common return key sequences. */ convert_nl_to_cr2(screen->sel.sel_str, len); #endif (*vt_str_parser->init)(vt_str_parser); vt_str_parser_set_str(vt_str_parser, screen->sel.sel_str, len); if (vt_term_is_bracketed_paste_mode(screen->term)) { write_to_pty(screen, "\x1b[200~", 6, NULL); } write_to_pty(screen, NULL, 0, vt_str_parser); if (vt_term_is_bracketed_paste_mode(screen->term)) { write_to_pty(screen, "\x1b[201~", 6, NULL); } return 1; } else { vt_char_encoding_t encoding; encoding = vt_term_get_encoding(screen->term); if (encoding == VT_UTF8 || (IS_UCS_SUBSET_ENCODING(encoding) && screen->receive_string_via_ucs)) { return ui_window_utf_selection_request(&screen->window, time) || ui_window_xct_selection_request(&screen->window, time); } else { return ui_window_xct_selection_request(&screen->window, time) || ui_window_utf_selection_request(&screen->window, time); } } } static int receive_string_via_ucs(ui_screen_t *screen) { vt_char_encoding_t encoding; encoding = vt_term_get_encoding(screen->term); if (IS_UCS_SUBSET_ENCODING(encoding) && screen->receive_string_via_ucs) { return 1; } else { return 0; } } /* referred in shortcut_match */ static void change_im(ui_screen_t *, char *); static void xterm_set_selection(void *, vt_char_t *, u_int, u_char *); static int shortcut_match(ui_screen_t *screen, KeySym ksym, u_int state) { if (ui_shortcut_match(screen->shortcut, OPEN_SCREEN, ksym, state)) { if (HAS_SYSTEM_LISTENER(screen, open_screen)) { (*screen->system_listener->open_screen)(screen->system_listener->self, screen); } return 1; } else if (ui_shortcut_match(screen->shortcut, OPEN_PTY, ksym, state)) { if (HAS_SYSTEM_LISTENER(screen, open_pty)) { (*screen->system_listener->open_pty)(screen->system_listener->self, screen, NULL); } return 1; } else if (ui_shortcut_match(screen->shortcut, NEXT_PTY, ksym, state)) { if (HAS_SYSTEM_LISTENER(screen, next_pty)) { (*screen->system_listener->next_pty)(screen->system_listener->self, screen); } return 1; } else if (ui_shortcut_match(screen->shortcut, PREV_PTY, ksym, state)) { if (HAS_SYSTEM_LISTENER(screen, prev_pty)) { (*screen->system_listener->prev_pty)(screen->system_listener->self, screen); } return 1; } else if (ui_shortcut_match(screen->shortcut, VSPLIT_SCREEN, ksym, state)) { if (HAS_SYSTEM_LISTENER(screen, split_screen)) { (*screen->system_listener->split_screen)(screen->system_listener->self, screen, 0, NULL); } return 1; } else if (ui_shortcut_match(screen->shortcut, HSPLIT_SCREEN, ksym, state)) { if (HAS_SYSTEM_LISTENER(screen, split_screen)) { (*screen->system_listener->split_screen)(screen->system_listener->self, screen, 1, NULL); } return 1; } else if (ui_shortcut_match(screen->shortcut, NEXT_SCREEN, ksym, state) && HAS_SYSTEM_LISTENER(screen, next_screen) && (*screen->system_listener->next_screen)(screen->system_listener->self, screen)) { return 1; } else if (ui_shortcut_match(screen->shortcut, PREV_SCREEN, ksym, state) && HAS_SYSTEM_LISTENER(screen, prev_screen) && (*screen->system_listener->prev_screen)(screen->system_listener->self, screen)) { return 1; } else if (ui_shortcut_match(screen->shortcut, CLOSE_SCREEN, ksym, state) && HAS_SYSTEM_LISTENER(screen, close_screen) && (*screen->system_listener->close_screen)(screen->system_listener->self, screen, 0)) { return 1; } else if (ui_shortcut_match(screen->shortcut, HEXPAND_SCREEN, ksym, state) && HAS_SYSTEM_LISTENER(screen, resize_screen) && (*screen->system_listener->resize_screen)(screen->system_listener->self, screen, 1, "+1")) { return 1; } else if (ui_shortcut_match(screen->shortcut, VEXPAND_SCREEN, ksym, state) && HAS_SYSTEM_LISTENER(screen, resize_screen) && (*screen->system_listener->resize_screen)(screen->system_listener->self, screen, 0, "+1")) { return 1; } /* for backward compatibility */ else if (ui_shortcut_match(screen->shortcut, EXT_KBD, ksym, state)) { change_im(screen, "kbd"); return 1; } #ifdef DEBUG else if (ui_shortcut_match(screen->shortcut, EXIT_PROGRAM, ksym, state)) { if (HAS_SYSTEM_LISTENER(screen, exit)) { (*screen->system_listener->exit)(screen->system_listener->self, 1); } return 1; } #endif #ifdef __DEBUG else if (ksym == XK_F10) { /* Performance benchmark */ struct timeval tv; struct timeval tv2; vt_char_t *str; int count; int y; u_int height; u_int ascent; u_int top_margin; char ch; str = vt_str_alloca(0x5e); vt_str_init(str, 0x5e); ch = ' '; for (count = 0; count < 0x5e; count++) { vt_char_set(str + count, ch, US_ASCII, 0, 0, VT_FG_COLOR, VT_BG_COLOR, 0, 0, 0, 0, 0); ch++; } height = ui_line_height(screen); ascent = ui_line_ascent(screen); top_margin = line_top_margin(screen); gettimeofday(&tv, NULL); for (count = 0; count < 5; count++) { for (y = 0; y < screen->window.height - height; y += height) { ui_draw_str(&screen->window, screen->font_man, screen->color_man, str, 0x5e, 0, y, height, ascent, top_margin, 0, 0); } ui_window_flush(&screen->window); ui_window_clear_all(&screen->window); } gettimeofday(&tv2, NULL); bl_debug_printf("Bench(draw) %d usec\n", ((int)(tv2.tv_sec - tv.tv_sec)) * 1000000 + (int)(tv2.tv_usec - tv.tv_usec)); count = 0; for (y = 0; y < screen->window.height - height; y += height) { ui_draw_str(&screen->window, screen->font_man, screen->color_man, str, 0x5e, 0, y, height, ascent, top_margin, 0, 0); count++; } ui_window_flush(&screen->window); gettimeofday(&tv, NULL); while (count > 0) { ui_window_scroll_upward(&screen->window, height); count--; ui_window_clear(&screen->window, 0, height * count, screen->window.width, height); } gettimeofday(&tv2, NULL); bl_debug_printf("Bench(scroll) %d usec\n", ((int)(tv2.tv_sec - tv.tv_sec)) * 1000000 + (int)(tv2.tv_usec - tv.tv_usec)); return 1; } #endif if (vt_term_is_backscrolling(screen->term)) { if (screen->use_extended_scroll_shortcut) { if (ui_shortcut_match(screen->shortcut, SCROLL_UP, ksym, state)) { bs_scroll_downward(screen, 1); return 1; } else if (ui_shortcut_match(screen->shortcut, SCROLL_DOWN, ksym, state)) { bs_scroll_upward(screen, 1); return 1; } #if 1 else if (ksym == 'u' || ksym == XK_Prior || ksym == XK_KP_Prior) { bs_half_page_downward(screen); return 1; } else if (ksym == 'd' || ksym == XK_Next || ksym == XK_KP_Next) { bs_half_page_upward(screen); return 1; } else if (ksym == 'k' || ksym == XK_Up || ksym == XK_KP_Up) { bs_scroll_downward(screen, 1); return 1; } else if (ksym == 'j' || ksym == XK_Down || ksym == XK_KP_Down) { bs_scroll_upward(screen, 1); return 1; } #endif } if (ui_shortcut_match(screen->shortcut, PAGE_UP, ksym, state)) { bs_half_page_downward(screen); return 1; } else if (ui_shortcut_match(screen->shortcut, PAGE_DOWN, ksym, state)) { bs_half_page_upward(screen); return 1; } else if (ksym == XK_Shift_L || ksym == XK_Shift_R || ksym == XK_Control_L || ksym == XK_Control_R || ksym == XK_Caps_Lock || ksym == XK_Shift_Lock || ksym == XK_Meta_L || ksym == XK_Meta_R || ksym == XK_Alt_L || ksym == XK_Alt_R || ksym == XK_Super_L || ksym == XK_Super_R || ksym == XK_Hyper_L || ksym == XK_Hyper_R || ksym == XK_Escape) { /* any modifier keys(X11/keysymdefs.h) */ return 1; } else if (ksym == 0) { /* button press -> reversed color is restored in button_press(). */ return 0; } else { exit_backscroll_mode(screen); /* Continue processing */ } } if (screen->use_extended_scroll_shortcut && ui_shortcut_match(screen->shortcut, SCROLL_UP, ksym, state)) { enter_backscroll_mode(screen); bs_scroll_downward(screen, 1); } else if (ui_shortcut_match(screen->shortcut, PAGE_UP, ksym, state)) { enter_backscroll_mode(screen); bs_half_page_downward(screen); } else if (ui_shortcut_match(screen->shortcut, PAGE_DOWN, ksym, state)) { /* do nothing */ } else if (ui_shortcut_match(screen->shortcut, INSERT_SELECTION, ksym, state)) { yank_event_received(screen, CurrentTime); } else if (ui_shortcut_match(screen->shortcut, RESET, ksym, state)) { vt_term_reset(screen->term, 1); } else { return 0; } return 1; } #ifdef USE_QUARTZ const char *cocoa_get_bundle_path(void); #endif static void start_menu(ui_screen_t *screen, char *str, int x, int y) { int global_x; int global_y; if (vt_term_has_pending_sequence(screen->term)) { bl_msg_printf("Restart %s after a while.\n", str); return; } ui_window_translate_coordinates(&screen->window, x, y, &global_x, &global_y); /* * XXX I don't know why but XGrabPointer() in child processes * fails without this. */ ui_window_ungrab_pointer(&screen->window); #ifdef USE_QUARTZ /* If program name was specified without directory, prepend LIBEXECDIR to it. */ if (strchr(str, '/') == NULL) { char *new_str; const char *bundle_path; bundle_path = cocoa_get_bundle_path(); if ((new_str = alloca(strlen(bundle_path) + 16 + strlen(str) + 1))) { sprintf(new_str, "%s/Contents/MacOS/%s", bundle_path, str); str = new_str; } } #endif #ifdef USE_WAYLAND vt_term_start_config_menu(screen->term, str, global_x, global_y, NULL); #else vt_term_start_config_menu(screen->term, str, global_x, global_y, screen->window.disp->name); #endif } static int shortcut_str(ui_screen_t *screen, KeySym ksym, u_int state, int x, int y) { char *str; if (!(str = ui_shortcut_str(screen->shortcut, ksym, state))) { return 0; } if (strncmp(str, "menu:", 5) == 0) { start_menu(screen, str + 5, x, y); } else if (strncmp(str, "exesel:", 7) == 0) { size_t str_len; char *sel; size_t sel_len; char *key; size_t key_len; if (screen->sel.sel_str == NULL || screen->sel.sel_len == 0) { return 0; } str += 7; str_len = strlen(str) + 1; sel_len = screen->sel.sel_len * VTCHAR_UTF_MAX_SIZE + 1; if (!(sel = alloca(sel_len))) { return 0; } (*vt_str_parser->init)(vt_str_parser); vt_str_parser_set_str(vt_str_parser, screen->sel.sel_str, screen->sel.sel_len); vt_term_init_encoding_conv(screen->term); sel_len = vt_term_convert_to(screen->term, sel, sel_len, vt_str_parser); sel[sel_len] = '\0'; key_len = str_len + strlen(sel) + 1; if (!(key = alloca(key_len))) { return 0; } if (strstr(str, "%s")) { sprintf(key, str, sel); } /* XXX Backward compatible with 3.8.7 or before */ #if 1 else { strcpy(key, str); switch(str[strlen(str) - 1]) { case ' ': case ':': /* XXX microsoft-edge: => microsoft-edge: */ str_len--; break; default: key[str_len - 1] = ' '; break; } strcpy(key + str_len, sel); } #endif if (strncmp(key, "mlclient", 8) == 0) { ui_screen_exec_cmd(screen, key); } #ifndef USE_WIN32API else { char **argv; int argc; if ((argv = bl_argv_alloca(key)) && bl_arg_str_to_array(argv, &argc, key)) { if (fork() == 0) { /* child process */ execvp(argv[0], argv); exit(1); } } } #endif } else if (strncmp(str, "proto:", 6) == 0) { char *seq; size_t len; str += 6; len = 7 + strlen(str) + 2; if ((seq = alloca(len))) { sprintf(seq, "\x1b]5379;%s\x07", str); /* * processing_vtseq == -1 means loopback processing of vtseq. * If processing_vtseq is -1, it is not set 1 in start_vt100_cmd() * which is called from vt_term_write_loopback(). */ screen->processing_vtseq = -1; vt_term_write_loopback(screen->term, seq, len - 1); ui_window_update(&screen->window, UPDATE_SCREEN | UPDATE_CURSOR); } } /* XXX Hack for libvte */ else if (IS_LIBVTE(screen) && ksym == 0 && state == Button3Mask && strcmp(str, "none") == 0) { /* do nothing */ } else { write_to_pty(screen, str, strlen(str), NULL); } return 1; } /* referred in key_pressed. */ static int compare_key_state_with_modmap(void *p, u_int state, int *is_shift, int *is_lock, int *is_ctl, int *is_alt, int *is_meta, int *is_numlock, int *is_super, int *is_hyper); typedef struct ksym_conv { KeySym before; KeySym after; } ksym_conv_t; static KeySym convert_ksym(KeySym ksym, ksym_conv_t *table, u_int table_size) { u_int count; for (count = 0; count < table_size; count++) { if (table[count].before == ksym) { return table[count].after; } } /* Not converted. */ return ksym; } static void key_pressed(ui_window_t *win, XKeyEvent *event) { ui_screen_t *screen; size_t size; u_char ch[UTF_MAX_SIZE]; u_char *kstr; KeySym ksym; ef_parser_t *parser; u_int masked_state; screen = (ui_screen_t *)win; if (!screen->hide_pointer && (vt_term_get_hide_pointer_mode(screen->term) >= 2 || (vt_term_get_hide_pointer_mode(screen->term) == 1 && !vt_term_get_mouse_report_mode(screen->term)))) { ui_window_set_cursor(win, XC_nil); if (ui_window_check_event_mask(win, PointerMotionMask)) { screen->hide_pointer = 1; } else { ui_window_add_event_mask(win, PointerMotionMask); screen->hide_pointer = 2; } } screen->blink_wait = -1; masked_state = event->state & screen->mod_ignore_mask; if ((size = ui_window_get_str(win, ch, sizeof(ch), &parser, &ksym, event)) > sizeof(ch)) { if (!(kstr = alloca(size))) { return; } size = ui_window_get_str(win, kstr, size, &parser, &ksym, event); } else { kstr = ch; } #ifdef USE_BRLAPI ui_brltty_speak_key(ksym, kstr, size); #endif #if 0 bl_debug_printf("state %x %x ksym %x str ", event->state, masked_state, ksym); { size_t i; for (i = 0; i < size; i++) { bl_msg_printf("%c", kstr[i]); } bl_msg_printf(" hex "); for (i = 0; i < size; i++) { bl_msg_printf("%x", kstr[i]); } bl_msg_printf("\n"); } #endif if (screen->im) { u_char kchar = 0; if (ui_shortcut_match(screen->shortcut, IM_HOTKEY, ksym, masked_state) || /* for backward compatibility */ ui_shortcut_match(screen->shortcut, EXT_KBD, ksym, masked_state)) { if ((*screen->im->switch_mode)(screen->im)) { return; } } if (size == 1) { kchar = kstr[0]; } #if defined(USE_WIN32GUI) && defined(UTF16_IME_CHAR) else if (size == 2 && kstr[0] == 0) { /* UTF16BE */ kchar = kstr[1]; } #endif if (!(*screen->im->key_event)(screen->im, kchar, ksym, event)) { if (vt_term_is_backscrolling(screen->term)) { exit_backscroll_mode(screen); ui_window_update(&screen->window, UPDATE_SCREEN); } return; } } #ifdef __DEBUG { int i; bl_debug_printf(BL_DEBUG_TAG " received sequence =>"); for (i = 0; i < size; i++) { bl_msg_printf("%.2x", kstr[i]); } bl_msg_printf("\n"); } #endif if (!shortcut_match(screen, ksym, masked_state) && !shortcut_str(screen, ksym, masked_state, 0, 0)) { int modcode; vt_special_key_t spkey; int is_numlock; modcode = 0; spkey = -1; if (event->state) /* Check unmasked (raw) state of event. */ { int is_shift; int is_meta; int is_alt; int is_ctl; if (compare_key_state_with_modmap(screen, event->state, &is_shift, NULL, &is_ctl, &is_alt, &is_meta, &is_numlock, NULL, NULL) && /* compatible with xterm (Modifier codes in input.c) */ (modcode = (is_shift ? 1 : 0) + (is_alt ? 2 : 0) + (is_ctl ? 4 : 0) + (is_meta ? 8 : 0))) { int key; modcode++; if ((key = ksym) < 0x80 || /* * XK_BackSpace, XK_Tab and XK_Return are defined as * 0xffXX in keysymdef.h, while they are less than * 0x80 on win32, framebuffer and wayland. */ (size == 1 && (key = kstr[0]) < 0x20)) { if (key == 0 && size > 0) { /* For win32gui */ key = ef_bytes_to_int(kstr, size); } if (vt_term_write_modified_key(screen->term, key, modcode)) { return; } } } } else { is_numlock = 0; } if (screen->use_vertical_cursor) { if (vt_term_get_vertical_mode(screen->term) & VERT_RTL) { ksym_conv_t table[] = { { XK_Up, XK_Left, }, { XK_KP_Up, XK_KP_Left, }, { XK_Down, XK_Right, }, { XK_KP_Down, XK_KP_Right, }, { XK_Left, XK_Down, }, { XK_KP_Left, XK_KP_Down, }, { XK_Right, XK_Up, }, { XK_KP_Right, XK_KP_Up, }, }; ksym = convert_ksym(ksym, table, sizeof(table) / sizeof(table[0])); } else if (vt_term_get_vertical_mode(screen->term) & VERT_LTR) { ksym_conv_t table[] = { { XK_Up, XK_Left, }, { XK_KP_Up, XK_KP_Left, }, { XK_Down, XK_Right, }, { XK_KP_Down, XK_KP_Right, }, { XK_Left, XK_Up, }, { XK_KP_Left, XK_KP_Up, }, { XK_Right, XK_Down, }, { XK_KP_Right, XK_KP_Down, }, }; ksym = convert_ksym(ksym, table, sizeof(table) / sizeof(table[0])); } } if (IsKeypadKey(ksym)) { if (ksym == XK_KP_Multiply) { spkey = SPKEY_KP_MULTIPLY; } else if (ksym == XK_KP_Add) { spkey = SPKEY_KP_ADD; } else if (ksym == XK_KP_Separator) { spkey = SPKEY_KP_SEPARATOR; } else if (ksym == XK_KP_Subtract) { spkey = SPKEY_KP_SUBTRACT; } else if (ksym == XK_KP_Decimal || ksym == XK_KP_Delete) { spkey = SPKEY_KP_DELETE; } else if (ksym == XK_KP_Divide) { spkey = SPKEY_KP_DIVIDE; } else if (ksym == XK_KP_F1) { spkey = SPKEY_KP_F1; } else if (ksym == XK_KP_F2) { spkey = SPKEY_KP_F2; } else if (ksym == XK_KP_F3) { spkey = SPKEY_KP_F3; } else if (ksym == XK_KP_F4) { spkey = SPKEY_KP_F4; } else if (ksym == XK_KP_Insert) { spkey = SPKEY_KP_INSERT; } else if (ksym == XK_KP_End) { spkey = SPKEY_KP_END; } else if (ksym == XK_KP_Down) { spkey = SPKEY_KP_DOWN; } else if (ksym == XK_KP_Next) { spkey = SPKEY_KP_NEXT; } else if (ksym == XK_KP_Left) { spkey = SPKEY_KP_LEFT; } else if (ksym == XK_KP_Begin) { spkey = SPKEY_KP_BEGIN; } else if (ksym == XK_KP_Right) { spkey = SPKEY_KP_RIGHT; } else if (ksym == XK_KP_Home) { spkey = SPKEY_KP_HOME; } else if (ksym == XK_KP_Up) { spkey = SPKEY_KP_UP; } else if (ksym == XK_KP_Prior) { spkey = SPKEY_KP_PRIOR; } else { goto no_keypad; } goto write_buf; } no_keypad: if ((ksym == XK_Delete #ifdef USE_XLIB && size == 1 #endif ) || ksym == XK_KP_Delete) { spkey = SPKEY_DELETE; } /* * XXX * In some environment, if backspace(1) -> 0-9 or space(2) pressed * continuously, * ksym in (2) as well as (1) is XK_BackSpace. */ else if (ksym == XK_BackSpace && size == 1 && kstr[0] == 0x8) { spkey = SPKEY_BACKSPACE; } else if (ksym == XK_Escape) { spkey = SPKEY_ESCAPE; } else if (size > 0) { /* do nothing */ } /* * following ksym is processed only if no key string is received * (size == 0) */ else if (ksym == XK_Up) { spkey = SPKEY_UP; } else if (ksym == XK_Down) { spkey = SPKEY_DOWN; } else if (ksym == XK_Right) { spkey = SPKEY_RIGHT; } else if (ksym == XK_Left) { spkey = SPKEY_LEFT; } else if (ksym == XK_Begin) { spkey = SPKEY_BEGIN; } else if (ksym == XK_End) { spkey = SPKEY_END; } else if (ksym == XK_Home) { spkey = SPKEY_HOME; } else if (ksym == XK_Prior) { spkey = SPKEY_PRIOR; } else if (ksym == XK_Next) { spkey = SPKEY_NEXT; } else if (ksym == XK_Insert) { spkey = SPKEY_INSERT; } else if (ksym == XK_Find) { spkey = SPKEY_FIND; } else if (ksym == XK_Execute) { spkey = SPKEY_EXECUTE; } else if (ksym == XK_Select) { spkey = SPKEY_SELECT; } else if (ksym == XK_ISO_Left_Tab) { spkey = SPKEY_ISO_LEFT_TAB; } else if (ksym == XK_F15 || ksym == XK_Help) { spkey = SPKEY_F15; } else if (ksym == XK_F16 || ksym == XK_Menu) { spkey = SPKEY_F16; } else if (XK_F1 <= ksym && ksym <= XK_FMAX) { spkey = SPKEY_F1 + ksym - XK_F1; } #ifdef SunXK_F36 else if (ksym == SunXK_F36) { spkey = SPKEY_F36; } else if (ksym == SunXK_F37) { spkey = SPKEY_F37; } #endif else { return; } write_buf: /* Check unmasked (raw) state of event. */ if (screen->mod_meta_mask & event->state) { if (screen->mod_meta_mode == MOD_META_OUTPUT_ESC) { write_to_pty(screen, mod_meta_prefix, strlen(mod_meta_prefix), NULL); } else if (screen->mod_meta_mode == MOD_META_SET_MSB) { size_t count; if (!IS_8BIT_ENCODING(vt_term_get_encoding(screen->term))) { static ef_parser_t *key_parser; /* XXX leaked */ if (!key_parser) { key_parser = vt_char_encoding_parser_new(VT_ISO8859_1); } parser = key_parser; } #if defined(USE_WIN32GUI) && defined(UTF16_IME_CHAR) size /= 2; for (count = 0; count < size; count++) { /* UTF16BE => 8bit */ if (0x20 <= kstr[count*2 + 1] && kstr[count*2 + 1] <= 0x7e) { kstr[count] = kstr[count*2] | 0x80; } } #else for (count = 0; count < size; count++) { if (0x20 <= kstr[count] && kstr[count] <= 0x7e) { kstr[count] |= 0x80; } } #endif } } if (spkey != -1 && write_special_key(screen, spkey, modcode, is_numlock)) { return; } if (size > 0) { ef_conv_t *utf_conv; if (parser && receive_string_via_ucs(screen) && (utf_conv = ui_get_selection_conv(1))) { /* XIM Text -> UCS -> PTY ENCODING */ u_char conv_buf[512]; size_t filled_len; (*parser->init)(parser); (*parser->set_str)(parser, kstr, size); (*utf_conv->init)(utf_conv); while (!parser->is_eos) { if ((filled_len = (*utf_conv->convert)(utf_conv, conv_buf, sizeof(conv_buf), parser)) == 0) { break; } write_to_pty(screen, conv_buf, filled_len, ui_get_selection_parser(1)); } } else { write_to_pty(screen, kstr, size, parser); } } } } static void selection_cleared(ui_window_t *win) { if (ui_sel_clear(&((ui_screen_t *)win)->sel)) { ui_window_update(win, UPDATE_SCREEN | UPDATE_CURSOR); } } static size_t convert_selection_to_xct(ui_screen_t *screen, u_char *str, size_t len) { size_t filled_len; ef_conv_t *xct_conv; #ifdef __DEBUG { int i; bl_debug_printf(BL_DEBUG_TAG " sending internal str: "); for (i = 0; i < screen->sel.sel_len; i++) { vt_char_dump(&screen->sel.sel_str[i]); } bl_msg_printf("\n -> converting to ->\n"); } #endif if (!(xct_conv = ui_get_selection_conv(0))) { return 0; } (*vt_str_parser->init)(vt_str_parser); vt_str_parser_set_str(vt_str_parser, screen->sel.sel_str, screen->sel.sel_len); (*xct_conv->init)(xct_conv); filled_len = (*xct_conv->convert)(xct_conv, str, len, vt_str_parser); #ifdef __DEBUG { int i; bl_debug_printf(BL_DEBUG_TAG " sending xct str: "); for (i = 0; i < filled_len; i++) { bl_msg_printf("%.2x", str[i]); } bl_msg_printf("\n"); } #endif return filled_len; } static size_t convert_selection_to_utf(ui_screen_t *screen, u_char *str, size_t len) { size_t filled_len; ef_conv_t *utf_conv; #ifdef __DEBUG { int i; bl_debug_printf(BL_DEBUG_TAG " sending internal str: "); for (i = 0; i < screen->sel.sel_len; i++) { vt_char_dump(&screen->sel.sel_str[i]); } bl_msg_printf("\n -> converting to ->\n"); } #endif if (!(utf_conv = ui_get_selection_conv(1))) { return 0; } (*vt_str_parser->init)(vt_str_parser); vt_str_parser_set_str(vt_str_parser, screen->sel.sel_str, screen->sel.sel_len); (*utf_conv->init)(utf_conv); filled_len = (*utf_conv->convert)(utf_conv, str, len, vt_str_parser); #ifdef __DEBUG { int i; bl_debug_printf(BL_DEBUG_TAG " sending utf str: "); for (i = 0; i < filled_len; i++) { bl_msg_printf("%.2x", str[i]); } bl_msg_printf("\n"); } #endif return filled_len; } static void xct_selection_requested(ui_window_t *win, XSelectionRequestEvent *event, Atom type) { ui_screen_t *screen; screen = (ui_screen_t *)win; if (screen->sel.sel_str == NULL || screen->sel.sel_len == 0) { ui_window_send_text_selection(win, event, NULL, 0, 0); } else { u_char *xct_str; size_t xct_len; size_t filled_len; xct_len = screen->sel.sel_len * VTCHAR_XCT_MAX_SIZE; /* * Don't use alloca() here because len can be too big value. * (VTCHAR_XCT_MAX_SIZE defined in vt_char.h is 160 byte.) */ if ((xct_str = malloc(xct_len)) == NULL) { return; } filled_len = convert_selection_to_xct(screen, xct_str, xct_len); ui_window_send_text_selection(win, event, xct_str, filled_len, type); free(xct_str); } } static void utf_selection_requested(ui_window_t *win, XSelectionRequestEvent *event, Atom type) { ui_screen_t *screen; screen = (ui_screen_t *)win; if (screen->sel.sel_str == NULL || screen->sel.sel_len == 0) { ui_window_send_text_selection(win, event, NULL, 0, 0); } else { u_char *utf_str; size_t utf_len; size_t filled_len; utf_len = screen->sel.sel_len * VTCHAR_UTF_MAX_SIZE; /* * Don't use alloca() here because len can be too big value. * (VTCHAR_UTF_MAX_SIZE defined in vt_char.h is 48 byte.) */ if ((utf_str = malloc(utf_len)) == NULL) { return; } filled_len = convert_selection_to_utf(screen, utf_str, utf_len); ui_window_send_text_selection(win, event, utf_str, filled_len, type); free(utf_str); } } static void xct_selection_notified(ui_window_t *win, u_char *str, size_t len) { ui_screen_t *screen; ef_conv_t *utf_conv; ef_parser_t *xct_parser; if (!(xct_parser = ui_get_selection_parser(0))) { return; } len = trim_trailing_newline_in_pasting1(str, len); #ifdef NL_TO_CR_IN_PAST_TEXT /* * Convert normal newline chars to carriage return chars which are * common return key sequences. */ convert_nl_to_cr1(str, len); #endif screen = (ui_screen_t *)win; if (vt_term_is_bracketed_paste_mode(screen->term)) { write_to_pty(screen, "\x1b[200~", 6, NULL); } #ifdef USE_XLIB /* * XXX * parsing UTF-8 sequence designated by ESC % G. * It is on xlib alone that it might be received. */ if (len > 3 && strncmp(str, "\x1b%G", 3) == 0) { #if 0 int i; for (i = 0; i < len; i++) { bl_msg_printf("%.2x ", str[i]); } #endif write_to_pty(screen, str + 3, len - 3, ui_get_selection_parser(1)); } else #endif if (receive_string_via_ucs(screen) && (utf_conv = ui_get_selection_conv(1))) { /* XCOMPOUND TEXT -> UCS -> PTY ENCODING */ u_char conv_buf[512]; size_t filled_len; (*xct_parser->init)(xct_parser); (*xct_parser->set_str)(xct_parser, str, len); (*utf_conv->init)(utf_conv); while (!xct_parser->is_eos) { if ((filled_len = (*utf_conv->convert)(utf_conv, conv_buf, sizeof(conv_buf), xct_parser)) == 0) { break; } write_to_pty(screen, conv_buf, filled_len, ui_get_selection_parser(1)); } } else { /* XCOMPOUND TEXT -> PTY ENCODING */ write_to_pty(screen, str, len, xct_parser); } if (vt_term_is_bracketed_paste_mode(screen->term)) { write_to_pty(screen, "\x1b[201~", 6, NULL); } } static void utf_selection_notified(ui_window_t *win, u_char *str, size_t len) { ui_screen_t *screen; len = trim_trailing_newline_in_pasting1(str, len); #ifdef NL_TO_CR_IN_PAST_TEXT /* * Convert normal newline chars to carriage return chars which are * common return key sequences. */ convert_nl_to_cr1(str, len); #endif screen = (ui_screen_t *)win; if (vt_term_is_bracketed_paste_mode(screen->term)) { write_to_pty(screen, "\x1b[200~", 6, NULL); } write_to_pty(screen, str, len, ui_get_selection_parser(1)); if (vt_term_is_bracketed_paste_mode(screen->term)) { write_to_pty(screen, "\x1b[201~", 6, NULL); } } #ifndef DISABLE_XDND static void set_xdnd_config(ui_window_t *win, char *dev, char *key, char *value) { ui_screen_t *screen; screen = (ui_screen_t *)win; if (strcmp(key, "scp") == 0) { /* value is always UTF-8 */ if (vt_term_is_zmodem_ready(screen->term)) { vt_term_set_config(screen->term, "send_file_utf8", value); vt_term_exec_cmd(screen->term, "zmodem_start"); } else if (vt_term_get_pty_mode(screen->term) == PTY_SSH) { char *cmd; if ((cmd = alloca(13 + strlen(value) + 1))) { sprintf(cmd, "scp \"%s\" . utf8", value); vt_term_exec_cmd(screen->term, cmd); } } } else { ui_screen_set_config(screen, dev, key, value); ui_window_update(&screen->window, UPDATE_SCREEN | UPDATE_CURSOR); } } #endif static void report_mouse_tracking(ui_screen_t *screen, int x, int y, int button, int state, int is_motion, int is_released /* is_released is 0 if PointerMotion */ ) { int key_state; int button_state; vt_line_t *line; int col; int row; u_int ui_rest; if (/* is_motion && */ button == 0) { /* PointerMotion */ key_state = button_state = 0; } else { /* * Shift = 4 * Meta = 8 * Control = 16 * Button Motion = 32 * * NOTE: with Ctrl/Shift, the click is interpreted as region selection at *present. * So Ctrl/Shift will never be catched here. */ key_state = ((state & ShiftMask) ? 4 : 0) + ((state & screen->mod_meta_mask) ? 8 : 0) + ((state & ControlMask) ? 16 : 0) + (is_motion /* && (state & (Button1Mask|Button2Mask|Button3Mask)) */ ? 32 : 0); /* for LOCATOR_REPORT */ button_state = (1 << (button - Button1)); if (state & Button1Mask) { button_state |= 1; } if (state & Button2Mask) { button_state |= 2; } if (state & Button3Mask) { button_state |= 4; } } if (vt_term_get_mouse_report_mode(screen->term) == LOCATOR_PIXEL_REPORT) { screen->prev_mouse_report_col = x + 1; screen->prev_mouse_report_row = y + 1; vt_term_report_mouse_tracking(screen->term, x + 1, y + 1, button, is_released, key_state, button_state); return; } if (vt_term_get_vertical_mode(screen->term)) { col = convert_y_to_row(screen, NULL, y); if ((line = vt_term_get_line_in_screen(screen->term, col)) == NULL) { return; } if (vt_term_is_using_multi_col_char(screen->term)) { int count; row = x / ui_col_width(screen); for (count = col; count >= 0; count--) { if ((line = vt_term_get_line_in_screen(screen->term, count)) && row < line->num_filled_chars && vt_char_cols(&line->chars[row]) > 1) { col++; } } } else { row = vt_convert_char_index_to_col(line, convert_x_to_char_index_with_shape(screen, line, &ui_rest, x), 0); } if (vt_term_get_vertical_mode(screen->term) & VERT_RTL) { row = vt_term_get_cols(screen->term) - row - 1; } } else { u_int width; int char_index; row = convert_y_to_row(screen, NULL, y); if ((line = vt_term_get_line_in_screen(screen->term, row)) == NULL) { return; } char_index = convert_x_to_char_index_with_shape(screen, line, &ui_rest, x); if (vt_line_is_rtl(line)) { /* XXX */ char_index = vt_line_convert_visual_char_index_to_logical(line, char_index); } col = vt_convert_char_index_to_col(line, char_index, 0); ui_font_manager_set_attr(screen->font_man, line->size_attr, vt_line_has_ot_substitute_glyphs(line)); width = ui_calculate_char_width(ui_get_font(screen->font_man, vt_char_font(vt_sp_ch())), vt_char_code(vt_sp_ch()), US_ASCII, NULL); if (ui_rest > width) { if ((col += ui_rest / width) >= vt_term_get_cols(screen->term)) { col = vt_term_get_cols(screen->term) - 1; } } } /* count starts from 1, not 0 */ col++; row++; if (is_motion && button <= Button3 && /* not wheel mouse */ screen->prev_mouse_report_col == col && screen->prev_mouse_report_row == row) { /* pointer is not moved. */ return; } vt_term_report_mouse_tracking(screen->term, col, row, button, is_released, key_state, button_state); screen->prev_mouse_report_col = col; screen->prev_mouse_report_row = row; } /* * Functions related to selection. */ static void start_selection(ui_screen_t *screen, int col_r, int row_r, ui_sel_type_t type, int is_rect) { int col_l; int row_l; vt_line_t *line; /* XXX */ if (vt_term_get_vertical_mode(screen->term)) { bl_msg_printf("Not supported selection in vertical mode.\n"); return; } if ((line = vt_term_get_line(screen->term, row_r)) == NULL) { return; } if (is_rect) { if (col_r == 0 || abs(col_r) + 1 == vt_term_get_cols(screen->term)) { col_l = col_r; } else { col_l = col_r - 1; } row_l = row_r; } else if ((!vt_line_is_rtl(line) && col_r == 0) || (vt_line_is_rtl(line) && abs(col_r) == vt_line_end_char_index(line))) { if ((line = vt_term_get_line(screen->term, row_r - 1)) == NULL || vt_line_is_empty(line)) { /* XXX col_l can be underflowed, but anyway it works. */ col_l = col_r - 1; row_l = row_r; } else { if (vt_line_is_rtl(line)) { col_l = 0; } else { col_l = vt_line_end_char_index(line); } row_l = row_r - 1; } } else { col_l = col_r - 1; row_l = row_r; } if (ui_start_selection(&screen->sel, col_l, row_l, col_r, row_r, type, is_rect)) { ui_window_update(&screen->window, UPDATE_SCREEN); } } static void selecting(ui_screen_t *screen, int char_index, int row) { /* XXX */ if (vt_term_get_vertical_mode(screen->term)) { bl_msg_printf("Not supported selection in vertical mode.\n"); return; } if (ui_selected_region_is_changed(&screen->sel, char_index, row, 1) && ui_selecting(&screen->sel, char_index, row)) { ui_window_update(&screen->window, UPDATE_SCREEN); } } static void selecting_with_motion(ui_screen_t *screen, int x, int y, Time time, int is_rect) { int char_index; int row; int ui_is_outside; u_int ui_rest; vt_line_t *line; if (x < 0) { x = 0; ui_is_outside = 1; } else if (x > screen->width) { x = screen->width; ui_is_outside = 1; } else { ui_is_outside = 0; } if (y < 0) { if (vt_term_get_num_logged_lines(screen->term) > 0) { if (!vt_term_is_backscrolling(screen->term)) { enter_backscroll_mode(screen); } bs_scroll_downward(screen, 1); } y = 0; } else if (y > screen->height) { if (vt_term_is_backscrolling(screen->term)) { bs_scroll_upward(screen, 1); } y = screen->height - ui_line_height(screen); } row = vt_term_convert_scr_row_to_abs(screen->term, convert_y_to_row(screen, NULL, y)); if ((line = vt_term_get_line(screen->term, row)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " line(%d) not found.\n", row); #endif return; } char_index = convert_x_to_char_index_with_shape(screen, line, &ui_rest, x); if (is_rect || screen->sel.is_rect) { /* converting char index to col. */ char_index = vt_convert_char_index_to_col(line, char_index, 0); if (vt_line_is_rtl(line)) { char_index += (vt_term_get_cols(screen->term) - vt_line_get_num_filled_cols(line)); char_index -= (ui_rest / ui_col_width(screen)); } else { char_index += (ui_rest / ui_col_width(screen)); } } else if (char_index == vt_line_end_char_index(line) && ui_rest > 0) { ui_is_outside = 1; /* Inform vt_screen that the mouse position is outside of the line. */ char_index++; } if (vt_line_is_rtl(line)) { char_index = -char_index; } if (!ui_is_selecting(&screen->sel)) { restore_selected_region_color_instantly(screen); start_selection(screen, char_index, row, SEL_CHAR, is_rect); } else { if (!ui_is_outside) { if (ui_is_after_sel_right_base_pos(&screen->sel, char_index, row)) { if (abs(char_index) > 0) { char_index--; } } #if 0 else if (ui_is_before_sel_left_base_pos(&screen->sel, char_index, row)) { if (abs(char_index) < vt_line_end_char_index(line)) { char_index++; } } #endif } selecting(screen, char_index, row); } } static int selecting_picture(ui_screen_t *screen, int char_index, int row) { vt_line_t *line; vt_char_t *ch; ui_inline_picture_t *pic; if (!(line = vt_term_get_line(screen->term, row)) || vt_line_is_empty(line) || !(ch = vt_char_at(line, char_index)) || !(ch = vt_get_picture_char(ch)) || !(pic = ui_get_inline_picture(vt_char_picture_id(ch)))) { return 0; } ui_window_send_picture_selection(&screen->window, pic->pixmap, pic->width, pic->height); return 1; } static void selecting_word(ui_screen_t *screen, int x, int y, Time time) { int char_index; int row; u_int ui_rest; int beg_row; int beg_char_index; int end_row; int end_char_index; vt_line_t *line; row = vt_term_convert_scr_row_to_abs(screen->term, convert_y_to_row(screen, NULL, y)); if ((line = vt_term_get_line(screen->term, row)) == NULL || vt_line_is_empty(line)) { return; } char_index = convert_x_to_char_index_with_shape(screen, line, &ui_rest, x); if (vt_line_end_char_index(line) == char_index && ui_rest > 0) { /* over end of line */ return; } if (selecting_picture(screen, char_index, row)) { return; } if (vt_term_get_word_region(screen->term, &beg_char_index, &beg_row, &end_char_index, &end_row, char_index, row) == 0) { return; } if (vt_line_is_rtl(vt_term_get_line(screen->term, beg_row))) { if (ui_is_selecting(&screen->sel)) { beg_char_index = -beg_char_index; } else { beg_char_index = -beg_char_index + 1; } } if (vt_line_is_rtl(vt_term_get_line(screen->term, end_row))) { end_char_index = -end_char_index; } if (!ui_is_selecting(&screen->sel)) { restore_selected_region_color_instantly(screen); start_selection(screen, beg_char_index, beg_row, SEL_WORD, 0); selecting(screen, end_char_index, end_row); ui_sel_lock(&screen->sel); } else { if (beg_row == end_row && vt_line_is_rtl(vt_term_get_line(screen->term, beg_row))) { int tmp; tmp = end_char_index; end_char_index = beg_char_index; beg_char_index = tmp; } if (ui_is_before_sel_left_base_pos(&screen->sel, beg_char_index, beg_row)) { selecting(screen, beg_char_index, beg_row); } else { selecting(screen, end_char_index, end_row); } } } static void selecting_line(ui_screen_t *screen, int y, Time time) { int row; int beg_char_index; int beg_row; int end_char_index; int end_row; row = vt_term_convert_scr_row_to_abs(screen->term, convert_y_to_row(screen, NULL, y)); if (vt_term_get_line_region(screen->term, &beg_row, &end_char_index, &end_row, row) == 0) { return; } if (vt_line_is_rtl(vt_term_get_line(screen->term, beg_row))) { beg_char_index = -vt_line_end_char_index(vt_term_get_line(screen->term, beg_row)); } else { beg_char_index = 0; } if (vt_line_is_rtl(vt_term_get_line(screen->term, end_row))) { end_char_index -= vt_line_end_char_index(vt_term_get_line(screen->term, end_row)); } if (!ui_is_selecting(&screen->sel)) { restore_selected_region_color_instantly(screen); start_selection(screen, beg_char_index, beg_row, SEL_LINE, 0); selecting(screen, end_char_index, end_row); ui_sel_lock(&screen->sel); } else if (ui_is_before_sel_left_base_pos(&screen->sel, beg_char_index, beg_row)) { selecting(screen, beg_char_index, beg_row); } else { selecting(screen, end_char_index, end_row); } } static void change_sb_mode(ui_screen_t *screen, ui_sb_mode_t sb_mode); static void pointer_motion(ui_window_t *win, XMotionEvent *event) { ui_screen_t *screen; screen = (ui_screen_t *)win; if (screen->hide_pointer) { ui_window_set_cursor(win, XC_xterm); if (screen->hide_pointer == 2) { ui_window_remove_event_mask(win, PointerMotionMask); } screen->hide_pointer = 0; } if (!(event->state & (ShiftMask | ControlMask)) && vt_term_get_mouse_report_mode(screen->term) >= ANY_EVENT_MOUSE_REPORT) { restore_selected_region_color_instantly(screen); report_mouse_tracking(screen, event->x, event->y, 0, event->state, 1, 0); } } static void button_motion(ui_window_t *win, XMotionEvent *event) { ui_screen_t *screen; screen = (ui_screen_t *)win; #ifdef FLICK_SCROLL if (screen->flick_time) { int diff = event->y - screen->flick_cur_y; if (!screen->grab_scroll) { #if 0 bl_debug_printf("Motion Time %d %d y %d %d\n", screen->flick_time, event->time, screen->flick_cur_y, event->y); #endif if (diff == 0) { return; } else if (screen->flick_time + 500 /* msec */ > event->time) { screen->grab_scroll = 1; } else { screen->flick_time = 0; screen->flick_cur_y = screen->flick_base_y = 0; } } if (screen->grab_scroll) { u_int line_height = ui_line_height(screen); if (diff > 0) { if (diff >= line_height) { enter_backscroll_mode(screen); bs_scroll_downward(screen, 1); screen->flick_base_y = screen->flick_cur_y; screen->flick_cur_y = event->y; } } else { if (diff <= -line_height) { bs_scroll_upward(screen, 1); screen->flick_base_y = screen->flick_cur_y; screen->flick_cur_y = event->y; } } screen->flick_time = event->time; return; } } #endif /* * event->state is never 0 because this function is 'button'_motion, * not 'pointer'_motion. */ if (!(event->state & (ShiftMask | ControlMask)) && vt_term_get_mouse_report_mode(screen->term)) { if (vt_term_get_mouse_report_mode(screen->term) >= BUTTON_EVENT_MOUSE_REPORT) { int button; if (event->state & Button1Mask) { button = Button1; } else if (event->state & Button2Mask) { button = Button2; } else if (event->state & Button3Mask) { button = Button3; } else { return; } restore_selected_region_color_instantly(screen); report_mouse_tracking(screen, event->x, event->y, button, event->state, 1, 0); } } else if (!(event->state & Button2Mask)) { switch (ui_is_selecting(&screen->sel)) { case SEL_WORD: selecting_word(screen, event->x, event->y, event->time); break; case SEL_LINE: selecting_line(screen, event->y, event->time); break; default: /* * XXX * Button3 selection is disabled on libvte. * If Button3 is pressed after selecting in order to show * "copy" menu, button_motion can be called by slight movement * of the mouse cursor, then selection is reset unexpectedly. */ if (!(event->state & Button3Mask) || !IS_LIBVTE(screen)) { int is_alt; int is_meta; selecting_with_motion( screen, event->x, event->y, event->time, (compare_key_state_with_modmap(screen, event->state, NULL, NULL, NULL, &is_alt, &is_meta, NULL, NULL, NULL) && (is_alt || is_meta))); } break; } } } static void button_press_continued(ui_window_t *win, XButtonEvent *event) { ui_screen_t *screen; screen = (ui_screen_t *)win; if (ui_is_selecting(&screen->sel) && (event->y < 0 || win->height < event->y)) { int is_alt; int is_meta; selecting_with_motion(screen, event->x, event->y, event->time, (compare_key_state_with_modmap(screen, event->state, NULL, NULL, NULL, &is_alt, &is_meta, NULL, NULL, NULL) && (is_alt || is_meta))); } } static void button_pressed(ui_window_t *win, XButtonEvent *event, int click_num) { ui_screen_t *screen; u_int state; screen = (ui_screen_t *)win; #ifdef FLICK_SCROLL if (event->button == Button1) { screen->flick_cur_y = screen->flick_base_y = event->y; screen->flick_time = event->time; if (screen->autoscroll_count) { screen->grab_scroll = 1; } else { screen->grab_scroll = 0; } } #endif screen->autoscroll_count = 0; if (vt_term_get_mouse_report_mode(screen->term) && !(event->state & (ShiftMask | ControlMask))) { restore_selected_region_color_instantly(screen); report_mouse_tracking(screen, event->x, event->y, event->button, event->state, 0, 0); return; } state = (Button1Mask << (event->button - Button1)) | event->state; if (event->button == Button1) { if (click_num == 2) { /* double clicked */ selecting_word(screen, event->x, event->y, event->time); return; } else if (click_num == 3) { /* triple click */ selecting_line(screen, event->y, event->time); return; } } if (shortcut_match(screen, 0, state) || shortcut_str(screen, 0, state, event->x, event->y)) { return; } if (event->button == Button3) { if (ui_sel_is_reversed(&screen->sel)) { /* expand if current selection exists. */ /* FIXME: move sel.* stuff should be in ui_selection.c */ screen->sel.is_selecting = SEL_CHAR; selecting_with_motion(screen, event->x, event->y, event->time, 0); /* keep sel as selected to handle succeeding MotionNotify */ } } else if (event->button == Button4) { /* wheel mouse */ enter_backscroll_mode(screen); if (event->state & ShiftMask) { bs_scroll_downward(screen, 1); } else if (event->state & ControlMask) { bs_page_downward(screen); } else { bs_half_page_downward(screen); } } else if (event->button == Button5) { /* wheel mouse */ enter_backscroll_mode(screen); if (event->state & ShiftMask) { bs_scroll_upward(screen, 1); } else if (event->state & ControlMask) { bs_page_upward(screen); } else { bs_half_page_upward(screen); } } else if (event->button < Button3) { restore_selected_region_color_instantly(screen); } } static void button_released(ui_window_t *win, XButtonEvent *event) { ui_screen_t *screen; screen = (ui_screen_t *)win; #ifdef FLICK_SCROLL if (screen->grab_scroll) { if (screen->flick_time + 10 /* msec */ > event->time) { int diff = event->y - screen->flick_base_y; int max; #if 0 bl_debug_printf("Release Time %d %d y %d %d\n", screen->flick_time, event->time, screen->flick_cur_y, event->y); #endif if (diff < -50) { diff += 50; } else if (diff > 50) { diff -= 50; } else { goto end; } diff /= 4; /* * XXX * If vt_term_get_rows(screen->term) < 15, window_scroll_{up|down}ward_region() or * flush_scroll_cache() could cause segfault on Android. */ if ((max = vt_term_get_rows(screen->term)) > 15) { max = 15; /* scroll 105 lines */ } if (diff > max) { diff = max; } else if (diff < -max) { diff = -max; } screen->autoscroll_count += diff; } end: screen->flick_time = 0; screen->flick_cur_y = screen->flick_base_y = 0; screen->grab_scroll = 0; } #endif if (vt_term_get_mouse_report_mode(screen->term) && !(event->state & (ShiftMask | ControlMask))) { if (event->button >= Button4) { /* Release events for the wheel buttons are not reported. */ } else { report_mouse_tracking(screen, event->x, event->y, event->button, event->state, 0, 1); } /* * In case button motion -> set mouse report -> button release, * ui_stop_selecting() should be called. * (It happens if you release shift key before stopping text selection * by moving mouse.) */ } else { if (event->button == Button2) { if (event->state & ControlMask) { /* FIXME: should check whether a menu is really active? */ return; } else { yank_event_received(screen, event->time); } } } if (ui_stop_selecting(&screen->sel)) { ui_window_update(&screen->window, UPDATE_CURSOR); } } static void idling(ui_window_t *win) { ui_screen_t *screen; screen = (ui_screen_t *)win; if (screen->autoscroll_count) { int count; if (screen->autoscroll_count < 0) { count = -screen->autoscroll_count; if (bs_scroll_upward(screen, count)) { screen->autoscroll_count++; } else { screen->autoscroll_count = 0; } } else { count = screen->autoscroll_count; enter_backscroll_mode(screen); if (bs_scroll_downward(screen, count)) { screen->autoscroll_count--; } else { screen->autoscroll_count = 0; } } } if (screen->blink_wait >= 0) { if (screen->blink_wait == 5) { if (screen->window.is_focused) { int update; update = vt_term_blink(screen->term); if (vt_term_get_cursor_style(screen->term) & CS_BLINK) { unhighlight_cursor(screen, 1); update = 1; } if (update) { ui_window_update(&screen->window, UPDATE_SCREEN_BLINK); } } screen->blink_wait = -1; } else { screen->blink_wait++; } } else { if (screen->blink_wait == -6) { int flag; flag = vt_term_blink(screen->term) ? UPDATE_SCREEN : 0; if (vt_term_get_cursor_style(screen->term) & CS_BLINK) { flag |= UPDATE_CURSOR; } if (flag) { ui_window_update(&screen->window, flag); } screen->blink_wait = 0; } else { screen->blink_wait--; } } #ifndef NO_IMAGE /* * 1-2: wait for the next frame. (0.1sec * 2) * 3: animate. */ if (++screen->anim_wait == 3) { if ((screen->anim_wait = ui_animate_inline_pictures(screen->term))) { ui_window_update(&screen->window, UPDATE_SCREEN); } } #endif } #ifdef HAVE_REGEX #include static int match(size_t *beg, size_t *len, void *regex, u_char *str, int backward) { regmatch_t pmatch[1]; if (regexec(regex, str, 1, pmatch, 0) != 0) { return 0; } *beg = pmatch[0].rm_so; *len = pmatch[0].rm_eo - pmatch[0].rm_so; if (backward) { while (1) { str += pmatch[0].rm_eo; if (regexec(regex, str, 1, pmatch, 0) != 0) { break; } (*beg) += ((*len) + pmatch[0].rm_so); *len = pmatch[0].rm_eo - pmatch[0].rm_so; } } return 1; } #else /* HAVE_REGEX */ static int match(size_t *beg, size_t *len, void *regex, u_char *str, int backward) { size_t regex_len; size_t str_len; u_char *p; if ((regex_len = strlen(regex)) > (str_len = strlen(str))) { return 0; } #if 0 { bl_msg_printf("S T R => "); p = str; while (*p) { bl_msg_printf("%.2x", *p); p++; } bl_msg_printf("\nREGEX => "); p = regex; while (*p) { bl_msg_printf("%.2x", *p); p++; } bl_msg_printf("\n"); } #endif if (backward) { p = str + str_len - regex_len; do { if (strncasecmp(p, regex, regex_len) == 0) { goto found; } } while (p-- != str); return 0; } else { p = str; do { if (strncasecmp(p, regex, regex_len) == 0) { goto found; } } while (*(++p)); return 0; } found: *beg = p - str; *len = regex_len; return 1; } #endif /* HAVE_REGEX */ static int search_find(ui_screen_t *screen, u_char *pattern, int backward) { int beg_char_index; int beg_row; int end_char_index; int end_row; #ifdef HAVE_REGEX regex_t regex; #endif if (pattern && *pattern #ifdef HAVE_REGEX && regcomp(®ex, pattern, REG_EXTENDED | REG_ICASE) == 0 #endif ) { vt_term_search_init(screen->term, match); #ifdef HAVE_REGEX if (vt_term_search_find(screen->term, &beg_char_index, &beg_row, &end_char_index, &end_row, ®ex, backward)) #else if (vt_term_search_find(screen->term, &beg_char_index, &beg_row, &end_char_index, &end_row, pattern, backward)) #endif { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Search find %d %d - %d %d\n", beg_char_index, beg_row, end_char_index, end_row); #endif ui_sel_clear(&screen->sel); start_selection(screen, beg_char_index, beg_row, SEL_CHAR, 0); selecting(screen, end_char_index, end_row); ui_stop_selecting(&screen->sel); ui_screen_scroll_to(screen, beg_row); } #ifdef HAVE_REGEX regfree(®ex); #endif } else { vt_term_search_final(screen->term); } return 1; } static void resize_window(ui_screen_t *screen) { /* screen will redrawn in window_resized() */ if (ui_window_resize(&screen->window, (screen->width = screen_width(screen)), (screen->height = screen_height(screen)), NOTIFY_TO_PARENT)) { /* * !! Notice !! * ui_window_resize() will invoke ConfigureNotify event but window_resized() * won't be called , since xconfigure.width , xconfigure.height are the same * as the already resized window. */ window_resized(&screen->window); } } static void modify_line_space_and_offset(ui_screen_t *screen) { u_int font_height = ui_get_usascii_font(screen->font_man)->height; if (screen->line_space < 0 && font_height < -screen->line_space * 4) { bl_msg_printf("Ignore line_space (%d)\n", screen->line_space); screen->line_space = 0; } if (font_height < abs(screen->baseline_offset) * 8) { bl_msg_printf("Ignore baseline_offset (%d)\n", screen->baseline_offset); screen->baseline_offset = 0; } if (screen->underline_offset != 0) { u_int ascent = ui_line_ascent(screen); if (((int)ascent) >= -screen->underline_offset && ascent + screen->underline_offset < ui_line_height(screen)) { return; } bl_msg_printf("Ignore underline_offset (%d)\n", screen->underline_offset); screen->underline_offset = 0; } } static void font_size_changed(ui_screen_t *screen) { u_int col_width; u_int line_height; modify_line_space_and_offset(screen); if (HAS_SCROLL_LISTENER(screen, line_height_changed)) { (*screen->screen_scroll_listener->line_height_changed)(screen->screen_scroll_listener->self, ui_line_height(screen)); } col_width = ui_col_width(screen); line_height = ui_line_height(screen); ui_window_set_normal_hints(&screen->window, col_width, line_height, col_width, line_height); resize_window(screen); } static void change_font_size(ui_screen_t *screen, u_int font_size) { if (font_size == ui_get_font_size(screen->font_man)) { /* not changed */ return; } if (!ui_change_font_size(screen->font_man, font_size)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ui_change_font_size(%d) failed.\n", font_size); #endif return; } /* redrawing all lines with new fonts. */ vt_term_set_modified_all_lines_in_screen(screen->term); font_size_changed(screen); /* this is because font_man->font_set may have changed in * ui_change_font_size() */ ui_xic_font_set_changed(&screen->window); } static void change_line_space(ui_screen_t *screen, int line_space) { if (screen->line_space == line_space) { /* not changed */ return; } /* letter_space and line_space are ignored on console. */ #ifndef USE_CONSOLE screen->line_space = line_space; font_size_changed(screen); #endif } static void change_letter_space(ui_screen_t *screen, u_int letter_space) { if (!ui_set_letter_space(screen->font_man, letter_space)) { return; } font_size_changed(screen); } static void change_screen_width_ratio(ui_screen_t *screen, u_int ratio) { if (screen->screen_width_ratio == ratio) { return; } screen->screen_width_ratio = ratio; resize_window(screen); } static void change_font_present(ui_screen_t *screen, ui_type_engine_t type_engine, ui_font_present_t font_present) { if (vt_term_get_vertical_mode(screen->term)) { if (font_present & FONT_VAR_WIDTH) { bl_msg_printf("Set use_variable_column_width=false forcibly.\n"); font_present &= ~FONT_VAR_WIDTH; } } if (!ui_change_font_present(screen->font_man, type_engine, font_present)) { return; } /* XXX This function is called from ui_screen_new via update_special_visual. */ if (!screen->window.my_window) { return; } ui_window_set_type_engine(&screen->window, ui_get_type_engine(screen->font_man)); /* redrawing all lines with new fonts. */ vt_term_set_modified_all_lines_in_screen(screen->term); font_size_changed(screen); } static int usascii_font_cs_changed(ui_screen_t *screen, vt_char_encoding_t encoding) { ef_charset_t cs; if (vt_term_get_unicode_policy(screen->term) & NOT_USE_UNICODE_FONT) { cs = ui_get_usascii_font_cs(VT_ISO8859_1); } else if (vt_term_get_unicode_policy(screen->term) & ONLY_USE_UNICODE_FONT) { cs = ui_get_usascii_font_cs(VT_UTF8); } else { cs = ui_get_usascii_font_cs(encoding); } if (ui_font_manager_usascii_font_cs_changed(screen->font_man, cs)) { font_size_changed(screen); /* * this is because font_man->font_set may have changed in * ui_font_manager_usascii_font_cs_changed() */ ui_xic_font_set_changed(&screen->window); return 1; } else { return 0; } } static void change_char_encoding(ui_screen_t *screen, vt_char_encoding_t encoding) { if (vt_term_get_encoding(screen->term) == encoding) { /* not changed */ return; } usascii_font_cs_changed(screen, encoding); if (!vt_term_change_encoding(screen->term, encoding)) { bl_error_printf("VT100 encoding and Terminal screen encoding are discrepant.\n"); } if (update_special_visual(screen)) { vt_term_set_modified_all_lines_in_screen(screen->term); } if (screen->im) { char *p; if ((p = alloca(strlen(screen->input_method) + 1))) { change_im(screen, strcpy(p, screen->input_method)); } } } static void change_log_size(ui_screen_t *screen, u_int logsize) { if (vt_term_get_log_size(screen->term) == logsize) { /* not changed */ return; } /* * this is necessary since vt_logs_t size is changed. */ ui_stop_selecting(&screen->sel); restore_selected_region_color_instantly(screen); exit_backscroll_mode(screen); vt_term_change_log_size(screen->term, logsize); if (HAS_SCROLL_LISTENER(screen, log_size_changed)) { (*screen->screen_scroll_listener->log_size_changed)(screen->screen_scroll_listener->self, logsize); } } static void change_sb_view(ui_screen_t *screen, char *name) { if (HAS_SCROLL_LISTENER(screen, change_view)) { (*screen->screen_scroll_listener->change_view)(screen->screen_scroll_listener->self, name); } } static void change_mod_meta_key(ui_screen_t *screen, char *key) { free(screen->mod_meta_key); if (strcmp(key, "none") == 0) { screen->mod_meta_key = NULL; } else { screen->mod_meta_key = strdup(key); } screen->mod_meta_mask = ui_window_get_mod_meta_mask(&(screen->window), screen->mod_meta_key); } static void change_mod_meta_mode(ui_screen_t *screen, ui_mod_meta_mode_t mod_meta_mode) { screen->mod_meta_mode = mod_meta_mode; } static void change_bel_mode(ui_screen_t *screen, ui_bel_mode_t bel_mode) { screen->bel_mode = bel_mode; } static void change_vertical_mode(ui_screen_t *screen, vt_vertical_mode_t vertical_mode) { if (vt_term_get_vertical_mode(screen->term) == vertical_mode) { /* not changed */ return; } vt_term_set_vertical_mode(screen->term, vertical_mode); if (update_special_visual(screen)) { /* redrawing under new vertical mode. */ vt_term_set_modified_all_lines_in_screen(screen->term); } } static void change_sb_mode(ui_screen_t *screen, ui_sb_mode_t sb_mode) { if (HAS_SCROLL_LISTENER(screen, change_sb_mode)) { (*screen->screen_scroll_listener->change_sb_mode)(screen->screen_scroll_listener->self, sb_mode); } } static void change_dynamic_comb_flag(ui_screen_t *screen, int use_dynamic_comb) { if (vt_term_is_using_dynamic_comb(screen->term) == use_dynamic_comb) { /* not changed */ return; } vt_term_set_use_dynamic_comb(screen->term, use_dynamic_comb); if (update_special_visual(screen)) { vt_term_set_modified_all_lines_in_screen(screen->term); } } static void change_receive_string_via_ucs_flag(ui_screen_t *screen, int flag) { screen->receive_string_via_ucs = flag; } static void change_fg_color(ui_screen_t *screen, char *name) { if (ui_color_manager_set_fg_color(screen->color_man, name) && ui_window_set_fg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_FG_COLOR))) { ui_xic_fg_color_changed(&screen->window); vt_term_set_modified_all_lines_in_screen(screen->term); if (HAS_SCROLL_LISTENER(screen, screen_color_changed)) { (*screen->screen_scroll_listener->screen_color_changed)(screen->screen_scroll_listener->self); } } } static void picture_modifier_changed(ui_screen_t *screen); static void change_bg_color(ui_screen_t *screen, char *name) { if (ui_color_manager_set_bg_color(screen->color_man, name) && ui_window_set_bg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_BG_COLOR))) { ui_xic_bg_color_changed(&screen->window); ui_get_xcolor_rgba(&screen->pic_mod.blend_red, &screen->pic_mod.blend_green, &screen->pic_mod.blend_blue, NULL, ui_get_xcolor(screen->color_man, VT_BG_COLOR)); picture_modifier_changed(screen); vt_term_set_modified_all_lines_in_screen(screen->term); if (HAS_SCROLL_LISTENER(screen, screen_color_changed)) { (*screen->screen_scroll_listener->screen_color_changed)(screen->screen_scroll_listener->self); } } } static void change_alt_color(ui_screen_t *screen, vt_color_t color, char *name) { if (ui_color_manager_set_alt_color(screen->color_man, color, *name ? name : NULL)) { vt_term_set_modified_all_lines_in_screen(screen->term); vt_term_set_alt_color_mode( screen->term, *name ? (vt_term_get_alt_color_mode(screen->term) | (1 << (color - VT_BOLD_COLOR))) : (vt_term_get_alt_color_mode(screen->term) & ~(1 << (color - VT_BOLD_COLOR)))); } } static void change_sb_fg_color(ui_screen_t *screen, char *name) { if (HAS_SCROLL_LISTENER(screen, change_fg_color)) { (*screen->screen_scroll_listener->change_fg_color)(screen->screen_scroll_listener->self, name); } } static void change_sb_bg_color(ui_screen_t *screen, char *name) { if (HAS_SCROLL_LISTENER(screen, change_bg_color)) { (*screen->screen_scroll_listener->change_bg_color)(screen->screen_scroll_listener->self, name); } } static void change_use_bold_font_flag(ui_screen_t *screen, int flag) { if (ui_set_use_bold_font(screen->font_man, flag)) { vt_term_set_modified_all_lines_in_screen(screen->term); } } static void change_use_italic_font_flag(ui_screen_t *screen, int flag) { if (ui_set_use_italic_font(screen->font_man, flag)) { vt_term_set_modified_all_lines_in_screen(screen->term); } } static void change_hide_underline_flag(ui_screen_t *screen, int flag) { if (screen->hide_underline != flag) { screen->hide_underline = flag; vt_term_set_modified_all_lines_in_screen(screen->term); } } static void change_underline_offset(ui_screen_t *screen, int offset) { if (screen->underline_offset != offset) { screen->underline_offset = offset; modify_line_space_and_offset(screen); } } static void change_baseline_offset(ui_screen_t *screen, int offset) { #ifndef USE_CONSOLE if (screen->baseline_offset != offset) { screen->baseline_offset = offset; modify_line_space_and_offset(screen); } #endif } static void larger_font_size(ui_screen_t *screen) { ui_larger_font(screen->font_man); font_size_changed(screen); /* this is because font_man->font_set may have changed in ui_larger_font() */ ui_xic_font_set_changed(&screen->window); /* redrawing all lines with new fonts. */ vt_term_set_modified_all_lines_in_screen(screen->term); } static void smaller_font_size(ui_screen_t *screen) { ui_smaller_font(screen->font_man); font_size_changed(screen); /* this is because font_man->font_set may have changed in ui_smaller_font() */ ui_xic_font_set_changed(&screen->window); /* redrawing all lines with new fonts. */ vt_term_set_modified_all_lines_in_screen(screen->term); } static int change_true_transbg_alpha(ui_screen_t *screen, u_int alpha) { int ret; if ((ret = ui_change_true_transbg_alpha(screen->color_man, alpha)) > 0) { /* True transparency works. Same processing as change_bg_color */ if (ui_window_set_bg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_BG_COLOR))) { ui_xic_bg_color_changed(&screen->window); vt_term_set_modified_all_lines_in_screen(screen->term); } } return ret; } static void change_transparent_flag(ui_screen_t *screen, int is_transparent) { if (screen->window.is_transparent == is_transparent #ifdef USE_XLIB /* * If wall picture is not still set, do set it. * This is necessary for gnome-terminal, because ConfigureNotify event * never * happens when it opens new tab. */ && screen->window.wall_picture_is_set == is_transparent #endif ) { /* not changed */ return; } if (is_transparent) { /* disable true transparency */ change_true_transbg_alpha(screen, 255); ui_window_set_transparent(&screen->window, ui_screen_get_picture_modifier(screen)); } else { ui_window_unset_transparent(&screen->window); set_wall_picture(screen); } if (HAS_SCROLL_LISTENER(screen, transparent_state_changed)) { (*screen->screen_scroll_listener->transparent_state_changed)( screen->screen_scroll_listener->self, is_transparent, ui_screen_get_picture_modifier(screen)); } } static void change_ctl_flag(ui_screen_t *screen, int use_ctl, vt_bidi_mode_t bidi_mode, int use_ot_layout) { int do_update; if (vt_term_is_using_ctl(screen->term) == use_ctl && vt_term_get_bidi_mode(screen->term) == bidi_mode && vt_term_is_using_ot_layout(screen->term) == use_ot_layout) { /* not changed */ return; } /* * If use_ctl flag is false and not changed, it is not necessary to update * even if * bidi_mode flag and use_ot_layout are changed. */ do_update = (use_ctl != vt_term_is_using_ctl(screen->term)) || vt_term_is_using_ctl(screen->term); vt_term_set_use_ctl(screen->term, use_ctl); vt_term_set_bidi_mode(screen->term, bidi_mode); vt_term_set_use_ot_layout(screen->term, use_ot_layout); if (do_update && update_special_visual(screen)) { vt_term_set_modified_all_lines_in_screen(screen->term); } } static void change_borderless_flag(ui_screen_t *screen, int flag) { if (ui_window_set_borderless_flag(&screen->window, flag)) { screen->borderless = flag; } } static void change_wall_picture(ui_screen_t *screen, char *file_path) { if (screen->pic_file_path) { if (strcmp(screen->pic_file_path, file_path) == 0) { /* not changed */ return; } free(screen->pic_file_path); } if (*file_path == '\0') { if (!screen->pic_file_path) { return; } screen->pic_file_path = NULL; ui_window_unset_wall_picture(&screen->window, 1); } else { screen->pic_file_path = strdup(file_path); if (set_wall_picture(screen)) { return; } } /* disable true transparency */ change_true_transbg_alpha(screen, 255); } static void picture_modifier_changed(ui_screen_t *screen) { if (screen->window.is_transparent) { ui_window_set_transparent(&screen->window, ui_screen_get_picture_modifier(screen)); if (HAS_SCROLL_LISTENER(screen, transparent_state_changed)) { (*screen->screen_scroll_listener->transparent_state_changed)( screen->screen_scroll_listener->self, 1, ui_screen_get_picture_modifier(screen)); } } else { set_wall_picture(screen); } } static void change_brightness(ui_screen_t *screen, u_int brightness) { if (screen->pic_mod.brightness == brightness) { /* not changed */ return; } screen->pic_mod.brightness = brightness; picture_modifier_changed(screen); } static void change_contrast(ui_screen_t *screen, u_int contrast) { if (screen->pic_mod.contrast == contrast) { /* not changed */ return; } screen->pic_mod.contrast = contrast; picture_modifier_changed(screen); } static void change_gamma(ui_screen_t *screen, u_int gamma) { if (screen->pic_mod.gamma == gamma) { /* not changed */ return; } screen->pic_mod.gamma = gamma; picture_modifier_changed(screen); } static void change_alpha(ui_screen_t *screen, u_int alpha) { if (!ui_window_has_wall_picture(&screen->window) && change_true_transbg_alpha(screen, alpha)) { /* True transparency works. */ if (alpha == 255) { /* Completely opaque. => reset pic_mod.alpha. */ screen->pic_mod.alpha = 0; } else { screen->pic_mod.alpha = alpha; } } else { /* True transparency doesn't work. */ if (screen->pic_mod.alpha == alpha) { /* not changed */ return; } screen->pic_mod.alpha = alpha; picture_modifier_changed(screen); } } static void change_fade_ratio(ui_screen_t *screen, u_int fade_ratio) { if (screen->fade_ratio == fade_ratio) { /* not changed */ return; } screen->fade_ratio = fade_ratio; ui_color_manager_unfade(screen->color_man); if (!screen->window.is_focused) { if (screen->fade_ratio < 100) { ui_color_manager_fade(screen->color_man, screen->fade_ratio); } } ui_window_set_fg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_FG_COLOR)); ui_window_set_bg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_BG_COLOR)); vt_term_set_modified_all_lines_in_screen(screen->term); } static void change_im(ui_screen_t *screen, char *input_method) { ui_im_t *im; ui_xic_deactivate(&screen->window); /* * Avoid to destroy anything inside im-module by calling ui_im_destroy() * after ui_im_new(). */ im = screen->im; free(screen->input_method); screen->input_method = NULL; if (!input_method) { return; } screen->input_method = strdup(input_method); if (strncmp(screen->input_method, "xim", 3) == 0) { activate_xic(screen); screen->im = NULL; } else { ui_xic_activate(&screen->window, "unused", ""); if ((screen->im = im_new(screen))) { if (screen->window.is_focused) { screen->im->focused(screen->im); } } else { free(screen->input_method); screen->input_method = NULL; } } if (im) { ui_im_destroy(im); } } /* * Callbacks of ui_config_event_listener_t events. */ static void get_config_intern(ui_screen_t *screen, char *dev, /* can be NULL */ char *key, /* can be "error" */ int to_menu, /* -1: don't output to pty and menu. */ int *flag /* 1(true), 0(false) or -1(other) is returned. */ ) { vt_term_t *term; char *value; char digit[DIGIT_STR_LEN(u_int) + 1]; if (dev) { if (!(term = vt_get_term(dev))) { goto error; } } else { term = screen->term; } if (vt_term_get_config(term, dev ? screen->term : NULL, key, to_menu, flag)) { return; } value = NULL; if (strcmp(key, "fg_color") == 0) { value = ui_color_manager_get_fg_color(screen->color_man); } else if (strcmp(key, "bg_color") == 0) { value = ui_color_manager_get_bg_color(screen->color_man); } else if (strcmp(key, "cursor_fg_color") == 0) { if ((value = ui_color_manager_get_cursor_fg_color(screen->color_man)) == NULL) { value = ""; } } else if (strcmp(key, "cursor_bg_color") == 0) { if ((value = ui_color_manager_get_cursor_bg_color(screen->color_man)) == NULL) { value = ""; } } else if (strcmp(key, "bd_color") == 0) { if ((value = ui_color_manager_get_alt_color(screen->color_man, VT_BOLD_COLOR)) == NULL) { value = ""; } } else if (strcmp(key, "ul_color") == 0) { if ((value = ui_color_manager_get_alt_color(screen->color_man, VT_UNDERLINE_COLOR)) == NULL) { value = ""; } } else if (strcmp(key, "bl_color") == 0) { if ((value = ui_color_manager_get_alt_color(screen->color_man, VT_BLINKING_COLOR)) == NULL) { value = ""; } } else if (strcmp(key, "rv_color") == 0) { if ((value = ui_color_manager_get_alt_color(screen->color_man, VT_REVERSE_COLOR)) == NULL) { value = ""; } } else if (strcmp(key, "it_color") == 0) { if ((value = ui_color_manager_get_alt_color(screen->color_man, VT_ITALIC_COLOR)) == NULL) { value = ""; } } else if (strcmp(key, "co_color") == 0) { if ((value = ui_color_manager_get_alt_color(screen->color_man, VT_CROSSED_OUT_COLOR)) == NULL) { value = ""; } } else if (strcmp(key, "sb_fg_color") == 0) { if (screen->screen_scroll_listener && screen->screen_scroll_listener->fg_color) { value = (*screen->screen_scroll_listener->fg_color)(screen->screen_scroll_listener->self); } } else if (strcmp(key, "sb_bg_color") == 0) { if (screen->screen_scroll_listener && screen->screen_scroll_listener->bg_color) { value = (*screen->screen_scroll_listener->bg_color)(screen->screen_scroll_listener->self); } } else if (strcmp(key, "hide_underline") == 0) { if (screen->hide_underline) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "underline_offset") == 0) { sprintf(digit, "%d", screen->underline_offset); value = digit; } else if (strcmp(key, "baseline_offset") == 0) { sprintf(digit, "%d", screen->baseline_offset); value = digit; } else if (strcmp(key, "fontsize") == 0) { sprintf(digit, "%d", ui_get_font_size(screen->font_man)); value = digit; } else if (strcmp(key, "line_space") == 0) { sprintf(digit, "%d", screen->line_space); value = digit; } else if (strcmp(key, "letter_space") == 0) { sprintf(digit, "%d", ui_get_letter_space(screen->font_man)); value = digit; } else if (strcmp(key, "screen_width_ratio") == 0) { sprintf(digit, "%d", screen->screen_width_ratio); value = digit; } else if (strcmp(key, "scrollbar_view_name") == 0) { if (screen->screen_scroll_listener && screen->screen_scroll_listener->view_name) { value = (*screen->screen_scroll_listener->view_name)(screen->screen_scroll_listener->self); } } else if (strcmp(key, "mod_meta_key") == 0) { if (screen->mod_meta_key == NULL) { value = "none"; } else { value = screen->mod_meta_key; } } else if (strcmp(key, "mod_meta_mode") == 0) { value = ui_get_mod_meta_mode_name(screen->mod_meta_mode); } else if (strcmp(key, "bel_mode") == 0) { value = ui_get_bel_mode_name(screen->bel_mode); } else if (strcmp(key, "scrollbar_mode") == 0) { if (screen->screen_scroll_listener && screen->screen_scroll_listener->sb_mode) { value = ui_get_sb_mode_name( (*screen->screen_scroll_listener->sb_mode)(screen->screen_scroll_listener->self)); } else { value = ui_get_sb_mode_name(SBM_NONE); } } else if (strcmp(key, "receive_string_via_ucs") == 0 || /* backward compatibility with 2.6.1 or before */ strcmp(key, "copy_paste_via_ucs") == 0) { if (screen->receive_string_via_ucs) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "use_transbg") == 0) { if (screen->window.is_transparent) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "brightness") == 0) { sprintf(digit, "%d", screen->pic_mod.brightness); value = digit; } else if (strcmp(key, "contrast") == 0) { sprintf(digit, "%d", screen->pic_mod.contrast); value = digit; } else if (strcmp(key, "gamma") == 0) { sprintf(digit, "%d", screen->pic_mod.gamma); value = digit; } else if (strcmp(key, "alpha") == 0) { if (screen->window.disp->depth < 32) { sprintf(digit, "%d", screen->color_man->alpha); } else { sprintf(digit, "%d", screen->pic_mod.alpha); } value = digit; } else if (strcmp(key, "fade_ratio") == 0) { sprintf(digit, "%d", screen->fade_ratio); value = digit; } else if (strcmp(key, "type_engine") == 0) { value = ui_get_type_engine_name(ui_get_type_engine(screen->font_man)); } else if (strcmp(key, "use_anti_alias") == 0) { ui_font_present_t font_present; font_present = ui_get_font_present(screen->font_man); if (font_present & FONT_AA) { value = "true"; } else if (font_present & FONT_NOAA) { value = "false"; } else { value = "default"; } } else if (strcmp(key, "use_variable_column_width") == 0) { if (ui_get_font_present(screen->font_man) & FONT_VAR_WIDTH) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "use_bold_font") == 0) { if (ui_is_using_bold_font(screen->font_man)) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "use_italic_font") == 0) { if (ui_is_using_italic_font(screen->font_man)) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "input_method") == 0) { if (screen->input_method) { value = screen->input_method; } else { value = "none"; } } else if (strcmp(key, "default_xim_name") == 0) { value = ui_xic_get_default_xim_name(); } else if (strcmp(key, "borderless") == 0) { if (screen->borderless) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "wall_picture") == 0) { if (screen->pic_file_path) { value = screen->pic_file_path; } else { value = ""; } } else if (strcmp(key, "gui") == 0) { value = GUI_TYPE; } else if (strcmp(key, "use_clipboard") == 0) { if (ui_is_using_clipboard_selection()) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "allow_osc52") == 0) { if (screen->xterm_listener.set_selection) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "use_extended_scroll_shortcut") == 0) { if (screen->use_extended_scroll_shortcut) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "pty_list") == 0) { value = vt_get_pty_list(); } else if (strcmp(key, "trim_trailing_newline_in_pasting") == 0) { if (trim_trailing_newline_in_pasting) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "fontconfig") == 0) { if (to_menu <= 0) { char *list = ui_font_manager_dump_font_config(screen->font_man); vt_term_response_config(screen->term, list, NULL, -1); free(list); return; } } else if (strcmp(key, "use_vertical_cursor") == 0) { if (screen->use_vertical_cursor) { value = "true"; } else { value = "false"; } } else if (strcmp(key, "click_interval") == 0) { sprintf(digit, "%d", ui_get_click_interval()); value = digit; } else if (strcmp(key, "emoji_path") == 0) { if ((value = ui_emoji_get_path(0, 0))) { char *p = strrchr(value, '/'); *p = '\0'; if ((p = alloca(strlen(value) + 1))) { strcpy(p, value); free(value); value = p; goto emoji_path_end; } else { free(value); } } value = ""; emoji_path_end: ; } #if defined(USE_FREETYPE) && defined(USE_FONTCONFIG) else if (strcmp(key, "use_aafont") == 0) { if (ui_is_using_aafont()) { value = "true"; } else { value = "false"; } } #endif if (value) { if (flag) { *flag = value ? true_or_false(value) : -1; } else { vt_term_response_config(screen->term, key, value, to_menu); } } else { error: vt_term_response_config(screen->term, "error", NULL, to_menu); } } static void get_config(void *p, char *dev, /* can be NULL */ char *key, /* can be "error" */ int to_menu) { get_config_intern(p, dev, key, to_menu, NULL); } static void set_font_config(void *p, char *file, /* can be NULL */ char *cs, char *val, int save) { ui_screen_t *screen; screen = p; /* USASCII, US-ASCII, US_ASCII */ if (strncmp(cs, "US", 2) == 0 && (strcmp(cs + 2, "ASCII") == 0 || strcmp(cs + 3, "ASCII") == 0)) { cs = ui_get_charset_name(ui_get_current_usascii_font_cs(screen->font_man)); } if (ui_customize_font_file(file, cs, val, save)) { screen->font_or_color_config_updated |= 0x1; } } static void get_font_config(void *p, char *file, /* can be NULL */ char *cs, int to_menu) { ui_screen_t *screen; char *font_name; screen = p; /* USASCII, US-ASCII, US_ASCII */ if (strncmp(cs, "US", 2) == 0 && (strcmp(cs + 2, "ASCII") == 0 || strcmp(cs + 3, "ASCII") == 0)) { cs = ui_get_charset_name(ui_get_current_usascii_font_cs(screen->font_man)); } font_name = ui_get_config_font_name2(file, ui_get_font_size(screen->font_man), cs); vt_term_response_config(screen->term, cs, font_name ? font_name : "", to_menu); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " #%s=%s (%s)\n", cs, font_name, to_menu ? "to menu" : "to pty"); #endif free(font_name); return; } static void set_color_config(void *p, char *file, /* ignored */ char *key, char *val, int save) { ui_screen_t *screen; screen = p; if (vt_customize_color_file(key, val, save)) { screen->font_or_color_config_updated |= 0x2; } } static void get_color_config(void *p, char *key, int to_menu) { ui_screen_t *screen; vt_color_t color; ui_color_t *xcolor; u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; char rgba[10]; screen = p; if ((color = vt_get_color(key)) == VT_UNKNOWN_COLOR || !(xcolor = ui_get_xcolor(screen->color_man, color))) { vt_term_response_config(screen->term, "error", NULL, to_menu); return; } ui_get_xcolor_rgba(&red, &green, &blue, &alpha, xcolor); sprintf(rgba, alpha == 255 ? "#%.2x%.2x%.2x" : "#%.2x%.2x%.2x%.2x", red, green, blue, alpha); vt_term_response_config(screen->term, key, rgba, to_menu); } /* * callbacks of ui_sel_event_listener_t events. */ static void reverse_color(void *p, int beg_char_index, int beg_row, int end_char_index, int end_row, int is_rect) { ui_screen_t *screen; vt_line_t *line; screen = (ui_screen_t *)p; /* * Char index -1 has special meaning in rtl lines, so don't use abs() here. */ if ((line = vt_term_get_line(screen->term, beg_row)) && vt_line_is_rtl(line)) { beg_char_index = -beg_char_index; } if ((line = vt_term_get_line(screen->term, end_row)) && vt_line_is_rtl(line)) { end_char_index = -end_char_index; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " reversing region %d %d %d %d.\n", beg_char_index, beg_row, end_char_index, end_row); #endif vt_term_reverse_color(screen->term, beg_char_index, beg_row, end_char_index, end_row, is_rect); } static void restore_color(void *p, int beg_char_index, int beg_row, int end_char_index, int end_row, int is_rect) { ui_screen_t *screen; vt_line_t *line; screen = (ui_screen_t *)p; /* * Char index -1 has special meaning in rtl lines, so don't use abs() here. */ if ((line = vt_term_get_line(screen->term, beg_row)) && vt_line_is_rtl(line)) { beg_char_index = -beg_char_index; } if ((line = vt_term_get_line(screen->term, end_row)) && vt_line_is_rtl(line)) { end_char_index = -end_char_index; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " restoring region %d %d %d %d.\n", beg_char_index, beg_row, end_char_index, end_row); #endif vt_term_restore_color(screen->term, beg_char_index, beg_row, end_char_index, end_row, is_rect); } static int select_in_window(void *p, vt_char_t **chars, u_int *len, int beg_char_index, int beg_row, int end_char_index, int end_row, int is_rect) { ui_screen_t *screen; vt_line_t *line; u_int size; screen = p; /* * Char index -1 has special meaning in rtl lines, so don't use abs() here. */ if ((line = vt_term_get_line(screen->term, beg_row)) && vt_line_is_rtl(line)) { beg_char_index = -beg_char_index; } if ((line = vt_term_get_line(screen->term, end_row)) && vt_line_is_rtl(line)) { end_char_index = -end_char_index; } if ((size = vt_term_get_region_size(screen->term, beg_char_index, beg_row, end_char_index, end_row, is_rect)) == 0) { return 0; } if ((*chars = vt_str_new(size)) == NULL) { return 0; } *len = vt_term_copy_region(screen->term, *chars, size, beg_char_index, beg_row, end_char_index, end_row, is_rect); #ifdef DEBUG bl_debug_printf("SELECTION: "); vt_str_dump(*chars, size); #endif #ifdef DEBUG if (size != *len) { bl_warn_printf(BL_DEBUG_TAG " vt_term_get_region_size() == %d and vt_term_copy_region() == %d" " are not the same size !\n", size, *len); } #endif if (!ui_window_set_selection_owner(&screen->window, CurrentTime)) { vt_str_destroy(*chars, size); return 0; } else { return 1; } } /* * callbacks of vt_screen_event_listener_t events. */ static int window_scroll_upward_region(void *p, int beg_row, int end_row, u_int size) { ui_screen_t *screen; screen = p; if (!ui_window_is_scrollable(&screen->window)) { return 0; } set_scroll_boundary(screen, beg_row, end_row); screen->scroll_cache_rows += size; return 1; } static int window_scroll_downward_region(void *p, int beg_row, int end_row, u_int size) { ui_screen_t *screen; screen = p; if (!ui_window_is_scrollable(&screen->window)) { return 0; } set_scroll_boundary(screen, beg_row, end_row); screen->scroll_cache_rows -= size; return 1; } static void line_scrolled_out(void *p) { ui_screen_t *screen; screen = p; ui_sel_line_scrolled_out(&screen->sel, -((int)vt_term_get_log_size(screen->term))); #ifndef NO_IMAGE /* * Note that scrolled out line hasn't been added to vt_logs_t yet here. * (see receive_scrolled_out_line() in vt_screen.c) */ if (vt_term_get_num_logged_lines(screen->term) >= -INLINEPIC_AVAIL_ROW) { vt_line_t *line; if ((line = vt_term_get_line(screen->term, INLINEPIC_AVAIL_ROW))) { int count; for (count = 0; count < line->num_filled_chars; count++) { vt_char_t *ch; if ((ch = vt_get_picture_char(line->chars + count))) { vt_char_copy(ch, vt_sp_ch()); } } } } #endif } /* * callbacks of ui_xim events. */ static int get_spot_intern(ui_screen_t *screen, vt_char_t *chars, int segment_offset, int return_line_bottom, int ignore_vertical_mode, int *x, int *y) { vt_line_t *line; vt_char_t *comb_chars; u_int comb_size; int i; *x = *y = 0; if ((line = vt_term_get_cursor_line(screen->term)) == NULL || vt_line_is_empty(line)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " cursor line doesn't exist ?.\n"); #endif return 0; } if (!vt_term_get_vertical_mode(screen->term) || ignore_vertical_mode) { int row; if ((row = vt_term_cursor_row_in_screen(screen->term)) < 0) { return 0; } *x = convert_char_index_to_x_with_shape(screen, line, vt_term_cursor_char_index(screen->term)); *y = convert_row_to_y(screen, row); if (return_line_bottom) { *y += ui_line_height(screen); } if (segment_offset > 0) { ui_font_manager_set_attr(screen->font_man, line->size_attr, vt_line_has_ot_substitute_glyphs(line)); i = 0; do { u_int width; width = ui_calculate_vtchar_width(ui_get_font(screen->font_man, vt_char_font(&chars[i])), &chars[i], NULL); *x += width; if (*x >= screen->width) { *x = 0; *y += ui_line_height(screen); } /* not count combining characters */ comb_chars = vt_get_combining_chars(&chars[i], &comb_size); if (comb_chars) { i += comb_size; } } while (++i < segment_offset); } } else { *x = convert_char_index_to_x_with_shape(screen, line, vt_term_cursor_char_index(screen->term)); *y = convert_row_to_y(screen, vt_term_cursor_row(screen->term)); *x += ui_col_width(screen); if (segment_offset > 0) { int width; u_int height; width = ui_col_width(screen); if (vt_term_get_vertical_mode(screen->term) == VERT_RTL) { width = -width; } height = ui_line_height(screen); i = 0; do { *y += height; if (*y >= screen->height) { *x += width; *y = 0; } /* not count combining characters */ comb_chars = vt_get_combining_chars(&chars[i], &comb_size); if (comb_chars) { i += comb_size; } } while (++i < segment_offset); } } return 1; } /* * this doesn't consider backscroll mode. */ static int get_spot(void *p, int *x, int *y) { #ifndef XIM_SPOT_IS_LINE_TOP #ifdef USE_QUARTZ return get_spot_intern(p, NULL, 0, 1, 0, x, y); #else return get_spot_intern(p, NULL, 0, 1, 1, x, y); #endif #else return get_spot_intern(p, NULL, 0, 0, 1, x, y); #endif } static XFontSet get_fontset(void *p) { ui_screen_t *screen; screen = p; return ui_get_fontset(screen->font_man); } static ui_color_t *get_fg_color(void *p) { ui_screen_t *screen; screen = p; return ui_get_xcolor(screen->color_man, VT_FG_COLOR); } static ui_color_t *get_bg_color(void *p) { ui_screen_t *screen; screen = p; return ui_get_xcolor(screen->color_man, VT_BG_COLOR); } /* * callbacks of ui_im events. */ static int get_im_spot(void *p, vt_char_t *chars, int segment_offset, int *x, int *y) { ui_screen_t *screen = p; if (!get_spot_intern(screen, chars, segment_offset, 1, 0, x, y)) { return 0; } ui_window_translate_coordinates(&screen->window, *x + screen->window.hmargin, *y + screen->window.vmargin, x, y); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " im spot => x %d y %d\n", *x, *y); #endif return 1; } static u_int get_line_height(void *p) { return ui_line_height((ui_screen_t *)p); } static int is_vertical(void *p) { if (vt_term_get_vertical_mode(((ui_screen_t *)p)->term)) { return 1; } else { return 0; } } static void draw_preedit_str(void *p, vt_char_t *chars, u_int num_chars, int cursor_offset) { ui_screen_t *screen; vt_line_t *line; ui_font_t *font; int x; int y; u_int total_width; u_int i; u_int start; u_int beg_row; u_int end_row; int preedit_cursor_x; int preedit_cursor_y; screen = p; if (screen->is_preediting) { ui_im_t *im; vt_term_set_modified_lines_in_screen(screen->term, screen->im_preedit_beg_row, screen->im_preedit_end_row); /* Avoid recursive call of ui_im_redraw_preedit() in redraw_screen(). */ im = screen->im; screen->im = NULL; ui_window_update(&screen->window, UPDATE_SCREEN); screen->im = im; } if (!num_chars) { screen->is_preediting = 0; return; } screen->is_preediting = 1; if ((line = vt_term_get_cursor_line(screen->term)) == NULL || vt_line_is_empty(line)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " cursor line doesn't exist ?.\n"); #endif return; } if (!vt_term_get_vertical_mode(screen->term)) { int row; row = vt_term_cursor_row_in_screen(screen->term); if (row < 0) { return; } beg_row = row; } else if (vt_term_get_vertical_mode(screen->term) == VERT_RTL) { u_int ncols; ncols = vt_term_get_cols(screen->term); beg_row = vt_term_cursor_col(screen->term); beg_row = ncols - beg_row - 1; } else /* VERT_LTR */ { beg_row = vt_term_cursor_col(screen->term); } end_row = beg_row; x = convert_char_index_to_x_with_shape(screen, line, vt_term_cursor_char_index(screen->term)); y = convert_row_to_y(screen, vt_term_cursor_row_in_screen(screen->term)); preedit_cursor_x = x; preedit_cursor_y = y; total_width = 0; #ifdef USE_WIN32GUI ui_set_gc(screen->window.gc, GetDC(screen->window.my_window)); #endif ui_font_manager_set_attr(screen->font_man, line->size_attr, 0); for (i = 0, start = 0; i < num_chars; i++) { u_int width; int need_wraparound = 0; int _x; int _y; font = ui_get_font(screen->font_man, vt_char_font(&chars[i])); width = ui_calculate_vtchar_width(font, &chars[i], NULL); total_width += width; if (!vt_term_get_vertical_mode(screen->term)) { if (x + total_width > screen->width) { need_wraparound = 1; _x = 0; _y = y + ui_line_height(screen); end_row++; } } else { need_wraparound = 1; _x = x; _y = y + ui_line_height(screen); start = i; if (_y > screen->height) { y = 0; _y = ui_line_height(screen); if (vt_term_get_vertical_mode(screen->term) == VERT_RTL) { x -= ui_col_width(screen); if (x < 0) { goto end; } } else /* VERT_LRT */ { x += ui_col_width(screen); if (x >= screen->width) { goto end; } } _x = x; end_row++; } } if (i == cursor_offset - 1) { if (!vt_term_get_vertical_mode(screen->term)) { preedit_cursor_x = x + total_width; preedit_cursor_y = y; } else { preedit_cursor_x = x; preedit_cursor_y = _y; } } if (need_wraparound) { if (!ui_draw_str(&screen->window, screen->font_man, screen->color_man, &chars[start], i - start + 1, x, y, ui_line_height(screen), ui_line_ascent(screen), line_top_margin(screen), screen->hide_underline, screen->underline_offset)) { break; } if (!vt_term_get_vertical_mode(screen->term) && _y + ui_line_height(screen) > screen->height) { goto end; } x = _x; y = _y; start = i; total_width = width; } if (vt_term_get_vertical_mode(screen->term)) { continue; } if (i == num_chars - 1) /* last? */ { if (!ui_draw_str(&screen->window, screen->font_man, screen->color_man, &chars[start], i - start + 1, x, y, ui_line_height(screen), ui_line_ascent(screen), line_top_margin(screen), screen->hide_underline, screen->underline_offset)) { break; } } } ui_window_flush(&screen->window); if (cursor_offset == num_chars) { if (!vt_term_get_vertical_mode(screen->term)) { if ((preedit_cursor_x = x + total_width) == screen->width) { preedit_cursor_x--; } preedit_cursor_y = y; } else { preedit_cursor_x = x; if ((preedit_cursor_y = y) == screen->height) { preedit_cursor_y--; } } } if (cursor_offset >= 0) { if (!vt_term_get_vertical_mode(screen->term)) { ui_window_fill(&screen->window, preedit_cursor_x, preedit_cursor_y, 1, ui_line_height(screen)); } else { ui_window_fill(&screen->window, preedit_cursor_x, preedit_cursor_y, ui_col_width(screen), 1); } } end: #ifdef USE_WIN32GUI ReleaseDC(screen->window.my_window, screen->window.gc->gc); ui_set_gc(screen->window.gc, None); #endif screen->im_preedit_beg_row = beg_row; screen->im_preedit_end_row = end_row; } /* used for changing IM from plugin side */ static void im_changed(void *p, char *input_method) { ui_screen_t *screen; ui_im_t *new; screen = p; if (!(input_method = strdup(input_method))) { return; } if (!(new = im_new(screen))) { free(input_method); return; } free(screen->input_method); screen->input_method = input_method; /* strdup'ed one */ ui_im_destroy(screen->im); screen->im = new; } static int compare_key_state_with_modmap(void *p, u_int state, int *is_shift, int *is_lock, int *is_ctl, int *is_alt, int *is_meta, int *is_numlock, int *is_super, int *is_hyper) { ui_screen_t *screen; XModifierKeymap *mod_map; u_int mod_mask[] = {Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask}; screen = p; if (is_shift) { *is_shift = 0; } if (is_lock) { *is_lock = 0; } if (is_ctl) { *is_ctl = 0; } if (is_alt) { *is_alt = 0; } if (is_meta) { *is_meta = 0; } if (is_numlock) { *is_numlock = 0; } if (is_super) { *is_super = 0; } if (is_hyper) { *is_hyper = 0; } if (is_shift && (state & ShiftMask)) { *is_shift = 1; } if (is_lock && (state & LockMask)) { *is_lock = 1; } if (is_ctl && (state & ControlMask)) { *is_ctl = 1; } if (!(mod_map = ui_window_get_modifier_mapping(&screen->window))) { /* Win32 or framebuffer */ if (is_alt && (state & ModMask)) { *is_alt = 1; } } else { int i; for (i = 0; i < 5; i++) { int index; int mod1_index; if (!(state & mod_mask[i])) { continue; } /* skip shift/lock/control */ mod1_index = mod_map->max_keypermod * 3; for (index = mod1_index + (mod_map->max_keypermod * i); index < mod1_index + (mod_map->max_keypermod * (i + 1)); index++) { KeySym sym; sym = XKeycodeToKeysym(screen->window.disp->display, mod_map->modifiermap[index], 0); switch (sym) { case XK_Meta_R: case XK_Meta_L: if (is_meta) { *is_meta = 1; } break; case XK_Alt_R: case XK_Alt_L: if (is_alt) { *is_alt = 1; } break; case XK_Super_R: case XK_Super_L: if (is_super) { *is_super = 1; } break; case XK_Hyper_R: case XK_Hyper_L: if (is_hyper) { *is_hyper = 1; } break; case XK_Num_Lock: if (is_numlock) { *is_numlock = 1; } default: break; } } } } return 1; } static void write_to_term(void *p, u_char *str, /* must be same as term encoding */ size_t len) { ui_screen_t *screen; screen = p; #ifdef __DEBUG { size_t count; bl_debug_printf(BL_DEBUG_TAG " written str: "); for (count = 0; count < len; count++) { bl_msg_printf("%.2x ", str[count]); } bl_msg_printf("\n"); } #endif vt_term_write(screen->term, str, len); } #ifdef DEBUG static void write_to_status_line(void *p, u_char *str /* must be same as term encoding */, size_t len) { ui_screen_t *screen = p; if (str) { vt_term_write_loopback(screen->term, "\x1b[2$~\x1b[1$}\x1b[H\x1b[2K", 17); vt_term_write_loopback(screen->term, str, len); vt_term_write_loopback(screen->term, "\x1b[0$}", 5); } else { vt_term_write_loopback(screen->term, "\x1b[0$~", 5); } } #endif /* * callbacks of vt_xterm_event_listener_t */ static void start_vt100_cmd(void *p) { ui_screen_t *screen; screen = p; #if 0 if (!vt_term_is_backscrolling(screen->term) || vt_term_is_backscrolling(screen->term) == BSM_DEFAULT) { ui_stop_selecting(&screen->sel); } #endif if (screen->sel.is_reversed) { if (ui_is_selecting(&screen->sel)) { ui_restore_selected_region_color_except_logs(&screen->sel); } else { ui_restore_selected_region_color(&screen->sel); } if (!vt_term_logical_visual_is_reversible(screen->term)) { /* * If vertical logical<=>visual conversion is enabled, ui_window_update() * in stop_vt100_cmd() can't reflect ui_restore_selected_region_color*() * functions above to screen. */ ui_window_update(&screen->window, UPDATE_SCREEN); } } unhighlight_cursor(screen, 0); /* * vt_screen_logical() is called in vt_term_unhighlight_cursor(), so * not called directly from here. */ /* processing_vtseq == -1 means loopback processing of vtseq. */ if (screen->processing_vtseq != -1) { screen->processing_vtseq = 1; } } static void stop_vt100_cmd(void *p) { ui_screen_t *screen; screen = p; screen->processing_vtseq = 0; if (ui_is_selecting(&screen->sel)) { /* * XXX Fixme XXX * If some lines are scrolled out after start_vt100_cmd(), * color of them is not reversed. */ ui_reverse_selected_region_color_except_logs(&screen->sel); } if (exit_backscroll_by_pty) { exit_backscroll_mode(screen); } if ((screen->font_or_color_config_updated & 0x1) && screen->system_listener->font_config_updated) { (*screen->system_listener->font_config_updated)(); } if ((screen->font_or_color_config_updated & 0x2) && screen->system_listener->color_config_updated) { (*screen->system_listener->color_config_updated)(); } screen->font_or_color_config_updated = 0; ui_window_update(&screen->window, UPDATE_SCREEN | UPDATE_CURSOR); } static void interrupt_vt100_cmd(void *p) { ui_screen_t *screen; screen = p; ui_window_update(&screen->window, UPDATE_SCREEN); /* Forcibly reflect to the screen. */ ui_display_sync(screen->window.disp); } static void xterm_resize(void *p, u_int width, u_int height, int flag) { ui_screen_t *screen; screen = p; if (flag) { ui_window_set_maximize_flag(&screen->window, flag - 1 /* converting to ui_maximize_flag_t */); return; } if (width == 0 && height == 0) { /* vt_term_t is already resized. */ resize_window(screen); return; } if (width == 0) { width = screen->width; } if (height == 0) { height = screen->height; } if (vt_term_has_status_line(screen->term)) { height += ui_line_height(screen); } /* screen will redrawn in window_resized() */ if (ui_window_resize(&screen->window, width, height, NOTIFY_TO_PARENT | LIMIT_RESIZE)) { /* * !! Notice !! * ui_window_resize() will invoke ConfigureNotify event but window_resized() * won't be called , since xconfigure.width , xconfigure.height are the same * as the already resized window. */ if (screen->window.window_resized) { (*screen->window.window_resized)(&screen->window); } } } static void xterm_reverse_video(void *p, int do_reverse) { ui_screen_t *screen; screen = p; if (do_reverse) { if (!ui_color_manager_reverse_video(screen->color_man)) { return; } } else { if (!ui_color_manager_restore_video(screen->color_man)) { return; } } ui_window_set_fg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_FG_COLOR)); ui_window_set_bg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_BG_COLOR)); vt_term_set_modified_all_lines_in_screen(screen->term); ui_window_update(&screen->window, UPDATE_SCREEN); } static void xterm_set_mouse_report(void *p) { ui_screen_t *screen; screen = p; if (vt_term_get_mouse_report_mode(screen->term)) { /* These are called in button_pressed() etc. */ #if 0 ui_stop_selecting(&screen->sel); restore_selected_region_color_instantly(screen); exit_backscroll_mode(screen); #endif } else { screen->prev_mouse_report_col = screen->prev_mouse_report_row = 0; } if (vt_term_get_mouse_report_mode(screen->term) < ANY_EVENT_MOUSE_REPORT) { /* pointer_motion may be overridden by ui_layout */ if (screen->window.pointer_motion == pointer_motion) { ui_window_remove_event_mask(&screen->window, PointerMotionMask); } } else { ui_window_add_event_mask(&screen->window, PointerMotionMask); } } static void xterm_request_locator(void *p) { ui_screen_t *screen; int button; int button_state; screen = p; if (screen->window.button_is_pressing) { button = screen->window.prev_clicked_button; button_state = (1 << (button - Button1)); } else { /* PointerMotion */ button = button_state = 0; } vt_term_report_mouse_tracking( screen->term, screen->prev_mouse_report_col > 0 ? screen->prev_mouse_report_col : 1, screen->prev_mouse_report_row > 0 ? screen->prev_mouse_report_row : 1, button, 0, 0, button_state); } static void xterm_bel(void *p) { ui_screen_t *screen; screen = p; ui_window_bell(&screen->window, screen->bel_mode); } static int xterm_im_is_active(void *p) { ui_screen_t *screen; screen = p; if (screen->im) { return (*screen->im->is_active)(screen->im); } return ui_xic_is_active(&screen->window); } static void xterm_switch_im_mode(void *p) { ui_screen_t *screen; screen = p; if (screen->im) { (*screen->im->switch_mode)(screen->im); return; } ui_xic_switch_mode(&screen->window); } static void xterm_set_selection(void *p, vt_char_t *str, /* Should be free'ed by the event listener. */ u_int len, u_char *targets) { ui_screen_t *screen; int use_clip_orig; screen = p; use_clip_orig = ui_is_using_clipboard_selection(); if (strchr(targets, 'c')) { if (!use_clip_orig) { ui_set_use_clipboard_selection(1); } } else if (!strchr(targets, 's') && strchr(targets, 'p')) { /* 'p' is specified while 'c' and 's' aren't specified. */ if (use_clip_orig) { ui_set_use_clipboard_selection(0); } } if (ui_window_set_selection_owner(&screen->window, CurrentTime)) { if (screen->sel.sel_str) { vt_str_destroy(screen->sel.sel_str, screen->sel.sel_len); } screen->sel.sel_str = str; screen->sel.sel_len = len; } if (use_clip_orig != ui_is_using_clipboard_selection()) { ui_set_use_clipboard_selection(use_clip_orig); } } static int xterm_get_rgb(void *p, u_int8_t *red, u_int8_t *green, u_int8_t *blue, vt_color_t color) { ui_screen_t *screen; ui_color_t *xcolor; screen = p; if (!(xcolor = ui_get_xcolor(screen->color_man, color))) { return 0; } ui_get_xcolor_rgba(red, green, blue, NULL, xcolor); return 1; } static void xterm_get_window_size(void *p, u_int *width, u_int *height) { ui_screen_t *screen; screen = p; *width = screen->width; *height = screen->height; if (vt_term_has_status_line(screen->term)) { *height -= ui_line_height(screen); } } static void xterm_get_display_size(void *p, u_int *width, u_int *height) { ui_screen_t *screen; screen = p; *width = screen->window.disp->width; *height = screen->window.disp->height; } #ifndef NO_IMAGE static vt_char_t *xterm_get_picture_data(void *p, char *file_path, int *num_cols /* can be 0 */, int *num_rows /* can be 0 */, int *num_cols_small /* set only if drcs_sixel is 1. */, int *num_rows_small /* set only if drcs_sixel is 1. */, u_int32_t **sixel_palette, int keep_aspect, int drcs_sixel) { ui_screen_t *screen; u_int width; u_int height; u_int width_orig; u_int height_orig; u_int col_width; u_int line_height; int idx; screen = p; if (vt_term_get_vertical_mode(screen->term)) { return NULL; } width_orig = width = (*num_cols) * (col_width = ui_col_width(screen)); height_orig = height = (*num_rows) * (line_height = ui_line_height(screen)); if (sixel_palette) { *sixel_palette = ui_set_custom_sixel_palette(*sixel_palette); } if ((idx = ui_load_inline_picture(screen->window.disp, file_path, &width, &height, col_width, line_height, keep_aspect, screen->term)) != -1) { vt_char_t *buf; u_int cols_padding[2]; u_int rows_padding[2]; screen->prev_inline_pic = idx; *num_cols = (width + col_width - 1) / col_width; *num_rows = (height + line_height - 1) / line_height; if (width_orig > 0 && width < width_orig) { u_int cols = (width_orig - width) / col_width; if (cols + *num_cols > vt_term_get_cols(screen->term)) { if (*num_cols >= vt_term_get_cols(screen->term)) { cols = 0; } else { cols = vt_term_get_cols(screen->term) - *num_cols; } } cols_padding[0] = cols / 2; cols_padding[1] = (cols + 1) / 2; } else { cols_padding[0] = cols_padding[1] = 0; } if (height_orig > 0 && height < height_orig) { u_int rows = (height_orig - height) / line_height; if (rows + *num_rows > vt_term_get_rows(screen->term)) { if (*num_rows >= vt_term_get_rows(screen->term)) { rows = 0; } else { rows = vt_term_get_rows(screen->term) - *num_rows; } } rows_padding[0] = rows / 2; rows_padding[1] = (rows + 1) / 2; } else { rows_padding[0] = rows_padding[1] = 0; } if (drcs_sixel) { /* compatible with rlogin */ *num_cols_small = width / col_width; *num_rows_small = height / line_height; } else { int max_num_cols = vt_term_get_cols(screen->term) - vt_term_cursor_col(screen->term); if (*num_cols > max_num_cols) { *num_cols = max_num_cols; } } if ((buf = vt_str_new((*num_cols + cols_padding[0] + cols_padding[1]) * (*num_rows + rows_padding[0] + rows_padding[1])))) { vt_char_t *buf_p; int col; int row; buf_p = buf; for (row = 0; row < rows_padding[0]; row++) { for (col = 0; col < *num_cols; col++) { vt_char_copy(buf_p++, vt_term_get_bce_ch(screen->term)); } } for (row = 0; row < *num_rows; row++) { for (col = 0; col < cols_padding[0]; col++) { vt_char_copy(buf_p++, vt_term_get_bce_ch(screen->term)); } for (col = 0; col < *num_cols; col++) { vt_char_copy(buf_p, vt_term_get_bce_ch(screen->term)); vt_char_combine_picture(buf_p++, idx, MAKE_INLINEPIC_POS(col, row, *num_rows)); } for (col = 0; col < cols_padding[1]; col++) { vt_char_copy(buf_p++, vt_term_get_bce_ch(screen->term)); } } for (row = 0; row < rows_padding[1]; row++) { for (col = 0; col < *num_cols; col++) { vt_char_copy(buf_p++, vt_term_get_bce_ch(screen->term)); } } *num_cols += (cols_padding[0] + cols_padding[1]); *num_rows += (rows_padding[0] + rows_padding[1]); return buf; } } return NULL; } static int xterm_get_emoji_data(void *p, vt_char_t *ch1, vt_char_t *ch2) { ui_screen_t *screen; char *file_path; u_int width; u_int height; int idx; screen = p; width = ui_col_width(screen) * vt_char_cols(ch1); height = ui_line_height(screen); if ((file_path = ui_emoji_get_path(vt_char_code(ch1), ch2 ? vt_char_code(ch2) : 0))) { idx = ui_load_inline_picture(screen->window.disp, file_path, &width, &height, width / vt_char_cols(ch1), height, 0, screen->term); free(file_path); if (idx != -1) { vt_char_combine_picture(ch1, idx, 0); return 1; } } return 0; } #ifndef DONT_OPTIMIZE_DRAWING_PICTURE static void xterm_show_tmp_picture(void *p, char *file_path) { ui_screen_t *screen; Pixmap pixmap; PixmapMask mask; u_int width; u_int height; screen = p; if (!vt_term_get_vertical_mode(screen->term) && ui_load_tmp_picture(screen->window.disp, file_path, &pixmap, &mask, &width, &height)) { ui_window_copy_area(&screen->window, pixmap, mask, 0, 0, width, height, 0, 0); ui_destroy_tmp_picture(screen->window.disp, pixmap, mask); /* * ui_display_sync() is not necessary here because xterm_show_tmp_picture() * is never called by DECINVM. */ } } #else #define xterm_show_tmp_picture NULL #endif #ifdef ENABLE_OSC5379PICTURE static void xterm_add_frame_to_animation(void *p, char *file_path, int *num_cols, int *num_rows) { ui_screen_t *screen; u_int width; u_int height; u_int col_width; u_int line_height; int idx; screen = p; if (vt_term_get_vertical_mode(screen->term) || screen->prev_inline_pic < 0) { return; } width = (*num_cols) *(col_width = ui_col_width(screen)); height = (*num_rows) *(line_height = ui_line_height(screen)); if ((idx = ui_load_inline_picture(screen->window.disp, file_path, &width, &height, col_width, line_height, 0, screen->term)) != -1 && screen->prev_inline_pic != idx) { ui_add_frame_to_animation(screen->prev_inline_pic, idx); screen->prev_inline_pic = idx; } } #endif #else #define xterm_get_picture_data NULL #define xterm_get_emoji_data NULL #define xterm_show_tmp_picture NULL #define xterm_add_frame_to_animation NULL #endif /* NO_IMAGE */ static int xterm_check_iscii_font(void *p, ef_charset_t cs) { return ui_font_cache_get_font(((ui_screen_t *)p)->font_man->font_cache, NORMAL_FONT_OF(cs)) != NULL; } static void xterm_lock_keyboard(void *p, int lock) { ui_screen_t *screen; screen = p; if (lock) { screen->window.key_pressed = NULL; } else { screen->window.key_pressed = key_pressed; } } /* * callbacks of vt_pty_event_listener_t */ static void pty_closed(void *p) { ui_screen_t *screen; screen = p; /* * Don't use ui_screen_detach() here because screen->term is deleting just * now. */ /* This should be done before screen->term is NULL */ ui_sel_clear(&screen->sel); /* * term is being destroyed in this context. * vt_close_dead_terms => vt_term_destroy => vt_pty_destroy => pty_closed. */ screen->term = NULL; (*screen->system_listener->pty_closed)(screen->system_listener->self, screen); } static void show_config(void *p, char *msg) { vt_term_show_message(((ui_screen_t *)p)->term, msg); } static int permit_exec_cmd(char *cmd) { bl_file_t *file; char *path; while (*cmd == ' ') { cmd++; } if (*cmd == '\"') { cmd++; } if (!(path = bl_get_user_rc_path("mlterm/execlist"))) { return 0; } file = bl_file_open(path, "r"); free(path); if (file) { char *line; size_t len; while ((line = bl_file_get_line(file, &len))) { if (line[len - 1] == '\n') { len--; } if (strncmp(cmd, line, len) == 0 && (cmd[len] == ' ' || cmd[len] == '\"')) { bl_file_close(file); return 1; } } } return 0; } /* --- global functions --- */ void ui_exit_backscroll_by_pty(int flag) { exit_backscroll_by_pty = flag; } void ui_allow_change_shortcut(int flag) { allow_change_shortcut = flag; } void ui_set_mod_meta_prefix(char *prefix /* allocated memory */ ) { static int was_replaced; if (was_replaced) { free(mod_meta_prefix); } else { was_replaced = 1; } if ((mod_meta_prefix = prefix) == NULL) { mod_meta_prefix = "\x1b"; was_replaced = 0; } } void ui_set_trim_trailing_newline_in_pasting(int trim) { trim_trailing_newline_in_pasting = trim; } #ifdef USE_IM_CURSOR_COLOR void ui_set_im_cursor_color(char *color) { im_cursor_color = strdup(color); } #endif /* * If term is NULL, don't call other functions of ui_screen until * ui_screen_attach() is called. (ui_screen_attach() must be called * before ui_screen_t is realized.) */ ui_screen_t *ui_screen_new(vt_term_t *term, /* can be NULL */ ui_font_manager_t *font_man, ui_color_manager_t *color_man, u_int brightness, u_int contrast, u_int gamma, u_int alpha, u_int fade_ratio, ui_shortcut_t *shortcut, u_int screen_width_ratio, char *mod_meta_key, ui_mod_meta_mode_t mod_meta_mode, ui_bel_mode_t bel_mode, int receive_string_via_ucs, char *pic_file_path, int use_transbg, int use_vertical_cursor, int use_extended_scroll_shortcut, int borderless, int line_space, char *input_method, int allow_osc52, u_int hmargin, u_int vmargin, int hide_underline, int underline_offset, int baseline_offset) { ui_screen_t *screen; u_int col_width; u_int line_height; #ifdef USE_OT_LAYOUT vt_ot_layout_set_shape_func(ui_convert_text_to_glyphs, ot_layout_get_ot_layout_font); #endif if ((screen = calloc(1, sizeof(ui_screen_t))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " malloc failed.\n"); #endif return NULL; } screen->use_vertical_cursor = use_vertical_cursor; screen->font_man = font_man; screen->color_man = color_man; /* letter_space, line_space and baseline_offset are ignored on console. */ #ifndef USE_CONSOLE screen->line_space = line_space; screen->baseline_offset = baseline_offset; #endif screen->underline_offset = underline_offset; modify_line_space_and_offset(screen); screen->sel_listener.self = screen; screen->sel_listener.select_in_window = select_in_window; screen->sel_listener.reverse_color = reverse_color; screen->sel_listener.restore_color = restore_color; ui_sel_init(&screen->sel, &screen->sel_listener); if (pic_file_path) { screen->pic_file_path = strdup(pic_file_path); } screen->pic_mod.brightness = brightness; screen->pic_mod.contrast = contrast; screen->pic_mod.gamma = gamma; /* * blend_xxx members will be set in window_realized(). */ #if 0 ui_get_xcolor_rgba(&screen->pic_mod.blend_red, &screen->pic_mod.blend_green, &screen->pic_mod.blend_blue, NULL, ui_get_xcolor(screen->color_man, VT_BG_COLOR)); #endif if (alpha != 255) { screen->pic_mod.alpha = alpha; } /* True transparency is disabled on pseudo transparency or wall picture. */ if (!use_transbg && !pic_file_path) { ui_change_true_transbg_alpha(color_man, alpha); } screen->fade_ratio = fade_ratio; screen->screen_width_ratio = screen_width_ratio; /* screen->term must be set before screen_height() */ screen->term = term; col_width = ui_col_width(screen); line_height = ui_line_height(screen); /* min: 1x1 */ if (!ui_window_init(&screen->window, (screen->width = screen->term ? screen_width(screen) : col_width), (screen->height = screen->term ? screen_height(screen) : line_height), col_width, line_height, col_width, line_height, hmargin, vmargin, 0, 1)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ui_window_init failed.\n"); #endif goto error; } screen->screen_listener.self = screen; screen->screen_listener.window_scroll_upward_region = window_scroll_upward_region; screen->screen_listener.window_scroll_downward_region = window_scroll_downward_region; screen->screen_listener.line_scrolled_out = line_scrolled_out; screen->xterm_listener.self = screen; screen->xterm_listener.start = start_vt100_cmd; screen->xterm_listener.stop = stop_vt100_cmd; screen->xterm_listener.interrupt = interrupt_vt100_cmd; screen->xterm_listener.resize = xterm_resize; screen->xterm_listener.reverse_video = xterm_reverse_video; screen->xterm_listener.set_mouse_report = xterm_set_mouse_report; screen->xterm_listener.request_locator = xterm_request_locator; screen->xterm_listener.set_window_name = ui_set_window_name; screen->xterm_listener.set_icon_name = ui_set_icon_name; screen->xterm_listener.bel = xterm_bel; screen->xterm_listener.im_is_active = xterm_im_is_active; screen->xterm_listener.switch_im_mode = xterm_switch_im_mode; screen->xterm_listener.set_selection = (allow_osc52 ? xterm_set_selection : NULL); screen->xterm_listener.get_rgb = xterm_get_rgb; screen->xterm_listener.get_window_size = xterm_get_window_size; screen->xterm_listener.get_display_size = xterm_get_display_size; screen->xterm_listener.get_picture_data = xterm_get_picture_data; screen->xterm_listener.get_emoji_data = xterm_get_emoji_data; screen->xterm_listener.show_tmp_picture = xterm_show_tmp_picture; #ifdef ENABLE_OSC5379PICTURE screen->xterm_listener.add_frame_to_animation = xterm_add_frame_to_animation; #endif screen->xterm_listener.check_iscii_font = xterm_check_iscii_font; screen->xterm_listener.lock_keyboard = xterm_lock_keyboard; screen->config_listener.self = screen; screen->config_listener.exec = ui_screen_exec_cmd; screen->config_listener.set = ui_screen_set_config; screen->config_listener.get = get_config; screen->config_listener.saved = NULL; screen->config_listener.set_font = set_font_config; screen->config_listener.get_font = get_font_config; screen->config_listener.set_color = set_color_config; screen->config_listener.get_color = get_color_config; screen->pty_listener.self = screen; screen->pty_listener.closed = pty_closed; screen->pty_listener.show_config = show_config; if (screen->term) { vt_term_attach(term, &screen->xterm_listener, &screen->config_listener, &screen->screen_listener, &screen->pty_listener); /* * setup_encoding_aux() in update_special_visual() must be called * after ui_window_init() */ update_special_visual(screen); } screen->xim_listener.self = screen; screen->xim_listener.get_spot = get_spot; screen->xim_listener.get_fontset = get_fontset; screen->xim_listener.get_fg_color = get_fg_color; screen->xim_listener.get_bg_color = get_bg_color; screen->window.xim_listener = &screen->xim_listener; if (input_method) { screen->input_method = strdup(input_method); } screen->im_listener.self = screen; screen->im_listener.get_spot = get_im_spot; screen->im_listener.get_line_height = get_line_height; screen->im_listener.is_vertical = is_vertical; screen->im_listener.draw_preedit_str = draw_preedit_str; screen->im_listener.im_changed = im_changed; screen->im_listener.compare_key_state_with_modmap = compare_key_state_with_modmap; screen->im_listener.write_to_term = write_to_term; #ifdef DEBUG screen->im_listener.write_to_status_line = write_to_status_line; #endif ui_window_set_cursor(&screen->window, XC_xterm); /* * event call backs. */ ui_window_add_event_mask(&screen->window, ButtonPressMask | ButtonMotionMask | ButtonReleaseMask | KeyPressMask); screen->window.window_realized = window_realized; screen->window.window_finalized = window_finalized; screen->window.window_destroyed = window_destroyed; screen->window.mapping_notify = mapping_notify; screen->window.window_exposed = window_exposed; screen->window.update_window = update_window; screen->window.window_focused = window_focused; screen->window.window_unfocused = window_unfocused; screen->window.key_pressed = key_pressed; screen->window.window_resized = window_resized; screen->window.pointer_motion = pointer_motion; screen->window.button_motion = button_motion; screen->window.button_released = button_released; screen->window.button_pressed = button_pressed; screen->window.button_press_continued = button_press_continued; screen->window.selection_cleared = selection_cleared; screen->window.xct_selection_requested = xct_selection_requested; screen->window.utf_selection_requested = utf_selection_requested; screen->window.xct_selection_notified = xct_selection_notified; screen->window.utf_selection_notified = utf_selection_notified; #ifndef DISABLE_XDND screen->window.set_xdnd_config = set_xdnd_config; #endif screen->window.idling = idling; #ifdef UIWINDOW_SUPPORTS_PREEDITING screen->window.preedit = preedit; #endif if (use_transbg) { ui_window_set_transparent(&screen->window, ui_screen_get_picture_modifier(screen)); } screen->shortcut = shortcut; if (mod_meta_key && strcmp(mod_meta_key, "none") != 0) { screen->mod_meta_key = strdup(mod_meta_key); } screen->mod_meta_mode = mod_meta_mode; screen->mod_meta_mask = 0; /* set later in get_mod_meta_mask() */ screen->mod_ignore_mask = ~0; /* set later in get_mod_ignore_mask() */ screen->bel_mode = bel_mode; screen->use_extended_scroll_shortcut = use_extended_scroll_shortcut; screen->borderless = borderless; screen->font_or_color_config_updated = 0; screen->hide_underline = hide_underline; screen->prev_inline_pic = -1; screen->receive_string_via_ucs = receive_string_via_ucs; if (!vt_str_parser) { if (!(vt_str_parser = vt_str_parser_new())) { goto error; } } return screen; error: free(screen->pic_file_path); free(screen->mod_meta_key); free(screen->input_method); free(screen); return NULL; } void ui_screen_destroy(ui_screen_t *screen) { if (screen->term) { vt_term_detach(screen->term); } ui_sel_final(&screen->sel); if (screen->bg_pic) { ui_release_picture(screen->bg_pic); } free(screen->pic_file_path); if (screen->icon) { ui_release_icon_picture(screen->icon); } free(screen->mod_meta_key); free(screen->input_method); if (screen->im) { ui_im_destroy(screen->im); } free(screen); } /* * Be careful that mlterm can die if ui_screen_attach is called * before ui_screen_t is realized, because callbacks of vt_term * may touch uninitialized object of ui_screen_t. */ int ui_screen_attach(ui_screen_t *screen, vt_term_t *term) { if (screen->term) { return 0; } screen->term = term; vt_term_attach(term, &screen->xterm_listener, &screen->config_listener, &screen->screen_listener, &screen->pty_listener); if (!screen->window.my_window) { return 1; } if (!usascii_font_cs_changed(screen, vt_term_get_encoding(screen->term))) { resize_window(screen); } update_special_visual(screen); /* Even if update_special_visual succeeded or not, all screen should be * redrawn. */ vt_term_set_modified_all_lines_in_screen(screen->term); if (HAS_SCROLL_LISTENER(screen, term_changed)) { (*screen->screen_scroll_listener->term_changed)(screen->screen_scroll_listener->self, vt_term_get_log_size(screen->term), vt_term_get_num_logged_lines(screen->term)); } /* * if vt_term_(icon|window)_name() returns NULL, screen->window.app_name * will be used in ui_set_(icon|window)_name(). */ ui_set_window_name(&screen->window, vt_term_window_name(screen->term)); ui_set_icon_name(&screen->window, vt_term_icon_name(screen->term)); /* reset icon to screen->term's one */ set_icon(screen); if (screen->im) { ui_im_t *im; im = screen->im; screen->im = im_new(screen); /* * Avoid to destroy anything inside im-module by calling ui_im_destroy() * after ui_im_new(). */ ui_im_destroy(im); } ui_window_update(&screen->window, UPDATE_SCREEN | UPDATE_CURSOR); return 1; } vt_term_t *ui_screen_detach(ui_screen_t *screen) { vt_term_t *term; if (screen->term == NULL) { return NULL; } /* This should be done before screen->term is NULL */ ui_sel_clear(&screen->sel); #if 1 exit_backscroll_mode(screen); #endif vt_term_detach(screen->term); term = screen->term; screen->term = NULL; return term; } int ui_screen_attached(ui_screen_t *screen) { return (screen->term != NULL); } void ui_set_system_listener(ui_screen_t *screen, ui_system_event_listener_t *system_listener) { screen->system_listener = system_listener; } void ui_set_screen_scroll_listener(ui_screen_t *screen, ui_screen_scroll_event_listener_t *screen_scroll_listener) { screen->screen_scroll_listener = screen_scroll_listener; } /* * for scrollbar scroll. * * Similar processing is done in bs_xxx(). */ void ui_screen_scroll_upward(ui_screen_t *screen, u_int size) { enter_backscroll_mode(screen); bs_scroll_upward(screen, size); } void ui_screen_scroll_downward(ui_screen_t *screen, u_int size) { enter_backscroll_mode(screen); bs_scroll_downward(screen, size); } void ui_screen_scroll_to(ui_screen_t *screen, int row) { enter_backscroll_mode(screen); if (vt_term_backscroll_to(screen->term, row)) { ui_window_update(&screen->window, UPDATE_SCREEN | UPDATE_CURSOR); if (HAS_SCROLL_LISTENER(screen, scrolled_to)) { (*screen->screen_scroll_listener->scrolled_to)(screen->screen_scroll_listener->self, row); } } } u_int ui_col_width(ui_screen_t *screen) { return ui_get_usascii_font(screen->font_man)->width; } u_int ui_line_height(ui_screen_t *screen) { return ui_get_usascii_font(screen->font_man)->height + screen->line_space; } u_int ui_line_ascent(ui_screen_t *screen) { return ui_get_usascii_font(screen->font_man)->ascent + line_top_margin(screen) + screen->baseline_offset; } /* * Return value * 0 -> Not processed * 1 -> Processed (regardless of processing succeeded or not) */ int ui_screen_exec_cmd(ui_screen_t *screen, char *cmd) { char *arg; if (vt_term_exec_cmd(screen->term, cmd)) { return 1; } else if (strcmp(cmd, "mlconfig") == 0) { start_menu(screen, cmd, screen->window.width / 2, screen->window.height / 2); return 1; } else if (strncmp(cmd, "mlclient", 8) == 0) { if (HAS_SYSTEM_LISTENER(screen, mlclient)) { /* * processing_vtseq == -1: process vtseq in loopback. * processing_vtseq == 0 : stop processing vtseq. */ if (screen->processing_vtseq > 0) { char *ign_opts[] = { "-e", "-initstr", "-#", "-osc52", "-shortcut", #ifdef USE_LIBSSH2 "-scp", #endif }; char *p; size_t count; /* * Executing value of "-e" or "--initstr" option is dangerous * in case 'cat dangerousfile'. */ for (count = 0; count < sizeof(ign_opts) / sizeof(ign_opts[0]); count++) { if ((p = strstr(cmd, ign_opts[count])) && (count > 0 || /* not -e option, or */ (p[2] < 'A' /* not match --extkey, --exitbs */ && /* * XXX * mlclient -e cat (which mltracelog.sh executes) * => 3.1.9 or later : mlclient "-e" "cat" * ^ ^ * p p+3 * 3.1.8 or before: mlclient "-e" "cat" * ^ ^ * p p+3 * * echo -e "\x1b]5379;mlclient -e cat" * => mlclient -e cat * ^ ^ * p p+3 */ !permit_exec_cmd(p + 3)))) { if (p[-1] == '-') { /* for --xxx style option */ p--; } bl_msg_printf("Remove %s from mlclient args.\n", p - 1); p[-1] = '\0'; /* Replace ' ', '\"' or '\''. */ } } } (*screen->system_listener->mlclient)(screen->system_listener->self, cmd[8] == 'x' ? screen : NULL, cmd, stdout); } return 1; } /* Separate cmd to command string and argument string. */ if ((arg = strchr(cmd, ' '))) { /* * If cmd is not matched below, *arg will be restored as ' ' * at the end of this function. */ *arg = '\0'; while (*(++arg) == ' ') ; if (*arg == '\0') { arg = NULL; } } /* * Backward compatibility with mlterm 3.0.10 or before which accepts * '=' like "paste=" is broken. */ if (strcmp(cmd, "paste") == 0) { /* * for vte.c * * processing_vtseq == -1: process vtseq in loopback. * processing_vtseq == 0 : stop processing vtseq. */ if (screen->processing_vtseq <= 0) { yank_event_received(screen, CurrentTime); } } else if (strcmp(cmd, "open_pty") == 0 || strcmp(cmd, "select_pty") == 0) { if (HAS_SYSTEM_LISTENER(screen, open_pty)) { /* arg is not NULL if cmd == "select_pty" */ (*screen->system_listener->open_pty)(screen->system_listener->self, screen, arg); } } else if (strcmp(cmd, "next_pty") == 0) { if (HAS_SYSTEM_LISTENER(screen, next_pty)) { (*screen->system_listener->next_pty)(screen->system_listener->self, screen); } } else if (strcmp(cmd, "prev_pty") == 0) { if (HAS_SYSTEM_LISTENER(screen, prev_pty)) { (*screen->system_listener->prev_pty)(screen->system_listener->self, screen); } } else if (strcmp(cmd, "close_pty") == 0) { /* * close_pty is useful if pty doesn't react anymore and * you want to kill it forcibly. */ if (HAS_SYSTEM_LISTENER(screen, close_pty)) { /* If arg is NULL, screen->term will be closed. */ (*screen->system_listener->close_pty)(screen->system_listener->self, screen, arg); } } else if (strcmp(cmd, "open_screen") == 0) { if (HAS_SYSTEM_LISTENER(screen, open_screen)) { (*screen->system_listener->open_screen)(screen->system_listener->self, screen); } } else if (strcmp(cmd, "close_screen") == 0) { if (HAS_SYSTEM_LISTENER(screen, close_screen)) { (*screen->system_listener->close_screen)(screen->system_listener->self, screen, 0); } } else if (strcmp(cmd + 1, "split_screen") == 0) { if (HAS_SYSTEM_LISTENER(screen, split_screen)) { (*screen->system_listener->split_screen)(screen->system_listener->self, screen, *cmd == 'h', arg); } } else if (strcmp(cmd + 1, "resize_screen") == 0) { if (HAS_SYSTEM_LISTENER(screen, resize_screen)) { (*screen->system_listener->resize_screen)(screen->system_listener->self, screen, *cmd == 'h', arg); } } else if (strcmp(cmd, "next_screen") == 0) { if (HAS_SYSTEM_LISTENER(screen, next_screen)) { (*screen->system_listener->next_screen)(screen->system_listener->self, screen); } } else if (strcmp(cmd, "prev_screen") == 0) { if (HAS_SYSTEM_LISTENER(screen, prev_screen)) { (*screen->system_listener->prev_screen)(screen->system_listener->self, screen); } } else if (strncmp(cmd, "search_", 7) == 0) { vt_char_encoding_t encoding; if (arg && (encoding = vt_term_get_encoding(screen->term)) != VT_UTF8) { char *p; size_t len; len = UTF_MAX_SIZE * strlen(arg) + 1; if ((p = alloca(len))) { *(p + vt_char_encoding_convert(p, len - 1, VT_UTF8, arg, strlen(arg), encoding)) = '\0'; arg = p; } } if (strcmp(cmd + 7, "prev") == 0) { search_find(screen, arg, 1); } else if (strcmp(cmd + 7, "next") == 0) { search_find(screen, arg, 0); } } else if (strcmp(cmd, "update_all") == 0) { ui_window_update_all(ui_get_root_window(&screen->window)); } else if (strcmp(cmd, "set_shortcut") == 0) { /* * processing_vtseq == -1: process vtseq in loopback. * processing_vtseq == 0 : stop processing vtseq. */ if (screen->processing_vtseq <= 0 || allow_change_shortcut) { char *opr; if (arg && (opr = strchr(arg, '='))) { *(opr++) = '\0'; ui_shortcut_parse(screen->shortcut, arg, opr); } } } else if (strcmp(cmd, "autoscroll") == 0) { if (!arg) { screen->autoscroll_count = -10; } else { screen->autoscroll_count = atoi(arg); } } #ifdef BL_DEBUG else if (strcmp(cmd, "test") == 0) { test(); } #endif else { if (arg) { *(cmd + strlen(cmd)) = ' '; } return 0; } return 1; } /* * Return value * 0 -> Not processed * 1 -> Processed (regardless of processing succeeded or not) */ int ui_screen_set_config(ui_screen_t *screen, char *dev, /* can be NULL */ char *key, char *value /* can be NULL */ ) { vt_term_t *term; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s=%s\n", key, value); #endif if (strcmp(value, "switch") == 0) { int flag; get_config_intern(screen, /* dev */ NULL, key, -1, &flag); if (flag == 1) { value = "false"; } else if (flag == 0) { value = "true"; } } if (dev) { /* * XXX * If vt_term_t isn't attached to ui_screen_t, return 0 because * many static functions used below use screen->term internally. */ if ((term = vt_get_term(dev)) && vt_term_is_attached(term)) { screen = term->parser->config_listener->self; } else { return 0; } } else { term = screen->term; } if (term && /* In case term is not attached yet. (for vte.c) */ vt_term_set_config(term, key, value)) { /* do nothing */ } else if (strcmp(key, "encoding") == 0) { vt_char_encoding_t encoding; if ((encoding = vt_get_char_encoding(value)) != VT_UNKNOWN_ENCODING) { change_char_encoding(screen, encoding); } } else if (strcmp(key, "fg_color") == 0) { change_fg_color(screen, value); } else if (strcmp(key, "bg_color") == 0) { change_bg_color(screen, value); } else if (strcmp(key, "cursor_fg_color") == 0) { ui_color_manager_set_cursor_fg_color(screen->color_man, *value == '\0' ? NULL : value); } else if (strcmp(key, "cursor_bg_color") == 0) { ui_color_manager_set_cursor_bg_color(screen->color_man, *value == '\0' ? NULL : value); } else if (strcmp(key, "bd_color") == 0) { change_alt_color(screen, VT_BOLD_COLOR, value); } else if (strcmp(key, "ul_color") == 0) { change_alt_color(screen, VT_UNDERLINE_COLOR, value); } else if (strcmp(key, "bl_color") == 0) { change_alt_color(screen, VT_BLINKING_COLOR, value); } else if (strcmp(key, "rv_color") == 0) { change_alt_color(screen, VT_REVERSE_COLOR, value); } else if (strcmp(key, "it_color") == 0) { change_alt_color(screen, VT_ITALIC_COLOR, value); } else if (strcmp(key, "co_color") == 0) { change_alt_color(screen, VT_CROSSED_OUT_COLOR, value); } else if (strcmp(key, "sb_fg_color") == 0) { change_sb_fg_color(screen, value); } else if (strcmp(key, "sb_bg_color") == 0) { change_sb_bg_color(screen, value); } else if (strcmp(key, "hide_underline") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { change_hide_underline_flag(screen, flag); } } else if (strcmp(key, "underline_offset") == 0) { int offset; if (bl_str_to_int(&offset, value)) { change_underline_offset(screen, offset); } } else if (strcmp(key, "baseline_offset") == 0) { int offset; if (bl_str_to_int(&offset, value)) { change_baseline_offset(screen, offset); } } else if (strcmp(key, "logsize") == 0) { u_int log_size; if (strcmp(value, "unlimited") == 0) { vt_term_unlimit_log_size(screen->term); } else if (bl_str_to_uint(&log_size, value)) { change_log_size(screen, log_size); } } else if (strcmp(key, "fontsize") == 0) { u_int font_size; if (strcmp(value, "larger") == 0) { larger_font_size(screen); } else if (strcmp(value, "smaller") == 0) { smaller_font_size(screen); } else { if (bl_str_to_uint(&font_size, value)) { change_font_size(screen, font_size); } } } else if (strcmp(key, "line_space") == 0) { int line_space; if (bl_str_to_int(&line_space, value)) { change_line_space(screen, line_space); } } else if (strcmp(key, "letter_space") == 0) { u_int letter_space; if (bl_str_to_uint(&letter_space, value)) { change_letter_space(screen, letter_space); } } else if (strcmp(key, "screen_width_ratio") == 0) { u_int ratio; if (bl_str_to_uint(&ratio, value)) { change_screen_width_ratio(screen, ratio); } } else if (strcmp(key, "scrollbar_view_name") == 0) { change_sb_view(screen, value); } else if (strcmp(key, "mod_meta_key") == 0) { change_mod_meta_key(screen, value); } else if (strcmp(key, "mod_meta_mode") == 0) { change_mod_meta_mode(screen, ui_get_mod_meta_mode_by_name(value)); } else if (strcmp(key, "bel_mode") == 0) { change_bel_mode(screen, ui_get_bel_mode_by_name(value)); } else if (strcmp(key, "vertical_mode") == 0) { change_vertical_mode(screen, vt_get_vertical_mode(value)); } else if (strcmp(key, "scrollbar_mode") == 0) { change_sb_mode(screen, ui_get_sb_mode_by_name(value)); } else if (strcmp(key, "exit_backscroll_by_pty") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { ui_exit_backscroll_by_pty(flag); } } else if (strcmp(key, "use_dynamic_comb") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { change_dynamic_comb_flag(screen, flag); } } else if (strcmp(key, "receive_string_via_ucs") == 0 || /* backward compatibility with 2.6.1 or before */ strcmp(key, "copy_paste_via_ucs") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { change_receive_string_via_ucs_flag(screen, flag); } } else if (strcmp(key, "use_transbg") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { change_transparent_flag(screen, flag); } } else if (strcmp(key, "brightness") == 0) { u_int brightness; if (bl_str_to_uint(&brightness, value)) { change_brightness(screen, brightness); } } else if (strcmp(key, "contrast") == 0) { u_int contrast; if (bl_str_to_uint(&contrast, value)) { change_contrast(screen, contrast); } } else if (strcmp(key, "gamma") == 0) { u_int gamma; if (bl_str_to_uint(&gamma, value)) { change_gamma(screen, gamma); } } else if (strcmp(key, "alpha") == 0) { u_int alpha; if (bl_str_to_uint(&alpha, value)) { change_alpha(screen, alpha); } } else if (strcmp(key, "fade_ratio") == 0) { u_int fade_ratio; if (bl_str_to_uint(&fade_ratio, value)) { change_fade_ratio(screen, fade_ratio); } } else if (strcmp(key, "type_engine") == 0) { change_font_present(screen, ui_get_type_engine_by_name(value), ui_get_font_present(screen->font_man)); } else if (strcmp(key, "use_anti_alias") == 0) { ui_font_present_t font_present; font_present = ui_get_font_present(screen->font_man); if (strcmp(value, "true") == 0) { font_present &= ~FONT_NOAA; font_present |= FONT_AA; } else if (strcmp(value, "false") == 0) { font_present |= FONT_NOAA; font_present &= ~FONT_AA; } else /* if( strcmp( value , "default") == 0) */ { font_present &= ~FONT_AA; font_present &= ~FONT_NOAA; } change_font_present(screen, ui_get_type_engine(screen->font_man), font_present); } else if (strcmp(key, "use_variable_column_width") == 0) { ui_font_present_t font_present; font_present = ui_get_font_present(screen->font_man); if (strcmp(value, "true") == 0) { font_present |= FONT_VAR_WIDTH; } else if (strcmp(value, "false") == 0) { font_present &= ~FONT_VAR_WIDTH; } else { return 1; } change_font_present(screen, ui_get_type_engine(screen->font_man), font_present); } else if (strcmp(key, "use_bold_font") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { change_use_bold_font_flag(screen, flag); } } else if (strcmp(key, "use_italic_font") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { change_use_italic_font_flag(screen, flag); } } else if (strcmp(key, "use_ctl") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { change_ctl_flag(screen, flag, vt_term_get_bidi_mode(term), vt_term_is_using_ot_layout(term)); } } else if (strcmp(key, "bidi_mode") == 0) { change_ctl_flag(screen, vt_term_is_using_ctl(term), vt_get_bidi_mode(value), vt_term_is_using_ot_layout(term)); } else if (strcmp(key, "bidi_separators") == 0) { vt_term_set_bidi_separators(screen->term, value); if (update_special_visual(screen)) { vt_term_set_modified_all_lines_in_screen(screen->term); } } #ifdef USE_OT_LAYOUT else if (strcmp(key, "use_ot_layout") == 0) { change_ctl_flag(screen, vt_term_is_using_ctl(term), vt_term_get_bidi_mode(term), strcmp(value, "true") == 0); } #endif else if (strcmp(key, "input_method") == 0) { change_im(screen, value); } else if (strcmp(key, "borderless") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { change_borderless_flag(screen, flag); } } else if (strcmp(key, "wall_picture") == 0) { change_wall_picture(screen, value); } else if (strcmp(key, "icon_path") == 0) { vt_term_set_icon_path(term, value); set_icon(screen); } else if (strcmp(key, "use_clipboard") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { ui_set_use_clipboard_selection(flag); } } else if (strcmp(key, "auto_restart") == 0) { vt_set_auto_restart_cmd(strcmp(value, "false") == 0 ? NULL : value); } else if (strcmp(key, "allow_osc52") == 0) { /* * processing_vtseq == -1: process vtseq in loopback. * processing_vtseq == 0 : stop processing vtseq. */ if (screen->processing_vtseq <= 0) { if (true_or_false(value) > 0) { screen->xterm_listener.set_selection = xterm_set_selection; } else { screen->xterm_listener.set_selection = NULL; } } } else if (strcmp(key, "allow_scp") == 0) { /* * processing_vtseq == -1: process vtseq in loopback. * processing_vtseq == 0 : stop processing vtseq. */ if (screen->processing_vtseq <= 0) { int flag; if ((flag = true_or_false(value)) >= 0) { vt_set_use_scp_full(flag); } } } else if (strcmp(key, "use_urgent_bell") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { ui_set_use_urgent_bell(flag); } } else if (strcmp(key, "use_extended_scroll_shortcut") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { screen->use_extended_scroll_shortcut = flag; } } else if (strstr(key, "_use_unicode_font")) { int flag; if ((flag = true_or_false(value)) != -1) { if (strncmp(key, "only", 4) == 0) { /* only_use_unicode_font */ vt_term_set_unicode_policy( screen->term, flag ? (vt_term_get_unicode_policy(screen->term) | ONLY_USE_UNICODE_FONT) & ~NOT_USE_UNICODE_FONT : vt_term_get_unicode_policy(screen->term) & ~ONLY_USE_UNICODE_FONT); } else if (strncmp(key, "not", 3) == 0) { /* not_use_unicode_font */ vt_term_set_unicode_policy( screen->term, flag ? (vt_term_get_unicode_policy(screen->term) | NOT_USE_UNICODE_FONT) & ~ONLY_USE_UNICODE_FONT : vt_term_get_unicode_policy(screen->term) & ~NOT_USE_UNICODE_FONT); } else { return 1; } usascii_font_cs_changed(screen, vt_term_get_encoding(screen->term)); } } else if (strcmp(key, "trim_trailing_newline_in_pasting") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { trim_trailing_newline_in_pasting = flag; } } else if (strcmp(key, "use_vertical_cursor") == 0) { int flag; if ((flag = true_or_false(value)) != -1) { screen->use_vertical_cursor = flag; } } else if (strcmp(key, "click_interval") == 0) { int interval; if (bl_str_to_int(&interval, value)) { ui_set_click_interval(interval); } } else if (strcmp(key, "emoji_path") == 0) { ui_emoji_set_path(value); } #ifdef ROTATABLE_DISPLAY else if (strcmp(key, "rotate_display") == 0) { ui_display_rotate(strcmp(value, "right") == 0 ? 1 : (strcmp(value, "left") == 0 ? -1 : 0)); } #endif #ifdef USE_CONSOLE else if (strcmp(key, "console_encoding") == 0) { vt_char_encoding_t encoding; if ((encoding = vt_get_char_encoding(value)) != VT_UNKNOWN_ENCODING) { ui_display_set_char_encoding(screen->window.disp, encoding); } } else if (strcmp(key, "console_sixel_colors") == 0) { ui_display_set_sixel_colors(screen->window.disp, value); } #endif else { return 0; } /* * processing_vtseq == -1 means loopback processing of vtseq. * If processing_vtseq is -1, it is not set 1 in start_vt100_cmd() * which is called from vt_term_write_loopback(). */ if (screen->processing_vtseq == -1) { char *msg; if ((msg = alloca(8 + strlen(key) + 1 + strlen(value) + 1))) { sprintf(msg, "Config: %s=%s", key, value); vt_term_show_message(screen->term, msg); /* * screen->processing_vtseq = 0 in * vt_term_show_message() -> stop_vt100_cmd(). */ screen->processing_vtseq = -1; } } return 1; } void ui_screen_reset_view(ui_screen_t *screen) { ui_color_manager_reload(screen->color_man); ui_window_set_bg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_BG_COLOR)); vt_term_set_modified_all_lines_in_screen(screen->term); font_size_changed(screen); ui_xic_font_set_changed(&screen->window); ui_window_update(&screen->window, UPDATE_SCREEN | UPDATE_CURSOR); } #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE void ui_screen_reload_color_cache(ui_screen_t *screen, int do_unload) { if (do_unload) { ui_color_cache_unload(screen->color_man->color_cache); } ui_color_manager_reload(screen->color_man); ui_window_set_fg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_FG_COLOR)); ui_xic_fg_color_changed(&screen->window); /* XXX should change scrollbar fg color */ ui_window_set_bg_color(&screen->window, ui_get_xcolor(screen->color_man, VT_BG_COLOR)); ui_xic_bg_color_changed(&screen->window); /* XXX should change scrollbar bg color */ } #endif ui_picture_modifier_t *ui_screen_get_picture_modifier(ui_screen_t *screen) { if (ui_picture_modifier_is_normal(&screen->pic_mod)) { return NULL; } else { return &screen->pic_mod; } } mlterm-3.8.9/uitoolkit/ui_screen.h010064400017600000144000000146171356600660700157230ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_SCREEN_H__ #define __UI_SCREEN_H__ #include /* FILE */ #include /* u_int/int8_t/size_t */ #include #include "ui_window.h" #include "ui_selection.h" #include "ui_shortcut.h" #include "ui_mod_meta_mode.h" #include "ui_bel_mode.h" #include "ui_sb_mode.h" #include "ui_im.h" #include "ui_picture.h" typedef struct ui_screen *ui_screen_ptr_t; typedef struct ui_system_event_listener { void *self; void (*open_screen)(void *, ui_screen_ptr_t); void (*split_screen)(void *, ui_screen_ptr_t, int, const char *); int (*close_screen)(void *, ui_screen_ptr_t, int); int (*next_screen)(void *, ui_screen_ptr_t); int (*prev_screen)(void *, ui_screen_ptr_t); int (*resize_screen)(void *, ui_screen_ptr_t, int, const char *); void (*open_pty)(void *, ui_screen_ptr_t, char *); void (*next_pty)(void *, ui_screen_ptr_t); void (*prev_pty)(void *, ui_screen_ptr_t); void (*close_pty)(void *, ui_screen_ptr_t, char *); void (*pty_closed)(void *, ui_screen_ptr_t); int (*mlclient)(void *, ui_screen_ptr_t, char *, FILE *); void (*font_config_updated)(void); void (*color_config_updated)(void); /* for debug */ void (*exit)(void *, int); } ui_system_event_listener_t; typedef struct ui_screen_scroll_event_listener { void *self; void (*bs_mode_entered)(void *); void (*bs_mode_exited)(void *); void (*scrolled_upward)(void *, u_int); void (*scrolled_downward)(void *, u_int); void (*scrolled_to)(void *, int); void (*log_size_changed)(void *, u_int); void (*line_height_changed)(void *, u_int); void (*change_fg_color)(void *, char *); char *(*fg_color)(void *); void (*change_bg_color)(void *, char *); char *(*bg_color)(void *); void (*change_view)(void *, char *); char *(*view_name)(void *); void (*transparent_state_changed)(void *, int, ui_picture_modifier_t *); ui_sb_mode_t (*sb_mode)(void *); void (*change_sb_mode)(void *, ui_sb_mode_t); void (*term_changed)(void *, u_int, u_int); void (*screen_color_changed)(void *); } ui_screen_scroll_event_listener_t; typedef struct ui_screen { ui_window_t window; ui_font_manager_t *font_man; ui_color_manager_t *color_man; vt_term_t *term; ui_selection_t sel; vt_screen_event_listener_t screen_listener; vt_xterm_event_listener_t xterm_listener; vt_config_event_listener_t config_listener; vt_pty_event_listener_t pty_listener; ui_sel_event_listener_t sel_listener; ui_xim_event_listener_t xim_listener; ui_im_event_listener_t im_listener; ui_shortcut_t *shortcut; char *mod_meta_key; u_int mod_meta_mask; u_int mod_ignore_mask; /* ui_mod_meta_mode_t */ int8_t mod_meta_mode; /* ui_bel_mode_t */ int8_t bel_mode; int8_t autoscroll_count; #ifdef FLICK_SCROLL int8_t grab_scroll; Time flick_time; int16_t flick_cur_y; int16_t flick_base_y; #endif int8_t is_preediting; u_int im_preedit_beg_row; u_int im_preedit_end_row; char *input_method; ui_im_t *im; /* * ui_window_t::{width|height} might contain right and bottom margins if window is maximized. * ui_screen_t::{width|height} never contains no margins. */ u_int width; u_int height; u_int screen_width_ratio; ui_system_event_listener_t *system_listener; ui_screen_scroll_event_listener_t *screen_scroll_listener; int scroll_cache_rows; int scroll_cache_boundary_start; int scroll_cache_boundary_end; char *pic_file_path; ui_picture_modifier_t pic_mod; ui_picture_t *bg_pic; ui_icon_picture_t *icon; int16_t prev_inline_pic; u_int16_t prev_mouse_report_col; u_int16_t prev_mouse_report_row; u_int8_t fade_ratio; int8_t line_space; int8_t receive_string_via_ucs; int8_t use_vertical_cursor; int8_t use_extended_scroll_shortcut; int8_t borderless; int8_t font_or_color_config_updated; /* 0x1 = font updated, 0x2 = color updated */ int8_t blink_wait; int8_t hide_underline; int8_t underline_offset; int8_t baseline_offset; int8_t processing_vtseq; int8_t anim_wait; int8_t hide_pointer; } ui_screen_t; void ui_exit_backscroll_by_pty(int flag); void ui_allow_change_shortcut(int flag); void ui_set_mod_meta_prefix(char *prefix); #define ui_free_mod_meta_prefix() ui_set_mod_meta_prefix(NULL) void ui_set_trim_trailing_newline_in_pasting(int trim); #ifdef USE_IM_CURSOR_COLOR void ui_set_im_cursor_color(char *color); #endif ui_screen_t *ui_screen_new(vt_term_t *term, ui_font_manager_t *font_man, ui_color_manager_t *color_man, u_int brightness, u_int contrast, u_int gamma, u_int alpha, u_int fade_ratio, ui_shortcut_t *shortcut, u_int screen_width_ratio, char *mod_meta_key, ui_mod_meta_mode_t mod_meta_mode, ui_bel_mode_t bel_mode, int receive_string_via_ucs, char *pic_file_path, int use_transbg, int use_vertical_cursor, int use_extended_scroll_shortcut, int borderless, int line_space, char *input_method, int allow_osc52, u_int hmargin, u_int vmargin, int hide_underline, int underline_offset, int baseline_offset); void ui_screen_destroy(ui_screen_t *screen); int ui_screen_attach(ui_screen_t *screen, vt_term_t *term); int ui_screen_attached(ui_screen_t *screen); vt_term_t *ui_screen_detach(ui_screen_t *screen); void ui_set_system_listener(ui_screen_t *screen, ui_system_event_listener_t *system_listener); void ui_set_screen_scroll_listener(ui_screen_t *screen, ui_screen_scroll_event_listener_t *screen_scroll_listener); void ui_screen_scroll_upward(ui_screen_t *screen, u_int size); void ui_screen_scroll_downward(ui_screen_t *screen, u_int size); void ui_screen_scroll_to(ui_screen_t *screen, int row); u_int ui_col_width(ui_screen_t *screen); u_int ui_line_height(ui_screen_t *screen); u_int ui_line_ascent(ui_screen_t *screen); int ui_screen_exec_cmd(ui_screen_t *screen, char *cmd); int ui_screen_set_config(ui_screen_t *screen, char *dev, char *key, char *value); void ui_screen_reset_view(ui_screen_t *screen); #ifdef WALL_PICTURE_SIXEL_REPLACES_SYSTEM_PALETTE void ui_screen_reload_color_cache(ui_screen_t *screen, int do_unload); #endif ui_picture_modifier_t *ui_screen_get_picture_modifier(ui_screen_t *screen); #endif mlterm-3.8.9/uitoolkit/ui_screen_manager.c010064400017600000144000001116611356600660700174050ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_screen_manager.h" #include /* sprintf */ #include /* memset/memcpy */ #include /* getenv */ #include /* getuid */ #include /* USE_WIN32API */ #ifndef USE_WIN32API #include /* getpwuid */ #endif #include #include /* bl_str_sep/bl_str_to_int/strdup */ #include /* bl_basename */ #include /* DIGIT_STR_LEN */ #include /* alloca/malloc/free */ #include #include #include /* u_int */ #include /* bl_arg_str_to_array */ #include #include #include #include #include "ui_layout.h" #include "ui_display.h" #if defined(USE_WIN32API) || defined(USE_LIBSSH2) #include "ui_connect_dialog.h" #endif #define MAX_SCREENS (MSU * max_screens_multiple) /* Default MAX_SCREENS is 32. */ #define MSU (8 * sizeof(dead_mask[0])) /* MAX_SCREENS_UNIT */ #if 0 #define __DEBUG #endif /* --- static variables --- */ static char *mlterm_version; static u_int max_screens_multiple; static u_int32_t *dead_mask; static ui_screen_t **screens; static u_int num_screens; static u_int depth; static u_int num_startup_screens; static ui_system_event_listener_t system_listener; static ui_main_config_t main_config; static ui_shortcut_t shortcut; /* --- static functions --- */ /* * Callbacks of vt_config_event_listener_t events. */ /* * Reload mlterm/main file and reset main_config. * Notice: Saved changes are not applied to the screens already opened. */ static void config_saved(void) { bl_conf_t *conf; char *argv[] = {"mlterm", NULL}; ui_main_config_final(&main_config); if ((conf = bl_conf_new()) == NULL) { return; } ui_prepare_for_main_config(conf); ui_main_config_init(&main_config, conf, 1, argv); bl_conf_destroy(conf); } static void font_config_updated(void) { u_int count; ui_font_cache_unload_all(); for (count = 0; count < num_screens; count++) { ui_screen_reset_view(screens[count]); } } static void color_config_updated(void) { u_int count; ui_color_cache_unload_all(); ui_display_reset_cmap(); for (count = 0; count < num_screens; count++) { ui_screen_reset_view(screens[count]); } } static vt_term_t *create_term_intern(void) { vt_term_t *term; if ((term = vt_create_term( main_config.term_type, main_config.cols, main_config.rows, main_config.tab_size, main_config.num_log_lines, main_config.encoding, main_config.is_auto_encoding, main_config.use_auto_detect, main_config.logging_vt_seq, main_config.unicode_policy, main_config.col_size_of_width_a, main_config.use_char_combining, main_config.use_multi_col_char, main_config.use_ctl, main_config.bidi_mode, main_config.bidi_separators, main_config.use_dynamic_comb, main_config.bs_mode, main_config.vertical_mode, main_config.use_local_echo, main_config.title, main_config.icon_name, main_config.use_ansi_colors, main_config.alt_color_mode, main_config.use_ot_layout, main_config.blink_cursor ? CS_BLINK|CS_BLOCK : CS_BLOCK, main_config.ignore_broadcasted_chars)) == NULL) { return NULL; } if (main_config.icon_path) { vt_term_set_icon_path(term, main_config.icon_path); } if (main_config.unlimit_log_size) { vt_term_unlimit_log_size(term); } return term; } static int open_pty_intern(vt_term_t *term, char *cmd_path, char **cmd_argv, ui_window_t *win, int show_dialog) { char *display; Window window; u_int width_pix; u_int height_pix; char *env[7]; /* MLTERM,TERM,WINDOWID,WAYLAND_DISPLAY,DISPLAY,COLORFGBG,NULL */ char **env_p; char wid_env[9 + DIGIT_STR_LEN(Window) + 1]; /* "WINDOWID="(9) + [32bit digit] + NULL(1) */ char *disp_env; char *term_env; char *uri; char *pass; #ifdef USE_LIBSSH2 char *privkey; #endif int ret; display = win->disp->name; window = win->my_window; if (vt_term_get_vertical_mode(term)) { width_pix = win->height * 100 / ((ui_screen_t*)win)->screen_width_ratio; height_pix = win->width; } else { width_pix = win->width * 100 / ((ui_screen_t*)win)->screen_width_ratio; height_pix = win->height; } env_p = env; *(env_p++) = mlterm_version; sprintf(wid_env, "WINDOWID=%ld", window); *(env_p++) = wid_env; #ifdef USE_WAYLAND /* "WAYLAND_DISPLAY="(16) + NULL(1) */ if (display && (disp_env = alloca(16 + strlen(display) + 1))) { sprintf(disp_env, "WAYLAND_DISPLAY=%s", display); *(env_p++) = disp_env; } *(env_p++) = "DISPLAY=:0.0"; #else /* "DISPLAY="(8) + NULL(1) */ if (display && (disp_env = alloca(8 + strlen(display) + 1))) { sprintf(disp_env, "DISPLAY=%s", display); *(env_p++) = disp_env; } #endif /* "TERM="(5) + NULL(1) */ if (main_config.term_type && (term_env = alloca(5 + strlen(main_config.term_type) + 1))) { sprintf(term_env, "TERM=%s", main_config.term_type); *(env_p++) = term_env; } *(env_p++) = "COLORFGBG=default;default"; /* NULL terminator */ *env_p = NULL; uri = NULL; pass = NULL; #ifdef USE_LIBSSH2 privkey = main_config.private_key; #endif #if defined(USE_WIN32API) || defined(USE_LIBSSH2) if (show_dialog || main_config.default_server) { char *default_server_dup; char *uri_dup; char *user; char *host; char *port; char *encoding = NULL; char *exec_cmd = NULL; int x11_fwd; void *session; x11_fwd = main_config.use_x11_forwarding; #ifdef USE_LIBSSH2 if (!show_dialog && main_config.default_server && (default_server_dup = alloca(strlen(main_config.default_server) + 1)) && bl_parse_uri(NULL, &user, &host, &port, NULL, &encoding, strcpy(default_server_dup, main_config.default_server)) && (session = vt_search_ssh_session(host, port, user))) { uri = strdup(main_config.default_server); pass = strdup(""); if (x11_fwd) { vt_pty_ssh_set_use_x11_forwarding(session, x11_fwd); } } else #endif if (!ui_connect_dialog(&uri, &pass, &exec_cmd, &privkey, &x11_fwd, display, window, main_config.default_server)) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Connect dialog is canceled.\n"); #endif /* * open_screen_intern() calls close_screen_intern() if this fuction * returns 0, then this thread will be terminated on Haiku. * (If mlclient --serv ... is executed and the connect dialog is cancelled, * the screen where mlclient is executed also exits.) * So don't return 0 even if the connect dialog is cancelled. * * (vt_term_open_pty() below never returns 0 because OPEN_PTY_ASYNC * is defined on Haiku.) */ #ifndef USE_BEOS if (vt_get_all_terms(NULL) > 1) { return 0; } #endif } else if ((uri_dup = alloca(strlen(uri) + 1))) { bl_parse_uri(NULL, &user, &host, &port, NULL, &encoding, strcpy(uri_dup, uri)); #ifdef USE_LIBSSH2 vt_pty_ssh_set_use_x11_forwarding(vt_search_ssh_session(host, port, user), x11_fwd); #endif } else { /* XXX Not recovering error. */ return 0; } #ifdef __DEBUG bl_debug_printf("Connect dialog: URI %s pass %s\n", uri, pass); #endif if (encoding) { if (vt_term_is_attached(term)) { /* * Don't use vt_term_change_encoding() here because * encoding change could cause special visual change * which should update the state of ui_screen_t. */ char *seq; size_t len; if ((seq = alloca((len = 16 + strlen(encoding) + 2)))) { sprintf(seq, "\x1b]5379;encoding=%s\x07", encoding); vt_term_write_loopback(term, seq, len - 1); } } else { vt_term_change_encoding(term, vt_get_char_encoding(encoding)); } } if (exec_cmd) { char *tmp = exec_cmd; if ((exec_cmd = alloca(strlen(exec_cmd) + 1))) { strcpy(exec_cmd, tmp); } free(tmp); if ((tmp = bl_argv_alloca(exec_cmd))) { int argc; if (bl_arg_str_to_array((char**)tmp, &argc, exec_cmd)) { cmd_argv = (char**)tmp; cmd_path = cmd_argv[0]; } } } } #endif #if 0 if (cmd_argv) { char **p; bl_debug_printf(BL_DEBUG_TAG " %s", cmd_path); p = cmd_argv; while (*p) { bl_msg_printf(" %s", *p); p++; } bl_msg_printf("\n"); } #endif /* * If cmd_path and pass are NULL, set default shell as cmd_path. * If uri is not NULL (= connecting to ssh/telnet/rlogin etc servers), * cmd_path is not changed. */ if (!uri && !cmd_path) { #ifdef __APPLE__ char *user; if ((user = getenv("USER")) && (cmd_argv = alloca(sizeof(char *) * 4))) { cmd_argv[0] = cmd_path = "login"; cmd_argv[1] = "-fp"; cmd_argv[2] = user; cmd_argv[3] = NULL; } else #endif { /* * SHELL env var -> /etc/passwd -> /bin/sh */ if ((cmd_path = getenv("SHELL")) == NULL || *cmd_path == '\0') { #ifndef USE_WIN32API struct passwd *pw; if ((pw = getpwuid(getuid())) == NULL || *(cmd_path = pw->pw_shell) == '\0') #endif { cmd_path = "/bin/sh"; } } } } /* * Set cmd_argv by cmd_path. */ if (cmd_path && !cmd_argv) { char *cmd_file; cmd_file = bl_basename(cmd_path); if ((cmd_argv = alloca(sizeof(char *) * 2)) == NULL) { return 0; } /* 2 = `-' and NULL */ if ((cmd_argv[0] = alloca(strlen(cmd_file) + 2)) == NULL) { return 0; } if (main_config.use_login_shell) { sprintf(cmd_argv[0], "-%s", cmd_file); } else { strcpy(cmd_argv[0], cmd_file); } cmd_argv[1] = NULL; } ret = vt_term_open_pty(term, cmd_path, cmd_argv, env, uri ? uri : display, main_config.work_dir, pass, #ifdef USE_LIBSSH2 main_config.public_key, privkey, #else NULL, NULL, #endif width_pix, height_pix); #if defined(USE_WIN32API) || defined(USE_LIBSSH2) if (uri) { if (ret && bl_compare_str(uri, main_config.default_server) != 0) { free(main_config.default_server); main_config.default_server = uri; } else { free(uri); } free(pass); if (privkey != main_config.private_key) { free(privkey); } } #endif return ret; } #ifndef NO_IMAGE static vt_char_t *get_picture_data(void *p, char *file_path, int *num_cols /* can be 0 */, int *num_rows /* can be 0 */, int *num_cols_small /* set only if drcs_sixel is 1. */, int *num_rows_small /* set only if drcs_sixel is 1. */, u_int32_t **sixel_palette, int keep_aspect, int drcs_sixel) { vt_char_t *data; if (num_screens > 0) { vt_term_t *orig_term; orig_term = screens[0]->term; screens[0]->term = p; /* XXX */ data = (*screens[0]->xterm_listener.get_picture_data)(screens[0]->xterm_listener.self, file_path, num_cols, num_rows, num_cols_small, num_rows_small, sixel_palette, 0, drcs_sixel); screens[0]->term = orig_term; } else { data = NULL; } return data; } static vt_term_t *detach_screen(ui_screen_t *screen) { vt_term_t *term; if ((term = ui_screen_detach(screen))) { vt_xterm_event_listener_t *listener; if (!(listener = vt_term_get_user_data(term, term))) { if (!(listener = calloc(1, sizeof(vt_xterm_event_listener_t)))) { return term; } listener->self = term; listener->get_picture_data = get_picture_data; vt_term_set_user_data(term, term, listener); } /* XXX */ term->parser->xterm_listener = listener; } return term; } #define ui_screen_detach(screen) detach_screen(screen) #endif #ifdef USE_WIN32GUI static void close_screen_win32(ui_screen_t *screen) { int is_orphan; if (UI_SCREEN_TO_LAYOUT(screen) && ui_layout_remove_child(UI_SCREEN_TO_LAYOUT(screen), screen)) { is_orphan = 1; } else { is_orphan = 0; /* * XXX Hack * In case SendMessage(WM_CLOSE) causes WM_KILLFOCUS * and operates screen->term which was already destroyed. * (see window_unfocused()) */ screen->window.window_unfocused = NULL; } SendMessage(ui_get_root_window(&screen->window)->my_window, WM_CLOSE, 0, 0); if (is_orphan && screen->window.window_destroyed) { (*screen->window.window_destroyed)(&screen->window); } } #endif static void close_screen_intern(ui_screen_t *screen) { ui_window_t *root; ui_display_t *disp; if (UI_SCREEN_TO_LAYOUT(screen)) { ui_layout_remove_child(UI_SCREEN_TO_LAYOUT(screen), screen); /* ui_get_root_window() below doesn't return ui_layout. */ } ui_screen_detach(screen); ui_font_manager_destroy(screen->font_man); ui_color_manager_destroy(screen->color_man); root = ui_get_root_window(&screen->window); disp = root->disp; if (!ui_display_remove_root(disp, root)) { ui_window_unmap(root); ui_window_final(root); } else if (disp->num_roots == 0) { ui_display_close(disp); } } static ui_screen_t *open_screen_intern(char *disp_name, vt_term_t *term, ui_layout_t *layout, int horizontal, const char *sep, int show_dialog) { ui_display_t *disp; ui_screen_t *screen; ui_font_manager_t *font_man; ui_color_manager_t *color_man; ui_window_t *root; ef_charset_t usascii_font_cs; void *p; /* * these are dynamically allocated. */ disp = NULL; font_man = NULL; color_man = NULL; screen = NULL; root = NULL; if (MAX_SCREENS <= num_screens) { return NULL; } if (!term) { if ((!layout || (term = vt_get_detached_term(NULL)) == NULL) && (term = create_term_intern()) == NULL) { return NULL; } } if (layout) { disp = layout->window.disp; } else if ((disp = ui_display_open(disp_name, depth)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ui_display_open failed.\n"); #endif goto error; } if (main_config.unicode_policy & NOT_USE_UNICODE_FONT || main_config.iso88591_font_for_usascii) { usascii_font_cs = ui_get_usascii_font_cs(VT_ISO8859_1); } else if (main_config.unicode_policy & ONLY_USE_UNICODE_FONT) { usascii_font_cs = ui_get_usascii_font_cs(VT_UTF8); } else { usascii_font_cs = ui_get_usascii_font_cs(vt_term_get_encoding(term)); } if ((font_man = ui_font_manager_new(disp->display, main_config.type_engine, main_config.font_present, main_config.font_size, usascii_font_cs, main_config.step_in_changing_font_size, main_config.letter_space, main_config.use_bold_font, main_config.use_italic_font)) == NULL) { const char *msg_fmt = "No fonts for %s"; char *msg; char *name; if (!(name = ui_get_charset_name(usascii_font_cs))) { name = "US-ASCII"; } if ((msg = alloca(13 + strlen(name) + 1))) { sprintf(msg, msg_fmt, name); bl_dialog(BL_DIALOG_ALERT, msg); } goto error; } if ((color_man = ui_color_manager_new( disp, main_config.fg_color, main_config.bg_color, main_config.cursor_fg_color, main_config.cursor_bg_color, main_config.bd_color, main_config.ul_color, main_config.bl_color, main_config.rv_color, main_config.it_color, main_config.co_color)) == NULL) { goto error; } if ((screen = ui_screen_new( term, font_man, color_man, main_config.brightness, main_config.contrast, main_config.gamma, main_config.alpha, main_config.fade_ratio, &shortcut, main_config.screen_width_ratio, main_config.mod_meta_key, main_config.mod_meta_mode, main_config.bel_mode, main_config.receive_string_via_ucs, main_config.pic_file_path, main_config.use_transbg, main_config.use_vertical_cursor, main_config.use_extended_scroll_shortcut, main_config.borderless, main_config.line_space, main_config.input_method, main_config.allow_osc52, main_config.hmargin, main_config.vmargin, main_config.hide_underline, main_config.underline_offset, main_config.baseline_offset)) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ui_screen_new() failed.\n"); #endif goto error; } /* Override config event listener. */ screen->config_listener.saved = config_saved; ui_set_system_listener(screen, &system_listener); if (layout) { if (!ui_layout_add_child(layout, screen, horizontal, sep)) { layout = NULL; goto error; } root = &layout->window; } else { if (main_config.use_mdi && (layout = ui_layout_new(screen, main_config.scrollbar_view_name, main_config.sb_fg_color, main_config.sb_bg_color, main_config.sb_mode, main_config.layout_hmargin, main_config.layout_vmargin))) { root = &layout->window; } else { root = &screen->window; } if (!ui_display_show_root(disp, root, main_config.x, main_config.y, main_config.geom_hint, main_config.app_name, main_config.parent_window)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ui_display_show_root() failed.\n"); #endif goto error; } } if ((p = realloc(screens, sizeof(ui_screen_t *) * (num_screens + 1))) == NULL) { /* * XXX * After ui_display_show_root() screen is not destroyed correctly by * 'goto error'(see following error handling in open_pty_intern), * but I don't know how to do. */ goto error; } screens = p; /* * New screen is successfully created here except vt_pty. */ if (vt_term_pty_is_opened(term)) { #if 0 /* mlclient /dev/... -e foo */ if (main_config.cmd_argv) { int count; for (count = 0; main_config.cmd_argv[count]; count++) { vt_term_write(term, main_config.cmd_argv[count], strlen(main_config.cmd_argv[count]), 0); vt_term_write(term, " ", 1, 0); } vt_term_write(term, "\n", 1, 0); } #endif } else { if (!open_pty_intern(term, main_config.cmd_path, main_config.cmd_argv, &screen->window, show_dialog)) { ui_screen_detach(screen); vt_destroy_term(term); #ifdef USE_WIN32GUI screens[num_screens++] = screen; close_screen_win32(screen); #else close_screen_intern(screen); #endif return NULL; } if (main_config.init_str) { vt_term_write(term, main_config.init_str, strlen(main_config.init_str)); } } /* Don't add screen to screens before "return NULL" above unless USE_WIN32GUI. */ screens[num_screens++] = screen; return screen; error: if (font_man) { ui_font_manager_destroy(font_man); } if (color_man) { ui_color_manager_destroy(color_man); } if (!root || !ui_display_remove_root(disp, root)) { /* * If root is still NULL or is not registered to disp yet. */ if (screen) { ui_screen_destroy(screen); } if (layout) { ui_layout_destroy(layout); } } if (disp && disp->num_roots == 0) { ui_display_close(disp); } vt_destroy_term(term); return NULL; } /* * callbacks of ui_system_event_listener_t */ /* * EXIT_PROGRAM shortcut calls this at last. * this is for debugging. */ #ifdef DEBUG #include "../main/main_loop.h" static void __exit(void *p, int status) { #ifdef USE_WIN32GUI u_int count; for (count = 0; count < num_screens; count++) { SendMessage(ui_get_root_window(&screens[count]->window), WM_CLOSE, 0, 0); } #endif #if 1 bl_mem_dump_all(); #endif main_loop_final(); #if defined(USE_WIN32API) && defined(USE_LIBSSH2) WSACleanup(); #endif bl_msg_printf("reporting unfreed memories --->\n"); bl_mem_free_all(); bl_dl_close_all(); exit(status); } #endif static void open_pty(void *p, ui_screen_t *screen, char *dev) { vt_term_t *new; if (dev) { if ((new = vt_get_detached_term(dev)) == NULL) { return; } } else { vt_char_encoding_t encoding; #if defined(USE_WIN32API) || defined(USE_LIBSSH2) char *default_server; char *new_cmd_line; char *new_cmd_line_dup; char *cmd_path; char **cmd_argv; #endif int ret; encoding = main_config.encoding; main_config.encoding = vt_term_get_encoding(screen->term); if ((new = create_term_intern()) == NULL) { main_config.encoding = encoding; return; } #if defined(USE_WIN32API) || defined(USE_LIBSSH2) if (!main_config.show_dialog) { default_server = main_config.default_server; main_config.default_server = vt_term_get_uri(screen->term); } if ((new_cmd_line = vt_term_get_cmd_line(screen->term)) && (new_cmd_line_dup = alloca(strlen(new_cmd_line) + 1))) { int argc; cmd_path = main_config.cmd_path; cmd_argv = main_config.cmd_argv; if ((main_config.cmd_argv = bl_argv_alloca(new_cmd_line)) && bl_arg_str_to_array(main_config.cmd_argv, &argc, strcpy(new_cmd_line_dup, new_cmd_line))) { main_config.cmd_path = main_config.cmd_argv[0]; } else { main_config.cmd_argv = cmd_argv; } } #endif ret = open_pty_intern(new, main_config.cmd_path, main_config.cmd_argv, &screen->window, #if defined(USE_WIN32API) || defined(USE_LIBSSH2) main_config.show_dialog #else 0 #endif ); main_config.encoding = encoding; #if defined(USE_WIN32API) || defined(USE_LIBSSH2) if (!main_config.show_dialog) { main_config.default_server = default_server; } if (new_cmd_line) { main_config.cmd_path = cmd_path; main_config.cmd_argv = cmd_argv; } #endif if (!ret) { vt_destroy_term(new); return; } } ui_screen_detach(screen); ui_screen_attach(screen, new); } static void next_pty(void *p, ui_screen_t *screen) { vt_term_t *old; vt_term_t *new; if ((old = ui_screen_detach(screen)) == NULL) { return; } if ((new = vt_next_term(old)) == NULL) { ui_screen_attach(screen, old); } else { ui_screen_attach(screen, new); } } static void prev_pty(void *p, ui_screen_t *screen) { vt_term_t *old; vt_term_t *new; if ((old = ui_screen_detach(screen)) == NULL) { return; } if ((new = vt_prev_term(old)) == NULL) { ui_screen_attach(screen, old); } else { ui_screen_attach(screen, new); } } static void close_pty(void *p, ui_screen_t *screen, char *dev) { vt_term_t *term; if (dev) { if ((term = vt_get_term(dev)) == NULL) { return; } } else { term = screen->term; } /* * Don't call vt_destroy_term directly, because close_pty() can be called * in the context of parsing vt100 sequence. */ bl_trigger_sig_child(vt_term_get_child_pid(term)); } static void pty_closed(void *p, ui_screen_t *screen /* screen->term was already destroyed. */ ) { int count; #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " pty which is attached to screen %p is closed.\n", screen); #endif for (count = num_screens - 1; count >= 0; count--) { if (screen == screens[count]) { vt_term_t *term; if ((term = vt_get_detached_term(NULL)) == NULL) { #ifdef COCOA_TOUCH if (vt_get_all_terms(NULL) == 0 && (term = create_term_intern())) { if (open_pty_intern(term, main_config.cmd_path, main_config.cmd_argv, &screen->window, #ifdef USE_LIBSSH2 main_config.show_dialog #else 0 #endif )) { ui_screen_attach(screen, term); return; } else { vt_destroy_term(term); } } #endif #ifdef __DEBUG bl_debug_printf(" no detached term. closing screen.\n"); #endif #ifdef USE_WIN32GUI close_screen_win32(screen); #else screens[count] = screens[--num_screens]; close_screen_intern(screen); #endif } else { #ifdef __DEBUG bl_debug_printf(" using detached term.\n"); #endif ui_screen_attach(screen, term); } return; } } } static void open_cloned_screen(ui_screen_t *cur_screen, ui_layout_t *layout, int horizontal, const char *sep, int show_dialog) { vt_char_encoding_t encoding; #if defined(USE_WIN32API) || defined(USE_LIBSSH2) char *default_server; char *new_cmd_line; char *new_cmd_line_dup; char *cmd_path; char **cmd_argv; #endif encoding = main_config.encoding; main_config.encoding = vt_term_get_encoding(cur_screen->term); #if defined(USE_WIN32API) || defined(USE_LIBSSH2) if (!show_dialog) { default_server = main_config.default_server; main_config.default_server = vt_term_get_uri(cur_screen->term); } if ((new_cmd_line = vt_term_get_cmd_line(cur_screen->term)) && (new_cmd_line_dup = alloca(strlen(new_cmd_line) + 1))) { int argc; cmd_path = main_config.cmd_path; cmd_argv = main_config.cmd_argv; if ((main_config.cmd_argv = bl_argv_alloca(new_cmd_line)) && bl_arg_str_to_array(main_config.cmd_argv, &argc, strcpy(new_cmd_line_dup, new_cmd_line))) { main_config.cmd_path = main_config.cmd_argv[0]; } else { main_config.cmd_argv = cmd_argv; } } #endif open_screen_intern(cur_screen->window.disp->name, NULL, layout, horizontal, sep, #if defined(USE_WIN32API) || defined(USE_LIBSSH2) main_config.show_dialog #else 0 #endif ); main_config.encoding = encoding; #if defined(USE_WIN32API) || defined(USE_LIBSSH2) if (!show_dialog) { main_config.default_server = default_server; } if (new_cmd_line) { main_config.cmd_path = cmd_path; main_config.cmd_argv = cmd_argv; } #endif } static void open_screen(void *p, ui_screen_t *screen /* Screen which triggers this event. */ ) { open_cloned_screen(screen, NULL, 0, NULL, #if defined(USE_WIN32API) || defined(USE_LIBSSH2) main_config.show_dialog #else 0 #endif ); } static void split_screen(void *p, ui_screen_t *screen, /* Screen which triggers this event. */ int horizontal, const char *sep) { if (UI_SCREEN_TO_LAYOUT(screen)) { open_cloned_screen(screen, UI_SCREEN_TO_LAYOUT(screen), horizontal, sep, #if defined(USE_WIN32API) || defined(USE_LIBSSH2) main_config.show_dialog #else 0 #endif ); } } static int close_screen(void *p, ui_screen_t *screen, /* Screen which triggers this event. */ int force) { u_int count; if (!force && (!UI_SCREEN_TO_LAYOUT(screen) || ui_layout_has_one_child(UI_SCREEN_TO_LAYOUT(screen)))) { return 0; } for (count = 0; count < num_screens; count++) { u_int idx; if (screen != screens[count]) { continue; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " screen %p is registered to be closed.\n", screen); #endif #ifdef USE_BEOS /* * Don't use ui_close_dead_screens(). * It doesn't clear dead_mask because BWindow::Quit() called from * close_screen_intern() exists the current thread. */ screens[count] = screens[--num_screens]; close_screen_intern(screen); #else idx = count / MSU; /* count / 8 */ dead_mask[idx] |= (1 << (count - MSU * idx)); #endif break; } return 1; } static int next_screen(void *self, ui_screen_t *screen) { if (UI_SCREEN_TO_LAYOUT(screen)) { return ui_layout_switch_screen(UI_SCREEN_TO_LAYOUT(screen), 0); } else { return 0; } } static int prev_screen(void *self, ui_screen_t *screen) { if (UI_SCREEN_TO_LAYOUT(screen)) { return ui_layout_switch_screen(UI_SCREEN_TO_LAYOUT(screen), 1); } else { return 0; } } static int resize_screen(void *self, ui_screen_t *screen, int horizontal, const char *size) { if (UI_SCREEN_TO_LAYOUT(screen)) { return ui_layout_resize(UI_SCREEN_TO_LAYOUT(screen), screen, horizontal, size); } else { return 0; } } static int mlclient(void *self, ui_screen_t *screen, char *args, FILE *fp /* Stream to output response of mlclient. */ ) { char **argv; int argc; if (!(argv = bl_argv_alloca(args)) || !bl_arg_str_to_array(argv, &argc, args)) { return 0; } #ifdef __DEBUG { int i; for (i = 0; i < argc; i++) { bl_msg_printf("%s\n", argv[i]); } } #endif if (argc == 0 #if defined(USE_FRAMEBUFFER) || screen == NULL #endif ) { return 0; } if (argc == 2 && (strcmp(argv[1], "-P") == 0 || strcmp(argv[1], "--ptylist") == 0)) { /* * mlclient -P or mlclient --ptylist */ vt_term_t **terms; u_int num; int count; num = vt_get_all_terms(&terms); for (count = 0; count < num; count++) { fprintf(fp, "#%s", vt_term_get_slave_name(terms[count])); if (vt_term_window_name(terms[count])) { fprintf(fp, "(whose title is %s)", vt_term_window_name(terms[count])); } if (vt_term_is_attached(terms[count])) { fprintf(fp, " is active:)\n"); } else { fprintf(fp, " is sleeping.zZ\n"); } } } else { bl_conf_t *conf; ui_main_config_t orig_conf; char *pty; int horizontal; char *sep; if (argc >= 2 && *(argv[1]) != '-') { /* * mlclient [dev] [options...] */ pty = argv[1]; argv[1] = argv[0]; argv = &argv[1]; argc--; } else { pty = NULL; } if ((conf = bl_conf_new()) == NULL) { return 0; } ui_prepare_for_main_config(conf); bl_conf_add_opt(conf, '\0', "hsep", 0, "hsep", ""); bl_conf_add_opt(conf, '\0', "vsep", 0, "vsep", ""); if (!bl_conf_parse_args(conf, &argc, &argv, 1)) { bl_conf_destroy(conf); return 0; } if (screen && UI_SCREEN_TO_LAYOUT(screen)) { char *p; if ((p = bl_conf_get_value(conf, "hsep"))) { horizontal = 1; } else if ((p = bl_conf_get_value(conf, "vsep"))) { horizontal = 0; } else { sep = NULL; goto end_check_sep; } if ((sep = alloca(strlen(p) + 1))) { strcpy(sep, p); } } else { sep = NULL; } end_check_sep: orig_conf = main_config; ui_main_config_init(&main_config, conf, argc, argv); bl_conf_destroy(conf); if (screen) { if (sep) { open_screen_intern(screen->window.disp->name, NULL, UI_SCREEN_TO_LAYOUT(screen), horizontal, sep, #if defined(USE_WIN32API) || defined(USE_LIBSSH2) main_config.show_dialog #else 0 #endif ); } else { vt_term_t *term; if ((term = create_term_intern())) { if (!open_pty_intern(term, main_config.cmd_path, main_config.cmd_argv, &screen->window, #if defined(USE_WIN32API) || defined(USE_LIBSSH2) main_config.show_dialog #else 0 #endif )) { vt_destroy_term(term); } else { ui_screen_detach(screen); ui_screen_attach(screen, term); } } } } else { vt_term_t *term = NULL; #ifdef USE_CONSOLE if (*main_config.disp_name) #endif { if ((pty && !(term = vt_get_detached_term(pty))) || !open_screen_intern(main_config.disp_name, term, NULL, 0, 0, 0)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " open_screen_intern() failed.\n"); #endif } } } ui_main_config_final(&main_config); main_config = orig_conf; } /* Flush fp stream because write(2) is called after this function is called. */ fflush(fp); return 1; } /* --- global functions --- */ int ui_screen_manager_init(char *_mlterm_version, u_int _depth, u_int _max_screens_multiple, u_int _num_startup_screens, ui_main_config_t *_main_config) { mlterm_version = _mlterm_version; depth = _depth; main_config = *_main_config; max_screens_multiple = _max_screens_multiple; if ((dead_mask = calloc(sizeof(*dead_mask), max_screens_multiple)) == NULL) { return 0; } if (_num_startup_screens > MAX_SCREENS) { num_startup_screens = MAX_SCREENS; } else { num_startup_screens = _num_startup_screens; } if (!vt_term_manager_init(max_screens_multiple)) { free(dead_mask); return 0; } vt_color_config_init(); ui_shortcut_init(&shortcut); /* BACKWARD COMPAT (3.1.7 or before) */ #if 1 { size_t count; char key0[] = "Control+Button1"; char key1[] = "Control+Button2"; char key2[] = "Control+Button3"; char key3[] = "Button3"; char *keys[] = {key0, key1, key2, key3}; for (count = 0; count < sizeof(keys) / sizeof(keys[0]); count++) { if (main_config.shortcut_strs[count]) { ui_shortcut_parse(&shortcut, keys[count], main_config.shortcut_strs[count]); } } } #endif if (*main_config.disp_name) { /* * setting DISPLAY environment variable to match "--display" option. */ char *env; #ifdef USE_WAYLAND if ((env = malloc(16 + strlen(main_config.disp_name) + 1))) { sprintf(env, "WAYLAND_DISPLAY=%s", main_config.disp_name); putenv(env); } #else if ((env = malloc(8 + strlen(main_config.disp_name) + 1))) { sprintf(env, "DISPLAY=%s", main_config.disp_name); putenv(env); } #endif } system_listener.self = NULL; #ifdef DEBUG system_listener.exit = __exit; #else system_listener.exit = NULL; #endif #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF system_listener.open_screen = NULL; #else system_listener.open_screen = open_screen; #endif system_listener.split_screen = split_screen; system_listener.close_screen = close_screen; system_listener.next_screen = next_screen; system_listener.prev_screen = prev_screen; system_listener.resize_screen = resize_screen; system_listener.open_pty = open_pty; system_listener.next_pty = next_pty; system_listener.prev_pty = prev_pty; system_listener.close_pty = close_pty; system_listener.pty_closed = pty_closed; system_listener.mlclient = mlclient; system_listener.font_config_updated = font_config_updated; system_listener.color_config_updated = color_config_updated; return 1; } void ui_screen_manager_final(void) { u_int count; ui_main_config_final(&main_config); for (count = 0; count < num_screens; count++) { close_screen_intern(screens[count]); } free(screens); free(dead_mask); vt_term_manager_final(); ui_display_close_all(); vt_color_config_final(); ui_shortcut_final(&shortcut); } #ifdef __ANDROID__ static int suspended; int ui_screen_manager_suspend(void) { u_int count; ui_close_dead_screens(); for (count = 0; count < num_screens; count++) { close_screen_intern(screens[count]); } free(screens); screens = NULL; num_screens = 0; ui_display_close_all(); suspended = 1; return 1; } #endif u_int ui_screen_manager_startup(void) { u_int count; u_int num_started; num_started = 0; #ifdef __ANDROID__ if (suspended) { /* reload ~/.mlterm/main. */ config_saved(); ui_shortcut_final(&shortcut); ui_shortcut_init(&shortcut); vt_color_config_final(); vt_color_config_init(); } #endif for (count = 0; count < num_startup_screens; count++) { if (!open_screen_intern(main_config.disp_name, vt_get_detached_term(NULL), NULL, 0, 0, #if defined(USE_LIBSSH2) && defined(__ANDROID__) !start_with_local_pty #elif defined(USE_WIN32API) 1 /* show dialog */ #else 0 #endif )) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " open_screen_intern() failed.\n"); #endif } else { num_started++; } } return num_started; } void ui_close_dead_screens(void) { if (num_screens > 0) { int idx; for (idx = (num_screens - 1) / MSU; idx >= 0; idx--) { if (dead_mask[idx]) { int count; for (count = MSU - 1; count >= 0; count--) { if (dead_mask[idx] & (0x1 << count)) { ui_screen_t *screen; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " closing screen %d-%d.", idx, count); #endif screen = screens[idx * MSU + count]; screens[idx * MSU + count] = screens[--num_screens]; close_screen_intern(screen); #ifdef __DEBUG bl_msg_printf(" => Finished. Rest %d\n", num_screens); #endif } } memset(&dead_mask[idx], 0, sizeof(dead_mask[idx])); } } } } u_int ui_get_all_screens(ui_screen_t ***_screens) { if (_screens) { *_screens = screens; } return num_screens; } int ui_mlclient(char *args, FILE *fp) { return mlclient(NULL, NULL, args, fp); } mlterm-3.8.9/uitoolkit/ui_screen_manager.h010064400017600000144000000011321356600660700174010ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_SCREEN_MANAGER_H__ #define __UI_SCREEN_MANAGER_H__ #include /* FILE */ #include "ui_screen.h" #include "ui_main_config.h" int ui_screen_manager_init(char *mlterm_version, u_int depth, u_int max_screens_multiple, u_int num_startup_screens, ui_main_config_t *main_config); void ui_screen_manager_final(void); u_int ui_screen_manager_startup(void); void ui_close_dead_screens(void); u_int ui_get_all_screens(ui_screen_t*** _screens); int ui_mlclient(char *args, FILE* fp); #endif mlterm-3.8.9/uitoolkit/ui_scrollbar.c010064400017600000144000000631721356600660700164220ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_scrollbar.h" #include /* abs */ #include #include /* free */ #include /* strdup */ #include "ui_sb_view_factory.h" #define HEIGHT_MARGIN(sb) ((sb)->top_margin + (sb)->bottom_margin) #define IS_TOO_SMALL(sb) ((sb)->window.height <= HEIGHT_MARGIN(sb)) #ifdef DEBUG #define MAX_BAR_HEIGHT(sb) \ (IS_TOO_SMALL(sb) \ ? 0 & bl_debug_printf(BL_DEBUG_TAG \ " scroll bar is too small , but MAX_BAR_HEIGHT " \ "was refered.\n") \ : (sb)->window.height - HEIGHT_MARGIN(sb)) #else #define MAX_BAR_HEIGHT(sb) ((sb)->window.height - HEIGHT_MARGIN(sb)) #endif #if 0 #define __DEBUG #endif /* * For ui_window_update() */ enum { UPDATE_UPBUTTON = 0x1, UPDATE_DOWNBUTTON = 0x2, UPDATE_BUTTON = UPDATE_UPBUTTON | UPDATE_DOWNBUTTON, UPDATE_SCROLLBAR = 0x4, FGCOLOR_CHANGED = 0x8, BGCOLOR_CHANGED = 0x10, }; /* --- static functions --- */ static void set_redraw_area(ui_scrollbar_t *sb, int y, /* Should exclude sb->top_margin. */ u_int height /* Should be over 0. Can be over sb->window.height - sb->bottom_margin. */ ) { if (sb->redraw_height == 0) { sb->redraw_y = y; sb->redraw_height = height; } else { if (y < sb->redraw_y) { sb->redraw_height += (sb->redraw_y - y); sb->redraw_y = y; } if (y + height > sb->redraw_y + sb->redraw_height) { sb->redraw_height = y + height - sb->redraw_y; } } } /* * Don't call directly draw_xxx functions. * Call ui_window_update() instead. */ static void draw_scrollbar(ui_scrollbar_t *sb) { if (IS_TOO_SMALL(sb)) { ui_window_blank(&sb->window); return; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " updating scrollbar from %d height %d\n", sb->bar_top_y, sb->bar_height); #endif if (sb->view->draw_scrollbar) { (*sb->view->draw_scrollbar)(sb->view, sb->top_margin + sb->bar_top_y, sb->bar_height); } } /* * Don't call directly draw_xxx functions. * Call ui_window_update() instead. */ static void draw_background(ui_scrollbar_t *sb) { if (IS_TOO_SMALL(sb)) { return; } if (sb->view->draw_background && sb->redraw_height > 0) { int y; int height; /* Redraw upward area of bar. */ if (sb->redraw_y < sb->bar_top_y) { y = sb->redraw_y; if (y + sb->redraw_height > sb->bar_top_y) { /* Redraw except bar area. */ height = sb->bar_top_y - y; } else { height = sb->redraw_height; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " updating background from %d height %d\n", y + sb->top_margin, height); #endif (*sb->view->draw_background)(sb->view, y + sb->top_margin, height); } /* Redraw downward area of bar. */ if (sb->redraw_y < sb->window.height - HEIGHT_MARGIN(sb) && sb->bar_top_y + sb->bar_height < sb->redraw_y + sb->redraw_height) { if (sb->redraw_y < sb->bar_top_y + sb->bar_height) { y = sb->bar_top_y + sb->bar_height; } else { y = sb->redraw_y; } if (sb->redraw_y + sb->redraw_height > sb->window.height - HEIGHT_MARGIN(sb)) { /* Redraw except bar area. */ height = sb->window.height - HEIGHT_MARGIN(sb) - y; } else { height = sb->redraw_y + sb->redraw_height - y; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " updating background from %d height %d\n", y + sb->top_margin, height); #endif (*sb->view->draw_background)(sb->view, y + sb->top_margin, height); } sb->redraw_y = 0; sb->redraw_height = 0; } } /* * Don't call directly draw_xxx functions. * Call ui_window_update() instead. */ static void draw_button(ui_scrollbar_t *sb, int upbutton, int downbutton) { if (IS_TOO_SMALL(sb)) { return; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " drawing button.\n"); #endif if (upbutton && sb->view->draw_up_button) { (*sb->view->draw_up_button)(sb->view, sb->is_pressing_up_button); } if (downbutton && sb->view->draw_down_button) { (*sb->view->draw_down_button)(sb->view, sb->is_pressing_down_button); } } /* * depends on sb->bar_height. */ static int calculate_bar_top_y(ui_scrollbar_t *sb) { if (IS_TOO_SMALL(sb) || MAX_BAR_HEIGHT(sb) == sb->bar_height || abs(sb->current_row) == sb->num_filled_log_lines) { return 0; } else { return (sb->current_row + sb->num_filled_log_lines) * (MAX_BAR_HEIGHT(sb) - sb->bar_height) / sb->num_filled_log_lines; } } /* * depends on sb->bar_height. */ static int calculate_current_row(ui_scrollbar_t *sb) { if (IS_TOO_SMALL(sb) || MAX_BAR_HEIGHT(sb) == sb->bar_height) { return 0; } else { /* * sb->bar_top_y / (sb->num_filled_log_lines / * (MAX_BAR_HEIGHT(sb) - sb->bar_height)) * => (sb->num_filled_log_lines / (MAX_BAR_HEIGHT(sb) - sb->bar_height)) * = pixel per line */ return sb->bar_top_y * sb->num_filled_log_lines / (MAX_BAR_HEIGHT(sb) - sb->bar_height) - sb->num_filled_log_lines; } } static u_int calculate_bar_height(ui_scrollbar_t *sb) { if (IS_TOO_SMALL(sb) || sb->num_filled_log_lines + sb->num_scr_lines == 0) { return 0; } else { u_int bar_height; bar_height = (sb->num_scr_lines * MAX_BAR_HEIGHT(sb)) / (sb->num_filled_log_lines + sb->num_scr_lines); if (bar_height < MAX_BAR_HEIGHT(sb) / 20) { bar_height = MAX_BAR_HEIGHT(sb) / 20; } return bar_height; } } static int is_updown_button_event( ui_scrollbar_t *sb, int y /* this value must include margin or be y on actual window */ ) { int up_button_y; int down_button_y; /* * minus value means y from the bottom. */ if (sb->up_button_y < 0) { up_button_y = sb->window.height + sb->up_button_y; } else { up_button_y = sb->up_button_y; } if (sb->down_button_y < 0) { down_button_y = sb->window.height + sb->down_button_y; } else { down_button_y = sb->down_button_y; } if (up_button_y <= y && y <= up_button_y + sb->up_button_height) { #ifdef __DEBUG bl_debug_printf("up button pressed\n"); #endif return 1; } else if (down_button_y <= y && y <= down_button_y + sb->down_button_height) { #ifdef __DEBUG bl_debug_printf("down button pressed\n"); #endif return -1; } else { return 0; } } /* * callbacks of ui_window_t events. */ static void trigger_sb_view_realized(ui_scrollbar_t *sb) { if (sb->view->realized) { (*sb->view->realized)(sb->view, sb->window.disp->display, sb->window.disp->screen, sb->window.my_window, ui_window_get_fg_gc(&sb->window), sb->window.height); } /* * FGCOLOR_CHANGED|BGCOLOR_CHANGED is necessary in order for * ui_sb_view_t::color_changed to be called. If it is not called, * fg or bg color of buttons are not correctly drawn especially * in changing transparent flag. */ ui_window_update(&sb->window, FGCOLOR_CHANGED | BGCOLOR_CHANGED); } static void window_realized(ui_window_t *win) { ui_scrollbar_t *sb; sb = (ui_scrollbar_t*)win; if (ui_load_named_xcolor(win->disp, &sb->fg_xcolor, sb->fg_color)) { ui_window_set_fg_color(win, &sb->fg_xcolor); } if (ui_load_named_xcolor(win->disp, &sb->bg_xcolor, sb->bg_color)) { ui_window_set_bg_color(win, &sb->bg_xcolor); } trigger_sb_view_realized(sb); } static void window_resized(ui_window_t *win) { ui_scrollbar_t *sb; #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " scrollbar resized.\n"); #endif sb = (ui_scrollbar_t*)win; if (IS_TOO_SMALL(sb)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " scrollbar is too small to be drawn.\n"); #endif sb->num_scr_lines = 0; sb->bar_height = 0; sb->bar_top_y = 0; } else { sb->num_scr_lines = MAX_BAR_HEIGHT(sb) / sb->line_height; sb->bar_height = calculate_bar_height(sb); sb->bar_top_y = MAX_BAR_HEIGHT(sb) - sb->bar_height; } sb->current_row = 0; if (sb->view->resized) { (*sb->view->resized)(sb->view, sb->window.my_window, sb->window.height); } set_redraw_area(sb, 0, sb->window.height); ui_window_update(&sb->window, UPDATE_SCROLLBAR | UPDATE_BUTTON); } static void window_exposed(ui_window_t *win, int x, int y, u_int width, u_int height) { ui_scrollbar_t *sb; sb = (ui_scrollbar_t*)win; if (y < sb->top_margin) { height -= (sb->top_margin - y); y = 0; } else { y -= sb->top_margin; height -= sb->top_margin; } set_redraw_area(sb, y, height); /* * XXX * GC values should be set(in ui_window_get_gc) before sb->view->func is * called. * For win32: Current gc is set every time window_exposed and update_window. */ sb->view->gc = ui_window_get_bg_gc(&sb->window); draw_background(sb); sb->view->gc = ui_window_get_fg_gc(&sb->window); draw_scrollbar(sb); draw_button(sb, 1, 1); } static void update_window(ui_window_t *win, int flag) { ui_scrollbar_t *sb; if (flag == 0 || !win->is_mapped /* ui_scrollbar_line_is_added() is called if is_mapped = 0 */) { return; } sb = (ui_scrollbar_t*)win; if (flag & (FGCOLOR_CHANGED | BGCOLOR_CHANGED)) { if (sb->view->color_changed) { if (flag & FGCOLOR_CHANGED) { sb->view->gc = ui_window_get_fg_gc(&sb->window); (*sb->view->color_changed)(sb->view, 1); } if (flag & BGCOLOR_CHANGED) { sb->view->gc = ui_window_get_bg_gc(&sb->window); (*sb->view->color_changed)(sb->view, 0); } } } if (flag & UPDATE_SCROLLBAR) { /* * XXX * GC values should be set(in ui_window_get_gc) before sb->view->func is * called. * For win32: Current gc is set every time window_exposed and update_window. */ sb->view->gc = ui_window_get_bg_gc(&sb->window); draw_background(sb); sb->view->gc = ui_window_get_fg_gc(&sb->window); draw_scrollbar(sb); } else { sb->view->gc = ui_window_get_fg_gc(&sb->window); } if (flag & ~UPDATE_SCROLLBAR) { draw_button(sb, (flag & UPDATE_UPBUTTON) != 0, (flag & UPDATE_DOWNBUTTON) != 0); } } static void up_button_pressed(ui_scrollbar_t *sb) { if (!ui_scrollbar_move_upward(sb, 1)) { return; } if (sb->sb_listener->screen_scroll_downward) { /* up button scrolls *down* screen */ (*sb->sb_listener->screen_scroll_downward)(sb->sb_listener->self, 1); } } static void down_button_pressed(ui_scrollbar_t *sb) { if (!ui_scrollbar_move_downward(sb, 1)) { return; } if (sb->sb_listener->screen_scroll_upward) { /* down button scrolls *up* screen */ (*sb->sb_listener->screen_scroll_upward)(sb->sb_listener->self, 1); } } static void button_pressed(ui_window_t *win, XButtonEvent *event, int click_num) { ui_scrollbar_t *sb; int result; int y; sb = (ui_scrollbar_t*)win; if (IS_TOO_SMALL(sb)) { return; } result = is_updown_button_event(sb, event->y); y = event->y - sb->top_margin; if (result == 0) { if (y < sb->bar_top_y) { ui_scrollbar_move_upward(sb, sb->num_scr_lines); if (sb->sb_listener->screen_scroll_downward) { /* down button scrolls *down* screen */ (*sb->sb_listener->screen_scroll_downward)(sb->sb_listener->self, sb->num_scr_lines); } } else if (y > sb->bar_top_y + sb->bar_height) { ui_scrollbar_move_downward(sb, sb->num_scr_lines); if (sb->sb_listener->screen_scroll_upward) { /* down button scrolls *up* screen */ (*sb->sb_listener->screen_scroll_upward)(sb->sb_listener->self, sb->num_scr_lines); } } } else if (result == 1) { sb->is_pressing_up_button = 1; ui_window_update(&sb->window, UPDATE_UPBUTTON); up_button_pressed(sb); } else if (result == -1) { sb->is_pressing_down_button = 1; ui_window_update(&sb->window, UPDATE_DOWNBUTTON); down_button_pressed(sb); } } static void button_press_continued(ui_window_t *win, XButtonEvent *event) { ui_scrollbar_t *sb; int result; sb = (ui_scrollbar_t*)win; result = is_updown_button_event(sb, event->y); if (sb->is_pressing_up_button && result == 1) { up_button_pressed(sb); } else if (sb->is_pressing_down_button && result == -1) { down_button_pressed(sb); } } static void button_motion(ui_window_t *win, XMotionEvent *event) { ui_scrollbar_t *sb; int new_row; int up_to_top_now; int y; int old_bar_top_y; int old_bar_height; sb = (ui_scrollbar_t*)win; if (sb->is_pressing_up_button || sb->is_pressing_down_button || is_updown_button_event(sb, event->y) != 0 || IS_TOO_SMALL(sb)) { return; } y = event->y - sb->top_margin; old_bar_top_y = sb->bar_top_y; old_bar_height = sb->bar_height; if (sb->bar_top_y == 0) { up_to_top_now = 1; } else { up_to_top_now = 0; } if (sb->is_motion == 0) { if (sb->bar_top_y <= y && y <= sb->bar_top_y + sb->bar_height) { /* on the bar */ sb->y_on_bar = y - sb->bar_top_y; } else { /* out of the bar */ sb->y_on_bar = sb->bar_height / 2; if (y < sb->y_on_bar) { sb->bar_top_y = 0; } else { sb->bar_top_y = y - sb->y_on_bar; } } sb->is_motion = 1; } else { if (y < sb->y_on_bar) { if (sb->bar_top_y != 0) { sb->bar_top_y = 0; } else { return; } } else if (y - sb->y_on_bar + sb->bar_height > MAX_BAR_HEIGHT(sb)) { sb->bar_top_y = MAX_BAR_HEIGHT(sb) - sb->bar_height; } else { sb->bar_top_y = y - sb->y_on_bar; } } if (!up_to_top_now && sb->bar_top_y == 0) { /* up to the top this time */ up_to_top_now = 1; } else { /* if bar is on the top , it is not *this* time(maybe previous...) */ up_to_top_now = 0; } new_row = calculate_current_row(sb); /* * if bar reaches the top this time , it doesn't return but draw_scrollbar(). */ if (!up_to_top_now && sb->current_row == new_row) { /* Restore bar_top_y and bar_height */ sb->bar_top_y = old_bar_top_y; sb->bar_height = old_bar_height; return; } sb->current_row = new_row; if (sb->sb_listener->screen_scroll_to) { (*sb->sb_listener->screen_scroll_to)(sb->sb_listener->self, sb->current_row); } set_redraw_area(sb, old_bar_top_y, old_bar_height); ui_window_update(&sb->window, UPDATE_SCROLLBAR); } static void button_released(ui_window_t *win, XButtonEvent *event) { ui_scrollbar_t *sb; sb = (ui_scrollbar_t*)win; if (sb->is_pressing_up_button) { sb->is_pressing_up_button = 0; ui_window_update(&sb->window, UPDATE_UPBUTTON); } if (sb->is_pressing_down_button) { sb->is_pressing_down_button = 0; ui_window_update(&sb->window, UPDATE_DOWNBUTTON); } if (sb->is_motion) { sb->is_motion = 0; } } /* --- global functions --- */ int ui_scrollbar_init(ui_scrollbar_t *sb, ui_scrollbar_event_listener_t *sb_listener, char *view_name, char *fg_color, char *bg_color, u_int height, u_int line_height, u_int num_log_lines, u_int num_filled_log_lines, int use_transbg, ui_picture_modifier_t *pic_mod) { u_int width; /* dynamically allocated */ sb->view_name = NULL; sb->view = NULL; sb->fg_color = NULL; sb->bg_color = NULL; if (view_name) { sb->view_name = strdup(view_name); } else { sb->view_name = strdup("simple"); } if (sb->view_name == NULL) { goto error; } if (use_transbg) { if ((sb->view = ui_transparent_sb_view_new(sb->view_name))) { goto view_created; } } if ((sb->view = ui_sb_view_new(sb->view_name)) == NULL) { free(sb->view_name); if ((sb->view_name = strdup("simple")) == NULL) { goto error; } if (use_transbg) { if ((sb->view = ui_transparent_sb_view_new(sb->view_name))) { goto view_created; } } if ((sb->view = ui_sb_view_new(sb->view_name)) == NULL) { goto error; } } use_transbg = 0; view_created: sb->view->win = &sb->window; sb->sb_listener = sb_listener; (*sb->view->get_geometry_hints)(sb->view, &width, &sb->top_margin, &sb->bottom_margin, &sb->up_button_y, &sb->up_button_height, &sb->down_button_y, &sb->down_button_height); if (sb->view->get_default_color) { char* _fg_color; char* _bg_color; (*sb->view->get_default_color)(sb->view, &_fg_color, &_bg_color); if (fg_color == NULL) { fg_color = _fg_color; } if (bg_color == NULL) { bg_color = _bg_color; } } else { if (fg_color == NULL) { fg_color = "black"; } if (bg_color == NULL) { bg_color = "white"; } } sb->fg_color = strdup(fg_color); sb->bg_color = strdup(bg_color); sb->is_pressing_up_button = 0; sb->is_pressing_down_button = 0; if (!ui_window_init(&sb->window, width, height, width, 0, 0, 0, 0, 0, 0, 0)) { goto error; } sb->line_height = line_height; if (IS_TOO_SMALL(sb)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " scrollbar is too small to be drawn.\n"); #endif sb->bar_height = 0; sb->num_scr_lines = 0; } else { sb->bar_height = height - HEIGHT_MARGIN(sb); sb->num_scr_lines = sb->bar_height / sb->line_height; } sb->num_log_lines = num_log_lines; sb->num_filled_log_lines = num_filled_log_lines; sb->bar_top_y = 0; sb->y_on_bar = 0; sb->current_row = 0; sb->redraw_y = 0; sb->redraw_height = 0; sb->is_motion = 0; if (use_transbg) { ui_window_set_transparent(&sb->window, pic_mod); } ui_window_set_cursor(&sb->window, XC_left_ptr); /* * event callbacks. */ ui_window_add_event_mask(&sb->window, ButtonPressMask | ButtonReleaseMask | ButtonMotionMask); sb->window.window_realized = window_realized; sb->window.button_pressed = button_pressed; sb->window.button_released = button_released; sb->window.button_press_continued = button_press_continued; sb->window.button_motion = button_motion; sb->window.window_resized = window_resized; sb->window.window_exposed = window_exposed; sb->window.update_window = update_window; return 1; error: free(sb->fg_color); free(sb->bg_color); free(sb->view_name); if (sb->view) { (*sb->view->destroy)(sb->view); } return 0; } void ui_scrollbar_final(ui_scrollbar_t *sb) { (*sb->view->destroy)(sb->view); ui_unload_scrollbar_view_lib(sb->view_name); ui_unload_xcolor(sb->window.disp, &sb->fg_xcolor); ui_unload_xcolor(sb->window.disp, &sb->bg_xcolor); free(sb->fg_color); free(sb->bg_color); free(sb->view_name); } void ui_scrollbar_set_num_log_lines(ui_scrollbar_t *sb, u_int num_log_lines) { if (sb->num_log_lines == num_log_lines) { return; } sb->num_log_lines = num_log_lines; if (sb->num_filled_log_lines > sb->num_log_lines) { sb->num_filled_log_lines = sb->num_log_lines; } set_redraw_area(sb, sb->bar_top_y, sb->bar_height); sb->bar_height = calculate_bar_height(sb); sb->bar_top_y = MAX_BAR_HEIGHT(sb) - sb->bar_height; ui_window_update(&sb->window, UPDATE_SCROLLBAR); } void ui_scrollbar_set_num_filled_log_lines(ui_scrollbar_t *sb, u_int lines) { if (lines > sb->num_log_lines) { lines = sb->num_log_lines; } if (sb->num_filled_log_lines == lines) { return; } sb->num_filled_log_lines = lines; set_redraw_area(sb, sb->bar_top_y, sb->bar_height); sb->bar_height = calculate_bar_height(sb); sb->bar_top_y = MAX_BAR_HEIGHT(sb) - sb->bar_height; ui_window_update(&sb->window, UPDATE_SCROLLBAR); } int ui_scrollbar_line_is_added(ui_scrollbar_t *sb) { int old_bar_top_y; u_int old_bar_height; if ((*sb->sb_listener->screen_is_static)(sb->sb_listener->self)) { if (sb->num_filled_log_lines < sb->num_log_lines) { sb->num_filled_log_lines++; } sb->current_row--; } else if (sb->num_filled_log_lines == sb->num_log_lines) { return 0; } else { sb->num_filled_log_lines++; } old_bar_height = sb->bar_height; sb->bar_height = calculate_bar_height(sb); old_bar_top_y = sb->bar_top_y; sb->bar_top_y = calculate_bar_top_y(sb); if (old_bar_top_y == sb->bar_top_y && old_bar_height == sb->bar_height) { return 1; } else { set_redraw_area(sb, old_bar_top_y, old_bar_height); ui_window_update(&sb->window, UPDATE_SCROLLBAR); return 1; } } void ui_scrollbar_reset(ui_scrollbar_t *sb) { if (sb->is_motion || sb->bar_top_y + sb->bar_height < MAX_BAR_HEIGHT(sb)) { set_redraw_area(sb, sb->bar_top_y, sb->bar_height); sb->bar_top_y = MAX_BAR_HEIGHT(sb) - sb->bar_height; sb->is_motion = 0; sb->current_row = 0; ui_window_update(&sb->window, UPDATE_SCROLLBAR); } } int ui_scrollbar_move_upward(ui_scrollbar_t *sb, u_int size) { #if 0 if (sb->bar_top_y == 0) #else /* * XXX Adhoc solution * Fix ui_screen.c:bs_{half_}page_{up|down}ward() instead. */ if (sb->current_row + sb->num_filled_log_lines == 0) #endif { return 0; } return ui_scrollbar_move(sb, sb->current_row - size); } int ui_scrollbar_move_downward(ui_scrollbar_t *sb, u_int size) { if (sb->current_row >= 0) { return 0; } return ui_scrollbar_move(sb, sb->current_row + size); } int ui_scrollbar_move(ui_scrollbar_t *sb, int row) { if (0 < row) { row = 0; } else if (row + (int)sb->num_filled_log_lines < 0) { row = -(sb->num_filled_log_lines); } if (sb->current_row == row) { return 0; } sb->current_row = row; set_redraw_area(sb, sb->bar_top_y, sb->bar_height); sb->bar_top_y = calculate_bar_top_y(sb); ui_window_update(&sb->window, UPDATE_SCROLLBAR); return 1; } int ui_scrollbar_set_line_height(ui_scrollbar_t *sb, u_int line_height) { if (sb->line_height == line_height) { return 0; } sb->line_height = line_height; set_redraw_area(sb, sb->bar_top_y, sb->bar_height); sb->bar_height = calculate_bar_height(sb); ui_window_update(&sb->window, UPDATE_SCROLLBAR); return 1; } int ui_scrollbar_set_fg_color(ui_scrollbar_t *sb, char *fg_color) { free(sb->fg_color); ui_unload_xcolor(sb->window.disp, &sb->fg_xcolor); sb->fg_color = strdup(fg_color); if (ui_load_named_xcolor(sb->window.disp, &sb->fg_xcolor, sb->fg_color)) { ui_window_set_fg_color(&sb->window, &sb->fg_xcolor); set_redraw_area(sb, 0, sb->window.height); ui_window_update(&sb->window, UPDATE_SCROLLBAR | UPDATE_BUTTON | FGCOLOR_CHANGED); } return 1; } int ui_scrollbar_set_bg_color(ui_scrollbar_t *sb, char *bg_color) { free(sb->bg_color); ui_unload_xcolor(sb->window.disp, &sb->bg_xcolor); sb->bg_color = strdup(bg_color); if (ui_load_named_xcolor(sb->window.disp, &sb->bg_xcolor, sb->bg_color)) { ui_window_set_bg_color(&sb->window, &sb->bg_xcolor); set_redraw_area(sb, 0, sb->window.height); ui_window_update(&sb->window, UPDATE_SCROLLBAR | UPDATE_BUTTON | BGCOLOR_CHANGED); } return 1; } int ui_scrollbar_change_view(ui_scrollbar_t *sb, char *name) { ui_sb_view_t *view; u_int width; if (strcmp(name, sb->view_name) == 0 || (name = strdup(name)) == NULL) { return 0; } if (sb->window.is_transparent) { if ((view = ui_transparent_sb_view_new(name)) == NULL) { /* nothing is done */ free(name); return 0; } } else { if ((view = ui_sb_view_new(name)) == NULL) { free(name); return 0; } } view->win = &sb->window; if (sb->view) { (*sb->view->destroy)(sb->view); ui_unload_scrollbar_view_lib(sb->view_name); } sb->view = view; free(sb->view_name); /* name is dynamically allocated above */ sb->view_name = name; (*sb->view->get_geometry_hints)(sb->view, &width, &sb->top_margin, &sb->bottom_margin, &sb->up_button_y, &sb->up_button_height, &sb->down_button_y, &sb->down_button_height); sb->bar_height = calculate_bar_height(sb); sb->bar_top_y = calculate_bar_top_y(sb); trigger_sb_view_realized(sb); if (sb->window.width != width) { ui_window_set_normal_hints(&sb->window, width, sb->window.min_height, 0, 0); ui_window_resize(&sb->window, width, sb->window.height, NOTIFY_TO_PARENT); } set_redraw_area(sb, 0, sb->window.height); ui_window_update(&sb->window, UPDATE_SCROLLBAR | UPDATE_BUTTON); return 1; } int ui_scrollbar_set_transparent(ui_scrollbar_t *sb, ui_picture_modifier_t *pic_mod, int force) { ui_sb_view_t *view; if (!force && sb->window.is_transparent) { /* already set */ return 1; } if ((view = ui_transparent_sb_view_new(sb->view_name)) == NULL) { /* nothing is done */ return 0; } view->win = &sb->window; if (sb->view) { (*sb->view->destroy)(sb->view); } sb->view = view; /* This should be done before ui_window_set_untransparent() , which calls * exposed event. */ trigger_sb_view_realized(sb); ui_window_set_transparent(&sb->window, pic_mod); set_redraw_area(sb, 0, sb->window.height); ui_window_update(&sb->window, UPDATE_SCROLLBAR | UPDATE_BUTTON); return 1; } int ui_scrollbar_unset_transparent(ui_scrollbar_t *sb) { ui_sb_view_t *view; if (!sb->window.is_transparent) { /* already unset */ return 1; } if ((view = ui_sb_view_new(sb->view_name)) == NULL) { /* nothing is done */ return 0; } view->win = &sb->window; if (sb->view) { (*sb->view->destroy)(sb->view); } sb->view = view; /* This should be done before ui_window_set_untransparent() , which calls * exposed event. */ trigger_sb_view_realized(sb); ui_window_unset_transparent(&sb->window); set_redraw_area(sb, 0, sb->window.height); ui_window_update(&sb->window, UPDATE_SCROLLBAR | UPDATE_BUTTON); return 1; } mlterm-3.8.9/uitoolkit/ui_scrollbar.h010064400017600000144000000051601356600660700164200ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_SCROLLBAR_H__ #define __UI_SCROLLBAR_H__ #include /* u_int */ #include #include "ui_window.h" #include "ui_sb_view.h" #include "ui_sb_mode.h" #include "ui_color_manager.h" #include "ui_picture.h" typedef struct ui_scrollbar_event_listener { void *self; int (*screen_scroll_to)(void *, int); int (*screen_scroll_upward)(void *, u_int); int (*screen_scroll_downward)(void *, u_int); int (*screen_is_static)(void *); } ui_scrollbar_event_listener_t; typedef struct ui_scrollbar { ui_window_t window; char *view_name; ui_sb_view_t *view; char *fg_color; char *bg_color; ui_color_t fg_xcolor; ui_color_t bg_xcolor; ui_scrollbar_event_listener_t *sb_listener; u_int bar_height; /* Scrollbar height */ u_int top_margin; /* Button area */ u_int bottom_margin; /* Button area */ u_int line_height; u_int num_scr_lines; u_int num_log_lines; u_int num_filled_log_lines; int bar_top_y; /* Scrollbar position without button area */ int y_on_bar; /* Used in button_motion event handler */ int current_row; int redraw_y; u_int redraw_height; int up_button_y; u_int up_button_height; int down_button_y; u_int down_button_height; int8_t is_pressing_up_button; int8_t is_pressing_down_button; int8_t is_motion; } ui_scrollbar_t; int ui_scrollbar_init(ui_scrollbar_t *sb, ui_scrollbar_event_listener_t *sb_listener, char *view_name, char *fg_color, char *bg_color, u_int height, u_int line_height, u_int num_log_lines, u_int num_filled_log_lines, int use_transbg, ui_picture_modifier_t *pic_mod); void ui_scrollbar_final(ui_scrollbar_t *sb); void ui_scrollbar_set_num_log_lines(ui_scrollbar_t *sb, u_int num_log_lines); void ui_scrollbar_set_num_filled_log_lines(ui_scrollbar_t *sb, u_int num_filled_log_lines); int ui_scrollbar_line_is_added(ui_scrollbar_t *sb); void ui_scrollbar_reset(ui_scrollbar_t *sb); int ui_scrollbar_move_upward(ui_scrollbar_t *sb, u_int size); int ui_scrollbar_move_downward(ui_scrollbar_t *sb, u_int size); int ui_scrollbar_move(ui_scrollbar_t *sb, int row); int ui_scrollbar_set_line_height(ui_scrollbar_t *sb, u_int line_height); int ui_scrollbar_set_fg_color(ui_scrollbar_t *sb, char *fg_color); int ui_scrollbar_set_bg_color(ui_scrollbar_t *sb, char *bg_color); int ui_scrollbar_change_view(ui_scrollbar_t *sb, char *name); int ui_scrollbar_set_transparent(ui_scrollbar_t *sb, ui_picture_modifier_t *pic_mod, int force); int ui_scrollbar_unset_transparent(ui_scrollbar_t *sb); #endif mlterm-3.8.9/uitoolkit/ui_selection.c010064400017600000144000000310561356600660700164200ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_selection.h" #include /* memset */ #include #include #include #if 0 #define __DEBUG #endif /* --- static functions --- */ static int update_sel_region(ui_selection_t *sel, int col, int row) { int rv_beg_col; int rv_beg_row; int rv_end_col; int rv_end_row; int do_reverse; int rs_beg_col; int rs_beg_row; int rs_end_col; int rs_end_row; int do_restore; if (sel->is_rect) { int conved; int conved_col; (*sel->sel_listener->restore_color)(sel->sel_listener->self, sel->beg_col, sel->beg_row, sel->end_col, sel->end_row, 1); if ((col < 0 && sel->base_col_r >= 0) || (col >= 0 && sel->base_col_r < 0)) { conved_col = -col; conved = 1; } else { conved_col = col; conved = 0; } if (conved_col < sel->base_col_r) { if (row <= sel->base_row_r) { sel->beg_col = col; sel->beg_row = row; sel->end_col = sel->base_col_l; sel->end_row = sel->base_row_l; } else { sel->beg_col = conved_col; sel->beg_row = sel->base_row_l; if (conved) { sel->end_col = -sel->base_col_l; } else { sel->end_col = sel->base_col_l; } sel->end_row = row; } } else { if (row <= sel->base_row_r) { if (conved) { sel->beg_col = -sel->base_col_r; } else { sel->beg_col = sel->base_col_r; } sel->beg_row = row; sel->end_col = conved_col; sel->end_row = sel->base_row_r; } else { sel->beg_col = sel->base_col_r; sel->beg_row = sel->base_row_r; sel->end_col = col; sel->end_row = row; } } (*sel->sel_listener->reverse_color)(sel->sel_listener->self, sel->beg_col, sel->beg_row, sel->end_col, sel->end_row, 1); return 1; } do_reverse = 0; do_restore = 0; if (sel->beg_row > row || (sel->beg_row == row && sel->beg_col > col)) { rv_beg_col = col; rv_beg_row = row; rv_end_col = sel->beg_col; rv_end_row = sel->beg_row; do_reverse = 1; sel->beg_col = col; sel->beg_row = row; if (sel->end_row > sel->base_row_r || (sel->end_row == sel->base_row_r && sel->end_col >= sel->base_col_r)) { rs_beg_col = sel->base_col_r; rs_beg_row = sel->base_row_r; rs_end_col = sel->end_col; rs_end_row = sel->end_row; do_restore = 1; sel->end_col = sel->base_col_l; sel->end_row = sel->base_row_l; } } else if ((sel->beg_row < row || (sel->beg_row == row && sel->beg_col <= col)) && (sel->end_row > row || (sel->end_row == row && sel->end_col >= col))) { if (row > sel->base_row_r || (row == sel->base_row_r && col >= sel->base_col_r)) { rs_beg_col = col + 1; /* don't restore col itself */ rs_beg_row = row; rs_end_col = sel->end_col; rs_end_row = sel->end_row; do_restore = 1; sel->end_col = col; sel->end_row = row; } else if (row < sel->base_row_l || (row == sel->base_row_l && col <= sel->base_col_l)) { rs_beg_col = sel->beg_col; rs_beg_row = sel->beg_row; rs_end_col = col - 1; /* don't restore col itself */ rs_end_row = row; do_restore = 1; sel->beg_col = col; sel->beg_row = row; } } else if (sel->end_row < row || (sel->end_row == row && sel->end_col < col)) { rv_beg_col = sel->end_col; rv_beg_row = sel->end_row; rv_end_col = col; rv_end_row = row; do_reverse = 1; sel->end_col = col; sel->end_row = row; if (sel->beg_row < sel->base_row_l || (sel->beg_row == sel->base_row_l && sel->beg_col <= sel->base_col_l)) { rs_beg_col = sel->beg_col; rs_beg_row = sel->beg_row; rs_end_col = sel->base_col_l; rs_end_row = sel->base_row_l; do_restore = 1; sel->beg_col = sel->base_col_r; sel->beg_row = sel->base_row_r; } } if (do_reverse) { (*sel->sel_listener->reverse_color)(sel->sel_listener->self, rv_beg_col, rv_beg_row, rv_end_col, rv_end_row, 0); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " reversing %d %d %d %d\n", rv_beg_col, rv_beg_row, rv_end_col, rv_end_row); #endif } if (do_restore) { (*sel->sel_listener->restore_color)(sel->sel_listener->self, rs_beg_col, rs_beg_row, rs_end_col, rs_end_row, 0); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " restoring %d %d %d %d\n", rs_beg_col, rs_beg_row, rs_end_col, rs_end_row); #endif if (sel->is_locked == 1) { if ((sel->end_row < sel->lock_row || (sel->end_row == sel->lock_row && sel->end_col < sel->lock_col))) { (*sel->sel_listener->reverse_color)(sel->sel_listener->self, rs_beg_col, rs_beg_row, (sel->end_col = sel->lock_col), (sel->end_row = sel->lock_row), 0); } } else if (sel->is_locked == -1) { if ((sel->beg_row > sel->lock_row || (sel->beg_row == sel->lock_row && sel->beg_col > sel->lock_col))) { (*sel->sel_listener->reverse_color)(sel->sel_listener->self, (sel->beg_col = sel->lock_col), (sel->beg_row = sel->lock_row), rs_end_col, rs_end_row, 0); } } } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " current region %d %d %d %d\n", sel->beg_col, sel->beg_row, sel->end_col, sel->end_row); #endif return 1; } /* --- global functions --- */ void ui_sel_init(ui_selection_t *sel, ui_sel_event_listener_t *sel_listener) { memset(sel, 0, sizeof(ui_selection_t)); sel->sel_listener = sel_listener; } void ui_sel_final(ui_selection_t *sel) { if (sel->sel_str) { vt_str_destroy(sel->sel_str, sel->sel_len); } } int ui_start_selection(ui_selection_t *sel, int col_l, int row_l, int col_r, int row_r, ui_sel_type_t type, int is_rect) { sel->is_reversed = 1; sel->is_selecting = type; sel->is_rect = is_rect; sel->base_col_r = sel->beg_col = sel->end_col = sel->prev_col = col_r; sel->base_row_r = sel->beg_row = sel->end_row = sel->prev_row = row_r; sel->base_col_l = col_l; sel->base_row_l = row_l; (*sel->sel_listener->reverse_color)(sel->sel_listener->self, sel->beg_col, sel->beg_row, sel->end_col, sel->end_row, sel->is_rect); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " selection started => %d %d\n", sel->beg_col, sel->beg_row); #endif return 1; } int ui_selecting(ui_selection_t *sel, int col, int row) { if (!sel->is_selecting) { return 0; } sel->prev_col = col; sel->prev_row = row; update_sel_region(sel, col, row); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " selecting %d %d => %d %d - %d %d.\n", col, row, sel->beg_col, sel->beg_row, sel->end_col, sel->end_row); #endif return 1; } int ui_stop_selecting(ui_selection_t *sel) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " selection stops => %d %d - %d %d.\n", sel->beg_col, sel->beg_row, sel->end_col, sel->end_row); #endif if (!sel->is_selecting) { return 0; } sel->is_selecting = 0; sel->is_locked = 0; if (sel->sel_str) { vt_str_destroy(sel->sel_str, sel->sel_len); } if (!(*sel->sel_listener->select_in_window)(sel->sel_listener->self, &sel->sel_str, &sel->sel_len, sel->beg_col, sel->beg_row, sel->end_col, sel->end_row, sel->is_rect)) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " select_in_window() failed.\n"); #endif sel->sel_str = NULL; sel->sel_len = 0; return 0; } return 1; } int ui_sel_clear(ui_selection_t *sel) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " selection is cleared.\n"); #endif if (sel->is_selecting) { if (sel->sel_str) { vt_str_destroy(sel->sel_str, sel->sel_len); sel->sel_str = NULL; sel->sel_len = 0; } sel->is_selecting = 0; sel->is_locked = 0; } return ui_restore_selected_region_color(sel); } int ui_restore_selected_region_color_except_logs(ui_selection_t *sel) { int beg_row; int beg_col; if (!sel->is_reversed) { return 0; } if (sel->end_row < 0) { return 1; } if ((beg_row = sel->beg_row) < 0) { beg_row = 0; beg_col = 0; } else { beg_col = sel->beg_col; } (*sel->sel_listener->restore_color)(sel->sel_listener->self, beg_col, beg_row, sel->end_col, sel->end_row, sel->is_rect); return 1; } int ui_reverse_selected_region_color_except_logs(ui_selection_t *sel) { int beg_row; int beg_col; if (!sel->is_reversed) { return 0; } if (sel->end_row < 0) { return 1; } if ((beg_row = sel->beg_row) < 0) { beg_row = 0; beg_col = 0; } else { beg_col = sel->beg_col; } (*sel->sel_listener->reverse_color)(sel->sel_listener->self, beg_col, beg_row, sel->end_col, sel->end_row, sel->is_rect); return 1; } int ui_restore_selected_region_color(ui_selection_t *sel) { if (!sel->is_reversed) { return 0; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " restore selected region color => %d %d - %d %d.\n", sel->beg_col, sel->beg_row, sel->end_col, sel->end_row); #endif (*sel->sel_listener->restore_color)(sel->sel_listener->self, sel->beg_col, sel->beg_row, sel->end_col, sel->end_row, sel->is_rect); sel->is_reversed = 0; return 1; } /* * Not used for now. */ #if 0 int ui_reverse_selected_region_color(ui_selection_t *sel) { if (sel->is_reversed) { return 0; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " reverse selected region color => %d %d - %d %d.\n", sel->beg_col, sel->beg_row, sel->end_col, sel->end_row); #endif (*sel->sel_listener->reverse_color)(sel->sel_listener->self, sel->beg_col, sel->beg_row, sel->end_col, sel->end_row, sel->is_rect); sel->is_reversed = 1; return 1; } #endif int ui_sel_line_scrolled_out(ui_selection_t *sel, int min_row) { if (!sel->is_selecting) { return 0; } if (sel->base_row_l > min_row) { sel->base_row_l--; } else { sel->base_col_l = -1; } if (sel->base_row_r > min_row) { sel->base_row_r--; } else { sel->base_col_r = 0; } if (sel->is_locked) { if (sel->lock_row > min_row) { sel->lock_row--; } else { sel->lock_col = 0; } } if (sel->beg_row > min_row) { sel->beg_row--; } else { sel->beg_col = 0; } if (sel->end_row > min_row) { sel->end_row--; } else { sel->end_col = 0; } if (sel->prev_row > min_row) { sel->prev_row--; } else { sel->prev_col = 0; } return 1; } int ui_selected_region_is_changed(ui_selection_t *sel, int col, int row, u_int base) { if (abs(sel->prev_col - col) >= base || abs(sel->prev_row - row) >= base) { return 1; } else { return 0; } } int ui_is_after_sel_right_base_pos(ui_selection_t *sel, int col, int row) { if (sel->is_rect) { return sel->base_col_r < col; } else { if (sel->base_row_r < row || (sel->base_row_r == row && sel->base_col_r < col)) { return 1; } else { return 0; } } } int ui_is_before_sel_left_base_pos(ui_selection_t *sel, int col, int row) { if (sel->is_rect) { return sel->base_col_l > col; } else { if (sel->base_row_l > row || (sel->base_row_l == row && sel->base_col_l > col)) { return 1; } else { return 0; } } } void ui_sel_lock(ui_selection_t *sel) { if (sel->beg_row < sel->base_row_l || (sel->beg_row == sel->base_row_l && sel->beg_col <= sel->base_col_l)) { /* * (Text surrounded by '*' is selected region. '|' is the base position.) * aaa*bbb*|ccc * ^ * +---- lock position ("bbb" is always selected.) * * This lock position is usually used in RTL lines. */ sel->lock_col = sel->beg_col; sel->lock_row = sel->beg_row; sel->is_locked = -1; } else { /* * (Text surrounded by '*' is selected region. '|' is the base position.) * aaa|*bbb*ccc * ^ * +---- lock position ("bbb" is always selected.) * * This lock position is usually used in LTR lines. */ sel->lock_col = sel->end_col; sel->lock_row = sel->end_row; sel->is_locked = 1; } } mlterm-3.8.9/uitoolkit/ui_selection.h010064400017600000144000000044231356600660700164230ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_SELECTION_H__ #define __UI_SELECTION_H__ #include /* u_int */ #include typedef enum { SEL_CHAR = 0x1, SEL_WORD = 0x2, SEL_LINE = 0x3, } ui_sel_type_t; typedef struct ui_sel_event_listener { void *self; int (*select_in_window)(void *, vt_char_t **, u_int *, int, int, int, int, int); void (*reverse_color)(void *, int, int, int, int, int); void (*restore_color)(void *, int, int, int, int, int); } ui_sel_event_listener_t; typedef struct ui_selection { ui_sel_event_listener_t *sel_listener; vt_char_t *sel_str; u_int sel_len; /* * Be careful that value of col must be munis in rtl line. * +-----------------------------+ * | a a a a a a a|<= RTL line * -1 -2 -3 -4 -5 -6 -7 <= index */ int base_col_l; int base_row_l; int base_col_r; int base_row_r; int beg_col; int beg_row; int end_col; int end_row; int lock_col; int lock_row; int prev_col; int prev_row; int8_t is_selecting; /* ui_sel_type_t is stored */ int8_t is_reversed; int8_t is_locked; int8_t is_rect; } ui_selection_t; void ui_sel_init(ui_selection_t *sel, ui_sel_event_listener_t *listener); void ui_sel_final(ui_selection_t *sel); int ui_start_selection(ui_selection_t *sel, int col_l, int row_l, int col_r, int row_r, ui_sel_type_t type, int is_rect); int ui_selecting(ui_selection_t *sel, int col, int row); int ui_stop_selecting(ui_selection_t *sel); int ui_restore_selected_region_color_except_logs(ui_selection_t *sel); int ui_reverse_selected_region_color_except_logs(ui_selection_t *sel); int ui_restore_selected_region_color(ui_selection_t *sel); int ui_reverse_selected_region_color(ui_selection_t *sel); int ui_sel_clear(ui_selection_t *sel); int ui_selected_region_is_changed(ui_selection_t *sel, int col, int row, u_int base); int ui_sel_line_scrolled_out(ui_selection_t *sel, int min_row); #define ui_is_selecting(sel) ((sel)->is_selecting) #define ui_sel_is_reversed(sel) ((sel)->is_reversed) int ui_is_after_sel_right_base_pos(ui_selection_t *sel, int col, int row); int ui_is_before_sel_left_base_pos(ui_selection_t *sel, int col, int row); void ui_sel_lock(ui_selection_t *sel); #endif mlterm-3.8.9/uitoolkit/ui_selection_encoding.h010064400017600000144000000006571356600660700202760ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_SELECTION_ENCODING_H__ #define __UI_SELECTION_ENCODING_H__ #include #include #include "ui.h" #ifdef USE_XLIB void ui_set_big5_selection_buggy(int buggy); #else #define ui_set_big5_selection_buggy(buggy) (0) #endif ef_parser_t *ui_get_selection_parser(int utf); ef_conv_t *ui_get_selection_conv(int utf); #endif mlterm-3.8.9/uitoolkit/ui_window.h010064400017600000144000000350041356600660700157440ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_WINDOW_H__ #define __UI_WINDOW_H__ #include #include #include "ui_display.h" #include "ui_font.h" #include "ui_color.h" #include "ui_gc.h" #include "ui_bel_mode.h" #define ACTUAL_WIDTH(win) ((win)->width + (win)->hmargin * 2) #define ACTUAL_HEIGHT(win) ((win)->height + (win)->vmargin * 2) /* * Don't use win->parent in xlib to check if win is root window or not * because mlterm can work as libvte. * vte window * | * mlterm window ... ui_window_t::parent == NULL * ui_window_t::parent_window == vte window */ #define PARENT_WINDOWID_IS_TOP(win) ((win)->parent_window == (win)->disp->my_window) typedef enum ui_resize_flag { NOTIFY_TO_NONE = 0x0, NOTIFY_TO_CHILDREN = 0x01, NOTIFY_TO_PARENT = 0x02, NOTIFY_TO_MYSELF = 0x04, LIMIT_RESIZE = 0x08, } ui_resize_flag_t; typedef enum ui_maximize_flag { MAXIMIZE_RESTORE = 0x0, MAXIMIZE_VERTICAL = 0x1, MAXIMIZE_HORIZONTAL = 0x2, MAXIMIZE_FULL = 0x3, } ui_maximize_flag_t; typedef enum ui_sizehint_flag { SIZEHINT_NONE = 0x0, SIZEHINT_WIDTH = 0x1, SIZEHINT_HEIGHT = 0x2, } ui_sizehint_flag_t; typedef struct ui_xim_event_listener { void *self; int (*get_spot)(void *, int *, int *); XFontSet (*get_fontset)(void *); ui_color_t *(*get_fg_color)(void *); ui_color_t *(*get_bg_color)(void *); } ui_xim_event_listener_t; /* Defined in ui_xic.h */ typedef struct ui_xic *ui_xic_ptr_t; /* Defined in ui_xim.h */ typedef struct ui_xim *ui_xim_ptr_t; /* Defined in ui_dnd.h */ typedef struct ui_dnd_context *ui_dnd_context_ptr_t; /* Defined in ui_picture.h */ typedef struct ui_picture_modifier *ui_picture_modifier_ptr_t; typedef struct ui_icon_picture *ui_icon_picture_ptr_t; typedef struct _XftDraw *xft_draw_ptr_t; typedef struct _cairo *cairo_ptr_t; typedef struct ui_window { ui_display_t *disp; Window my_window; #ifdef USE_XLIB /* * Don't remove if USE_XFT and USE_CAIRO are not defined to keep the size of * ui_window_t * for ui_im_xxx_screen_t. */ xft_draw_ptr_t xft_draw; cairo_ptr_t cairo_draw; #endif ui_color_t fg_color; ui_color_t bg_color; ui_gc_t *gc; Window parent_window; /* This member of root window is DefaultRootWindow */ struct ui_window *parent; /* This member of root window is NULL */ struct ui_window **children; u_int num_children; u_int cursor_shape; long event_mask; int x; /* relative to a root window. */ int y; /* relative to a root window. */ u_int width; u_int height; u_int min_width; u_int min_height; u_int width_inc; u_int height_inc; /* actual window size is +margin on north/south/east/west */ u_int16_t hmargin; u_int16_t vmargin; /* * mlterm-con doesn't use these members, but they are necessary to keep * the size of ui_window_t as the same as mlterm-fb for input method plugins. */ #ifdef MANAGE_SUB_WINDOWS_BY_MYSELF u_int clip_y; u_int clip_height; #endif /* used by ui_xim */ ui_xim_ptr_t xim; ui_xim_event_listener_t *xim_listener; ui_xic_ptr_t xic; /* Only root window manages xic in win32 */ #if defined(USE_WIN32GUI) WORD update_window_flag; int cmd_show; #elif defined(USE_QUARTZ) || defined(USE_BEOS) int update_window_flag; #endif /* button */ Time prev_clicked_time; int prev_clicked_button; XButtonEvent prev_button_press_event; ui_picture_modifier_ptr_t pic_mod; /* * XDND */ /* * Don't remove if DISABLE_XDND is defined to keep the size of ui_window_t for * ui_im_xxx_screen_t. */ ui_dnd_context_ptr_t dnd; /* * XClassHint */ char *app_name; /* * flags etc. */ #ifdef USE_XLIB int8_t wall_picture_is_set; /* Actually set picture (including transparency) or not. */ int8_t wait_copy_area_response; /* Used for XCopyArea() */ int8_t configure_root; #else Pixmap wall_picture; #endif #ifdef USE_WIN32GUI int8_t is_sel_owner; #endif int8_t is_transparent; int8_t is_scrollable; int8_t is_focused; int8_t inputtable; /* 1: focused, -1: unfocused */ int8_t is_mapped; #ifdef __ANDROID__ int8_t saved_mapped; #endif int8_t create_gc; /* button */ int8_t button_is_pressing; int8_t click_num; u_int8_t sizehint_flag; void (*window_realized)(struct ui_window *); void (*window_finalized)(struct ui_window *); void (*window_destroyed)(struct ui_window *); void (*mapping_notify)(struct ui_window *); /* Win32: gc->gc is not None. */ void (*window_exposed)(struct ui_window *, int, int, u_int, u_int); /* Win32: gc->gc is not None. */ void (*update_window)(struct ui_window *, int); void (*window_focused)(struct ui_window *); void (*window_unfocused)(struct ui_window *); void (*key_pressed)(struct ui_window *, XKeyEvent *); void (*pointer_motion)(struct ui_window *, XMotionEvent *); void (*button_motion)(struct ui_window *, XMotionEvent *); void (*button_released)(struct ui_window *, XButtonEvent *); void (*button_pressed)(struct ui_window *, XButtonEvent *, int); void (*button_press_continued)(struct ui_window *, XButtonEvent *); void (*window_resized)(struct ui_window *); void (*child_window_resized)(struct ui_window *, struct ui_window *); void (*selection_cleared)(struct ui_window *); void (*xct_selection_requested)(struct ui_window *, XSelectionRequestEvent *, Atom); void (*utf_selection_requested)(struct ui_window *, XSelectionRequestEvent *, Atom); void (*xct_selection_notified)(struct ui_window *, u_char *, size_t); void (*utf_selection_notified)(struct ui_window *, u_char *, size_t); /* * Don't remove if DISABLE_XDND is defined to keep the size of ui_window_t * for ui_im_xxx_screen_t. */ void (*set_xdnd_config)(struct ui_window *, char *, char *, char *); void (*idling)(struct ui_window *); #ifdef UIWINDOW_SUPPORTS_PREEDITING void (*preedit)(struct ui_window *, const char *, const char *); #endif } ui_window_t; int ui_window_init(ui_window_t *win, u_int width, u_int height, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc, u_int hmargin, u_int vmargin, int create_gc, int inputtable); void ui_window_final(ui_window_t *win); void ui_window_set_type_engine(ui_window_t *win, ui_type_engine_t type_engine); void ui_window_add_event_mask(ui_window_t *win, long event_mask); void ui_window_remove_event_mask(ui_window_t *win, long event_mask); #define ui_window_check_event_mask(win, mask) ((win)->event_mask & (mask)) /* int ui_window_grab_pointer( ui_window_t * win) ; */ void ui_window_ungrab_pointer(ui_window_t *win); int ui_window_set_wall_picture(ui_window_t *win, Pixmap pic, int do_expose); int ui_window_unset_wall_picture(ui_window_t *win, int do_expose); #ifdef USE_XLIB #define ui_window_has_wall_picture(win) ((win)->wall_picture_is_set) #else #define ui_window_has_wall_picture(win) ((win)->wall_picture != None) #endif int ui_window_set_transparent(ui_window_t *win, ui_picture_modifier_ptr_t pic_mod); int ui_window_unset_transparent(ui_window_t *win); void ui_window_set_cursor(ui_window_t *win, u_int cursor_shape); int ui_window_set_fg_color(ui_window_t *win, ui_color_t *fg_color); int ui_window_set_bg_color(ui_window_t *win, ui_color_t *bg_color); int ui_window_add_child(ui_window_t *win, ui_window_t *child, int x, int y, int map); int ui_window_remove_child(ui_window_t *win, ui_window_t *child); ui_window_t *ui_get_root_window(ui_window_t *win); GC ui_window_get_fg_gc(ui_window_t *win); GC ui_window_get_bg_gc(ui_window_t *win); int ui_window_show(ui_window_t *win, int hint); void ui_window_map(ui_window_t *win); void ui_window_unmap(ui_window_t *win); int ui_window_resize(ui_window_t *win, u_int width, u_int height, ui_resize_flag_t flag); int ui_window_resize_with_margin(ui_window_t *win, u_int width, u_int height, ui_resize_flag_t flag); void ui_window_set_maximize_flag(ui_window_t *win, ui_maximize_flag_t flag); void ui_window_set_normal_hints(ui_window_t *win, u_int min_width, u_int min_height, u_int width_inc, u_int height_inc); void ui_window_set_override_redirect(ui_window_t *win, int flag); int ui_window_set_borderless_flag(ui_window_t *win, int flag); int ui_window_move(ui_window_t *win, int x, int y); void ui_window_clear(ui_window_t *win, int x, int y, u_int width, u_int height); void ui_window_clear_all(ui_window_t *win); void ui_window_fill(ui_window_t *win, int x, int y, u_int width, u_int height); void ui_window_fill_with(ui_window_t *win, ui_color_t *color, int x, int y, u_int width, u_int height); void ui_window_blank(ui_window_t *win); #if 0 /* Not used */ void ui_window_blank_with(ui_window_t *win, ui_color_t *color); #endif /* if flag is 0, no update. */ void ui_window_update(ui_window_t *win, int flag); void ui_window_update_all(ui_window_t *win); void ui_window_idling(ui_window_t *win); int ui_window_receive_event(ui_window_t *win, XEvent *event); size_t ui_window_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event); #ifdef MANAGE_ROOT_WINDOWS_BY_MYSELF int ui_window_is_scrollable(ui_window_t *win); #else #define ui_window_is_scrollable(win) ((win)->is_scrollable) #endif int ui_window_scroll_upward(ui_window_t *win, u_int height); int ui_window_scroll_upward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height); int ui_window_scroll_downward(ui_window_t *win, u_int height); int ui_window_scroll_downward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int height); int ui_window_scroll_leftward(ui_window_t *win, u_int width); int ui_window_scroll_leftward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width); int ui_window_scroll_rightward_region(ui_window_t *win, int boundary_start, int boundary_end, u_int width); int ui_window_scroll_rightward(ui_window_t *win, u_int width); int ui_window_copy_area(ui_window_t *win, Pixmap src, PixmapMask mask, int src_x, int src_y, u_int width, u_int height, int dst_x, int dst_y); void ui_window_set_clip(ui_window_t *win, int x, int y, u_int width, u_int height); void ui_window_unset_clip(ui_window_t *win); void ui_window_draw_decsp_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int len); void ui_window_draw_decsp_image_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, u_char *str, u_int len); /* * ui_window_draw_*_string functions are used by ui_draw_str.[ch]. * Use ui_draw_str* functions usually. */ #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XCORE) void ui_window_draw_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, u_int len); void ui_window_draw_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, XChar2b *str, u_int len); void ui_window_draw_image_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, u_char *str, u_int len); void ui_window_draw_image_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, XChar2b *str, u_int len); #endif #ifdef USE_CONSOLE void ui_window_console_draw_decsp_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, u_char *str, u_int len, int line_style); void ui_window_console_draw_string(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, u_char *str, u_int len, int line_style); void ui_window_console_draw_string16(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, ui_color_t *bg_color, int x, int y, XChar2b *str, u_int len, int line_style); #endif #if !defined(NO_DYNAMIC_LOAD_TYPE) || defined(USE_TYPE_XFT) || defined(USE_TYPE_CAIRO) void ui_window_ft_draw_string8(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, u_char *str, size_t len); void ui_window_ft_draw_string32(ui_window_t *win, ui_font_t *font, ui_color_t *fg_color, int x, int y, /* FcChar32 */ u_int32_t *str, u_int len); #endif void ui_window_draw_rect_frame(ui_window_t *win, int x1, int y1, int x2, int y2); void ui_set_use_clipboard_selection(int use_it); int ui_is_using_clipboard_selection(void); int ui_window_set_selection_owner(ui_window_t *win, Time time); #define ui_window_is_selection_owner(win) ((win) == (win)->disp->selection_owner) int ui_window_string_selection_request(ui_window_t *win, Time time); int ui_window_xct_selection_request(ui_window_t *win, Time time); int ui_window_utf_selection_request(ui_window_t *win, Time time); void ui_window_send_picture_selection(ui_window_t *win, Pixmap pixmap, u_int width, u_int height); void ui_window_send_text_selection(ui_window_t *win, XSelectionRequestEvent *event, u_char *sel_data, size_t sel_len, Atom sel_type); void ui_set_window_name(ui_window_t *win, u_char *name); void ui_set_icon_name(ui_window_t *win, u_char *name); void ui_window_set_icon(ui_window_t *win, ui_icon_picture_ptr_t icon); void ui_window_remove_icon(ui_window_t *win); void ui_set_click_interval(int interval); int ui_get_click_interval(void); #define ui_window_get_modifier_mapping(win) ui_display_get_modifier_mapping((win)->disp) u_int ui_window_get_mod_ignore_mask(ui_window_t *win, KeySym *keysyms); u_int ui_window_get_mod_meta_mask(ui_window_t *win, char *mod_key); #ifdef SUPPORT_URGENT_BELL void ui_set_use_urgent_bell(int use); #else #define ui_set_use_urgent_bell(use) (0) #endif void ui_window_bell(ui_window_t *win, ui_bel_mode_t mode); void ui_window_translate_coordinates(ui_window_t *win, int x, int y, int *global_x, int *global_y); void ui_window_set_input_focus(ui_window_t *win); #ifdef USE_XLIB void ui_window_flush(ui_window_t *win); #else #define ui_window_flush(win) (0) #endif #ifdef DEBUG void ui_window_dump_children(ui_window_t *win); #endif #endif mlterm-3.8.9/uitoolkit/ui_shortcut.c010064400017600000144000000230031356600660700162770ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_shortcut.h" #include /* sscanf */ #include /* strchr/memcpy */ #include /* HAVE_WINDOWS_H */ #include #include #include #include #include /* strdup */ #ifndef CommandMask #define CommandMask (0) #endif /* * !! Notice !! * Mod1Mask - Mod5Mask are not distinguished. */ typedef struct key_func_table { char *name; ui_key_func_t func; } key_func_table_t; /* --- static variables --- */ static char *key_file = "mlterm/key"; /* * Button*Mask is disabled until Button* is specified in ~/.mlterm/key to avoid * such a problem as * http://sourceforge.net/mailarchive/message.php?msg_id=30866232 */ static int button_mask = 0; /* --- static variables --- */ static key_func_table_t key_func_table[] = { { "IM_HOTKEY", IM_HOTKEY, }, { "EXT_KBD", EXT_KBD, }, { "OPEN_SCREEN", OPEN_SCREEN, }, { "OPEN_PTY", OPEN_PTY, }, { "NEXT_PTY", NEXT_PTY, }, { "PREV_PTY", PREV_PTY, }, { "VSPLIT_SCREEN", VSPLIT_SCREEN, }, { "HSPLIT_SCREEN", HSPLIT_SCREEN, }, { "NEXT_SCREEN", NEXT_SCREEN, }, { "PREV_SCREEN", PREV_SCREEN, }, { "CLOSE_SCREEN", CLOSE_SCREEN, }, { "HEXPAND_SCREEN", HEXPAND_SCREEN, }, { "VEXPAND_SCREEN", VEXPAND_SCREEN, }, { "PAGE_UP", PAGE_UP, }, { "PAGE_DOWN", PAGE_DOWN, }, { "SCROLL_UP", SCROLL_UP, }, { "SCROLL_DOWN", SCROLL_DOWN, }, { "INSERT_SELECTION", INSERT_SELECTION, }, { "RESET", RESET, }, { "EXIT_PROGRAM", EXIT_PROGRAM, }, /* obsoleted: alias of OPEN_SCREEN */ { "NEW_PTY", OPEN_SCREEN, }, }; /* --- static functions --- */ static int read_conf(ui_shortcut_t *shortcut, char *filename) { bl_file_t *from; char *key; char *value; if (!(from = bl_file_open(filename, "r"))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " %s couldn't be opened.\n", filename); #endif return 0; } while (bl_conf_io_read(from, &key, &value)) { /* * [shortcut key]=[operation] */ ui_shortcut_parse(shortcut, key, value); } bl_file_close(from); return 1; } /* --- global functions --- */ void ui_shortcut_init(ui_shortcut_t *shortcut) { char *rcpath; ui_key_t default_key_map[] = { /* IM_HOTKEY */ { 0, 0, 0, }, /* EXT_KBD(obsolete) */ { 0, 0, 0, }, #if defined(USE_QUARTZ) || (defined(USE_SDL2) && defined(__APPLE__)) /* OPEN_SCREEN */ { XK_F1, CommandMask, 1, }, /* OPEN_PTY */ { XK_F2, CommandMask, 1, }, /* NEXT_PTY */ { XK_F3, CommandMask, 1, }, /* PREV_PTY */ { XK_F4, CommandMask, 1, }, #else /* OPEN_SCREEN */ { XK_F1, ControlMask, 1, }, /* OPEN_PTY */ { XK_F2, ControlMask, 1, }, /* NEXT_PTY */ { XK_F3, ControlMask, 1, }, /* PREV_PTY */ { XK_F4, ControlMask, 1, }, #endif /* HSPLIT_SCREEN */ { XK_F1, ShiftMask, 1, }, /* VSPLIT_SCREEN */ { XK_F2, ShiftMask, 1, }, /* NEXT_SCREEN */ { XK_F3, ShiftMask, 1, }, /* PREV_SCREEN */ { XK_F4, ShiftMask, 1, }, /* CLOSE_SCREEN */ { XK_F5, ShiftMask, 1, }, /* HEXPAND_SCREEN */ { XK_F6, ShiftMask, 1, }, /* VEXPAND_SCREEN */ { XK_F7, ShiftMask, 1, }, /* PAGE_UP(compatible with kterm) */ { XK_Prior, ShiftMask, 1, }, /* PAGE_DOWN(compatible with kterm) */ { XK_Next, ShiftMask, 1, }, /* SCROLL_UP */ { XK_Up, ShiftMask, 1, }, /* SCROLL_DOWN */ { XK_Down, ShiftMask, 1, }, /* INSERT_SELECTION */ #if defined(USE_QUARTZ) || (defined(USE_SDL2) && defined(__APPLE__)) { 'v', CommandMask, 1, }, #else { XK_Insert, ShiftMask, 1, }, #endif { XK_Pause, 0, 1, }, #ifdef DEBUG /* EXIT PROGRAM(only for debug) */ { XK_F1, ControlMask | ShiftMask, 1, }, #else { 0, 0, 0, }, #endif }; memcpy(&shortcut->map, &default_key_map, sizeof(default_key_map)); if ((shortcut->str_map = malloc(2 * sizeof(ui_str_key_t)))) { shortcut->str_map_size = 2; shortcut->str_map[0].ksym = 0; shortcut->str_map[0].state = Button1Mask | ControlMask; shortcut->str_map[0].str = #ifdef HAVE_WINDOWS_H strdup("menu:mlterm-menu.exe"); #else strdup("menu:mlterm-menu"); #endif shortcut->str_map[1].ksym = 0; shortcut->str_map[1].state = Button3Mask | ControlMask; shortcut->str_map[1].str = #ifdef HAVE_WINDOWS_H strdup("menu:mlconfig.exe"); #else strdup("menu:mlconfig"); #endif button_mask |= (Button1Mask | Button3Mask); } else { shortcut->str_map_size = 0; } if ((rcpath = bl_get_sys_rc_path(key_file))) { read_conf(shortcut, rcpath); free(rcpath); } if ((rcpath = bl_get_user_rc_path(key_file))) { read_conf(shortcut, rcpath); free(rcpath); } } void ui_shortcut_final(ui_shortcut_t *shortcut) { u_int count; for (count = 0; count < shortcut->str_map_size; count++) { free(shortcut->str_map[count].str); } free(shortcut->str_map); } int ui_shortcut_match(ui_shortcut_t *shortcut, ui_key_func_t func, KeySym ksym, u_int state) { if (shortcut->map[func].is_used == 0) { return 0; } /* ingoring except these masks */ state &= (ModMask | ControlMask | ShiftMask | CommandMask | button_mask); if (state & button_mask) { state &= ~Mod2Mask; /* XXX NumLock */ } if (shortcut->map[func].ksym == ksym && shortcut->map[func].state == (state | ((state & ModMask) && (shortcut->map[func].state & ModMask) == ModMask ? ModMask : 0))) { return 1; } else { return 0; } } char *ui_shortcut_str(ui_shortcut_t *shortcut, KeySym ksym, u_int state) { u_int count; /* ingoring except these masks */ state &= (ModMask | ControlMask | ShiftMask | CommandMask | button_mask); if (state & button_mask) { state &= ~Mod2Mask; /* XXX NumLock */ } for (count = 0; count < shortcut->str_map_size; count++) { if (shortcut->str_map[count].ksym == ksym && shortcut->str_map[count].state == (state | ((state & ModMask) && (shortcut->str_map[count].state & ModMask) == ModMask ? ModMask : 0))) { return shortcut->str_map[count].str; } } return NULL; } int ui_shortcut_parse(ui_shortcut_t *shortcut, char *key, char *oper) { char *p; KeySym ksym; u_int state; int count; if (strcmp(key, "UNUSED") == 0) { goto replace_shortcut_map; } state = 0; while ((p = strchr(key, '+')) != NULL) { *(p++) = '\0'; if (strcmp(key, "Control") == 0) { state |= ControlMask; } else if (strcmp(key, "Shift") == 0) { state |= ShiftMask; } else if (strcmp(key, "Mod") == 0 || strcmp(key, "Alt") == 0) { state |= ModMask; } else if (strncmp(key, "Mod", 3) == 0) { switch (key[3]) { case 0: state |= ModMask; break; case '1': state |= Mod1Mask; break; case '2': state |= Mod2Mask; break; case '3': state |= Mod3Mask; break; case '4': state |= Mod4Mask; break; case '5': state |= Mod5Mask; break; #ifdef DEBUG default: bl_warn_printf(BL_DEBUG_TAG " unrecognized Mod mask(%s)\n", key); break; #endif } } else if (strcmp(key, "Command") == 0) { state |= CommandMask; } #ifdef DEBUG else { bl_warn_printf(BL_DEBUG_TAG " unrecognized mask(%s)\n", key); } #endif key = p; } if (strncmp(key, "Button", 6) == 0) { state |= (Button1Mask << (key[6] - '1')); ksym = 0; } else if ((ksym = XStringToKeysym(key)) == NoSymbol) { return 0; } for (count = 0; count < sizeof(key_func_table) / sizeof(key_func_table_t); count++) { ui_key_t *map_entry; map_entry = shortcut->map + key_func_table[count].func; if (map_entry->ksym == ksym && map_entry->state == state) { map_entry->is_used = 0; break; } } for (count = 0; count < shortcut->str_map_size; count++) { if (shortcut->str_map[count].ksym == ksym && shortcut->str_map[count].state == state) { free(shortcut->str_map[count].str); shortcut->str_map[count] = shortcut->str_map[--shortcut->str_map_size]; break; } } if (*oper == '"') { char *str; char *p; ui_str_key_t *str_map; if (!(str = bl_str_unescape(++oper)) || !(p = strrchr(str, '\"')) || !(str_map = realloc(shortcut->str_map, sizeof(ui_str_key_t) * (shortcut->str_map_size + 1)))) { free(str); return 0; } *p = '\0'; str_map[shortcut->str_map_size].ksym = ksym; str_map[shortcut->str_map_size].state = state; str_map[shortcut->str_map_size].str = str; shortcut->str_map_size++; shortcut->str_map = str_map; } else { replace_shortcut_map: for (count = 0; count < sizeof(key_func_table) / sizeof(key_func_table_t); count++) { if (strcmp(oper, key_func_table[count].name) == 0) { if (strcmp(key, "UNUSED") == 0) { shortcut->map[key_func_table[count].func].is_used = 0; return 1; } else { shortcut->map[key_func_table[count].func].is_used = 1; shortcut->map[key_func_table[count].func].ksym = ksym; shortcut->map[key_func_table[count].func].state = state; goto success; } } } return 0; } success: if (state & ButtonMask) { int mask; for (mask = Button1Mask; mask <= Button7Mask; mask <<= 1) { if (state & mask) { button_mask |= mask; break; } } } return 1; } mlterm-3.8.9/uitoolkit/ui_shortcut.h010064400017600000144000000023051356600660700163060ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ /* * This manages short-cut keys of ui_screen key events. */ #ifndef __UI_SHORTCUT_H__ #define __UI_SHORTCUT_H__ #include "ui.h" #include typedef enum ui_key_func { IM_HOTKEY, EXT_KBD, OPEN_SCREEN, OPEN_PTY, NEXT_PTY, PREV_PTY, HSPLIT_SCREEN, VSPLIT_SCREEN, NEXT_SCREEN, PREV_SCREEN, CLOSE_SCREEN, HEXPAND_SCREEN, VEXPAND_SCREEN, PAGE_UP, PAGE_DOWN, SCROLL_UP, SCROLL_DOWN, INSERT_SELECTION, RESET, EXIT_PROGRAM, MAX_KEY_MAPS } ui_key_func_t; typedef struct ui_key { KeySym ksym; u_int state; int is_used; } ui_key_t; typedef struct ui_str_key { KeySym ksym; u_int state; char *str; } ui_str_key_t; typedef struct ui_shortcut { ui_key_t map[MAX_KEY_MAPS]; ui_str_key_t *str_map; u_int str_map_size; } ui_shortcut_t; void ui_shortcut_init(ui_shortcut_t *shortcut); void ui_shortcut_final(ui_shortcut_t *shortcut); int ui_shortcut_match(ui_shortcut_t *shortcut, ui_key_func_t func, KeySym sym, u_int state); char *ui_shortcut_str(ui_shortcut_t *shortcut, KeySym sym, u_int state); int ui_shortcut_parse(ui_shortcut_t *shortcut, char *key, char *oper); #endif mlterm-3.8.9/uitoolkit/ui_simple_sb_view.c010064400017600000144000000151601356600660700174400ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include #include #include #include "ui_sb_view.h" #include "ui_window.h" #define TOP_MARGIN 14 #define BOTTOM_MARGIN 14 #define HEIGHT_MARGIN (TOP_MARGIN + BOTTOM_MARGIN) #define WIDTH 13 typedef struct simple_sb_view { ui_sb_view_t view; ui_color_t black; ui_color_t white; int is_transparent; } simple_sb_view_t; /* --- static variables --- */ static char *arrow_up_src[] = {" ", " -----------#", " -----#-----#", " -----#-----#", " ----###----#", " ----###----#", " ---#####---#", " ---#####---#", " --#######--#", " --#######--#", " -#########-#", " -----------#", " -----------#", "#############" }; static char *arrow_down_src[] = {" ", " -----------#", " -----------#", " -#########-#", " --#######--#", " --#######--#", " ---#####---#", " ---#####---#", " ----###----#", " ----###----#", " -----#-----#", " -----#-----#", " -----------#", "#############" }; static char *arrow_up_dent_src[] = { " ", " -----------#", " ----- -----#", " ----- -----#", " ---- ----#", " ---- ----#", " --- ---#", " --- ---#", " -- --#", " -- --#", " - -#", " -----------#", " -----------#", "#############" }; static char *arrow_down_dent_src[] = { " ", " -----------#", " -----------#", " - -#", " -- --#", " -- --#", " --- ---#", " --- ---#", " ---- ----#", " ---- ----#", " ----- -----#", " ----- -----#", " -----------#", "#############" }; /* --- static functions --- */ static size_t count_char(char c, char *str) { char *p; p = str; while (*p == c) { p++; } return p - str; } static int draw_icon(ui_sb_view_t *view, int x, int y, char **data, unsigned int width, unsigned int height) { simple_sb_view_t *simple_sb; int x_off; int y_off; simple_sb = (simple_sb_view_t*)view; if (simple_sb->is_transparent) { ui_window_clear(view->win, x, y, width, height); } for (y_off = 0; y_off < height; y_off++) { for (x_off = 0; x_off < width;) { size_t count; count = count_char(data[y_off][x_off], data[y_off] + x_off); if (data[y_off][x_off] == '-') { if (!simple_sb->is_transparent) { ui_window_fill(view->win, x + x_off, y + y_off, count, 1); } } else if (data[y_off][x_off] == '#') { ui_window_fill_with(view->win, &simple_sb->black, x + x_off, y + y_off, count, 1); } else { ui_window_fill_with(view->win, &simple_sb->white, x + x_off, y + y_off, count, 1); } x_off += count; } } return 1; } static void get_geometry_hints(ui_sb_view_t *view, unsigned int *width, unsigned int *top_margin, unsigned int *bottom_margin, int *up_button_y, unsigned int *up_button_height, int *down_button_y, unsigned int *down_button_height) { *width = WIDTH; *top_margin = TOP_MARGIN; *bottom_margin = BOTTOM_MARGIN; *up_button_y = 0; *up_button_height = TOP_MARGIN; *down_button_y = -BOTTOM_MARGIN; *down_button_height = BOTTOM_MARGIN; } static void get_default_color(ui_sb_view_t *view, char **fg_color, char **bg_color) { *fg_color = "gray"; *bg_color = "lightgray"; } static void realized(ui_sb_view_t *view, Display *display, int screen, Window window, GC gc, unsigned int height) { simple_sb_view_t *simple_sb; simple_sb = (simple_sb_view_t*)view; view->display = display; view->screen = screen; view->window = window; view->gc = gc; view->height = height; ui_load_rgb_xcolor(view->win->disp, &simple_sb->black, 0x00, 0x00, 0x00, 0xff); ui_load_rgb_xcolor(view->win->disp, &simple_sb->white, 0xff, 0xff, 0xff, 0xff); } static void resized(ui_sb_view_t *view, Window window, unsigned int height) { view->window = window; view->height = height; } static void destroy(ui_sb_view_t *view) { free(view); } static void draw_arrow_up_icon(ui_sb_view_t *view, int is_dent) { draw_icon(view, 0, 0, is_dent ? arrow_up_dent_src : arrow_up_src, WIDTH, TOP_MARGIN); } static void draw_arrow_down_icon(ui_sb_view_t *view, int is_dent) { draw_icon(view, 0, view->height - BOTTOM_MARGIN, is_dent ? arrow_down_dent_src : arrow_down_src, WIDTH, BOTTOM_MARGIN); } static void draw_scrollbar(ui_sb_view_t *view, int bar_top_y, unsigned int bar_height) { simple_sb_view_t *simple_sb; simple_sb = (simple_sb_view_t*)view; /* drawing bar */ if (simple_sb->is_transparent) { ui_window_clear(view->win, 1, bar_top_y, WIDTH - 1, bar_height); } else { ui_window_fill(view->win, 1, bar_top_y, WIDTH - 1, bar_height); } /* left side shade */ ui_window_fill_with(view->win, &simple_sb->white, 0, bar_top_y, 1, bar_height); /* up side shade */ ui_window_fill_with(view->win, &simple_sb->white, 0, bar_top_y, WIDTH, 1); /* right side shade */ ui_window_fill_with(view->win, &simple_sb->black, WIDTH - 1, bar_top_y, 1, bar_height); /* down side shade */ ui_window_fill_with(view->win, &simple_sb->black, 1, bar_top_y + bar_height - 1, WIDTH - 1, 1); } static void draw_background(ui_sb_view_t *view, int y, unsigned int height) { ui_window_clear(view->win, 0, y, WIDTH, height); } static void draw_up_button(ui_sb_view_t *view, int is_pressed) { draw_arrow_up_icon(view, is_pressed); } static void draw_down_button(ui_sb_view_t *view, int is_pressed) { draw_arrow_down_icon(view, is_pressed); } /* --- global functions --- */ ui_sb_view_t *ui_simple_sb_view_new(void) { simple_sb_view_t *simple_sb; if ((simple_sb = calloc(1, sizeof(simple_sb_view_t))) == NULL) { return NULL; } simple_sb->view.version = 1; simple_sb->view.get_geometry_hints = get_geometry_hints; simple_sb->view.get_default_color = get_default_color; simple_sb->view.realized = realized; simple_sb->view.resized = resized; simple_sb->view.destroy = destroy; simple_sb->view.draw_scrollbar = draw_scrollbar; simple_sb->view.draw_background = draw_background; simple_sb->view.draw_up_button = draw_up_button; simple_sb->view.draw_down_button = draw_down_button; return &simple_sb->view; } ui_sb_view_t *ui_simple_transparent_sb_view_new(void) { simple_sb_view_t *simple_sb; if ((simple_sb = (simple_sb_view_t*)ui_simple_sb_view_new()) == NULL) { return NULL; } simple_sb->is_transparent = 1; return &simple_sb->view; } mlterm-3.8.9/uitoolkit/ui_simple_sb_view.h010064400017600000144000000004101356600660700174350ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_SIMPLE_SB_VIEW_H__ #define __UI_SIMPLE_SB_VIEW_H__ #include "ui_sb_view.h" ui_sb_view_t *ui_simple_sb_view_new(void); ui_sb_view_t *ui_simple_transparent_sb_view_new(void); #endif mlterm-3.8.9/uitoolkit/ui_type_engine.c010064400017600000144000000015431356600660700167370ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_type_engine.h" #include /* strcmp */ #include /* u_int */ /* --- static variables --- */ /* Order of this table must be same as ui_type_engine_t. */ static char *type_engine_name_table[] = { "xcore", "xft", "cairo", }; /* --- global functions --- */ ui_type_engine_t ui_get_type_engine_by_name(char *name) { if (strcmp("xcore", name) == 0) { return TYPE_XCORE; } else if (strcmp("xft", name) == 0) { return TYPE_XFT; } else if (strcmp("cairo", name) == 0) { return TYPE_CAIRO; } /* default value */ return TYPE_XCORE; } char *ui_get_type_engine_name(ui_type_engine_t engine) { if ((u_int)engine >= TYPE_ENGINE_MAX) { /* default value */ engine = TYPE_XCORE; } return type_engine_name_table[engine]; } mlterm-3.8.9/uitoolkit/ui_type_engine.h010064400017600000144000000006101356600660700167360ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_TYPE_ENGINE_H__ #define __UI_TYPE_ENGINE_H__ typedef enum ui_type_engine { TYPE_XCORE, /* Contains WIN32 native fonts. */ TYPE_XFT, TYPE_CAIRO, TYPE_ENGINE_MAX } ui_type_engine_t; ui_type_engine_t ui_get_type_engine_by_name(char *name); char *ui_get_type_engine_name(ui_type_engine_t mode); #endif mlterm-3.8.9/uitoolkit/ui_xic.h010064400017600000144000000031071356600660700152170ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_XIC_H__ #define __UI_XIC_H__ #include /* size_t */ #if defined(USE_WIN32GUI) || defined(USE_QUARTZ) || defined(USE_BEOS) #include #endif #include "ui.h" #include "ui_window.h" typedef struct ui_xic { XIC ic; #if defined(USE_WIN32GUI) WORD prev_keydown_wparam; ef_parser_t *parser; #elif defined(USE_QUARTZ) || defined(USE_BEOS) ef_parser_t *parser; #elif defined(USE_XLIB) XFontSet fontset; XIMStyle style; #endif } ui_xic_t; int ui_xic_activate(ui_window_t *win, char *name, char *locale); int ui_xic_deactivate(ui_window_t *win); char *ui_xic_get_xim_name(ui_window_t *win); char *ui_xic_get_default_xim_name(void); int ui_xic_fg_color_changed(ui_window_t *win); int ui_xic_bg_color_changed(ui_window_t *win); int ui_xic_font_set_changed(ui_window_t *win); int ui_xic_resized(ui_window_t *win); int ui_xic_set_spot(ui_window_t *win); size_t ui_xic_get_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event); size_t ui_xic_get_utf8_str(ui_window_t *win, u_char *seq, size_t seq_len, ef_parser_t **parser, KeySym *keysym, XKeyEvent *event); int ui_xic_filter_event(ui_window_t *win, XEvent *event); int ui_xic_set_focus(ui_window_t *win); int ui_xic_unset_focus(ui_window_t *win); int ui_xic_is_active(ui_window_t *win); int ui_xic_switch_mode(ui_window_t *win); int ui_xim_activated(ui_window_t *win); int ui_xim_destroyed(ui_window_t *win); #endif mlterm-3.8.9/uitoolkit/Makefile.in010064400017600000144000000067541356600660700156460ustar kenuserstop_builddir = .. top_srcdir = @top_srcdir@ prefix = @prefix@ sysconfdir = @sysconfdir@ exec_prefix = @exec_prefix@ datadir = @datadir@ bindir = @bindir@ libdir = @libdir@ libexecdir = @libexecdir@ CC = @CC@ LIBTOOL = @LIBTOOL@ INSTALL = @INSTALL@ BINDIR = $(DESTDIR)$(bindir) VPATH = $(top_srcdir)/uitoolkit/@GUI@:$(top_srcdir)/uitoolkit OBJ1 = ui_screen_manager.o ui_display.o ui_window.o ui_screen.o \ ui_xic.o ui_color_manager.o ui_font_manager.o ui_picture.o ui_font.o \ ui_color.o ui_selection.o ui_font_config.o ui_main_config.o \ ui_shortcut.o ui_bel_mode.o ui_sb_mode.o ui_mod_meta_mode.o ui_font_cache.o \ ui_draw_str.o ui_gc.o ui_color_cache.o ui_dnd.o ui_scrollbar.o ui_layout.o \ ui_sb_view_factory.o ui_simple_sb_view.o ui_imagelib.o ui_connect_dialog.o \ ui_type_engine.o ui_im.o ui_im_candidate_screen.o ui_brltty.o \ ui_selection_encoding.o ui_emoji.o test.o OBJ2_xlib = ui_event_source.o ui_decsp_font.o ui_xim.o ui_im_status_screen.o @TYPE_LOADER_OBJ@ OBJ2_win32 = ui_event_source.o ui_gdiobj_pool.o ui.o ui_im_status_screen.o OBJ2_fb = ui.o ui_event_source.o ui_decsp_font.o ui_virtual_kbd.o ui_im_status_screen.o OBJ2_beos = ui.o ui_event_source.o beos.o ui_im_status_screen.o OBJ2_quartz = ui.o @COCOAOBJ@ ui_event_source-cocoa.o ui_im_status_screen-cocoa.o OBJ2_console = ui.o ui_event_source.o ui_im_status_screen.o OBJ2_wayland = ui.o ui_event_source.o ui_decsp_font.o ui_im_status_screen.o \ xdg-shell-unstable-v6-client-protocol.o gtk-primary-selection.o OBJ2_sdl2 = ui.o ui_event_source.o ui_decsp_font.o ui_im_status_screen.o syswminfo.o RSOBJ_win32 = winrs.o RSOBJ_sdl2_win32 = winrs.o RSOBJ_sdl2 = $(RSOBJ_@GUI@_@SDL2GUI@) OBJ = $(OBJ1) $(OBJ2_@GUI@) XDISPLAY_DEPENDS_fb = ui_display_freebsd.c ui_display_linux.c ui_display_wscons.c ui_display_x68kgrf.c LIBNAME = libuitoolkit # XDATADIR is to avoid conflicting with DATADIR structure in w32api/objidl.h. CFLAGS = $(CFLAGS_LOCAL) @POBL_CFLAGS@ @MEF_CFLAGS@ @DEB_CFLAGS@ @MATH_CFLAGS@ \ @IMAGELIB_CFLAGS@ @X_CFLAGS@ @GUI_CFLAGS@ @SSH2_CFLAGS@ @XUTF8_CFLAGS@ @DND_CFLAGS@ \ @IM_CFLAGS@ @SB_CFLAGS@ @REGEX_CFLAGS@ @CTL_CFLAGS@ @TYPE_CFLAGS@ @FT_CFLAGS@ \ @IMAGE_CFLAGS@ @TOOLS_CFLAGS@ @OT_LAYOUT_CFLAGS@ @SIXEL_CFLAGS@ @BRLAPI_CFLAGS@ \ @SDL2_CFLAGS@ @CFLAGS@ @CPPFLAGS@ \ -DBINDIR=\"$(bindir)\" -DLIBDIR=\"$(libdir)\" -DLIBEXECDIR=\"$(libexecdir)\" \ -DXDATADIR=\"$(datadir)\" \ -I$(top_srcdir)/vtemu -I$(top_srcdir)/uitoolkit/libotl -I/usr/local/include LIBTOOL_CC = $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) all: $(LIBNAME).a debug: $(LIBNAME).a # If winrs.o is archived to libuitoolkit.a, connect dialog is not shown correctly. $(LIBNAME).a: $(OBJ) $(RSOBJ_@GUI@) $(LIBTOOL_LINK) -o $(LIBNAME).a $(OBJ:.o=.lo) .SUFFIXES: .c.o .m.o .cpp.o .c.o: $(LIBTOOL_CC) -c $< .m.o: $(LIBTOOL_CC) -c $< .cpp.o: $(LIBTOOL_CC) -c $< ui_display.o: ui_display.c $(XDISPLAY_DEPENDS_@GUI@) $(LIBTOOL_CC) -c $< winrs.o: winrs.rs cp $(top_srcdir)/contrib/icon/mlterm-icon-win32.ico . \ # windres-2.11.90(included in MSYS-DTK 1.0.1) doesn't accept '-I[DIR]' option. `echo $(CC)|sed -n 's/\([^-]*-[^-]*-[^-]*-\).*/\1/p'`windres `echo "@POBL_CFLAGS@ @MEF_CFLAGS@"|sed 's/-I/--include-dir /'` @GUI_CFLAGS@ @SSH2_CFLAGS@ $< winrs.o \ install: uninstall: wc: find . -name "*.[ch]" -a \! -name "test_*" | xargs wc -l clean: rm -rf *.a *.la $(OBJ) $(OBJ:.o=.lo) $(RSOBJ_win32) mlterm-icon-win32.ico .libs distclean: clean rm -f Makefile mlterm-3.8.9/uitoolkit/test.c010064400017600000144000000011251356600660700147070ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifdef BL_DEBUG #include "ui.h" /* USE_XLIB */ void TEST_bl_args(void); void TEST_bl_map(void); void TEST_bl_path(void); void TEST_ui_font_config(void); #ifndef NO_IMAGE void TEST_sixel_realloc_pixels(void); #endif #ifndef USE_XLIB void TEST_xstringtokeysym(void); #endif /* -- global functions --- */ void test(void) { TEST_bl_args(); TEST_bl_map(); TEST_bl_path(); TEST_ui_font_config(); #ifndef NO_IMAGE TEST_sixel_realloc_pixels(); #endif #ifndef USE_XLIB TEST_xstringtokeysym(); #endif } #endif /* BL_DEBUG */ mlterm-3.8.9/uitoolkit/ui.h010064400017600000144000000025141356600660700143550ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_H__ #define __UI_H__ #if defined(USE_WIN32GUI) #include "win32/ui.h" #define GUI_TYPE "win32" #elif defined(USE_CONSOLE) #include "console/ui.h" #define GUI_TYPE "console" #elif defined(USE_FRAMEBUFFER) #include "fb/ui.h" #define GUI_TYPE "fb" #elif defined(USE_QUARTZ) #include "quartz/ui.h" #define GUI_TYPE "quartz" #elif defined(USE_BEOS) #include "beos/ui.h" #define GUI_TYPE "beos" #elif defined(USE_WAYLAND) #include "wayland/ui.h" #define GUI_TYPE "wayland" #elif defined(USE_SDL2) #include "sdl2/ui.h" #define GUI_TYPE "sdl2" #else #include "xlib/ui.h" #define USE_XLIB #define GUI_TYPE "xlib" #endif /* * Note for XStringToKeysym(char *str) * The values of 'a'-'z' keysyms are always 0x61-0x7a, but the values of other * keysyms (signs, digits etc) aren't necessarily their ascii values. */ /* * Xlib utility definitions. */ #define ModMask (Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask) #ifndef Button6 #define Button6 6 #endif #ifndef Button6Mask #define Button6Mask (Button5Mask << 1) #endif #ifndef Button7 #define Button7 7 #endif #ifndef Button7Mask #define Button7Mask (Button5Mask << 2) #endif #define ButtonMask \ (Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask | Button6Mask | Button7Mask) #endif mlterm-3.8.9/uitoolkit/ui_bel_mode.c010064400017600000144000000014461356600660700162010ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_bel_mode.h" #include /* strcmp */ #include /* u_int */ /* --- static variables --- */ /* Order of this table must be same as ui_bel_mode_t. */ static char *bel_mode_name_table[] = {"none", "sound", "visual", "sound|visual"}; /* --- global functions --- */ ui_bel_mode_t ui_get_bel_mode_by_name(char *name) { ui_bel_mode_t mode; for (mode = 0; mode < BEL_MODE_MAX; mode++) { if (strcmp(bel_mode_name_table[mode], name) == 0) { return mode; } } /* default value */ return BEL_SOUND; } char *ui_get_bel_mode_name(ui_bel_mode_t mode) { if ((u_int)mode >= BEL_MODE_MAX) { /* default value */ mode = BEL_SOUND; } return bel_mode_name_table[mode]; } mlterm-3.8.9/uitoolkit/ui_bel_mode.h010064400017600000144000000005761356600660700162110ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_BEL_MODE_H__ #define __UI_BEL_MODE_H__ typedef enum ui_bel_mode { BEL_NONE = 0x0, BEL_SOUND = 0x1, BEL_VISUAL = 0x2, /* BEL_SOUND|BEL_VISUAL */ BEL_MODE_MAX = 0x4 } ui_bel_mode_t; ui_bel_mode_t ui_get_bel_mode_by_name(char *name); char *ui_get_bel_mode_name(ui_bel_mode_t mode); #endif mlterm-3.8.9/uitoolkit/ui_brltty.c010064400017600000144000000255341356600660700157570ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifdef USE_BRLAPI #include "ui_brltty.h" #include #include #include #include /* SIZEOF_WCHAR_T_STR */ #include /* WORDS_BIGENDIAN */ #include #include #include /* bl_priv_change_e(u|g)id */ #include #include #include #include #include #include "vt_str_parser.h" #include "vt_term.h" #include "ui_event_source.h" /* --- static variables --- */ static vt_term_t *focus_term; static int brltty_fd = -1; static ef_parser_t *parser; static ef_conv_t *conv; static ef_conv_t *wconv; static u_int display_cols; static u_int display_rows; static int viewport_row; static int viewport_col; /* --- static functions --- */ static void write_line_to_display(vt_line_t *line, int cursor /* The first position is 1 not 0 */) { u_char *buf; if (cursor > 0) { if (viewport_col >= cursor) { cursor = BRLAPI_CURSOR_OFF; } else { cursor -= viewport_col; } } if (viewport_col >= vt_line_get_num_filled_chars_except_sp(line)) { brlapi_writeText(cursor, ""); return; } (*parser->init)(parser); vt_str_parser_set_str(parser, line->chars + viewport_col, vt_line_get_num_filled_chars_except_sp(line) - viewport_col); (*wconv->init)(conv); if ((buf = alloca(display_cols * sizeof(wchar_t) + 4))) { ssize_t len; if ((len = (*wconv->convert)(wconv, buf, display_cols * sizeof(wchar_t), parser)) > 0) { memset(buf + len, 0, 4); brlapi_writeWText(cursor, buf); } } } static void speak(const u_char *msg, size_t len) { const char *path; if ((path = getenv("BRLTTY_SPEECH_INPUT"))) { int fd; if ((fd = open(path, O_WRONLY|O_NONBLOCK, 0200)) != -1) { #ifdef DEBUG char *buf = alloca(len + 1); memcpy(buf, msg, len); buf[len] = '\0'; bl_debug_printf("SPEECH: %s %x\n", buf, *buf); #endif write(fd, msg, len); close(fd); } } } static void speak_line(vt_line_t *line, int full) { u_char *buf; int beg; u_int cols; cols = vt_line_get_num_filled_chars_except_sp(line); if (full) { if (cols == 0) { return; } beg = 0; } else { if ((beg = viewport_col) >= cols) { return; } if ((cols -= viewport_col) >= display_cols) { cols = display_cols; } } (*parser->init)(parser); vt_str_parser_set_str(parser, line->chars + beg, cols); (*conv->init)(conv); if ((buf = alloca(display_cols * UTF_MAX_SIZE))) { ssize_t len; if ((len = (*conv->convert)(conv, buf, display_cols * UTF_MAX_SIZE, parser)) > 0) { speak(buf, len); } } } static void read_key(void) { brlapi_keyCode_t key; if (brltty_fd < 0 || focus_term == NULL) { return; } if (brlapi_readKey(1, &key) > 0) { brlapi_expandedKeyCode_t ekey; #ifdef DEBUG brlapi_describedKeyCode_t dkey; #endif brlapi_expandKeyCode(key, &ekey); #ifdef DEBUG bl_debug_printf("Keycode %x: type %u, command %u, argument %u, flags %u\n", key, ekey.type, ekey.command, ekey.argument, ekey.flags); brlapi_describeKeyCode(key, &dkey); bl_debug_printf("type %s, command %s, argument %u, flags %u\n", dkey.type, dkey.command, dkey.argument, dkey.flags); #endif if (ekey.command) { vt_line_t *line; if (ekey.command == BRLAPI_KEY_CMD_TOP || ekey.command == BRLAPI_KEY_CMD_TOP_LEFT) { viewport_row = 0; } else if (ekey.command == BRLAPI_KEY_CMD_BOT || ekey.command == BRLAPI_KEY_CMD_BOT_LEFT) { viewport_row = vt_term_get_rows(focus_term) - 1; } else if (ekey.command == BRLAPI_KEY_CMD_LNUP) { viewport_row--; } else if (ekey.command == BRLAPI_KEY_CMD_LNDN) { viewport_row++; } else if (ekey.command == BRLAPI_KEY_CMD_CHRRT) { viewport_col++; } else if (ekey.command == BRLAPI_KEY_CMD_CHRLT) { viewport_col--; } else if (ekey.command == BRLAPI_KEY_CMD_FWINRT) { viewport_col ++; } else if (ekey.command == BRLAPI_KEY_CMD_FWINLT) { viewport_col --; } else if (ekey.command == BRLAPI_KEY_CMD_FWINRTSKIP) { viewport_col += display_cols; } else if (ekey.command == BRLAPI_KEY_CMD_FWINLTSKIP) { viewport_col -= display_cols; } else if (ekey.command == BRLAPI_KEY_CMD_HOME) { viewport_row = vt_term_cursor_row(focus_term); viewport_col = 0; } else if (ekey.command == BRLAPI_KEY_CMD_SAY_LINE || ekey.command == BRLAPI_KEY_CMD_SPEAK_CURR_LINE) { if ((line = vt_term_get_line(focus_term, viewport_row))) { speak_line(line, 1); } return; } else if (ekey.command == BRLAPI_KEY_CMD_SAY_ABOVE) { int row; for (row = 0; row <= viewport_row; row++) { if ((line = vt_term_get_line(focus_term, row))) { speak_line(line, 1); } } return; } else if (ekey.command == BRLAPI_KEY_CMD_SAY_BELOW) { int row; for (row = viewport_row; row < vt_term_get_rows(focus_term); row++) { if ((line = vt_term_get_line(focus_term, row))) { speak_line(line, 1); } } return; } else { return; } if (viewport_col < 0) { viewport_col = 0; } else if (viewport_col >= vt_term_get_cols(focus_term)) { viewport_col = vt_term_get_cols(focus_term) - 1; } if (viewport_row < 0) { viewport_row = 0; } else if (viewport_row >= vt_term_get_rows(focus_term)) { viewport_row = vt_term_get_rows(focus_term) - 1; } if ((line = vt_term_get_line(focus_term, viewport_row))) { vt_line_set_modified_all(line); write_line_to_display(line, viewport_row == vt_term_cursor_row(focus_term) ? vt_term_cursor_char_index(focus_term) + 1 : BRLAPI_CURSOR_OFF); speak_line(line, 0); } } else if (ekey.argument < 0xff) { u_char c = ekey.argument; vt_term_write(focus_term, &c, 1); } } } static void viewport_home(void) { viewport_row = vt_term_cursor_row(focus_term); if (display_cols <= vt_term_cursor_char_index(focus_term)) { viewport_col = vt_term_cursor_char_index(focus_term) - display_cols + 1; } else { viewport_col = 0; } } /* --- global functions --- */ int ui_brltty_init(void) { char name[BRLAPI_MAXNAMELENGTH+1]; brlapi_connectionSettings_t set = { NULL, NULL }; bl_priv_restore_euid(); bl_priv_restore_egid(); brltty_fd = brlapi_openConnection(&set, &set); bl_priv_change_euid(bl_getuid()); bl_priv_change_egid(bl_getgid()); if (brltty_fd < 0) { bl_warn_printf("Failed to connect to brltty (%s)\n", brlapi_strerror(&brlapi_error)); return -1; } if (brlapi_getDriverName(name, sizeof(name)) < 0) { #ifdef DEBUG bl_debug_printf("brlapi_getDriverName failed (%s)\n", brlapi_strerror(&brlapi_error)); #endif } #ifdef DEBUG else { bl_debug_printf("Driver name: %s\n", name); } #endif if (brlapi_getDisplaySize(&display_cols, &display_rows) < 0) { bl_warn_printf("Illegal brltty display size (%s)\n", brlapi_strerror(&brlapi_error)); goto error; } else { #ifdef DEBUG bl_debug_printf("Braille display line %d column %d\n", display_rows, display_cols); #endif if (display_cols == 0 || display_rows == 0) { bl_warn_printf("Illegal brltty display size (%s)\n", brlapi_strerror(&brlapi_error)); goto error; } } /* Try entering raw mode, immediately go out from raw mode */ if (brlapi_enterRawMode(name) < 0) { #ifdef DEBUG bl_debug_printf("brlapi_enterRawMode failed (%s)\n", brlapi_strerror(&brlapi_error)); #endif } else { brlapi_leaveRawMode(); } if (brlapi_enterTtyMode(0 /* BRLAPI_TTY_DEFAULT */, NULL) < 0) { bl_warn_printf("Failed to enter tty mode (%s)\n", brlapi_strerror(&brlapi_error)); goto error; } if (!parser) { parser = vt_str_parser_new(); } if (!conv) { conv = ef_utf8_conv_new(); } if (!wconv) { #ifdef SIZEOF_WCHAR_T_STR if (strcmp(SIZEOF_WCHAR_T_STR, "4") == 0) { #ifdef WORDS_BIGENDIAN wconv = ef_utf32_conv_new(); #else wconv = ef_utf32le_conv_new(); #endif } else #endif { #ifdef WORDS_BIGENDIAN wconv = ef_utf16_conv_new(); #else wconv = ef_utf16le_conv_new(); #endif } } #ifdef DEBUG bl_debug_printf("Connect to brltty successfully.\n"); #endif ui_event_source_add_fd(brltty_fd, read_key); return brltty_fd; error: brlapi_closeConnection(); brltty_fd = -1; return -1; } int ui_brltty_final(void) { if (brltty_fd >= 0) { ui_event_source_remove_fd(brltty_fd); brlapi_leaveTtyMode(); brlapi_closeConnection(); (*parser->destroy)(parser); (*conv->destroy)(conv); (*wconv->destroy)(wconv); } return brltty_fd; } void ui_brltty_focus(vt_term_t *term) { if (focus_term == NULL) { speak("m l term started", 16); } focus_term = term; } void ui_brltty_write(void) { vt_line_t *line; if (brltty_fd < 0 || focus_term == NULL) { return; } line = vt_term_get_cursor_line(focus_term); if (!vt_line_is_modified(line) && viewport_row == vt_term_cursor_row(focus_term)) { return; } viewport_home(); write_line_to_display(line, vt_term_cursor_char_index(focus_term) + 1); } void ui_brltty_speak_key(KeySym ksym, const u_char *kstr, size_t len) { const char *path; if ((path = getenv("BRLTTY_SPEECH_INPUT"))) { int fd; if ((fd = open(path, O_WRONLY|O_NONBLOCK, 0200)) != -1) { char *str; if (ksym == XK_BackSpace) { str = "backspace"; } else if (ksym == XK_Delete) { str = "delete"; } else if (ksym == ' ') { str = "space"; } else if (ksym == XK_Return) { str = "return"; } else if (ksym == XK_Tab) { str = "tab"; } else if (ksym == XK_Insert) { str = "insert"; } else if (ksym == XK_Home) { str = "home"; } else if (ksym == XK_End) { str = "end"; } else if (ksym == XK_F1) { str = "f1"; } else if (ksym == XK_F2) { str = "f2"; } else if (ksym == XK_F3) { str = "f3"; } else if (ksym == XK_F4) { str = "f4"; } else if (ksym == XK_Prior) { str = "page up"; } else if (ksym == XK_Next) { str = "page down"; } else if (ksym == XK_Up) { str = "up"; } else if (ksym == XK_Down) { str = "down"; } else if (ksym == XK_Right) { str = "right"; } else if (ksym == XK_Left) { str = "left"; } else { str = NULL; } if (str) { len = strlen(str); } else { str = kstr; } write(fd, str, len); close(fd); } } } #endif mlterm-3.8.9/uitoolkit/ui_brltty.h010064400017600000144000000005371356600660700157600ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_BRLTTY_H__ #define __UI_BRLTTY_H__ #include #include "ui.h" int ui_brltty_init(void); int ui_brltty_final(void); void ui_brltty_focus(vt_term_t *term); void ui_brltty_write(void); void ui_brltty_key(KeySym ksym, const u_char *kstr, size_t len); #endif mlterm-3.8.9/uitoolkit/ui_color.h010064400017600000144000000016421356600660700155540ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_COLOR_H__ #define __UI_COLOR_H__ #include #include /* alloca */ #include "ui_display.h" typedef struct ui_color { /* Public */ u_int32_t pixel; #ifdef UI_COLOR_HAS_RGB /* Private except ui_color_cache.c */ u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; #endif } ui_color_t; int ui_load_named_xcolor(ui_display_t *disp, ui_color_t *xcolor, char *name); int ui_load_rgb_xcolor(ui_display_t *disp, ui_color_t *xcolor, u_int8_t red, u_int8_t green, u_int8_t blue, u_int8_t alpha); void ui_unload_xcolor(ui_display_t *disp, ui_color_t *xcolor); void ui_get_xcolor_rgba(u_int8_t *red, u_int8_t *green, u_int8_t *blue, u_int8_t *alpha, ui_color_t *xcolor); int ui_xcolor_fade(ui_display_t*, ui_color_t *xcolor, u_int fade_ratio); #endif mlterm-3.8.9/uitoolkit/ui_color_cache.c010064400017600000144000000152031356600660700166700ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_color_cache.h" #include #include /* --- static variables --- */ static ui_color_cache_t **color_caches; static u_int num_caches; /* --- static functions --- */ static ui_color_cache_256ext_t *acquire_color_cache_256ext(ui_display_t *disp) { u_int count; ui_color_cache_256ext_t *cache; for (count = 0; count < num_caches; count++) { if (color_caches[count]->disp == disp && color_caches[count]->cache_256ext) { color_caches[count]->cache_256ext->ref_count++; return color_caches[count]->cache_256ext; } } if ((cache = calloc(1, sizeof(ui_color_cache_256ext_t))) == NULL) { return NULL; } cache->ref_count = 1; return cache; } static ui_color_t *get_cached_256ext_xcolor(ui_color_cache_t *color_cache, vt_color_t color) { u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; if (!IS_256EXT_COLOR(color)) { return NULL; } if (!color_cache->cache_256ext && !(color_cache->cache_256ext = acquire_color_cache_256ext(color_cache->disp))) { return NULL; } if (color_cache->cache_256ext->is_loaded[color - 16]) { if (IS_256_COLOR(color) || !vt_ext_color_is_changed(color)) { return &color_cache->cache_256ext->xcolors[color - 16]; } else { u_int count; for (count = 0; count < num_caches; count++) { if (color_caches[count]->cache_256ext) { ui_unload_xcolor(color_caches[count]->disp, &color_caches[count]->cache_256ext->xcolors[color - 16]); color_caches[count]->cache_256ext->is_loaded[color - 16] = 0; } } } } if (!vt_get_color_rgba(color, &red, &green, &blue, &alpha) || !ui_load_rgb_xcolor(color_cache->disp, &color_cache->cache_256ext->xcolors[color - 16], red, green, blue, alpha)) { return NULL; } /* * 16-479 colors ignore color_cache->fade_ratio. */ #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " new color %x %x\n", color, color_cache->cache_256ext->xcolors[color - 16].pixel); #endif color_cache->cache_256ext->is_loaded[color - 16] = 1; return &color_cache->cache_256ext->xcolors[color - 16]; } static ui_color_t *get_cached_vtsys_xcolor(ui_color_cache_t *color_cache, vt_color_t color) { u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; if (!IS_VTSYS_COLOR(color)) { return NULL; } if (color_cache->is_loaded[color]) { return &color_cache->xcolors[color]; } if (!vt_get_color_rgba(color, &red, &green, &blue, &alpha) || !ui_load_rgb_xcolor(color_cache->disp, &color_cache->xcolors[color], red, green, blue, alpha)) { return NULL; } if (color_cache->fade_ratio < 100) { if (!ui_xcolor_fade(color_cache->disp, &color_cache->xcolors[color], color_cache->fade_ratio)) { return NULL; } } #ifdef DEBUG #ifdef UI_COLOR_HAS_RGB bl_debug_printf(BL_DEBUG_TAG " new color %x red %x green %x blue %x\n", color, color_cache->xcolors[color].red, color_cache->xcolors[color].green, color_cache->xcolors[color].blue); #endif #endif color_cache->is_loaded[color] = 1; return &color_cache->xcolors[color]; } /* --- global functions --- */ ui_color_cache_t *ui_acquire_color_cache(ui_display_t *disp, u_int8_t fade_ratio) { u_int count; ui_color_cache_t *color_cache; void *p; for (count = 0; count < num_caches; count++) { if (color_caches[count]->disp == disp && color_caches[count]->fade_ratio == fade_ratio) { color_caches[count]->ref_count++; return color_caches[count]; } } if ((p = realloc(color_caches, sizeof(ui_color_cache_t*) * (num_caches + 1))) == NULL) { return NULL; } color_caches = p; if ((color_cache = calloc(1, sizeof(ui_color_cache_t))) == NULL) { return NULL; } color_cache->disp = disp; color_cache->fade_ratio = fade_ratio; if (!ui_load_rgb_xcolor(color_cache->disp, &color_cache->black, 0, 0, 0, 0xff)) { free(color_cache); return NULL; } color_cache->ref_count = 1; color_caches[num_caches++] = color_cache; return color_cache; } void ui_release_color_cache(ui_color_cache_t *color_cache) { u_int count; if (--color_cache->ref_count > 0) { return; } for (count = 0; count < num_caches; count++) { if (color_caches[count] == color_cache) { color_caches[count] = color_caches[--num_caches]; ui_color_cache_unload(color_cache); ui_unload_xcolor(color_cache->disp, &color_cache->black); free(color_cache); if (num_caches == 0) { free(color_caches); color_caches = NULL; } return; } } } void ui_color_cache_unload(ui_color_cache_t *color_cache) { vt_color_t color; for (color = 0; color < sizeof(color_cache->xcolors) / sizeof(color_cache->xcolors[0]); color++) { if (color_cache->is_loaded[color]) { ui_unload_xcolor(color_cache->disp, &color_cache->xcolors[color]); color_cache->is_loaded[color] = 0; } } if (color_cache->cache_256ext && --color_cache->cache_256ext->ref_count == 0) { ui_color_cache_256ext_t *cache_256ext; cache_256ext = color_cache->cache_256ext; for (color = 0; color < sizeof(cache_256ext->xcolors) / sizeof(cache_256ext->xcolors[0]); color++) { if (cache_256ext->is_loaded[color]) { ui_unload_xcolor(color_cache->disp, &cache_256ext->xcolors[color]); cache_256ext->is_loaded[color] = 0; } } free(cache_256ext); color_cache->cache_256ext = NULL; } } void ui_color_cache_unload_all(void) { u_int count; for (count = 0; count < num_caches; count++) { ui_color_cache_unload(color_caches[count]); } } /* Not cached */ int ui_load_xcolor(ui_color_cache_t *color_cache, ui_color_t *xcolor, char *name) { if (!ui_load_named_xcolor(color_cache->disp, xcolor, name)) { return 0; } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " new color %x\n", xcolor->pixel); #endif if (color_cache->fade_ratio < 100) { if (!ui_xcolor_fade(color_cache->disp, xcolor, color_cache->fade_ratio)) { return 0; } } #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " new color %s %x\n", name, xcolor->pixel); #endif return 1; } /* Always return non-null value. */ ui_color_t *ui_get_cached_xcolor(ui_color_cache_t *color_cache, vt_color_t color) { ui_color_t *xcolor; if ((xcolor = get_cached_vtsys_xcolor(color_cache, color))) { return xcolor; } if ((xcolor = get_cached_256ext_xcolor(color_cache, color))) { return xcolor; } bl_msg_printf("Loading color 0x%x failed. Using black color instead.\n", color); return &color_cache->black; } mlterm-3.8.9/uitoolkit/ui_color_cache.h010064400017600000144000000020241356600660700166720ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __UI_COLOR_CACHE_H__ #define __UI_COLOR_CACHE_H__ #include #include "ui_color.h" typedef struct ui_color_cache_256ext { ui_color_t xcolors[MAX_256EXT_COLORS]; u_int8_t is_loaded[MAX_256EXT_COLORS]; u_int ref_count; } ui_color_cache_256ext_t; typedef struct ui_color_cache { ui_display_t *disp; ui_color_t xcolors[MAX_VTSYS_COLORS]; u_int8_t is_loaded[MAX_VTSYS_COLORS]; ui_color_cache_256ext_t *cache_256ext; ui_color_t black; u_int8_t fade_ratio; u_int16_t ref_count; /* 0 - 65535 */ } ui_color_cache_t; ui_color_cache_t *ui_acquire_color_cache(ui_display_t *disp, u_int8_t fade_ratio); void ui_release_color_cache(ui_color_cache_t *color_cache); void ui_color_cache_unload(ui_color_cache_t *color_cache); void ui_color_cache_unload_all(void); int ui_load_xcolor(ui_color_cache_t *color_cache, ui_color_t *xcolor, char *name); ui_color_t *ui_get_cached_xcolor(ui_color_cache_t *color_cache, vt_color_t color); #endif mlterm-3.8.9/uitoolkit/ui_color_manager.c010064400017600000144000000255441356600660700172500ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ui_color_manager.h" #include /* sprintf */ #include /* memset */ #include #include #include /* strdup */ enum { _FG_COLOR = 0x0, _BG_COLOR = 0x1, _BOLD_COLOR = 0x2, _UNDERLINE_COLOR = 0x3, _BLINKING_COLOR = 0x4, _REVERSE_COLOR = 0x5, _ITALIC_COLOR = 0x6, _CROSSED_OUT_COLOR = 0x7, _CUR_FG_COLOR = 0x8, _CUR_BG_COLOR = 0x9, MAX_SYS_COLORS = 0xa, }; /* --- static functions --- */ static int sys_color_set(ui_color_manager_t *color_man, char *name, int color) { ui_color_t xcolor; if (bl_compare_str(color_man->sys_colors[color].name, name) == 0) { /* Not changed (specified color name is not changed) */ return 0; } if (name) { if (!ui_load_xcolor(color_man->color_cache, &xcolor, name)) { if (!color_man->sys_colors[color].name && color <= _BG_COLOR) { /* _FG_COLOR and _BG_COLOR are necessarily loaded. */ name = "black"; xcolor = color_man->color_cache->black; } else { /* Not changed (specified color name is illegal) */ return 0; } } } if (color_man->sys_colors[color].name) { ui_unload_xcolor(color_man->color_cache->disp, &color_man->sys_colors[color].xcolor); free(color_man->sys_colors[color].name); } if (name) { if (color == _BG_COLOR && color_man->alpha < 255) { u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t alpha; ui_get_xcolor_rgba(&red, &green, &blue, &alpha, &xcolor); /* * If alpha of bg color is already less than 255, * default alpha value is not applied. */ if (alpha == 255) { ui_unload_xcolor(color_man->color_cache->disp, &xcolor); ui_load_rgb_xcolor(color_man->color_cache->disp, &xcolor, red, green, blue, color_man->alpha); } } color_man->sys_colors[color].name = strdup(name); color_man->sys_colors[color].xcolor = xcolor; } else { color_man->sys_colors[color].name = NULL; } return 1; } /* --- global functions --- */ ui_color_manager_t *ui_color_manager_new(ui_display_t *disp, char *fg_color, /* can be NULL(=> "black".) */ char *bg_color, /* can be NULL(=> "white".) */ char *cursor_fg_color, /* can be NULL(=> reversed color) */ char *cursor_bg_color, /* can be NULL(=> reversed color) */ char *bd_color, /* can be NULL */ char *ul_color, /* can be NULL */ char *bl_color, /* can be NULL */ char *rv_color, /* can be NULL */ char *it_color, /* can be NULL */ char *co_color /* can be NULL */) { ui_color_manager_t *color_man; if ((color_man = calloc(1, sizeof(ui_color_manager_t))) == NULL) { return NULL; } if (!(color_man->color_cache = ui_acquire_color_cache(disp, 100))) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " ui_aquire_color_cache failed.\n"); #endif free(color_man); return NULL; } color_man->alpha = 255; sys_color_set(color_man, fg_color ? fg_color : "black", _FG_COLOR); sys_color_set(color_man, bg_color ? bg_color : "white", _BG_COLOR); sys_color_set(color_man, cursor_fg_color, _CUR_FG_COLOR); sys_color_set(color_man, cursor_bg_color, _CUR_BG_COLOR); sys_color_set(color_man, bd_color, _BOLD_COLOR); sys_color_set(color_man, ul_color, _UNDERLINE_COLOR); sys_color_set(color_man, bl_color, _BLINKING_COLOR); sys_color_set(color_man, rv_color, _REVERSE_COLOR); sys_color_set(color_man, it_color, _ITALIC_COLOR); sys_color_set(color_man, co_color, _CROSSED_OUT_COLOR); return color_man; } void ui_color_manager_destroy(ui_color_manager_t *color_man) { int count; for (count = 0; count < MAX_SYS_COLORS; count++) { if (color_man->sys_colors[count].name) { ui_unload_xcolor(color_man->color_cache->disp, &color_man->sys_colors[count].xcolor); free(color_man->sys_colors[count].name); } } ui_release_color_cache(color_man->color_cache); if (color_man->alt_color_cache) { ui_release_color_cache(color_man->alt_color_cache); } free(color_man); } int ui_color_manager_set_fg_color(ui_color_manager_t *color_man, char *name /* never NULL */) { return sys_color_set(color_man, name, _FG_COLOR); } int ui_color_manager_set_bg_color(ui_color_manager_t *color_man, char *name /* never NULL */) { return sys_color_set(color_man, name, _BG_COLOR); } int ui_color_manager_set_cursor_fg_color(ui_color_manager_t *color_man, char *name /* can be NULL */) { return sys_color_set(color_man, name, _CUR_FG_COLOR); } int ui_color_manager_set_cursor_bg_color(ui_color_manager_t *color_man, char *name /* can be NULL */) { return sys_color_set(color_man, name, _CUR_BG_COLOR); } int ui_color_manager_set_alt_color(ui_color_manager_t *color_man, vt_color_t color, /* VT_BOLD_COLOR - VT_CROSSED_OUT_COLOR */ char *name /* never NULL */) { return sys_color_set(color_man, name, color - VT_FG_COLOR); } char *ui_color_manager_get_fg_color(ui_color_manager_t *color_man) { return color_man->sys_colors[_FG_COLOR].name; } char *ui_color_manager_get_bg_color(ui_color_manager_t *color_man) { return color_man->sys_colors[_BG_COLOR].name; } char *ui_color_manager_get_cursor_fg_color(ui_color_manager_t *color_man) { return color_man->sys_colors[_CUR_FG_COLOR].name; } char *ui_color_manager_get_cursor_bg_color(ui_color_manager_t *color_man) { return color_man->sys_colors[_CUR_BG_COLOR].name; } char *ui_color_manager_get_alt_color(ui_color_manager_t *color_man, vt_color_t color /* VT_BOLD_COLOR - VT_CROSSED_OUT_COLOR */) { return color_man->sys_colors[color - VT_FG_COLOR].name; } ui_color_t *ui_get_xcolor(ui_color_manager_t *color_man, vt_color_t color) { if (color_man->is_reversed) { if (color == VT_FG_COLOR) { color = VT_BG_COLOR; } else if (color == VT_BG_COLOR) { color = VT_FG_COLOR; } } if (IS_FG_BG_COLOR(color)) { return &color_man->sys_colors[color - VT_FG_COLOR].xcolor; } else if (IS_ALT_COLOR(color)) { if (color_man->sys_colors[color - VT_FG_COLOR].name) { return &color_man->sys_colors[color - VT_FG_COLOR].xcolor; } else { return &color_man->sys_colors[_FG_COLOR].xcolor; } } else { return ui_get_cached_xcolor(color_man->color_cache, color); } } /* * If fading status is changed, 1 is returned. */ int ui_color_manager_fade(ui_color_manager_t *color_man, u_int fade_ratio /* valid value is 0 - 99 */) { ui_color_cache_t *color_cache; if (fade_ratio >= 100) { return 0; } if (fade_ratio == color_man->color_cache->fade_ratio) { return 0; } if (color_man->alt_color_cache && fade_ratio == color_man->alt_color_cache->fade_ratio) { color_cache = color_man->alt_color_cache; color_man->alt_color_cache = color_man->color_cache; } else { if ((color_cache = ui_acquire_color_cache(color_man->color_cache->disp, fade_ratio)) == NULL) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " ui_aquire_color_cache failed.\n"); #endif return 0; } if (color_man->color_cache->fade_ratio == 100) { if (color_man->alt_color_cache) { ui_release_color_cache(color_man->alt_color_cache); } color_man->alt_color_cache = color_man->color_cache; } } color_man->color_cache = color_cache; ui_color_manager_reload(color_man); return 1; } /* * If fading status is changed, 1 is returned. */ int ui_color_manager_unfade(ui_color_manager_t *color_man) { ui_color_cache_t *color_cache; if (color_man->alt_color_cache == NULL || color_man->color_cache->fade_ratio == 100) { return 0; } color_cache = color_man->alt_color_cache; color_man->alt_color_cache = color_man->color_cache; color_man->color_cache = color_cache; ui_color_manager_reload(color_man); return 1; } int ui_color_manager_reverse_video(ui_color_manager_t *color_man) { if (color_man->is_reversed) { return 0; } color_man->is_reversed = 1; return 1; } int ui_color_manager_restore_video(ui_color_manager_t *color_man) { if (!color_man->is_reversed) { return 0; } color_man->is_reversed = 0; return 1; } /* * Swap the color of VT_BG_COLOR <=> that of cursor fg color. * Deal VT_BG_COLOR as cursor fg color. */ int ui_color_manager_adjust_cursor_fg_color(ui_color_manager_t *color_man) { struct sys_color tmp_color; if (!color_man->sys_colors[_CUR_FG_COLOR].name) { return 0; } tmp_color = color_man->sys_colors[_BG_COLOR]; color_man->sys_colors[_BG_COLOR] = color_man->sys_colors[_CUR_FG_COLOR]; color_man->sys_colors[_CUR_FG_COLOR] = tmp_color; return 1; } /* * Swap the color of VT_FG_COLOR <=> that of cursor bg color. * Deal VT_FG_COLOR as cursor bg color. */ int ui_color_manager_adjust_cursor_bg_color(ui_color_manager_t *color_man) { struct sys_color tmp_color; if (!color_man->sys_colors[_CUR_BG_COLOR].name) { return 0; } tmp_color = color_man->sys_colors[_FG_COLOR]; color_man->sys_colors[_FG_COLOR] = color_man->sys_colors[_CUR_BG_COLOR]; color_man->sys_colors[_CUR_BG_COLOR] = tmp_color; return 1; } /* * Reload system colors. */ void ui_color_manager_reload(ui_color_manager_t *color_man) { int color; for (color = 0; color < MAX_SYS_COLORS; color++) { if (color_man->sys_colors[color].name) { char *name; name = color_man->sys_colors[color].name; color_man->sys_colors[color].name = NULL; /* reload */ sys_color_set(color_man, name, color); free(name); } } } int ui_change_true_transbg_alpha(ui_color_manager_t *color_man, u_int8_t alpha) { #ifndef SUPPORT_TRUE_TRANSPARENT_BG return 0; #else #ifdef USE_WIN32GUI if (alpha == 0) { /* If alpha == 0, window disappears completely. */ return 0; } #else if (color_man->color_cache->disp->depth != 32) { return 0; } else #endif if (alpha == color_man->alpha) { return -1; } else { u_int8_t red; u_int8_t green; u_int8_t blue; u_int8_t cur_alpha; ui_get_xcolor_rgba(&red, &green, &blue, &cur_alpha, &color_man->sys_colors[_BG_COLOR].xcolor); if (cur_alpha == color_man->alpha) { ui_unload_xcolor(color_man->color_cache->disp, &color_man->sys_colors[_BG_COLOR].xcolor); ui_load_rgb_xcolor(color_man->color_cache->disp, &color_man->sys_colors[_BG_COLOR].xcolor, red, green, blue, alpha); } color_man->alpha = alpha; return 1; } #endif } mlterm-3.8.9/tool004075500017600000144000000000001356600660700124435ustar kenusersmlterm-3.8.9/tool/mlimgloader004075500017600000144000000000001356600660700147375ustar kenusersmlterm-3.8.9/tool/mlimgloader/Makefile.in010064400017600000144000000041711356600660700170630ustar kenuserstop_builddir = ../.. top_srcdir = @top_srcdir@ prefix = @prefix@ sysconfdir = @sysconfdir@ exec_prefix = @exec_prefix@ datadir = @datadir@ bindir = @bindir@ libdir = @libdir@ libexecdir = @libexecdir@ CC = @CC@ LIBTOOL = @LIBTOOL@ INSTALL = @INSTALL@ LIBEXECDIR = $(DESTDIR)$(libexecdir)/mlterm LIBEXECDIR_win32 = $(DESTDIR)$(bindir) VPATH = $(top_srcdir)/tool/mlimgloader OBJ = @MLIMGLOADER_LIB@.o LPOBL = @LPOBL@ LPOBL_DEB = -lpobl_deb CFLAGS1 = $(CFLAGS_LOCAL) @POBL_CFLAGS@ @DEB_CFLAGS@ @GUI_CFLAGS@ @CFLAGS@ @CPPFLAGS@ \ @X_CFLAGS_AUX@ -I/usr/local/include CFLAGS2_gdk-pixbuf = @GDK_PIXBUF_CFLAGS@ @X_CFLAGS@ @EMOJI_CFLAGS@ CFLAGS = $(CFLAGS1) $(CFLAGS2_@MLIMGLOADER_LIB@) -DLIBEXECDIR=\"$(libexecdir)\" \ -DBINDIR=\"$(bindir)\" LIBS1 = $(LIBS_LOCAL) $(LPOBL) -L/usr/local/lib -R/usr/local/lib LIBS2_xlib_gdk-pixbuf = @X_LIBS@ @X_EXTRA_LIBS@ @GDK_PIXBUF_LIBS@ @EMOJI_LIBS@ LIBS2_xlib_gdiplus = $(LIBS2_win32_gdiplus) LIBS2_fb_gdk-pixbuf = $(LIBS2_xlib_gdk-pixbuf) LIBS2_console_gdk-pixbuf = $(LIBS2_xlib_gdk-pixbuf) LIBS2_wayland_gdk-pixbuf = $(LIBS2_xlib_gdk-pixbuf) LIBS2_sdl2_gdiplus = $(LIBS2_win32_gdiplus) LIBS2_sdl2_gdk-pixbuf = $(LIBS2_xlib_gdk-pixbuf) LIBS2_beos_gdk-pixbuf = $(LIBS2_xlib_gdk-pixbuf) # Segfault in cygwin without them. LIBS2_win32_gdk-pixbuf = -mwindows @GDK_PIXBUF_LIBS@ LIBS2_win32_gdiplus = -mwindows -lgdiplus -lstdc++ -lole32 LIBS2_win32_none = -mwindows LIBS = $(LIBS1) $(LIBS2_@GUI@_@MLIMGLOADER_LIB@) PROG = mlimgloader LIBTOOL_CC = $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) all: $(PROG) $(PROG): $(OBJ) $(LIBTOOL_LINK) $(CFLAGS) -o $(PROG) $(OBJ:.o=.lo) $(LIBS) .SUFFIXES: .c .o .c.o: $(LIBTOOL_CC) -c $< .cpp.o: $(LIBTOOL_CC) -c $< $(LIBEXECDIR@WIN32TAG@): mkdir -p $(LIBEXECDIR@WIN32TAG@) install: $(LIBEXECDIR@WIN32TAG@) $(LIBTOOL_INSTALL) $(PROG) $(LIBEXECDIR@WIN32TAG@) uninstall: rm -f $(LIBEXECDIR@WIN32TAG@)/$(PROG) wc: find . -name "*.[ch]" -a \! -name "test_*" | xargs wc -l clean: rm -rf $(PROG) $(PROG).exe *core $(OBJ) $(OBJ:.o=.lo) .libs distclean: clean rm -f Makefile mlterm-3.8.9/tool/mlimgloader/gdiplus.cpp010064400017600000144000000234341356600660700171740ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include /* STDOUT_FILENO */ #include /* mbstowcs_s */ #include /* wcslen */ extern "C" { #include #include /* bl_get_user_rc_path */ #include #if defined(__CYGWIN__) || defined(__MSYS__) #include /* bl_conv_to_win32_path */ #endif } #include /* u_int32_t/u_int16_t */ #include /* SSIZE_MAX, USE_WIN32API */ #ifdef USE_WIN32API #include /* O_BINARY */ #endif #define _WIN32_WINNT 0x0502 /* for SetDllDirectory */ #include #include using namespace Gdiplus; #if 0 #define __DEBUG #endif #ifndef IID_PPV_ARGS /* IStream IID (objidl.h) */ static const IID __uuid_inst = { 0x0000000c, 0x0000, 0x0000, {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; #define IID_PPV_ARGS(iface) __uuid_inst, reinterpret_cast(iface) #endif #ifndef URL_MK_UNIFORM #define URL_MK_UNIFORM 1 #endif /* --- static functions --- */ #define BUILTIN_IMAGELIB /* Necessary to use create_cardinals_from_sixel() */ #include "../../common/c_imagelib.c" static void help(void) { /* Don't output to stdout where mlterm waits for image data. */ fprintf(stderr, "mlimgloader 0 [width] [height] [file path] stdout (-a)\n"); fprintf(stderr, " -a: keep aspect ratio.\n"); } /* path: cygwin style path on cygwin/msys. win32 style path on win32. */ static u_int32_t *create_cardinals_from_file(const char *path, u_int width, u_int height, int keep_aspect) { u_int32_t *cardinal = NULL; if (strcasecmp(path + strlen(path) - 4, ".six") == 0 && (cardinal = create_cardinals_from_sixel(path)) && (width == 0 || height == 0)) { return cardinal; } Gdiplus::GdiplusStartupInput startup; ULONG_PTR token; if (Gdiplus::GdiplusStartup(&token, &startup, NULL) != Gdiplus::Ok) { return NULL; } /* MAX_PATH which is 260 (3+255+1+1) is defined in win32 alone. */ wchar_t wpath[MAX_PATH]; #if defined(__CYGWIN__) || defined(__MSYS__) char winpath[MAX_PATH]; #endif HMODULE module; IBindCtx *ctx; IMoniker *moniker; IStream *stream = NULL; Gdiplus::Bitmap *bitmap; if (cardinal) { /* Resize sixel graphics */ Gdiplus::Bitmap src(cardinal[0], cardinal[1], cardinal[0] * 4, PixelFormat32bppARGB, (BYTE*)(cardinal + 2)); if (!(bitmap = new Bitmap(width, height, PixelFormat32bppARGB))) { goto end1; } Graphics *graphics; if (!(graphics = Graphics::FromImage(bitmap))) { delete bitmap; goto end1; } Gdiplus::Rect rect(0, 0, width, height); graphics->DrawImage(&src, rect, 0, 0, cardinal[0], cardinal[1], UnitPixel); delete graphics; free(cardinal); } else { /* Image except sixel graphics */ int hash = hash_path(path); if (strstr(path, "://")) { typedef HRESULT (*func)(IMoniker*, LPCWSTR, IMoniker**, DWORD); func create_url_moniker; SetDllDirectory(""); if ((module = LoadLibrary("urlmon")) && (create_url_moniker = (func)GetProcAddress(module, "CreateURLMonikerEx"))) { MultiByteToWideChar(CP_UTF8, 0, path, strlen(path) + 1, wpath, MAX_PATH); if ((*create_url_moniker)(NULL, wpath, &moniker, URL_MK_UNIFORM) == S_OK) { if (CreateBindCtx(0, &ctx) == S_OK) { if (moniker->BindToStorage(ctx, NULL, IID_PPV_ARGS(&stream)) != S_OK) { ctx->Release(); moniker->Release(); } } else { moniker->Release(); } } if (!stream) { FreeLibrary(module); } } } #if defined(__CYGWIN__) || defined(__MSYS__) /* In case win32 style path is specified on cygwin/msys. */ else if (strchr(path, '/')) { /* cygwin style path => win32 style path. */ if (bl_conv_to_win32_path(path, winpath, sizeof(winpath)) == 0) { path = winpath; } } #endif char *dir; if (strcmp(path + strlen(path) - 4, ".gif") == 0 && /* Animation GIF */ #if defined(__CYGWIN__) || defined(__MSYS__) /* converted to win32 by bl_conv_to_win32_path */ (!strstr(path, "mlterm\\anim") && (dir = bl_get_user_rc_path("mlterm/"))) #else (!strstr(path, "mlterm/anim") && (dir = bl_get_user_rc_path("mlterm\\"))) #endif ) { char new_path[strlen(dir) + 8 + 5 + DIGIT_STR_LEN(int) + 1]; sprintf(new_path, "%sanim%d.gif", dir, hash); FILE *fp; if (stream && (fp = fopen(new_path, "wb"))) { BYTE buf[10240]; ULONG rd_len; HRESULT res; do { res = stream->Read(buf, sizeof(buf), &rd_len); fwrite(buf, 1, rd_len, fp); } while (res == Gdiplus::Ok); fclose(fp); stream->Release(); ctx->Release(); moniker->Release(); FreeLibrary(module); stream = NULL; path = new_path; } split_animation_gif(path, dir, hash); free(dir); /* Replace path by the splitted file. */ #if defined(__CYGWIN__) || defined(__MSYS__) if (bl_conv_to_win32_path(new_path, winpath, sizeof(winpath)) == 0) { path = winpath; } else #endif { path = new_path; } if (!stream) { MultiByteToWideChar(CP_UTF8, 0, path, strlen(path) + 1, wpath, MAX_PATH); } } else { if (!stream) { MultiByteToWideChar(CP_UTF8, 0, path, strlen(path) + 1, wpath, MAX_PATH); } } cardinal = NULL; if (width == 0 && height == 0) { if (stream ? !(bitmap = Gdiplus::Bitmap::FromStream(stream)) : !(bitmap = Gdiplus::Bitmap::FromFile(wpath))) { goto end2; } } else { Image *image; if ((stream ? !(image = Image::FromStream(stream)) : !(image = Image::FromFile(wpath))) || image->GetLastStatus() != Gdiplus::Ok) { goto end2; } u_int img_width = image->GetWidth(); u_int img_height = image->GetHeight(); if (width == 0) { width = img_width;; } else if (height == 0) { height = img_height; } if (keep_aspect) { u_int w = height * img_width / img_height; if (w < width) { width = w; } else { u_int h = width * img_height / img_width; if (h < height) { height = h; } } } if (!(bitmap = new Bitmap(width, height, PixelFormat32bppARGB))) { delete image; goto end2; } Graphics *graphics; if (!(graphics = Graphics::FromImage(bitmap))) { delete image; goto end3; } Gdiplus::Rect rect(0, 0, width, height); graphics->DrawImage(image, rect, 0, 0, img_width, img_height, UnitPixel); delete image; delete graphics; } } if (bitmap->GetLastStatus() != Gdiplus::Ok) { goto end3; } width = bitmap->GetWidth(); height = bitmap->GetHeight(); u_int32_t *p; if (width > ((SSIZE_MAX / sizeof(*cardinal)) - 2) / height || /* integer overflow */ !(p = cardinal = (u_int32_t*)malloc((width * height + 2) * sizeof(*cardinal)))) { goto end3; } *(p++) = width; *(p++) = height; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { Gdiplus::Color pixel; bitmap->GetPixel(x, y, &pixel); *(p++) = (pixel.GetA() << 24) | (pixel.GetR() << 16) | (pixel.GetG() << 8) | pixel.GetB(); } } end3: delete bitmap; end2: if (stream) { stream->Release(); ctx->Release(); moniker->Release(); FreeLibrary(module); } end1: Gdiplus::GdiplusShutdown(token); return cardinal; } /* --- global functions --- */ int PASCAL WinMain(HINSTANCE hinst, HINSTANCE hprev, char *cmdline, int cmdshow) { WCHAR **w_argv; int argc; #if 0 bl_set_msg_log_file_name("mlterm/msg.log"); #endif w_argv = CommandLineToArgvW(GetCommandLineW(), &argc); if (argc == 0) { GlobalFree(w_argv); return -1; } char *argv[argc]; for (int count = 0; count < argc; count++) { int len = WideCharToMultiByte(CP_UTF8, 0, w_argv[count], wcslen(w_argv[count]) + 1, NULL, 0, NULL, NULL); if ((argv[count] = (char*)malloc(len))) { WideCharToMultiByte(CP_UTF8, 0, w_argv[count], wcslen(w_argv[count]) + 1, argv[count], len, NULL, NULL); } else { argc = count; break; } } GlobalFree(w_argv); if ((argc != 6 && argc != 7) || strcmp(argv[5], "stdout") != 0) { help(); return -1; } char new_path[strlen(argv[4]) + 1]; if (strstr(argv[4], ".rgs")) { strcpy(new_path, argv[4]); if (convert_regis_to_bmp(new_path)) { argv[4] = new_path; } } u_int width = atoi(argv[2]); u_int height = atoi(argv[3]); /* * attr.width / attr.height aren't trustworthy because this program can be * called before window is actually resized. */ u_char *cardinal; ssize_t size; /* should declare before 'goto' */ if (!(cardinal = (u_char*)create_cardinals_from_file(argv[4], width, height, (argc == 7 && strcmp(argv[6], "-a") == 0)))) { goto error; } width = ((u_int32_t*)cardinal)[0]; height = ((u_int32_t*)cardinal)[1]; size = sizeof(u_int32_t) * (width * height + 2); #ifdef USE_WIN32API setmode(STDOUT_FILENO, O_BINARY); #endif while (size > 0) { ssize_t n_wr; if ((n_wr = write(STDOUT_FILENO, cardinal, size)) < 0) { goto error; } cardinal += n_wr; size -= n_wr; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Exit image loader\n"); #endif /* XXX should free(argv[n]) */ return 0; error: /* XXX should free(argv[n]) */ bl_error_printf("Couldn't load %s\n", argv[4]); return -1; } mlterm-3.8.9/tool/mlimgloader/gdk-pixbuf.c010064400017600000144000000401411356600660700172170ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include #include /* strstr */ /* * Don't include bl_mem.h. * 'data' which is malloc'ed for XCreateImage() in pixbuf_to_ximage_truecolor() * is free'ed in XDestroyImage(). * If malloc is replaced bl_mem_malloc in bl_mem.h, bl_mem_free_all() will * free 'data' which is already free'ed in XDestroyImage() and * segmentation fault error can happen. */ #include /* malloc/free/atoi */ #include #include #include /* u_int32_t/u_int16_t */ #include /* SSIZE_MAX, USE_WIN32API */ #if defined(__CYGWIN__) || defined(__MSYS__) #include /* bl_conv_to_win32_path */ #endif #ifdef USE_WIN32API #include /* O_BINARY */ #endif #define USE_FS 1 #if (GDK_PIXBUF_MAJOR < 2) #define g_object_ref(pixbuf) gdk_pixbuf_ref(pixbuf) #define g_object_unref(pixbuf) gdk_pixbuf_unref(pixbuf) #endif #if 0 #define __DEBUG #endif /* --- static functions --- */ #ifdef HAVE_XLIB #define USE_XLIB /* Necessary to use closest_color_index(), lsb() and msb() */ #include #include #endif #define BUILTIN_IMAGELIB /* Necessary to use gdk_pixbuf_new_from() etc */ #include "../../common/c_imagelib.c" static void help(void) { /* Don't output to stdout where mlterm waits for image data. */ fprintf(stderr, "mlimgloader [window id] [width] [height] [src file] [dst] (-a)\n"); fprintf(stderr, " dst: \"pixmap\", \"stdout\" or regular file path.\n"); fprintf(stderr, " -a : keep aspect ratio.\n"); } /* * Create GdkPixbuf from the specified file path. * The returned pixbuf shouled be unrefed by the caller. */ static GdkPixbuf *load_file(char *path, u_int width /* 0 == image width */, u_int height /* 0 == image height */, int keep_aspect, GdkInterpType scale_type) { GdkPixbuf *pixbuf_tmp; GdkPixbuf *pixbuf; if (!(pixbuf_tmp = gdk_pixbuf_new_from(path))) { return NULL; } /* loading from file/cache ends here */ if (width == 0 && height == 0) { pixbuf = pixbuf_tmp; } else { if (width == 0) { width = gdk_pixbuf_get_width(pixbuf_tmp); } else if (height == 0) { height = gdk_pixbuf_get_height(pixbuf_tmp); } if (keep_aspect) { u_int w = height * gdk_pixbuf_get_width(pixbuf_tmp) / gdk_pixbuf_get_height(pixbuf_tmp); if (w < width) { width = w; } else { u_int h = width * gdk_pixbuf_get_height(pixbuf_tmp) / gdk_pixbuf_get_width(pixbuf_tmp); if (h < height) { height = h; } } } pixbuf = gdk_pixbuf_scale_simple(pixbuf_tmp, width, height, scale_type); g_object_unref(pixbuf_tmp); #ifdef __DEBUG if (pixbuf) { bl_warn_printf(BL_DEBUG_TAG " creating a scaled pixbuf(%d x %d)\n", width, height); } #endif } /* scaling ends here */ return pixbuf; } #ifdef USE_XLIB /* returned cmap shuold be freed by the caller */ static int fetch_colormap(Display *display, Visual *visual, Colormap colormap, XColor **color_list) { int num_cells, i; num_cells = visual->map_entries; if ((*color_list = calloc(num_cells, sizeof(XColor))) == NULL) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " couldn't allocate color table\n"); #endif return 0; } for (i = 0; i < num_cells; i++) { ((*color_list)[i]).pixel = i; } XQueryColors(display, colormap, *color_list, num_cells); return num_cells; } static int pixbuf_to_pixmap_pseudocolor(Display *display, Visual *visual, Colormap colormap, GC gc, GdkPixbuf *pixbuf, Pixmap pixmap) { int width, height, rowstride; u_int bytes_per_pixel; int x, y; int num_cells; #ifdef USE_FS char *diff_next; char *diff_cur; char *temp; #endif /* USE_FS */ u_char *line; u_char *pixel; XColor *color_list; int closest; int diff_r, diff_g, diff_b; int ret_val = 0; if ((num_cells = fetch_colormap(display, visual, colormap, &color_list)) == 0) { return 0; } width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); #ifdef USE_FS if ((diff_cur = calloc(1, width * 3)) == NULL) { goto error1; } if ((diff_next = calloc(1, width * 3)) == NULL) { goto error2; } #endif /* USE_FS */ bytes_per_pixel = (gdk_pixbuf_get_has_alpha(pixbuf)) ? 4 : 3; rowstride = gdk_pixbuf_get_rowstride(pixbuf); line = gdk_pixbuf_get_pixels(pixbuf); for (y = 0; y < height; y++) { pixel = line; #ifdef USE_FS closest = closest_color_index(color_list, num_cells, pixel[0] - diff_cur[0], pixel[1] - diff_cur[1], pixel[2] - diff_cur[2]); diff_r = (color_list[closest].red >> 8) - pixel[0]; diff_g = (color_list[closest].green >> 8) - pixel[1]; diff_b = (color_list[closest].blue >> 8) - pixel[2]; diff_cur[3 * 1 + 0] += diff_r / 2; diff_cur[3 * 1 + 1] += diff_g / 2; diff_cur[3 * 1 + 2] += diff_b / 2; /* initialize next line */ diff_next[3 * 0 + 0] = diff_r / 4; diff_next[3 * 0 + 1] = diff_g / 4; diff_next[3 * 0 + 2] = diff_b / 4; diff_next[3 * 1 + 0] = diff_r / 4; diff_next[3 * 1 + 1] = diff_g / 4; diff_next[3 * 1 + 2] = diff_b / 4; #else closest = closest_color_index(color_list, num_cells, pixel[0], pixel[1], pixel[2]); #endif /* USE_FS */ XSetForeground(display, gc, closest); XDrawPoint(display, pixmap, gc, 0, y); pixel += bytes_per_pixel; for (x = 1; x < width - 2; x++) { #ifdef USE_FS closest = closest_color_index(color_list, num_cells, pixel[0] - diff_cur[3 * x + 0], pixel[1] - diff_cur[3 * x + 1], pixel[2] - diff_cur[3 * x + 2]); diff_r = (color_list[closest].red >> 8) - pixel[0]; diff_g = (color_list[closest].green >> 8) - pixel[1]; diff_b = (color_list[closest].blue >> 8) - pixel[2]; diff_cur[3 * (x + 1) + 0] += diff_r / 2; diff_cur[3 * (x + 1) + 1] += diff_g / 2; diff_cur[3 * (x + 1) + 2] += diff_b / 2; diff_next[3 * (x - 1) + 0] += diff_r / 8; diff_next[3 * (x - 1) + 1] += diff_g / 8; diff_next[3 * (x - 1) + 2] += diff_b / 8; diff_next[3 * (x + 0) + 0] += diff_r / 8; diff_next[3 * (x + 0) + 1] += diff_g / 8; diff_next[3 * (x + 0) + 2] += diff_b / 8; /* initialize next line */ diff_next[3 * (x + 1) + 0] = diff_r / 4; diff_next[3 * (x + 1) + 1] = diff_g / 4; diff_next[3 * (x + 1) + 2] = diff_b / 4; #else closest = closest_color_index(color_list, num_cells, pixel[0], pixel[1], pixel[2]); #endif /* USE_FS */ XSetForeground(display, gc, closest); XDrawPoint(display, pixmap, gc, x, y); pixel += bytes_per_pixel; } #ifdef USE_FS closest = closest_color_index(color_list, num_cells, pixel[0] - diff_cur[3 * x + 0], pixel[1] - diff_cur[3 * x + 1], pixel[2] - diff_cur[3 * x + 2]); diff_r = (color_list[closest].red >> 8) - pixel[0]; diff_g = (color_list[closest].green >> 8) - pixel[1]; diff_b = (color_list[closest].blue >> 8) - pixel[2]; diff_next[3 * (x - 1) + 0] += diff_r / 4; diff_next[3 * (x - 1) + 1] += diff_g / 4; diff_next[3 * (x - 1) + 2] += diff_b / 4; diff_next[3 * (x + 0) + 0] += diff_r / 4; diff_next[3 * (x + 0) + 1] += diff_g / 4; diff_next[3 * (x + 0) + 2] += diff_b / 4; temp = diff_cur; diff_cur = diff_next; diff_next = temp; #else closest = closest_color_index(color_list, num_cells, pixel[0], pixel[1], pixel[2]); #endif /* USE_FS */ XSetForeground(display, gc, closest); XDrawPoint(display, pixmap, gc, x, y); line += rowstride; } ret_val = 1; #ifdef USE_FS error2: free(diff_cur); free(diff_next); #endif /* USE_FS */ error1: free(color_list); return ret_val; } static XImage *pixbuf_to_ximage_truecolor(Display *display, Visual *visual, Colormap colormap, GC gc, u_int depth, GdkPixbuf *pixbuf) { XVisualInfo vinfo_template; XVisualInfo *vinfolist; int nitem; u_int x, y; u_int width, height, rowstride, bytes_per_pixel; u_char *line; u_long r_mask, g_mask, b_mask; int r_offset, g_offset, b_offset; int r_limit, g_limit, b_limit; XImage *image; char *data; vinfo_template.visualid = XVisualIDFromVisual(visual); if (!(vinfolist = XGetVisualInfo(display, VisualIDMask, &vinfo_template, &nitem))) { return NULL; } r_mask = vinfolist[0].red_mask; g_mask = vinfolist[0].green_mask; b_mask = vinfolist[0].blue_mask; XFree(vinfolist); r_offset = lsb(r_mask); g_offset = lsb(g_mask); b_offset = lsb(b_mask); r_limit = 8 + r_offset - msb(r_mask); g_limit = 8 + g_offset - msb(g_mask); b_limit = 8 + b_offset - msb(b_mask); width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); /* set num of bytes per pixel of display */ bytes_per_pixel = depth > 16 ? 4 : 2; if (width > SSIZE_MAX / bytes_per_pixel / height) { return NULL; /* integer overflow */ } if (!(data = malloc(width * height * bytes_per_pixel))) { return NULL; } if (!(image = XCreateImage(display, visual, depth, ZPixmap, 0, data, width, height, /* in case depth isn't multiple of 8 */ bytes_per_pixel * 8, width * bytes_per_pixel))) { free(data); return NULL; } /* set num of bytes per pixel of pixbuf */ bytes_per_pixel = (gdk_pixbuf_get_has_alpha(pixbuf)) ? 4 : 3; rowstride = gdk_pixbuf_get_rowstride(pixbuf); line = gdk_pixbuf_get_pixels(pixbuf); for (y = 0; y < height; y++) { u_char *pixel; pixel = line; for (x = 0; x < width; x++) { XPutPixel(image, x, y, (depth == 32 ? 0xff000000 : 0) | (((pixel[0] >> r_limit) << r_offset) & r_mask) | (((pixel[1] >> g_limit) << g_offset) & g_mask) | (((pixel[2] >> b_limit) << b_offset) & b_mask)); pixel += bytes_per_pixel; } line += rowstride; } return image; } static int pixbuf_to_pixmap(Display *display, Visual *visual, Colormap colormap, GC gc, u_int depth, GdkPixbuf *pixbuf, Pixmap pixmap) { if (visual->class == TrueColor) { XImage *image; if ((image = pixbuf_to_ximage_truecolor(display, visual, colormap, gc, depth, pixbuf))) { XPutImage(display, pixmap, gc, image, 0, 0, 0, 0, gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf)); XDestroyImage(image); return 1; } else { return 0; } } else /* if( visual->class == PseudoColor) */ { return pixbuf_to_pixmap_pseudocolor(display, visual, colormap, gc, pixbuf, pixmap); } } static int pixbuf_to_pixmap_and_mask(Display *display, Window win, Visual *visual, Colormap colormap, GC gc, u_int depth, GdkPixbuf *pixbuf, Pixmap *pixmap, /* Created in this function. */ Pixmap *mask /* Created in this function. */ ) { u_int width; u_int height; width = gdk_pixbuf_get_width(pixbuf); height = gdk_pixbuf_get_height(pixbuf); *pixmap = XCreatePixmap(display, win, width, height, depth); if (!pixbuf_to_pixmap(display, visual, colormap, gc, depth, pixbuf, *pixmap)) { XFreePixmap(display, *pixmap); return 0; } if (gdk_pixbuf_get_has_alpha(pixbuf)) { int x, y; int rowstride; u_char *line; u_char *pixel; GC mask_gc; XGCValues gcv; int has_tp; /* * DefaultRootWindow should not be used because depth and visual * of DefaultRootWindow don't always match those of mlterm window. * Use x_display_get_group_leader instead. */ *mask = XCreatePixmap(display, win, width, height, 1); mask_gc = XCreateGC(display, *mask, 0, &gcv); XSetForeground(display, mask_gc, 0); XFillRectangle(display, *mask, mask_gc, 0, 0, width, height); XSetForeground(display, mask_gc, 1); line = gdk_pixbuf_get_pixels(pixbuf); rowstride = gdk_pixbuf_get_rowstride(pixbuf); has_tp = 0; for (y = 0; y < height; y++) { pixel = line + 3; for (x = 0; x < width; x++) { if (*pixel > 127) { XDrawPoint(display, *mask, mask_gc, x, y); } else { has_tp = 1; } pixel += 4; } line += rowstride; } XFreeGC(display, mask_gc); if (!has_tp) { /* mask is not necessary. */ XFreePixmap(display, *mask); *mask = None; } } else { /* no mask */ *mask = None; } return 1; } #endif /* USE_XLIB */ /* --- global functions --- */ int main(int argc, char **argv) { GdkPixbuf *pixbuf; u_int width; u_int height; #if 0 bl_set_msg_log_file_name("mlterm/msg.log"); #endif if (argc != 7 && argc != 6) { help(); return -1; } #if GDK_PIXBUF_MAJOR >= 2 g_type_init(); #endif /*GDK_PIXBUF_MAJOR*/ width = atoi(argv[2]); height = atoi(argv[3]); /* * attr.width / attr.height aren't trustworthy because this program can be * called before window is actually resized. */ if (!(pixbuf = load_file(argv[4], width, height, (argc == 7 && strcmp(argv[6], "-a") == 0), GDK_INTERP_BILINEAR))) { #if defined(__CYGWIN__) || defined(__MSYS__) #define MAX_PATH 260 /* 3+255+1+1 */ char winpath[MAX_PATH]; if (bl_conv_to_win32_path(argv[4], winpath, sizeof(winpath)) < 0 || !(pixbuf = load_file(winpath, width, height, GDK_INTERP_BILINEAR))) #endif { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Failed to load %s\n", argv[4]); #endif goto error; } } if (strcmp(argv[5], "stdout") == 0) { u_char *cardinal; ssize_t size; if (!(cardinal = (u_char *)create_cardinals_from_pixbuf(pixbuf))) { goto error; } width = ((u_int32_t *)cardinal)[0]; height = ((u_int32_t *)cardinal)[1]; size = sizeof(u_int32_t) * (width * height + 2); #ifdef USE_WIN32API setmode(STDOUT_FILENO, O_BINARY); #endif while (size > 0) { ssize_t n_wr; if ((n_wr = write(STDOUT_FILENO, cardinal, size)) < 0) { goto error; } cardinal += n_wr; size -= n_wr; } } #ifdef USE_XLIB else if (strcmp(argv[5], "pixmap") == 0) { Display *display; Visual *visual; Colormap colormap; u_int depth; GC gc; Pixmap pixmap; Pixmap mask; Window win; XWindowAttributes attr; char buf[10]; if (!(display = XOpenDisplay(NULL))) { goto error; } if ((win = atoi(argv[1])) == 0) { win = DefaultRootWindow(display); visual = DefaultVisual(display, DefaultScreen(display)); colormap = DefaultColormap(display, DefaultScreen(display)); depth = DefaultDepth(display, DefaultScreen(display)); gc = DefaultGC(display, DefaultScreen(display)); } else { XGCValues gc_value; XGetWindowAttributes(display, win, &attr); visual = attr.visual; colormap = attr.colormap; depth = attr.depth; gc = XCreateGC(display, win, 0, &gc_value); } if (!pixbuf_to_pixmap_and_mask(display, win, visual, colormap, gc, depth, pixbuf, &pixmap, &mask)) { goto error; } XSync(display, False); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Loaded pixmap %lu %lu\n", pixmap, mask); #endif fprintf(stdout, "%lu %lu", pixmap, mask); fflush(stdout); close(STDOUT_FILENO); /* Wait for parent process receiving pixmap. */ read(STDIN_FILENO, buf, sizeof(buf)); } #endif /* USE_XLIB */ #if GDK_PIXBUF_MAJOR >= 2 else { char *type; GError *error = NULL; if (!(type = strrchr(argv[5], '.'))) { goto error; } type++; if (strcmp(type, "jpg") == 0) { type = "jpeg"; } gdk_pixbuf_save(pixbuf, argv[5], type, &error, NULL); } #endif #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Exit image loader\n"); #endif return 0; error: bl_error_printf("Couldn't load %s\n", argv[4]); return -1; } mlterm-3.8.9/tool/mlimgloader/none.c010064400017600000144000000043621356600660700161230ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include #include /* strstr */ #include /* atoi */ #include #include /* u_int32_t/u_int16_t */ #include /* SSIZE_MAX, USE_WIN32API */ #include /* alloca */ #if defined(__CYGWIN__) || defined(__MSYS__) #include /* bl_conv_to_win32_path */ #endif #ifdef USE_WIN32API #include /* O_BINARY */ #endif #if 0 #define __DEBUG #endif /* --- static functions --- */ #define BUILTIN_IMAGELIB /* Necessary to use create_cardinals_from_sixel() */ #include "../../common/c_imagelib.c" static void help(void) { /* Don't output to stdout where mlterm waits for image data. */ fprintf(stderr, "mlimgloader 0 0 0 [file path] stdout (-a)\n"); fprintf(stderr, " -a: ignored.\n"); } /* --- global functions --- */ int main(int argc, char **argv) { u_char *cardinal; ssize_t size; u_int width; u_int height; #if 0 bl_set_msg_log_file_name("mlterm/msg.log"); #endif if ((argc != 6 && argc != 7) || strcmp(argv[5], "stdout") != 0) { help(); return -1; } if (strstr(argv[4], ".rgs")) { char *new_path; if ((new_path = alloca(strlen(argv[4]) + 1))) { if (convert_regis_to_bmp(strcpy(new_path, argv[4]))) { argv[4] = new_path; } } } if (!(cardinal = (u_char*)create_cardinals_from_sixel(argv[4]))) { #if defined(__CYGWIN__) || defined(__MSYS__) #define MAX_PATH 260 /* 3+255+1+1 */ char winpath[MAX_PATH]; if (bl_conv_to_win32_path(argv[4], winpath, sizeof(winpath)) < 0 || !(cardinal = (u_char*)create_cardinals_from_sixel(winpath))) #endif { goto error; } } width = ((u_int32_t*)cardinal)[0]; height = ((u_int32_t*)cardinal)[1]; size = sizeof(u_int32_t) * (width * height + 2); #ifdef USE_WIN32API setmode(STDOUT_FILENO, O_BINARY); #endif while (size > 0) { ssize_t n_wr; if ((n_wr = write(STDOUT_FILENO, cardinal, size)) < 0) { goto error; } cardinal += n_wr; size -= n_wr; } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " Exit image loader\n"); #endif return 0; error: bl_error_printf("Couldn't load %s\n", argv[4]); return -1; } mlterm-3.8.9/tool/cross004075500017600000144000000000001356600660700135745ustar kenusersmlterm-3.8.9/tool/cross/cross-pkg-config010064400017600000144000000002511356600660700167440ustar kenusers#!/bin/sh #env > /tmp/pkg-config-cross-debug.$$ PKG_CONFIG_ORIG=/usr/bin/pkg-config PKG_CONFIG_LIBDIR=/usr/$PKG_CONFIG_CROSS_TARGET/lib/pkgconfig $PKG_CONFIG_ORIG $@ mlterm-3.8.9/tool/mlclient004075500017600000144000000000001356600660700142525ustar kenusersmlterm-3.8.9/tool/mlclient/Makefile010064400017600000144000000004171356600660700157700ustar kenusersVPATH = . CC = gcc CFLAGS = -O2 -Wall -g INSTALL = /usr/bin/install -c OBJ = main.o PROG = mlclient all: $(PROG) $(PROG): $(OBJ) $(CC) -o $(PROG) $(OBJ) $(LIBS) cp $(PROG) $(PROG)x .SUFFIXES: .c.o .c.o: $(CC) $(CFLAGS) -c $< clean: rm -f $(OBJ) $(PROG)* *core mlterm-3.8.9/tool/mlclient/Makefile.in010064400017600000144000000012071356600660700163730ustar kenuserstop_builddir = ../.. top_srcdir = @top_srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ VPATH = ${top_srcdir}/tool/mlclient CC = @CC@ CFLAGS = @CFLAGS@ @CPPFLAGS@ LIBS = @SOCK_LIBS@ INSTALL = @INSTALL@ BINDIR = $(DESTDIR)$(bindir) OBJ = main.o PROG = mlclient all: $(PROG) $(PROG): $(OBJ) $(CC) -o $(PROG) $(OBJ) $(LIBS) @LDFLAGS@ cp $(PROG) $(PROG)x .SUFFIXES: .c.o .c.o: $(CC) $(CFLAGS) -c $< clean: rm -f $(OBJ) $(PROG)* *core distclean: clean rm -f Makefile $(BINDIR): mkdir -p $(BINDIR) install: $(BINDIR) $(INSTALL) -m 755 $(PROG)* $(BINDIR) uninstall: rm -f $(BINDIR)/$(PROG) $(BINDIR)/$(PROG)x mlterm-3.8.9/tool/mlclient/main.c010064400017600000144000000111271356600660700154200ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include /* free */ #include #include #include /* write */ #include /* memset */ #include #include #ifndef AF_LOCAL #define AF_LOCAL AF_UNIX #endif /* --- static variables --- */ static char *na_options[] = { "-@/--screens", "-R/--fsrange", "-Y/--decsp", "-c/--cp932", "-i/--xim", "-j/--daemon", " --depth", " --maxptys", " --keepalive", " --metaprefix", " --deffont", }; /* --- static functions --- */ static void version(void) { printf("mlclient(x)\n"); } static void help(int is_mlclientx) { int count; printf("mlclient(x) [prefix options] [options]\n\n"); printf("prefix optioins:\n"); printf(" /dev/...: specify pty with which a new window is opened.\n\n"); printf("options:\n"); printf(" -P/--ptylist: print pty list.\n"); printf(" --kill: kill mlterm server.\n"); if (is_mlclientx) { printf(" --hsep=value: open new pty in horizontally splitted screen.\n"); printf(" --vsep=value: open new pty in vertically splitted screen.\n"); } printf( " (--ptylist and --kill options are available only if mlterm server is " "alive.)\n\n"); printf(" N.A. options among those of mlterm.\n"); for (count = 0; count < sizeof(na_options) / sizeof(na_options[0]); count++) { printf(" %s\n", na_options[count]); } if (is_mlclientx) { printf(" ...and options related to window, font, color and appearance\n"); } } static int set_daemon_socket_path(struct sockaddr_un *addr) { const char subdir[] = "/.config/mlterm"; const char *dir; size_t len; struct stat st; if ((dir = getenv("HOME")) == NULL || '/' != dir[0]) { return 0; } if ((len = strlen(dir) + sizeof(subdir) + 1 + 6) <= sizeof(addr->sun_path)) { sprintf(addr->sun_path, "%s%s", dir, subdir); if (stat(addr->sun_path, &st) == 0) { strcat(addr->sun_path, "/socket"); return 1; } } if (len - 7 > sizeof(addr->sun_path)) { return 0; } sprintf(addr->sun_path, "%s/.mlterm/socket", dir); return 1; } static int write_argv(int argc, char **argv, int fd) { char *p; int count; /* Extract program name. */ if ((p = strrchr(argv[0], '/'))) { argv[0] = p + 1; } /* Don't quote argv[0] by "" for "\x1b]5379;mlclient" sequence. */ write(fd, argv[0], strlen(argv[0])); if (argc == 1) { return 1; } for (count = 1; count < argc; count++) { p = argv[count]; write(fd, " \"", 2); while (*p) { if (*p == '\"') { write(fd, "\\\"", 2); } #if 0 else if (*p == '=') { /* * mlterm 3.0.6 or before doesn't accept '=' in * "\x1b]5379;mlclient" sequence. */ write(fd, "\" \"", 3); } #endif else { write(fd, p, 1); } p++; } write(fd, "\"", 1); } return 1; } /* --- global functions --- */ int main(int argc, char **argv) { int count; char *p; for (count = 1; count < argc; count++) { p = argv[count]; if (*p == '-') { p++; if (*p == '-') { /* long option */ p++; } if (strcmp(p, "help") == 0 || strcmp(p, "h") == 0) { help(strstr(argv[0], "mlclientx") != NULL); return 0; } else if (strcmp(p, "version") == 0 || strcmp(p, "v") == 0) { version(); return 0; } else if (strcmp(p, "e") == 0) { /* argvs after -e are NOT options for mlterm */ break; } } } if (strstr(argv[0], "mlclientx") == NULL) { int fd; struct sockaddr_un servaddr; if ((fd = socket(AF_LOCAL, SOCK_STREAM, 0)) != -1) { memset(&servaddr, 0, sizeof(servaddr)); servaddr.sun_family = AF_LOCAL; if (set_daemon_socket_path(&servaddr)) { if (connect(fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) != -1) { char buf[256]; ssize_t len; write_argv(argc, argv, fd); write(fd, "\n", 1); while ((len = read(fd, buf, sizeof(buf))) > 0) { write(STDERR_FILENO, buf, len); if (len == 16 && strncmp(buf, "Error happened.\n", 16) == 0) { close(fd); goto config_proto; } } close(fd); return 0; } } close(fd); } fprintf(stderr, "Mlterm server is dead.\n"); } config_proto: fprintf(stderr, "Retrying by configuration protocol.\n"); write(STDOUT_FILENO, "\x1b]5379;", 7); write_argv(argc, argv, STDOUT_FILENO); write(STDOUT_FILENO, "\x07", 1); return 0; } mlterm-3.8.9/tool/mlconfig004075500017600000144000000000001356600660700142415ustar kenusersmlterm-3.8.9/tool/mlconfig/po004075500017600000144000000000001356600661000146515ustar kenusersmlterm-3.8.9/tool/mlconfig/po/POTFILES.in010064400017600000144000000015011356600660700165050ustar kenusers# List of source files containing translatable strings. # Copyright (C) 2002 Turbolinux Inc. # mlconfig - configuration tool tool/mlconfig/gtkxlfdsel.c tool/mlconfig/main.c tool/mlconfig/mc_alpha.c tool/mlconfig/mc_auto_detect.c tool/mlconfig/mc_bgtype.c tool/mlconfig/mc_char_encoding.c tool/mlconfig/mc_char_width.c tool/mlconfig/mc_click.c tool/mlconfig/mc_color.c tool/mlconfig/mc_combo.c tool/mlconfig/mc_ctl.c tool/mlconfig/mc_flags.c tool/mlconfig/mc_font.c tool/mlconfig/mc_geometry.c tool/mlconfig/mc_im.c tool/mlconfig/mc_io.c tool/mlconfig/mc_logsize.c tool/mlconfig/mc_opentype.c tool/mlconfig/mc_pty.c tool/mlconfig/mc_radio.c tool/mlconfig/mc_ratio.c tool/mlconfig/mc_sb_view.c tool/mlconfig/mc_space.c tool/mlconfig/mc_tabsize.c tool/mlconfig/mc_unicode_areas.c tool/mlconfig/mc_wall_pic.c tool/mlconfig/mc_wordsep.c mlterm-3.8.9/tool/mlconfig/po/ar.po010064400017600000144000000367011356600660700157040ustar kenusers# translation of ar.po to Arabic # Copyright (C) 2006 Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # # Khaled Hosny , 2006. msgid "" msgstr "" "Project-Id-Version: ar\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-03-03 22:12+0900\n" "PO-Revision-Date: 2006-08-12 17:40+0300\n" "Last-Translator: Khaled Hosny \n" "Language-Team: Arabic \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ar\n" "X-Generator: KBabel 1.11.2\n" #: tool/mlconfig/gtkxlfdsel.c:225 #, fuzzy msgid "Foundry:" msgstr "صوت" #: tool/mlconfig/gtkxlfdsel.c:226 msgid "Family:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:227 #, fuzzy msgid "Weight:" msgstr "Ø§ï»¹Ø±ØªÙØ§Ø¹" #: tool/mlconfig/gtkxlfdsel.c:228 msgid "Slant:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:229 #, fuzzy msgid "Set Width:" msgstr "العرض" #: tool/mlconfig/gtkxlfdsel.c:230 msgid "Add Style:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:231 msgid "Pixel Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:232 msgid "Point Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:233 msgid "Resolution X:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:234 msgid "Resolution Y:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:235 msgid "Spacing:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:236 msgid "Average Width:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:237 msgid "Charset:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:469 msgid "Font Property" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:470 msgid "Requested Value" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:471 msgid "Actual Value" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:504 tool/mlconfig/main.c:551 msgid "Font" msgstr "الخط" #: tool/mlconfig/gtkxlfdsel.c:514 tool/mlconfig/gtkxlfdsel.c:2156 #: tool/mlconfig/gtkxlfdsel.c:2386 #, fuzzy msgid "Font:" msgstr "الخط" #: tool/mlconfig/gtkxlfdsel.c:519 msgid "Font Style:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:524 msgid "Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:656 tool/mlconfig/gtkxlfdsel.c:878 msgid "Reset Filter" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:670 msgid "Metric:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:674 msgid "Points" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:681 msgid "Pixels" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:697 msgid "Preview:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:726 msgid "Font Information" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:759 msgid "Requested Font Name:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:770 msgid "Actual Font Name:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:781 #, c-format msgid "%i fonts available with a total of %i styles." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:796 msgid "Filter" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:809 msgid "Font Types:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:817 msgid "Bitmap" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:823 msgid "Scalable" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:829 msgid "Scaled Bitmap" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:897 msgid "*" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1224 msgid "(nil)" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1224 msgid "regular" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1229 tool/mlconfig/gtkxlfdsel.c:1985 msgid "italic" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1230 tool/mlconfig/gtkxlfdsel.c:1986 msgid "oblique" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1231 tool/mlconfig/gtkxlfdsel.c:1987 msgid "reverse italic" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1232 tool/mlconfig/gtkxlfdsel.c:1988 msgid "reverse oblique" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1233 tool/mlconfig/gtkxlfdsel.c:1989 #, fuzzy msgid "other" msgstr "أخرى" #: tool/mlconfig/gtkxlfdsel.c:1240 msgid "[M]" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1241 msgid "[C]" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1803 msgid "The selected font is not available." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1809 msgid "The selected font is not a valid font." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1866 msgid "This is a 2-byte font and may not be displayed correctly." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1973 msgid "(unknown)" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1984 msgid "roman" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1996 msgid "proportional" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1997 msgid "monospaced" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1998 msgid "char cell" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:2161 #, fuzzy msgid "Font: (Filter Applied)" msgstr "حجم الخط (بكسل)" #: tool/mlconfig/gtkxlfdsel.c:2637 msgid "MAX_FONTS exceeded. Some fonts may be missing." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:3477 msgid "OK" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:3484 tool/mlconfig/main.c:372 msgid "Apply" msgstr "تطبيق" #: tool/mlconfig/gtkxlfdsel.c:3490 tool/mlconfig/main.c:373 msgid "Cancel" msgstr "إلغاء" #: tool/mlconfig/gtkxlfdsel.c:3506 #, fuzzy msgid "Font Selection" msgstr " اختر" #: tool/mlconfig/main.c:216 msgid "Send" msgstr "" #: tool/mlconfig/main.c:217 msgid "Recv" msgstr "" #: tool/mlconfig/main.c:218 msgid "Return" msgstr "" #: tool/mlconfig/main.c:219 #, fuzzy msgid "Exit" msgstr "Ø­ÙØ¸ ثم خروج" #: tool/mlconfig/main.c:230 msgid "Local" msgstr "" #: tool/mlconfig/main.c:247 msgid "Remote" msgstr "" #: tool/mlconfig/main.c:370 msgid "Save&Exit" msgstr "Ø­ÙØ¸ ثم خروج" #: tool/mlconfig/main.c:371 msgid "Apply&Exit" msgstr "تطبيق ثم خروج" #: tool/mlconfig/main.c:382 msgid "Font size (temporary)" msgstr "حجم الخط (مؤقت)" #: tool/mlconfig/main.c:390 msgid "Larger" msgstr "أكبر" #: tool/mlconfig/main.c:391 msgid "Smaller" msgstr "أصغر" #: tool/mlconfig/main.c:406 msgid "Command" msgstr "" #: tool/mlconfig/main.c:414 msgid "Full reset" msgstr "إعادة تعيين" #: tool/mlconfig/main.c:415 msgid "Snapshot" msgstr "" #: tool/mlconfig/main.c:417 msgid "SCP" msgstr "" #: tool/mlconfig/main.c:433 msgid "PTY List" msgstr "قائمة الـPTY" #: tool/mlconfig/main.c:441 msgid " New " msgstr " جديد" #: tool/mlconfig/main.c:442 tool/mlconfig/mc_font.c:1264 #: tool/mlconfig/mc_wall_pic.c:62 msgid "Select" msgstr " اختر" #: tool/mlconfig/main.c:467 msgid "mlterm configuration" msgstr "إعداد mlterm" #: tool/mlconfig/main.c:502 tool/mlconfig/mc_char_encoding.c:157 msgid "Encoding" msgstr "الترميز " #: tool/mlconfig/main.c:588 msgid "Background" msgstr "الخلÙية" #: tool/mlconfig/main.c:599 msgid "Picture/Transparent" msgstr "صورة\\Ø´ÙØ§ÙØ©" #: tool/mlconfig/main.c:637 tool/mlconfig/mc_bgtype.c:105 msgid "Color" msgstr "لون" #: tool/mlconfig/main.c:658 msgid "Scrollbar" msgstr "شريط التمرير" #: tool/mlconfig/main.c:689 msgid "Others" msgstr "أخرى" #: tool/mlconfig/mc_alpha.c:49 msgid "Alpha" msgstr "" #: tool/mlconfig/mc_auto_detect.c:65 msgid "Auto detect" msgstr "" #: tool/mlconfig/mc_auto_detect.c:70 #, fuzzy msgid "Encoding list" msgstr "الترميز " #: tool/mlconfig/mc_bgtype.c:98 msgid "Background type" msgstr "نوع الخلÙية" #: tool/mlconfig/mc_bgtype.c:117 tool/mlconfig/mc_wall_pic.c:52 msgid "Picture" msgstr "صورة" #: tool/mlconfig/mc_bgtype.c:129 msgid "Pseudo transparent" msgstr "Ø´ÙØ§ÙØ©" #: tool/mlconfig/mc_char_encoding.c:24 msgid "auto" msgstr "تلقائى" #: tool/mlconfig/mc_char_encoding.c:26 msgid "--- Unicode ---" msgstr "--- يونيكود ---" #: tool/mlconfig/mc_char_encoding.c:28 msgid "--- ISO 8859 encodings ---" msgstr "--- ترميزات ISO 8859 ---" #: tool/mlconfig/mc_char_encoding.c:35 msgid "--- Other 8bit ---" msgstr "--- باقى الـ8bit ---" #: tool/mlconfig/mc_char_encoding.c:43 msgid "--- Japanese ---" msgstr "--- يابانى ---" #: tool/mlconfig/mc_char_encoding.c:46 msgid "--- Korean ---" msgstr "--- كورى ---" #: tool/mlconfig/mc_char_encoding.c:48 msgid "--- traditional Chinese ---" msgstr "--- صينى تقليدى ---" #: tool/mlconfig/mc_char_encoding.c:50 msgid "--- simplified Chinese ---" msgstr "--- صينى مبسّط ---" #: tool/mlconfig/mc_char_encoding.c:151 tool/mlconfig/mc_im.c:309 #: tool/mlconfig/mc_im.c:358 tool/mlconfig/mc_im.c:430 #: tool/mlconfig/mc_im.c:433 #, c-format msgid "auto (currently %s)" msgstr "تلقائى (حالياً %s)" #: tool/mlconfig/mc_char_width.c:85 msgid "Add full width areas" msgstr "" #: tool/mlconfig/mc_char_width.c:90 msgid "Add half width areas" msgstr "" #: tool/mlconfig/mc_click.c:49 msgid "Double click interval (msec)" msgstr "" #: tool/mlconfig/mc_color.c:36 tool/mlconfig/mc_color.c:37 msgid "Foreground color" msgstr "لون المقدمة" #: tool/mlconfig/mc_color.c:36 tool/mlconfig/mc_color.c:37 msgid "Background color" msgstr "لون الخلÙية" #: tool/mlconfig/mc_color.c:37 msgid "Bold " msgstr "" #: tool/mlconfig/mc_color.c:37 msgid "Italic" msgstr "" #: tool/mlconfig/mc_color.c:37 msgid "Underline" msgstr "" #: tool/mlconfig/mc_color.c:38 msgid "Blink" msgstr "" #: tool/mlconfig/mc_color.c:38 msgid "Cross out" msgstr "" #: tool/mlconfig/mc_color.c:138 msgid "Cursor color" msgstr "" #: tool/mlconfig/mc_color.c:161 msgid "Substituting color" msgstr "" #: tool/mlconfig/mc_color.c:208 msgid "VT basic 16 colors" msgstr "" #: tool/mlconfig/mc_ctl.c:59 msgid "Bidi separators" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Xft" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Cairo" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Anti Alias" msgstr "تحسين الحواÙ" #: tool/mlconfig/mc_flags.c:30 msgid "Variable column width" msgstr "عرض العمود متغيّر" #: tool/mlconfig/mc_flags.c:30 msgid "Combining" msgstr "الوصل" #: tool/mlconfig/mc_flags.c:31 msgid "Combining = 1 (or 0) logical column(s)" msgstr "الوصل = 1 (أو 0) عمود منطقى" #: tool/mlconfig/mc_flags.c:31 msgid "Process received strings via Unicode" msgstr "العمليات تتلقى النص عن طريق يونيكود" #: tool/mlconfig/mc_flags.c:32 msgid "Fullwidth = 2 (or 1) logical column(s)" msgstr "العرض الكامل = 2 (أو 1) أعمدة منطقية" #: tool/mlconfig/mc_flags.c:32 msgid "Complex Text Layout" msgstr "" #: tool/mlconfig/mc_flags.c:33 msgid "Ambiguouswidth = fullwidth" msgstr "" #: tool/mlconfig/mc_flags.c:33 msgid "CLIPBOARD Selection" msgstr "" #: tool/mlconfig/mc_flags.c:33 msgid "Local echo" msgstr "" #: tool/mlconfig/mc_flags.c:34 msgid "Blink cursor" msgstr "" #: tool/mlconfig/mc_flags.c:34 msgid "Don't scroll automatically in scrolling back" msgstr "" #: tool/mlconfig/mc_flags.c:35 msgid "Scroll by Shift+Up or Shift+Down" msgstr "" #: tool/mlconfig/mc_flags.c:35 msgid "Select URI by double click" msgstr "" #: tool/mlconfig/mc_flags.c:35 msgid "OpenType Layout" msgstr "" #: tool/mlconfig/mc_flags.c:36 msgid "Trim trailing CR/LF in pasting" msgstr "" #: tool/mlconfig/mc_flags.c:36 msgid "Send keys to all windows" msgstr "" #: tool/mlconfig/mc_font.c:1186 msgid "Font size (pixels)" msgstr "حجم الخط (بكسل)" #: tool/mlconfig/mc_font.c:1248 #, fuzzy msgid "Font name" msgstr "الخط" #: tool/mlconfig/mc_font.c:1274 msgid "Font width" msgstr "" #: tool/mlconfig/mc_font.c:1278 msgid "Narrow" msgstr "" #: tool/mlconfig/mc_font.c:1283 msgid "Widen" msgstr "" #: tool/mlconfig/mc_font.c:1288 msgid "Default" msgstr "" #: tool/mlconfig/mc_font.c:1303 msgid "Unicode areas you won't convert to other charsets" msgstr "" #: tool/mlconfig/mc_font.c:1306 msgid " Edit " msgstr "" #: tool/mlconfig/mc_geometry.c:36 msgid "Columns" msgstr "" #: tool/mlconfig/mc_geometry.c:36 msgid "Rows" msgstr "" #: tool/mlconfig/mc_im.c:364 msgid "XIM Server" msgstr "خادم XIM " #: tool/mlconfig/mc_im.c:367 msgid "XIM locale" msgstr "محلية XIM " #: tool/mlconfig/mc_im.c:442 msgid "Option" msgstr "خيار" #: tool/mlconfig/mc_im.c:534 msgid "Dictionary" msgstr "" #: tool/mlconfig/mc_im.c:535 msgid "Sticky shift key" msgstr "" #: tool/mlconfig/mc_im.c:584 #, fuzzy msgid "Server" msgstr "خادم XIM " #: tool/mlconfig/mc_im.c:719 msgid "Input Method" msgstr "طريقة اﻹدخال" #: tool/mlconfig/mc_im.c:743 tool/mlconfig/mc_radio.c:55 #: tool/mlconfig/mc_radio.c:58 tool/mlconfig/mc_radio.c:61 #: tool/mlconfig/mc_radio.c:64 msgid "None" msgstr "لا" #: tool/mlconfig/mc_logsize.c:50 msgid "Backlog size (lines)" msgstr "حجم السجل (أسطر)" #: tool/mlconfig/mc_opentype.c:92 msgid "Select opentype features" msgstr "" #: tool/mlconfig/mc_opentype.c:178 msgid "Select opentype scripts" msgstr "" #: tool/mlconfig/mc_opentype.c:254 msgid "Features" msgstr "" #: tool/mlconfig/mc_opentype.c:259 msgid "Script" msgstr "" #: tool/mlconfig/mc_radio.c:55 msgid "Meta key outputs" msgstr "خرج Ù…ÙØªØ§Ø­ Meta" #: tool/mlconfig/mc_radio.c:55 msgid "Esc" msgstr "Esc" #: tool/mlconfig/mc_radio.c:55 msgid "8bit" msgstr "8 بت" #: tool/mlconfig/mc_radio.c:58 msgid "Bell mode" msgstr " نمط الجرس " #: tool/mlconfig/mc_radio.c:58 msgid "Sound" msgstr "صوت" #: tool/mlconfig/mc_radio.c:58 msgid "Visual" msgstr "مرئى" #: tool/mlconfig/mc_radio.c:58 msgid "Both" msgstr "" #: tool/mlconfig/mc_radio.c:61 msgid "Position" msgstr "الموضع" #: tool/mlconfig/mc_radio.c:61 msgid "Left" msgstr "يسار" #: tool/mlconfig/mc_radio.c:61 msgid "Right" msgstr "يمين" #: tool/mlconfig/mc_radio.c:61 msgid "Auto hide" msgstr "" #: tool/mlconfig/mc_radio.c:64 msgid "Vertical mode" msgstr " النمط الرأسى " #: tool/mlconfig/mc_radio.c:64 msgid "CJK" msgstr "CJK" #: tool/mlconfig/mc_radio.c:64 msgid "Mongol" msgstr "منغولى" #: tool/mlconfig/mc_radio.c:67 msgid "Box drawing" msgstr "" #: tool/mlconfig/mc_radio.c:67 tool/mlconfig/mc_radio.c:70 msgid "As it is" msgstr "" #: tool/mlconfig/mc_radio.c:67 #, fuzzy msgid "Unicode" msgstr "--- يونيكود ---" #: tool/mlconfig/mc_radio.c:67 msgid "DEC Special" msgstr "" #: tool/mlconfig/mc_radio.c:70 msgid "Font policy" msgstr "" #: tool/mlconfig/mc_radio.c:70 msgid "Always unicode" msgstr "" #: tool/mlconfig/mc_radio.c:70 msgid "Never unicode" msgstr "" #: tool/mlconfig/mc_radio.c:73 msgid "Save log" msgstr "" #: tool/mlconfig/mc_radio.c:73 #, fuzzy msgid "No" msgstr "لا" #: tool/mlconfig/mc_radio.c:73 msgid "Raw format" msgstr "" #: tool/mlconfig/mc_radio.c:73 msgid "Ttyrec format" msgstr "" #: tool/mlconfig/mc_ratio.c:31 msgid "Contrast " msgstr "التباين" #: tool/mlconfig/mc_ratio.c:31 msgid "Gamma" msgstr "الغاما" #: tool/mlconfig/mc_ratio.c:31 msgid "Brightness" msgstr "السطوع" #: tool/mlconfig/mc_ratio.c:31 msgid "Fade ratio on unfocus" msgstr "نسبة اﻹبهات عند عدم التركيز" #: tool/mlconfig/mc_ratio.c:32 msgid "Screen size ratio against font size" msgstr "نسبة الشاشة لحجم الخط" #: tool/mlconfig/mc_sb_view.c:119 msgid "View" msgstr "المنظر" #: tool/mlconfig/mc_space.c:31 msgid "Line space (pixels)" msgstr "Ù…Ø³Ø§ÙØ© ما بين السطور (بكسل)" #: tool/mlconfig/mc_space.c:31 #, fuzzy msgid "Letter space (pixels)" msgstr "Ù…Ø³Ø§ÙØ© ما بين السطور (بكسل)" #: tool/mlconfig/mc_space.c:31 #, fuzzy msgid "Baseline position (pixels)" msgstr "Ù…Ø³Ø§ÙØ© ما بين السطور (بكسل)" #: tool/mlconfig/mc_space.c:32 #, fuzzy msgid "Underline position (pixels)" msgstr "Ù…Ø³Ø§ÙØ© ما بين السطور (بكسل)" #: tool/mlconfig/mc_tabsize.c:50 msgid "Tab width (columns)" msgstr "عرض Tab (أعمدة)" #: tool/mlconfig/mc_unicode_areas.c:131 msgid "" "Set unicode area in the following format.\n" "Format: U+XXXX-XXXX or U+XXXX (U+ is optional)" msgstr "" #: tool/mlconfig/mc_wordsep.c:111 msgid "Word separators" msgstr "" #~ msgid "ISCII language" #~ msgstr "لغة ISCII" mlterm-3.8.9/tool/mlconfig/po/de.po010064400017600000144000000361271356600660700156740ustar kenusers# German translations for mlterm # Copyright (C) 2002 Araki Ken # This file is distributed under the same license as the mlterm package. # Mike Fabian , 2002. # msgid "" msgstr "" "Project-Id-Version: mlterm 2.6.3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-03-03 22:12+0900\n" "PO-Revision-Date: 2003-03-24 17:32+0100\n" "Last-Translator: Mike Fabian \n" "Language-Team: German \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de\n" #: tool/mlconfig/gtkxlfdsel.c:225 #, fuzzy msgid "Foundry:" msgstr "akustisch" #: tool/mlconfig/gtkxlfdsel.c:226 msgid "Family:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:227 #, fuzzy msgid "Weight:" msgstr "Höhe" #: tool/mlconfig/gtkxlfdsel.c:228 msgid "Slant:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:229 #, fuzzy msgid "Set Width:" msgstr "Breite" #: tool/mlconfig/gtkxlfdsel.c:230 msgid "Add Style:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:231 msgid "Pixel Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:232 msgid "Point Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:233 msgid "Resolution X:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:234 msgid "Resolution Y:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:235 msgid "Spacing:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:236 msgid "Average Width:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:237 msgid "Charset:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:469 msgid "Font Property" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:470 msgid "Requested Value" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:471 msgid "Actual Value" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:504 tool/mlconfig/main.c:551 msgid "Font" msgstr "Font" #: tool/mlconfig/gtkxlfdsel.c:514 tool/mlconfig/gtkxlfdsel.c:2156 #: tool/mlconfig/gtkxlfdsel.c:2386 #, fuzzy msgid "Font:" msgstr "Font" #: tool/mlconfig/gtkxlfdsel.c:519 msgid "Font Style:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:524 msgid "Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:656 tool/mlconfig/gtkxlfdsel.c:878 msgid "Reset Filter" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:670 msgid "Metric:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:674 msgid "Points" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:681 msgid "Pixels" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:697 msgid "Preview:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:726 msgid "Font Information" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:759 msgid "Requested Font Name:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:770 msgid "Actual Font Name:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:781 #, c-format msgid "%i fonts available with a total of %i styles." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:796 msgid "Filter" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:809 msgid "Font Types:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:817 msgid "Bitmap" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:823 msgid "Scalable" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:829 msgid "Scaled Bitmap" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:897 msgid "*" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1224 msgid "(nil)" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1224 msgid "regular" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1229 tool/mlconfig/gtkxlfdsel.c:1985 msgid "italic" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1230 tool/mlconfig/gtkxlfdsel.c:1986 msgid "oblique" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1231 tool/mlconfig/gtkxlfdsel.c:1987 msgid "reverse italic" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1232 tool/mlconfig/gtkxlfdsel.c:1988 msgid "reverse oblique" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1233 tool/mlconfig/gtkxlfdsel.c:1989 #, fuzzy msgid "other" msgstr "Sonstiges" #: tool/mlconfig/gtkxlfdsel.c:1240 msgid "[M]" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1241 msgid "[C]" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1803 msgid "The selected font is not available." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1809 msgid "The selected font is not a valid font." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1866 msgid "This is a 2-byte font and may not be displayed correctly." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1973 msgid "(unknown)" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1984 msgid "roman" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1996 msgid "proportional" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1997 msgid "monospaced" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1998 msgid "char cell" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:2161 #, fuzzy msgid "Font: (Filter Applied)" msgstr "Fontgröße (Pixel)" #: tool/mlconfig/gtkxlfdsel.c:2637 msgid "MAX_FONTS exceeded. Some fonts may be missing." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:3477 msgid "OK" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:3484 tool/mlconfig/main.c:372 msgid "Apply" msgstr "Anwenden" #: tool/mlconfig/gtkxlfdsel.c:3490 tool/mlconfig/main.c:373 msgid "Cancel" msgstr "Abbrechen" #: tool/mlconfig/gtkxlfdsel.c:3506 #, fuzzy msgid "Font Selection" msgstr " Auswahl " #: tool/mlconfig/main.c:216 msgid "Send" msgstr "" #: tool/mlconfig/main.c:217 msgid "Recv" msgstr "" #: tool/mlconfig/main.c:218 msgid "Return" msgstr "" #: tool/mlconfig/main.c:219 #, fuzzy msgid "Exit" msgstr "Speichern & Beenden" #: tool/mlconfig/main.c:230 msgid "Local" msgstr "" #: tool/mlconfig/main.c:247 msgid "Remote" msgstr "" #: tool/mlconfig/main.c:370 msgid "Save&Exit" msgstr "Speichern & Beenden" #: tool/mlconfig/main.c:371 msgid "Apply&Exit" msgstr "Anwenden & Beenden" #: tool/mlconfig/main.c:382 msgid "Font size (temporary)" msgstr "Fontgröße (temporär)" #: tool/mlconfig/main.c:390 msgid "Larger" msgstr "Größer" #: tool/mlconfig/main.c:391 msgid "Smaller" msgstr "Kleiner" #: tool/mlconfig/main.c:406 msgid "Command" msgstr "" #: tool/mlconfig/main.c:414 msgid "Full reset" msgstr "Alles Zurücksetzen" #: tool/mlconfig/main.c:415 msgid "Snapshot" msgstr "" #: tool/mlconfig/main.c:417 msgid "SCP" msgstr "" #: tool/mlconfig/main.c:433 msgid "PTY List" msgstr "PTY Liste" #: tool/mlconfig/main.c:441 msgid " New " msgstr " Neu " #: tool/mlconfig/main.c:442 tool/mlconfig/mc_font.c:1264 #: tool/mlconfig/mc_wall_pic.c:62 msgid "Select" msgstr " Auswahl " #: tool/mlconfig/main.c:467 msgid "mlterm configuration" msgstr "mlterm Konfiguration" #: tool/mlconfig/main.c:502 tool/mlconfig/mc_char_encoding.c:157 msgid "Encoding" msgstr "Kodierung" #: tool/mlconfig/main.c:588 msgid "Background" msgstr "Hintergrund" #: tool/mlconfig/main.c:599 msgid "Picture/Transparent" msgstr "Bild/Transparenz" #: tool/mlconfig/main.c:637 tool/mlconfig/mc_bgtype.c:105 msgid "Color" msgstr "Farbe" #: tool/mlconfig/main.c:658 msgid "Scrollbar" msgstr "Scrollbalken" #: tool/mlconfig/main.c:689 msgid "Others" msgstr "Sonstiges" #: tool/mlconfig/mc_alpha.c:49 msgid "Alpha" msgstr "" #: tool/mlconfig/mc_auto_detect.c:65 msgid "Auto detect" msgstr "" #: tool/mlconfig/mc_auto_detect.c:70 #, fuzzy msgid "Encoding list" msgstr "Kodierung" #: tool/mlconfig/mc_bgtype.c:98 msgid "Background type" msgstr "Hintergrundtyp" #: tool/mlconfig/mc_bgtype.c:117 tool/mlconfig/mc_wall_pic.c:52 msgid "Picture" msgstr "Bild" #: tool/mlconfig/mc_bgtype.c:129 msgid "Pseudo transparent" msgstr "Pseudo transparent" #: tool/mlconfig/mc_char_encoding.c:24 msgid "auto" msgstr "Auto" #: tool/mlconfig/mc_char_encoding.c:26 msgid "--- Unicode ---" msgstr "--- Unicode ---" #: tool/mlconfig/mc_char_encoding.c:28 msgid "--- ISO 8859 encodings ---" msgstr "--- ISO 8859 Kodierungen ---" #: tool/mlconfig/mc_char_encoding.c:35 msgid "--- Other 8bit ---" msgstr "--- Sonstige 8bit Kodierungen ---" #: tool/mlconfig/mc_char_encoding.c:43 msgid "--- Japanese ---" msgstr "--- Japanisch ---" #: tool/mlconfig/mc_char_encoding.c:46 msgid "--- Korean ---" msgstr "--- Koreanisch ---" #: tool/mlconfig/mc_char_encoding.c:48 msgid "--- traditional Chinese ---" msgstr "--- traditionelles Chinesisch ---" #: tool/mlconfig/mc_char_encoding.c:50 msgid "--- simplified Chinese ---" msgstr "--- vereinfachtes Chinesisch ---" #: tool/mlconfig/mc_char_encoding.c:151 tool/mlconfig/mc_im.c:309 #: tool/mlconfig/mc_im.c:358 tool/mlconfig/mc_im.c:430 #: tool/mlconfig/mc_im.c:433 #, c-format msgid "auto (currently %s)" msgstr "automatisch (aktuell: %s)" #: tool/mlconfig/mc_char_width.c:85 msgid "Add full width areas" msgstr "" #: tool/mlconfig/mc_char_width.c:90 msgid "Add half width areas" msgstr "" #: tool/mlconfig/mc_click.c:49 msgid "Double click interval (msec)" msgstr "" #: tool/mlconfig/mc_color.c:36 tool/mlconfig/mc_color.c:37 msgid "Foreground color" msgstr "Vordergrundfarbe" #: tool/mlconfig/mc_color.c:36 tool/mlconfig/mc_color.c:37 msgid "Background color" msgstr "Hintergrundfarbe" #: tool/mlconfig/mc_color.c:37 msgid "Bold " msgstr "" #: tool/mlconfig/mc_color.c:37 msgid "Italic" msgstr "" #: tool/mlconfig/mc_color.c:37 msgid "Underline" msgstr "" #: tool/mlconfig/mc_color.c:38 msgid "Blink" msgstr "" #: tool/mlconfig/mc_color.c:38 msgid "Cross out" msgstr "" #: tool/mlconfig/mc_color.c:138 msgid "Cursor color" msgstr "" #: tool/mlconfig/mc_color.c:161 msgid "Substituting color" msgstr "" #: tool/mlconfig/mc_color.c:208 msgid "VT basic 16 colors" msgstr "" #: tool/mlconfig/mc_ctl.c:59 msgid "Bidi separators" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Xft" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Cairo" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Anti Alias" msgstr "Anti-Aliasing" #: tool/mlconfig/mc_flags.c:30 msgid "Variable column width" msgstr "Proportionalschrift" #: tool/mlconfig/mc_flags.c:30 msgid "Combining" msgstr "Zusammengesetzte Zeichen" #: tool/mlconfig/mc_flags.c:31 msgid "Combining = 1 (or 0) logical column(s)" msgstr "Zusammengesetzte Zeichen =1 (oder 0) logische Spalte(n)" #: tool/mlconfig/mc_flags.c:31 msgid "Process received strings via Unicode" msgstr "Prozess empfängt Strings als Unicode" #: tool/mlconfig/mc_flags.c:32 msgid "Fullwidth = 2 (or 1) logical column(s)" msgstr "Volle Breite = 2 (oder 1) logische Spalte(n)" #: tool/mlconfig/mc_flags.c:32 msgid "Complex Text Layout" msgstr "" #: tool/mlconfig/mc_flags.c:33 msgid "Ambiguouswidth = fullwidth" msgstr "" #: tool/mlconfig/mc_flags.c:33 msgid "CLIPBOARD Selection" msgstr "" #: tool/mlconfig/mc_flags.c:33 msgid "Local echo" msgstr "" #: tool/mlconfig/mc_flags.c:34 msgid "Blink cursor" msgstr "" #: tool/mlconfig/mc_flags.c:34 msgid "Don't scroll automatically in scrolling back" msgstr "" #: tool/mlconfig/mc_flags.c:35 msgid "Scroll by Shift+Up or Shift+Down" msgstr "" #: tool/mlconfig/mc_flags.c:35 msgid "Select URI by double click" msgstr "" #: tool/mlconfig/mc_flags.c:35 msgid "OpenType Layout" msgstr "" #: tool/mlconfig/mc_flags.c:36 msgid "Trim trailing CR/LF in pasting" msgstr "" #: tool/mlconfig/mc_flags.c:36 msgid "Send keys to all windows" msgstr "" #: tool/mlconfig/mc_font.c:1186 msgid "Font size (pixels)" msgstr "Fontgröße (Pixel)" #: tool/mlconfig/mc_font.c:1248 #, fuzzy msgid "Font name" msgstr "Font" #: tool/mlconfig/mc_font.c:1274 msgid "Font width" msgstr "" #: tool/mlconfig/mc_font.c:1278 msgid "Narrow" msgstr "" #: tool/mlconfig/mc_font.c:1283 msgid "Widen" msgstr "" #: tool/mlconfig/mc_font.c:1288 msgid "Default" msgstr "" #: tool/mlconfig/mc_font.c:1303 msgid "Unicode areas you won't convert to other charsets" msgstr "" #: tool/mlconfig/mc_font.c:1306 msgid " Edit " msgstr "" #: tool/mlconfig/mc_geometry.c:36 msgid "Columns" msgstr "" #: tool/mlconfig/mc_geometry.c:36 msgid "Rows" msgstr "" #: tool/mlconfig/mc_im.c:364 msgid "XIM Server" msgstr "XIM Server" #: tool/mlconfig/mc_im.c:367 msgid "XIM locale" msgstr "XIM Locale" #: tool/mlconfig/mc_im.c:442 msgid "Option" msgstr "Option" #: tool/mlconfig/mc_im.c:534 msgid "Dictionary" msgstr "" #: tool/mlconfig/mc_im.c:535 msgid "Sticky shift key" msgstr "" #: tool/mlconfig/mc_im.c:584 #, fuzzy msgid "Server" msgstr "XIM Server" #: tool/mlconfig/mc_im.c:719 msgid "Input Method" msgstr "Input Methode" #: tool/mlconfig/mc_im.c:743 tool/mlconfig/mc_radio.c:55 #: tool/mlconfig/mc_radio.c:58 tool/mlconfig/mc_radio.c:61 #: tool/mlconfig/mc_radio.c:64 msgid "None" msgstr "Keine" #: tool/mlconfig/mc_logsize.c:50 msgid "Backlog size (lines)" msgstr "Verlaufsspeicher Größe (Zeilen)" #: tool/mlconfig/mc_opentype.c:92 msgid "Select opentype features" msgstr "" #: tool/mlconfig/mc_opentype.c:178 msgid "Select opentype scripts" msgstr "" #: tool/mlconfig/mc_opentype.c:254 msgid "Features" msgstr "" #: tool/mlconfig/mc_opentype.c:259 msgid "Script" msgstr "" #: tool/mlconfig/mc_radio.c:55 msgid "Meta key outputs" msgstr "Verhalten der Meta Taste:" #: tool/mlconfig/mc_radio.c:55 msgid "Esc" msgstr "Esc" #: tool/mlconfig/mc_radio.c:55 msgid "8bit" msgstr "8 Bit" #: tool/mlconfig/mc_radio.c:58 msgid "Bell mode" msgstr "Signalglocke" #: tool/mlconfig/mc_radio.c:58 msgid "Sound" msgstr "akustisch" #: tool/mlconfig/mc_radio.c:58 msgid "Visual" msgstr "visuell" #: tool/mlconfig/mc_radio.c:58 msgid "Both" msgstr "" #: tool/mlconfig/mc_radio.c:61 msgid "Position" msgstr "Position" #: tool/mlconfig/mc_radio.c:61 msgid "Left" msgstr "Links" #: tool/mlconfig/mc_radio.c:61 msgid "Right" msgstr "Rechts" #: tool/mlconfig/mc_radio.c:61 msgid "Auto hide" msgstr "" #: tool/mlconfig/mc_radio.c:64 msgid "Vertical mode" msgstr "Vertikaler Modus" #: tool/mlconfig/mc_radio.c:64 msgid "CJK" msgstr "CJK" #: tool/mlconfig/mc_radio.c:64 msgid "Mongol" msgstr "Mongolisch" #: tool/mlconfig/mc_radio.c:67 msgid "Box drawing" msgstr "" #: tool/mlconfig/mc_radio.c:67 tool/mlconfig/mc_radio.c:70 msgid "As it is" msgstr "" #: tool/mlconfig/mc_radio.c:67 #, fuzzy msgid "Unicode" msgstr "--- Unicode ---" #: tool/mlconfig/mc_radio.c:67 msgid "DEC Special" msgstr "" #: tool/mlconfig/mc_radio.c:70 msgid "Font policy" msgstr "" #: tool/mlconfig/mc_radio.c:70 msgid "Always unicode" msgstr "" #: tool/mlconfig/mc_radio.c:70 msgid "Never unicode" msgstr "" #: tool/mlconfig/mc_radio.c:73 msgid "Save log" msgstr "" #: tool/mlconfig/mc_radio.c:73 #, fuzzy msgid "No" msgstr "Keine" #: tool/mlconfig/mc_radio.c:73 msgid "Raw format" msgstr "" #: tool/mlconfig/mc_radio.c:73 msgid "Ttyrec format" msgstr "" #: tool/mlconfig/mc_ratio.c:31 msgid "Contrast " msgstr "Kontrast" #: tool/mlconfig/mc_ratio.c:31 msgid "Gamma" msgstr "Gamma" #: tool/mlconfig/mc_ratio.c:31 msgid "Brightness" msgstr "Helligkeit" #: tool/mlconfig/mc_ratio.c:31 msgid "Fade ratio on unfocus" msgstr "Verblassungsrate bei Fokusverlust" #: tool/mlconfig/mc_ratio.c:32 msgid "Screen size ratio against font size" msgstr "Bildschirmgröße relativ zur Fontgröße" #: tool/mlconfig/mc_sb_view.c:119 msgid "View" msgstr "Aussehen" #: tool/mlconfig/mc_space.c:31 msgid "Line space (pixels)" msgstr "Zeilenabstand (Pixel)" #: tool/mlconfig/mc_space.c:31 #, fuzzy msgid "Letter space (pixels)" msgstr "Zeilenabstand (Pixel)" #: tool/mlconfig/mc_space.c:31 #, fuzzy msgid "Baseline position (pixels)" msgstr "Zeilenabstand (Pixel)" #: tool/mlconfig/mc_space.c:32 #, fuzzy msgid "Underline position (pixels)" msgstr "Zeilenabstand (Pixel)" #: tool/mlconfig/mc_tabsize.c:50 msgid "Tab width (columns)" msgstr "Tabulatorbreite (Spalten)" #: tool/mlconfig/mc_unicode_areas.c:131 msgid "" "Set unicode area in the following format.\n" "Format: U+XXXX-XXXX or U+XXXX (U+ is optional)" msgstr "" #: tool/mlconfig/mc_wordsep.c:111 msgid "Word separators" msgstr "" #~ msgid "ISCII language" #~ msgstr "ISCII Sprache" mlterm-3.8.9/tool/mlconfig/po/ja.po010064400017600000144000000371611356600660700156750ustar kenusersmsgid "" msgstr "" "Project-Id-Version: mlterm 2.6.3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-03-03 22:12+0900\n" "PO-Revision-Date: 2002-11-25 19:24+0100\n" "Last-Translator: Tomohiro KUBOTA \n" "Language-Team: Japanese \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=euc-jp\n" "Content-Transfer-Encoding: 8bit\n" "Language: ja\n" #: tool/mlconfig/gtkxlfdsel.c:225 #, fuzzy msgid "Foundry:" msgstr "²»" #: tool/mlconfig/gtkxlfdsel.c:226 msgid "Family:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:227 #, fuzzy msgid "Weight:" msgstr "¹â¤µ" #: tool/mlconfig/gtkxlfdsel.c:228 msgid "Slant:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:229 #, fuzzy msgid "Set Width:" msgstr "Éý" #: tool/mlconfig/gtkxlfdsel.c:230 msgid "Add Style:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:231 msgid "Pixel Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:232 msgid "Point Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:233 msgid "Resolution X:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:234 msgid "Resolution Y:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:235 msgid "Spacing:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:236 msgid "Average Width:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:237 msgid "Charset:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:469 msgid "Font Property" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:470 msgid "Requested Value" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:471 msgid "Actual Value" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:504 tool/mlconfig/main.c:551 msgid "Font" msgstr "¥Õ¥©¥ó¥È" #: tool/mlconfig/gtkxlfdsel.c:514 tool/mlconfig/gtkxlfdsel.c:2156 #: tool/mlconfig/gtkxlfdsel.c:2386 #, fuzzy msgid "Font:" msgstr "¥Õ¥©¥ó¥È" #: tool/mlconfig/gtkxlfdsel.c:519 #, fuzzy msgid "Font Style:" msgstr "¥Õ¥©¥ó¥È̾" #: tool/mlconfig/gtkxlfdsel.c:524 msgid "Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:656 tool/mlconfig/gtkxlfdsel.c:878 msgid "Reset Filter" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:670 msgid "Metric:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:674 msgid "Points" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:681 msgid "Pixels" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:697 msgid "Preview:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:726 msgid "Font Information" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:759 msgid "Requested Font Name:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:770 #, fuzzy msgid "Actual Font Name:" msgstr "¥Õ¥©¥ó¥È̾" #: tool/mlconfig/gtkxlfdsel.c:781 #, c-format msgid "%i fonts available with a total of %i styles." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:796 msgid "Filter" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:809 #, fuzzy msgid "Font Types:" msgstr "¥Õ¥©¥ó¥È̾" #: tool/mlconfig/gtkxlfdsel.c:817 msgid "Bitmap" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:823 msgid "Scalable" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:829 msgid "Scaled Bitmap" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:897 msgid "*" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1224 msgid "(nil)" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1224 msgid "regular" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1229 tool/mlconfig/gtkxlfdsel.c:1985 #, fuzzy msgid "italic" msgstr "¥¤¥¿¥ê¥Ã¥¯" #: tool/mlconfig/gtkxlfdsel.c:1230 tool/mlconfig/gtkxlfdsel.c:1986 msgid "oblique" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1231 tool/mlconfig/gtkxlfdsel.c:1987 msgid "reverse italic" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1232 tool/mlconfig/gtkxlfdsel.c:1988 msgid "reverse oblique" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1233 tool/mlconfig/gtkxlfdsel.c:1989 #, fuzzy msgid "other" msgstr "¤½¤Î¾" #: tool/mlconfig/gtkxlfdsel.c:1240 msgid "[M]" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1241 msgid "[C]" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1803 msgid "The selected font is not available." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1809 msgid "The selected font is not a valid font." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1866 msgid "This is a 2-byte font and may not be displayed correctly." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1973 msgid "(unknown)" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1984 msgid "roman" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1996 msgid "proportional" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1997 msgid "monospaced" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1998 msgid "char cell" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:2161 #, fuzzy msgid "Font: (Filter Applied)" msgstr "¥Õ¥©¥ó¥È¥µ¥¤¥º(¥Ô¥¯¥»¥ë)" #: tool/mlconfig/gtkxlfdsel.c:2637 msgid "MAX_FONTS exceeded. Some fonts may be missing." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:3477 msgid "OK" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:3484 tool/mlconfig/main.c:372 msgid "Apply" msgstr "ŬÍÑ" #: tool/mlconfig/gtkxlfdsel.c:3490 tool/mlconfig/main.c:373 msgid "Cancel" msgstr "¥­¥ã¥ó¥»¥ë" #: tool/mlconfig/gtkxlfdsel.c:3506 #, fuzzy msgid "Font Selection" msgstr "ÁªÂò" #: tool/mlconfig/main.c:216 msgid "Send" msgstr "" #: tool/mlconfig/main.c:217 msgid "Recv" msgstr "" #: tool/mlconfig/main.c:218 msgid "Return" msgstr "" #: tool/mlconfig/main.c:219 #, fuzzy msgid "Exit" msgstr "Êݸ&½ªÎ»" #: tool/mlconfig/main.c:230 #, fuzzy msgid "Local" msgstr "¥í¡¼¥«¥ë¥¨¥³¡¼" #: tool/mlconfig/main.c:247 msgid "Remote" msgstr "" #: tool/mlconfig/main.c:370 msgid "Save&Exit" msgstr "Êݸ&½ªÎ»" #: tool/mlconfig/main.c:371 msgid "Apply&Exit" msgstr "ŬÍÑ&½ªÎ»" #: tool/mlconfig/main.c:382 msgid "Font size (temporary)" msgstr "¥Õ¥©¥ó¥È¥µ¥¤¥º (°ì»þÀßÄê)" #: tool/mlconfig/main.c:390 msgid "Larger" msgstr "Â礭¤¯" #: tool/mlconfig/main.c:391 msgid "Smaller" msgstr "¾®¤µ¤¯" #: tool/mlconfig/main.c:406 msgid "Command" msgstr "" #: tool/mlconfig/main.c:414 msgid "Full reset" msgstr "Á´¥ê¥»¥Ã¥È" #: tool/mlconfig/main.c:415 msgid "Snapshot" msgstr "" #: tool/mlconfig/main.c:417 msgid "SCP" msgstr "" #: tool/mlconfig/main.c:433 msgid "PTY List" msgstr "²¾ÁÛüËö°ìÍ÷" #: tool/mlconfig/main.c:441 msgid " New " msgstr "¿·µ¬" #: tool/mlconfig/main.c:442 tool/mlconfig/mc_font.c:1264 #: tool/mlconfig/mc_wall_pic.c:62 #, fuzzy msgid "Select" msgstr "ÁªÂò" #: tool/mlconfig/main.c:467 msgid "mlterm configuration" msgstr "mlterm¤ÎÀßÄê" #: tool/mlconfig/main.c:502 tool/mlconfig/mc_char_encoding.c:157 msgid "Encoding" msgstr "¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°" #: tool/mlconfig/main.c:588 msgid "Background" msgstr "ÇØ·Ê" #: tool/mlconfig/main.c:599 msgid "Picture/Transparent" msgstr "ÊÉ»æ/Æ©ÌÀ" #: tool/mlconfig/main.c:637 tool/mlconfig/mc_bgtype.c:105 msgid "Color" msgstr "¿§" #: tool/mlconfig/main.c:658 msgid "Scrollbar" msgstr "¥¹¥¯¥í¡¼¥ë¥Ð¡¼" #: tool/mlconfig/main.c:689 msgid "Others" msgstr "¤½¤Î¾" #: tool/mlconfig/mc_alpha.c:49 msgid "Alpha" msgstr "¥¢¥ë¥Õ¥¡" #: tool/mlconfig/mc_auto_detect.c:65 msgid "Auto detect" msgstr "¼«Æ°È½Äê" #: tool/mlconfig/mc_auto_detect.c:70 msgid "Encoding list" msgstr "Âоݥ¨¥ó¥³¡¼¥Ç¥£¥ó¥°" #: tool/mlconfig/mc_bgtype.c:98 msgid "Background type" msgstr "ÇØ·Ê¤Î¥¿¥¤¥×" #: tool/mlconfig/mc_bgtype.c:117 tool/mlconfig/mc_wall_pic.c:52 msgid "Picture" msgstr "ÊÉ»æ" #: tool/mlconfig/mc_bgtype.c:129 msgid "Pseudo transparent" msgstr "µ¼»÷Æ©ÌÀ" #: tool/mlconfig/mc_char_encoding.c:24 msgid "auto" msgstr "¼«Æ°" #: tool/mlconfig/mc_char_encoding.c:26 msgid "--- Unicode ---" msgstr "--- Unicode ---" #: tool/mlconfig/mc_char_encoding.c:28 msgid "--- ISO 8859 encodings ---" msgstr "--- ISO 8859 ¥¨¥ó¥³¡¼¥Ç¥£¥ó¥° ---" #: tool/mlconfig/mc_char_encoding.c:35 msgid "--- Other 8bit ---" msgstr "-- ¤½¤Î¾8¥Ó¥Ã¥È ---" #: tool/mlconfig/mc_char_encoding.c:43 msgid "--- Japanese ---" msgstr "--- ÆüËܸì ---" #: tool/mlconfig/mc_char_encoding.c:46 msgid "--- Korean ---" msgstr "--- ´Ú¹ñ¸ì ---" #: tool/mlconfig/mc_char_encoding.c:48 msgid "--- traditional Chinese ---" msgstr "--- Ãæ¹ñ¸ì(ÈËÂλú) ---" #: tool/mlconfig/mc_char_encoding.c:50 msgid "--- simplified Chinese ---" msgstr "--- Ãæ¹ñ¸ì(´ÊÂλú) ---" #: tool/mlconfig/mc_char_encoding.c:151 tool/mlconfig/mc_im.c:309 #: tool/mlconfig/mc_im.c:358 tool/mlconfig/mc_im.c:430 #: tool/mlconfig/mc_im.c:433 #, c-format msgid "auto (currently %s)" msgstr "¼«Æ° (¸½ºß %s)" #: tool/mlconfig/mc_char_width.c:85 msgid "Add full width areas" msgstr "Á´³ÑÉýʸ»ú¤ÎÈϰϤòÄɲÃ" #: tool/mlconfig/mc_char_width.c:90 msgid "Add half width areas" msgstr "Ⱦ³ÑÉýʸ»ú¤ÎÈϰϤòÄɲÃ" #: tool/mlconfig/mc_click.c:49 msgid "Double click interval (msec)" msgstr "¥À¥Ö¥ë¥¯¥ê¥Ã¥¯¤Î´Ö³Ö(¥ß¥êÉÃ)" #: tool/mlconfig/mc_color.c:36 tool/mlconfig/mc_color.c:37 msgid "Foreground color" msgstr "Á°·Ê¿§" #: tool/mlconfig/mc_color.c:36 tool/mlconfig/mc_color.c:37 msgid "Background color" msgstr "ÇØ·Ê¿§" #: tool/mlconfig/mc_color.c:37 msgid "Bold " msgstr "¥Ü¡¼¥ë¥É" #: tool/mlconfig/mc_color.c:37 msgid "Italic" msgstr "¥¤¥¿¥ê¥Ã¥¯" #: tool/mlconfig/mc_color.c:37 msgid "Underline" msgstr "²¼Àþ" #: tool/mlconfig/mc_color.c:38 msgid "Blink" msgstr "ÅÀÌÇ" #: tool/mlconfig/mc_color.c:38 msgid "Cross out" msgstr "¼è¾ÃÀþ" #: tool/mlconfig/mc_color.c:138 msgid "Cursor color" msgstr "¥«¡¼¥½¥ë" #: tool/mlconfig/mc_color.c:161 msgid "Substituting color" msgstr "ʸ»ú°À­¤ËÂ夨¤ÆÉ½¼¨¤¹¤ë¿§" #: tool/mlconfig/mc_color.c:208 msgid "VT basic 16 colors" msgstr "¥«¥é¡¼¥Ñ¥ì¥Ã¥È(16¿§)" #: tool/mlconfig/mc_ctl.c:59 #, fuzzy msgid "Bidi separators" msgstr "BiDi¤Î¶èÀÚ¤êʸ»ú" #: tool/mlconfig/mc_flags.c:30 msgid "Xft" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Cairo" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Anti Alias" msgstr "¥¢¥ó¥Á¥¨¥¤¥ê¥¢¥¹" #: tool/mlconfig/mc_flags.c:30 msgid "Variable column width" msgstr "²ÄÊÑĹ¥³¥é¥àÉý" #: tool/mlconfig/mc_flags.c:30 msgid "Combining" msgstr "·ë¹çʸ»ú½èÍý" #: tool/mlconfig/mc_flags.c:31 msgid "Combining = 1 (or 0) logical column(s)" msgstr "·ë¹çʸ»ú¤ÎÏÀÍýÉý¤ò(0¤Ç¤Ï¤Ê¤¯)1¤Ë¤¹¤ë" #: tool/mlconfig/mc_flags.c:31 msgid "Process received strings via Unicode" msgstr "Unicode·Ðͳ¤Ç¥Ú¡¼¥¹¥È¤ò½èÍý¤¹¤ë" #: tool/mlconfig/mc_flags.c:32 msgid "Fullwidth = 2 (or 1) logical column(s)" msgstr "Á´³Ñʸ»ú¤ÎÏÀÍýÉý¤ò(1¤Ç¤Ï¤Ê¤¯)2¤Ë¤¹¤ë" #: tool/mlconfig/mc_flags.c:32 msgid "Complex Text Layout" msgstr "Complex Text Layout" #: tool/mlconfig/mc_flags.c:33 msgid "Ambiguouswidth = fullwidth" msgstr "Unicode¤ÎÛ£Ëæ¤ÊÉý¤Îʸ»ú¤òÁ´³Ñʸ»ú¤È¤·¤Æ°·¤¦" #: tool/mlconfig/mc_flags.c:33 msgid "CLIPBOARD Selection" msgstr "ÁªÂòʸ»úÎó¤ò¥¯¥ê¥Ã¥×¥Ü¡¼¥É¤ËÊݸ" #: tool/mlconfig/mc_flags.c:33 msgid "Local echo" msgstr "¥í¡¼¥«¥ë¥¨¥³¡¼" #: tool/mlconfig/mc_flags.c:34 msgid "Blink cursor" msgstr "¥«¡¼¥½¥ëÅÀÌÇ" #: tool/mlconfig/mc_flags.c:34 msgid "Don't scroll automatically in scrolling back" msgstr "¥¹¥¯¥í¡¼¥ë¥Ð¥Ã¥¯Ãæ¤Ï¼«Æ°Åª¤Ë¥¹¥¯¥í¡¼¥ë¤·¤Ê¤¤" #: tool/mlconfig/mc_flags.c:35 msgid "Scroll by Shift+Up or Shift+Down" msgstr "Shift+UpËô¤ÏShift+Down¤Ë¤è¤ë¥¹¥¯¥í¡¼¥ë" #: tool/mlconfig/mc_flags.c:35 msgid "Select URI by double click" msgstr "¥À¥Ö¥ë¥¯¥ê¥Ã¥¯¤ÇURI¤òÁªÂò" #: tool/mlconfig/mc_flags.c:35 #, fuzzy msgid "OpenType Layout" msgstr "Complex Text Layout" #: tool/mlconfig/mc_flags.c:36 msgid "Trim trailing CR/LF in pasting" msgstr "ŽÉÕ¤±»þ¤ËËöÈø¤Î²þ¹Ô¥³¡¼¥É¤òºï½ü" #: tool/mlconfig/mc_flags.c:36 msgid "Send keys to all windows" msgstr "Á´¥¦¥£¥ó¥É¥¦¤ËƱ»þÁ÷¿®" #: tool/mlconfig/mc_font.c:1186 msgid "Font size (pixels)" msgstr "¥Õ¥©¥ó¥È¥µ¥¤¥º(¥Ô¥¯¥»¥ë)" #: tool/mlconfig/mc_font.c:1248 msgid "Font name" msgstr "¥Õ¥©¥ó¥È̾" #: tool/mlconfig/mc_font.c:1274 msgid "Font width" msgstr "¥Õ¥©¥ó¥ÈÉý" #: tool/mlconfig/mc_font.c:1278 msgid "Narrow" msgstr "" #: tool/mlconfig/mc_font.c:1283 msgid "Widen" msgstr "" #: tool/mlconfig/mc_font.c:1288 msgid "Default" msgstr "" #: tool/mlconfig/mc_font.c:1303 msgid "Unicode areas you won't convert to other charsets" msgstr "Unicode¤«¤é¾¤Îʸ»ú½¸¹ç¤ËÊÑ´¹¤·¤Ê¤¤ÈϰÏ" #: tool/mlconfig/mc_font.c:1306 msgid " Edit " msgstr "ÊÔ½¸" #: tool/mlconfig/mc_geometry.c:36 msgid "Columns" msgstr "·å¿ô" #: tool/mlconfig/mc_geometry.c:36 msgid "Rows" msgstr "¹Ô¿ô" #: tool/mlconfig/mc_im.c:364 msgid "XIM Server" msgstr "XIM¥µ¡¼¥Ð" #: tool/mlconfig/mc_im.c:367 msgid "XIM locale" msgstr "ÆþÎÏ¥í¥±¡¼¥ë" #: tool/mlconfig/mc_im.c:442 msgid "Option" msgstr "¥ª¥×¥·¥ç¥ó" #: tool/mlconfig/mc_im.c:534 msgid "Dictionary" msgstr "" #: tool/mlconfig/mc_im.c:535 msgid "Sticky shift key" msgstr "" #: tool/mlconfig/mc_im.c:584 #, fuzzy msgid "Server" msgstr "XIM¥µ¡¼¥Ð" #: tool/mlconfig/mc_im.c:719 msgid "Input Method" msgstr "ÆþÎϥ᥽¥Ã¥É" #: tool/mlconfig/mc_im.c:743 tool/mlconfig/mc_radio.c:55 #: tool/mlconfig/mc_radio.c:58 tool/mlconfig/mc_radio.c:61 #: tool/mlconfig/mc_radio.c:64 msgid "None" msgstr "¤Ê¤·" #: tool/mlconfig/mc_logsize.c:50 msgid "Backlog size (lines)" msgstr "¥í¥°¥µ¥¤¥º(¹Ô)" #: tool/mlconfig/mc_opentype.c:92 msgid "Select opentype features" msgstr "" #: tool/mlconfig/mc_opentype.c:178 msgid "Select opentype scripts" msgstr "" #: tool/mlconfig/mc_opentype.c:254 msgid "Features" msgstr "" #: tool/mlconfig/mc_opentype.c:259 msgid "Script" msgstr "" #: tool/mlconfig/mc_radio.c:55 msgid "Meta key outputs" msgstr "¥á¥¿¥­¡¼²¡²¼»þ¤Îµóư" #: tool/mlconfig/mc_radio.c:55 msgid "Esc" msgstr "Esc" #: tool/mlconfig/mc_radio.c:55 msgid "8bit" msgstr "8¥Ó¥Ã¥È" #: tool/mlconfig/mc_radio.c:58 msgid "Bell mode" msgstr "¥Ù¥ë" #: tool/mlconfig/mc_radio.c:58 msgid "Sound" msgstr "²»" #: tool/mlconfig/mc_radio.c:58 msgid "Visual" msgstr "ɽ¼¨" #: tool/mlconfig/mc_radio.c:58 msgid "Both" msgstr "ξÊý" #: tool/mlconfig/mc_radio.c:61 msgid "Position" msgstr "¾ì½ê" #: tool/mlconfig/mc_radio.c:61 msgid "Left" msgstr "º¸" #: tool/mlconfig/mc_radio.c:61 msgid "Right" msgstr "±¦" #: tool/mlconfig/mc_radio.c:61 msgid "Auto hide" msgstr "¼«Æ°Åª¤Ë±£¤¹" #: tool/mlconfig/mc_radio.c:64 msgid "Vertical mode" msgstr "½Ä½ñ¤­" #: tool/mlconfig/mc_radio.c:64 msgid "CJK" msgstr "ÆüÃæ´Ú" #: tool/mlconfig/mc_radio.c:64 msgid "Mongol" msgstr "¥â¥ó¥´¥ë" #: tool/mlconfig/mc_radio.c:67 msgid "Box drawing" msgstr "·ÓÀþ" #: tool/mlconfig/mc_radio.c:67 tool/mlconfig/mc_radio.c:70 msgid "As it is" msgstr "¤½¤Î¤Þ¤Þɽ¼¨" #: tool/mlconfig/mc_radio.c:67 msgid "Unicode" msgstr "Unicode¤ËÊÑ´¹" #: tool/mlconfig/mc_radio.c:67 msgid "DEC Special" msgstr "DEC Special¤ËÊÑ´¹" #: tool/mlconfig/mc_radio.c:70 msgid "Font policy" msgstr "ɽ¼¨¥Õ¥©¥ó¥È" #: tool/mlconfig/mc_radio.c:70 msgid "Always unicode" msgstr "Unicode¤Î¤ß" #: tool/mlconfig/mc_radio.c:70 msgid "Never unicode" msgstr "Unicode°Ê³°" #: tool/mlconfig/mc_radio.c:73 msgid "Save log" msgstr "¥í¥°¤òÊݸ" #: tool/mlconfig/mc_radio.c:73 msgid "No" msgstr "Êݸ¤·¤Ê¤¤" #: tool/mlconfig/mc_radio.c:73 msgid "Raw format" msgstr "¤½¤Î¤Þ¤ÞÊݸ" #: tool/mlconfig/mc_radio.c:73 msgid "Ttyrec format" msgstr "ttyrec·Á¼°¤ÇÊݸ" #: tool/mlconfig/mc_ratio.c:31 msgid "Contrast " msgstr "¥³¥ó¥È¥é¥¹¥È" #: tool/mlconfig/mc_ratio.c:31 msgid "Gamma" msgstr "¥¬¥ó¥Þ" #: tool/mlconfig/mc_ratio.c:31 msgid "Brightness" msgstr "µ±ÅÙ" #: tool/mlconfig/mc_ratio.c:31 msgid "Fade ratio on unfocus" msgstr "Focus¤¬¤Ê¤¤¤È¤­¤Îµ±ÅÙ" #: tool/mlconfig/mc_ratio.c:32 msgid "Screen size ratio against font size" msgstr "¥¹¥¯¥ê¡¼¥ó¥µ¥¤¥º¤È¥Õ¥©¥ó¥È¥µ¥¤¥º¤Î³ä¹ç" #: tool/mlconfig/mc_sb_view.c:119 msgid "View" msgstr "¸«¤«¤±" #: tool/mlconfig/mc_space.c:31 msgid "Line space (pixels)" msgstr "¹Ô´Ö³Ö(¥Ô¥¯¥»¥ë)" #: tool/mlconfig/mc_space.c:31 msgid "Letter space (pixels)" msgstr "»ú´Ö(¥Ô¥¯¥»¥ë)" #: tool/mlconfig/mc_space.c:31 msgid "Baseline position (pixels)" msgstr "¥Ù¡¼¥¹¥é¥¤¥ó¤Î°ÌÃÖ(¥Ô¥¯¥»¥ë)" #: tool/mlconfig/mc_space.c:32 msgid "Underline position (pixels)" msgstr "¥¢¥ó¥À¡¼¥é¥¤¥ó¤Î°ÌÃÖ(¥Ô¥¯¥»¥ë)" #: tool/mlconfig/mc_tabsize.c:50 msgid "Tab width (columns)" msgstr "¥¿¥ÖÉý(ʸ»ú)" #: tool/mlconfig/mc_unicode_areas.c:131 msgid "" "Set unicode area in the following format.\n" "Format: U+XXXX-XXXX or U+XXXX (U+ is optional)" msgstr "" "¼¡¤Î·Á¼°¤ÇUnicode¤ÎÈϰϤò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤\n" " U+XXXX-XXXXËô¤ÏU+XXXX (U+¤Ï¤Ê¤¯¤Æ¤â¹½¤¤¤Þ¤»¤ó)" #: tool/mlconfig/mc_wordsep.c:111 msgid "Word separators" msgstr "ñ¸ì¶èÀÚ¤êʸ»ú" #~ msgid " Bel mode " #~ msgstr "¥Ù¥ë" #~ msgid "Transparent" #~ msgstr "ÊÉ»æ/Æ©ÌÀ" #~ msgid "ISCII language" #~ msgstr "ISCII¸À¸ì" #~ msgid "Meta key outputs:" #~ msgstr "¥á¥¿¥­¡¼" mlterm-3.8.9/tool/mlconfig/po/remove-potcdate.sin010064400017600000144000000006601356600660700205460ustar kenusers# Sed script that remove the POT-Creation-Date line in the header entry # from a POT file. # # The distinction between the first and the following occurrences of the # pattern is achieved by looking at the hold space. /^"POT-Creation-Date: .*"$/{ x # Test if the hold space is empty. s/P/P/ ta # Yes it was empty. First occurrence. Remove the line. g d bb :a # The hold space was nonempty. Following occurrences. Do nothing. x :b } mlterm-3.8.9/tool/mlconfig/po/vi.po010064400017600000144000000364061356600660700157220ustar kenusers# Vietnamese translation for mlterm # This file is distributed under the same license as the mlterm package. # # Pham Thanh Long , 2006. msgid "" msgstr "" "Project-Id-Version: mlterm\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-03-03 22:12+0900\n" "PO-Revision-Date: 2006-04-17 21:11+0700\n" "Last-Translator: Pham Thanh Long \n" "Language-Team: Vietnam \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: \n" "X-Generator: KBabel 1.11.1\n" #: tool/mlconfig/gtkxlfdsel.c:225 #, fuzzy msgid "Foundry:" msgstr "Âm thanh" #: tool/mlconfig/gtkxlfdsel.c:226 msgid "Family:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:227 #, fuzzy msgid "Weight:" msgstr "Cao" #: tool/mlconfig/gtkxlfdsel.c:228 msgid "Slant:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:229 #, fuzzy msgid "Set Width:" msgstr "Rá»™ng" #: tool/mlconfig/gtkxlfdsel.c:230 msgid "Add Style:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:231 msgid "Pixel Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:232 msgid "Point Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:233 msgid "Resolution X:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:234 msgid "Resolution Y:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:235 msgid "Spacing:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:236 msgid "Average Width:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:237 msgid "Charset:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:469 msgid "Font Property" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:470 msgid "Requested Value" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:471 msgid "Actual Value" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:504 tool/mlconfig/main.c:551 msgid "Font" msgstr "Phông" #: tool/mlconfig/gtkxlfdsel.c:514 tool/mlconfig/gtkxlfdsel.c:2156 #: tool/mlconfig/gtkxlfdsel.c:2386 #, fuzzy msgid "Font:" msgstr "Phông" #: tool/mlconfig/gtkxlfdsel.c:519 msgid "Font Style:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:524 msgid "Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:656 tool/mlconfig/gtkxlfdsel.c:878 msgid "Reset Filter" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:670 msgid "Metric:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:674 msgid "Points" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:681 msgid "Pixels" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:697 msgid "Preview:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:726 msgid "Font Information" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:759 msgid "Requested Font Name:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:770 msgid "Actual Font Name:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:781 #, c-format msgid "%i fonts available with a total of %i styles." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:796 msgid "Filter" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:809 msgid "Font Types:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:817 msgid "Bitmap" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:823 msgid "Scalable" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:829 msgid "Scaled Bitmap" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:897 msgid "*" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1224 msgid "(nil)" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1224 msgid "regular" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1229 tool/mlconfig/gtkxlfdsel.c:1985 msgid "italic" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1230 tool/mlconfig/gtkxlfdsel.c:1986 msgid "oblique" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1231 tool/mlconfig/gtkxlfdsel.c:1987 msgid "reverse italic" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1232 tool/mlconfig/gtkxlfdsel.c:1988 msgid "reverse oblique" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1233 tool/mlconfig/gtkxlfdsel.c:1989 #, fuzzy msgid "other" msgstr "Khác" #: tool/mlconfig/gtkxlfdsel.c:1240 msgid "[M]" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1241 msgid "[C]" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1803 msgid "The selected font is not available." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1809 msgid "The selected font is not a valid font." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1866 msgid "This is a 2-byte font and may not be displayed correctly." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1973 msgid "(unknown)" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1984 msgid "roman" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1996 msgid "proportional" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1997 msgid "monospaced" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1998 msgid "char cell" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:2161 #, fuzzy msgid "Font: (Filter Applied)" msgstr "Cỡ chữ (pixel)" #: tool/mlconfig/gtkxlfdsel.c:2637 msgid "MAX_FONTS exceeded. Some fonts may be missing." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:3477 msgid "OK" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:3484 tool/mlconfig/main.c:372 msgid "Apply" msgstr "Ãp dụng" #: tool/mlconfig/gtkxlfdsel.c:3490 tool/mlconfig/main.c:373 msgid "Cancel" msgstr "Thôi" #: tool/mlconfig/gtkxlfdsel.c:3506 #, fuzzy msgid "Font Selection" msgstr " Chá»n " #: tool/mlconfig/main.c:216 msgid "Send" msgstr "" #: tool/mlconfig/main.c:217 msgid "Recv" msgstr "" #: tool/mlconfig/main.c:218 msgid "Return" msgstr "" #: tool/mlconfig/main.c:219 #, fuzzy msgid "Exit" msgstr "Lưu & Thoát" #: tool/mlconfig/main.c:230 msgid "Local" msgstr "" #: tool/mlconfig/main.c:247 msgid "Remote" msgstr "" #: tool/mlconfig/main.c:370 msgid "Save&Exit" msgstr "Lưu & Thoát" #: tool/mlconfig/main.c:371 msgid "Apply&Exit" msgstr "Ãp dụng & Thoát" #: tool/mlconfig/main.c:382 msgid "Font size (temporary)" msgstr "Cỡ phông (tạm thá»i)" #: tool/mlconfig/main.c:390 msgid "Larger" msgstr "Lá»›n hÆ¡n" #: tool/mlconfig/main.c:391 msgid "Smaller" msgstr "Nhá» hÆ¡n" #: tool/mlconfig/main.c:406 msgid "Command" msgstr "" #: tool/mlconfig/main.c:414 msgid "Full reset" msgstr "Lập lại toàn bá»™" #: tool/mlconfig/main.c:415 msgid "Snapshot" msgstr "" #: tool/mlconfig/main.c:417 msgid "SCP" msgstr "" #: tool/mlconfig/main.c:433 msgid "PTY List" msgstr "Danh sách PTY" #: tool/mlconfig/main.c:441 msgid " New " msgstr " Má»›i " #: tool/mlconfig/main.c:442 tool/mlconfig/mc_font.c:1264 #: tool/mlconfig/mc_wall_pic.c:62 #, fuzzy msgid "Select" msgstr " Chá»n " #: tool/mlconfig/main.c:467 msgid "mlterm configuration" msgstr "Cấu hình mlterm" #: tool/mlconfig/main.c:502 tool/mlconfig/mc_char_encoding.c:157 msgid "Encoding" msgstr "Mã hoá" #: tool/mlconfig/main.c:588 msgid "Background" msgstr "Ná»n" #: tool/mlconfig/main.c:599 msgid "Picture/Transparent" msgstr "Ảnh/Trong suốt" #: tool/mlconfig/main.c:637 tool/mlconfig/mc_bgtype.c:105 msgid "Color" msgstr "Màu sắc" #: tool/mlconfig/main.c:658 msgid "Scrollbar" msgstr "Thanh cuá»™n" #: tool/mlconfig/main.c:689 msgid "Others" msgstr "Khác" #: tool/mlconfig/mc_alpha.c:49 msgid "Alpha" msgstr "" #: tool/mlconfig/mc_auto_detect.c:65 msgid "Auto detect" msgstr "" #: tool/mlconfig/mc_auto_detect.c:70 #, fuzzy msgid "Encoding list" msgstr "Mã hoá" #: tool/mlconfig/mc_bgtype.c:98 msgid "Background type" msgstr "Kiểu ná»n" #: tool/mlconfig/mc_bgtype.c:117 tool/mlconfig/mc_wall_pic.c:52 msgid "Picture" msgstr "Hình ảnh" #: tool/mlconfig/mc_bgtype.c:129 msgid "Pseudo transparent" msgstr "Trong suốt" #: tool/mlconfig/mc_char_encoding.c:24 msgid "auto" msgstr "tá»± động" #: tool/mlconfig/mc_char_encoding.c:26 msgid "--- Unicode ---" msgstr "--- Unicode ---" #: tool/mlconfig/mc_char_encoding.c:28 msgid "--- ISO 8859 encodings ---" msgstr "--- Mã ISO 8859 ---" #: tool/mlconfig/mc_char_encoding.c:35 msgid "--- Other 8bit ---" msgstr "--- Mã 8bit khác ---" #: tool/mlconfig/mc_char_encoding.c:43 msgid "--- Japanese ---" msgstr "--- Nhật Bản ---" #: tool/mlconfig/mc_char_encoding.c:46 msgid "--- Korean ---" msgstr "--- Hàn Quốc ---" #: tool/mlconfig/mc_char_encoding.c:48 msgid "--- traditional Chinese ---" msgstr "--- Hán phồn thể ---" #: tool/mlconfig/mc_char_encoding.c:50 msgid "--- simplified Chinese ---" msgstr "--- Hán giản thể ---" #: tool/mlconfig/mc_char_encoding.c:151 tool/mlconfig/mc_im.c:309 #: tool/mlconfig/mc_im.c:358 tool/mlconfig/mc_im.c:430 #: tool/mlconfig/mc_im.c:433 #, c-format msgid "auto (currently %s)" msgstr "tá»± động (hiện tại %s)" #: tool/mlconfig/mc_char_width.c:85 msgid "Add full width areas" msgstr "" #: tool/mlconfig/mc_char_width.c:90 msgid "Add half width areas" msgstr "" #: tool/mlconfig/mc_click.c:49 msgid "Double click interval (msec)" msgstr "" #: tool/mlconfig/mc_color.c:36 tool/mlconfig/mc_color.c:37 msgid "Foreground color" msgstr "Màu chữ" #: tool/mlconfig/mc_color.c:36 tool/mlconfig/mc_color.c:37 msgid "Background color" msgstr "Màu ná»n" #: tool/mlconfig/mc_color.c:37 msgid "Bold " msgstr "" #: tool/mlconfig/mc_color.c:37 msgid "Italic" msgstr "" #: tool/mlconfig/mc_color.c:37 msgid "Underline" msgstr "" #: tool/mlconfig/mc_color.c:38 msgid "Blink" msgstr "" #: tool/mlconfig/mc_color.c:38 msgid "Cross out" msgstr "" #: tool/mlconfig/mc_color.c:138 msgid "Cursor color" msgstr "" #: tool/mlconfig/mc_color.c:161 msgid "Substituting color" msgstr "" #: tool/mlconfig/mc_color.c:208 msgid "VT basic 16 colors" msgstr "" #: tool/mlconfig/mc_ctl.c:59 msgid "Bidi separators" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Xft" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Cairo" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Anti Alias" msgstr "Chống răng cưa" #: tool/mlconfig/mc_flags.c:30 msgid "Variable column width" msgstr "Äá»™ rá»™ng cá»™t linh hoạt" #: tool/mlconfig/mc_flags.c:30 msgid "Combining" msgstr "Tổ hợp" #: tool/mlconfig/mc_flags.c:31 msgid "Combining = 1 (or 0) logical column(s)" msgstr "Tổ hợp = 1 (hoặc 0) cá»™t logic" #: tool/mlconfig/mc_flags.c:31 msgid "Process received strings via Unicode" msgstr "Xá»­ lí chuá»—i nhận được qua Unicode" #: tool/mlconfig/mc_flags.c:32 msgid "Fullwidth = 2 (or 1) logical column(s)" msgstr "Äá»™ rá»™ng đầy đủ = 2 (hoặc 1) cá»™t logic" #: tool/mlconfig/mc_flags.c:32 msgid "Complex Text Layout" msgstr "Complex Text Layout" #: tool/mlconfig/mc_flags.c:33 msgid "Ambiguouswidth = fullwidth" msgstr "" #: tool/mlconfig/mc_flags.c:33 msgid "CLIPBOARD Selection" msgstr "" #: tool/mlconfig/mc_flags.c:33 msgid "Local echo" msgstr "" #: tool/mlconfig/mc_flags.c:34 msgid "Blink cursor" msgstr "" #: tool/mlconfig/mc_flags.c:34 msgid "Don't scroll automatically in scrolling back" msgstr "" #: tool/mlconfig/mc_flags.c:35 msgid "Scroll by Shift+Up or Shift+Down" msgstr "" #: tool/mlconfig/mc_flags.c:35 msgid "Select URI by double click" msgstr "" #: tool/mlconfig/mc_flags.c:35 #, fuzzy msgid "OpenType Layout" msgstr "Complex Text Layout" #: tool/mlconfig/mc_flags.c:36 msgid "Trim trailing CR/LF in pasting" msgstr "" #: tool/mlconfig/mc_flags.c:36 msgid "Send keys to all windows" msgstr "" #: tool/mlconfig/mc_font.c:1186 msgid "Font size (pixels)" msgstr "Cỡ chữ (pixel)" #: tool/mlconfig/mc_font.c:1248 #, fuzzy msgid "Font name" msgstr "Phông" #: tool/mlconfig/mc_font.c:1274 msgid "Font width" msgstr "" #: tool/mlconfig/mc_font.c:1278 msgid "Narrow" msgstr "" #: tool/mlconfig/mc_font.c:1283 msgid "Widen" msgstr "" #: tool/mlconfig/mc_font.c:1288 msgid "Default" msgstr "" #: tool/mlconfig/mc_font.c:1303 msgid "Unicode areas you won't convert to other charsets" msgstr "" #: tool/mlconfig/mc_font.c:1306 msgid " Edit " msgstr "" #: tool/mlconfig/mc_geometry.c:36 msgid "Columns" msgstr "" #: tool/mlconfig/mc_geometry.c:36 msgid "Rows" msgstr "" #: tool/mlconfig/mc_im.c:364 msgid "XIM Server" msgstr "Máy chá»§ XIM" #: tool/mlconfig/mc_im.c:367 msgid "XIM locale" msgstr "XIM bản địa" #: tool/mlconfig/mc_im.c:442 msgid "Option" msgstr "Tuỳ chá»n" #: tool/mlconfig/mc_im.c:534 msgid "Dictionary" msgstr "" #: tool/mlconfig/mc_im.c:535 msgid "Sticky shift key" msgstr "" #: tool/mlconfig/mc_im.c:584 #, fuzzy msgid "Server" msgstr "Máy chá»§ XIM" #: tool/mlconfig/mc_im.c:719 msgid "Input Method" msgstr "Phương thức nhập" #: tool/mlconfig/mc_im.c:743 tool/mlconfig/mc_radio.c:55 #: tool/mlconfig/mc_radio.c:58 tool/mlconfig/mc_radio.c:61 #: tool/mlconfig/mc_radio.c:64 msgid "None" msgstr "Không" #: tool/mlconfig/mc_logsize.c:50 msgid "Backlog size (lines)" msgstr "Số dòng cuá»™n" #: tool/mlconfig/mc_opentype.c:92 msgid "Select opentype features" msgstr "" #: tool/mlconfig/mc_opentype.c:178 msgid "Select opentype scripts" msgstr "" #: tool/mlconfig/mc_opentype.c:254 msgid "Features" msgstr "" #: tool/mlconfig/mc_opentype.c:259 msgid "Script" msgstr "" #: tool/mlconfig/mc_radio.c:55 #, fuzzy msgid "Meta key outputs" msgstr "Meta key outputs:" #: tool/mlconfig/mc_radio.c:55 msgid "Esc" msgstr "Esc" #: tool/mlconfig/mc_radio.c:55 msgid "8bit" msgstr "8bit" #: tool/mlconfig/mc_radio.c:58 #, fuzzy msgid "Bell mode" msgstr " Chế độ chuông " #: tool/mlconfig/mc_radio.c:58 msgid "Sound" msgstr "Âm thanh" #: tool/mlconfig/mc_radio.c:58 msgid "Visual" msgstr "Trá»±c quan" #: tool/mlconfig/mc_radio.c:58 msgid "Both" msgstr "" #: tool/mlconfig/mc_radio.c:61 msgid "Position" msgstr "Vị trí" #: tool/mlconfig/mc_radio.c:61 msgid "Left" msgstr "Trái" #: tool/mlconfig/mc_radio.c:61 msgid "Right" msgstr "Phải" #: tool/mlconfig/mc_radio.c:61 msgid "Auto hide" msgstr "" #: tool/mlconfig/mc_radio.c:64 msgid "Vertical mode" msgstr " Chế độ thẳng đứng " #: tool/mlconfig/mc_radio.c:64 msgid "CJK" msgstr "CJK" #: tool/mlconfig/mc_radio.c:64 msgid "Mongol" msgstr "Mông Cổ" #: tool/mlconfig/mc_radio.c:67 msgid "Box drawing" msgstr "" #: tool/mlconfig/mc_radio.c:67 tool/mlconfig/mc_radio.c:70 msgid "As it is" msgstr "" #: tool/mlconfig/mc_radio.c:67 #, fuzzy msgid "Unicode" msgstr "--- Unicode ---" #: tool/mlconfig/mc_radio.c:67 msgid "DEC Special" msgstr "" #: tool/mlconfig/mc_radio.c:70 msgid "Font policy" msgstr "" #: tool/mlconfig/mc_radio.c:70 msgid "Always unicode" msgstr "" #: tool/mlconfig/mc_radio.c:70 msgid "Never unicode" msgstr "" #: tool/mlconfig/mc_radio.c:73 msgid "Save log" msgstr "" #: tool/mlconfig/mc_radio.c:73 #, fuzzy msgid "No" msgstr "Không" #: tool/mlconfig/mc_radio.c:73 msgid "Raw format" msgstr "" #: tool/mlconfig/mc_radio.c:73 msgid "Ttyrec format" msgstr "" #: tool/mlconfig/mc_ratio.c:31 #, fuzzy msgid "Contrast " msgstr "Äá»™ tương phản" #: tool/mlconfig/mc_ratio.c:31 msgid "Gamma" msgstr "Gamma" #: tool/mlconfig/mc_ratio.c:31 msgid "Brightness" msgstr "Äá»™ sáng" #: tool/mlconfig/mc_ratio.c:31 msgid "Fade ratio on unfocus" msgstr "Tỉ lệ má» dần khi rá»i bá» tiêu Ä‘iểm" #: tool/mlconfig/mc_ratio.c:32 msgid "Screen size ratio against font size" msgstr "Tỉ lệ màn hình vá»›i cỡ phông" #: tool/mlconfig/mc_sb_view.c:119 msgid "View" msgstr "Xem" #: tool/mlconfig/mc_space.c:31 msgid "Line space (pixels)" msgstr "Khoảng cách dòng (pixel)" #: tool/mlconfig/mc_space.c:31 #, fuzzy msgid "Letter space (pixels)" msgstr "Khoảng cách dòng (pixel)" #: tool/mlconfig/mc_space.c:31 #, fuzzy msgid "Baseline position (pixels)" msgstr "Khoảng cách dòng (pixel)" #: tool/mlconfig/mc_space.c:32 #, fuzzy msgid "Underline position (pixels)" msgstr "Khoảng cách dòng (pixel)" #: tool/mlconfig/mc_tabsize.c:50 msgid "Tab width (columns)" msgstr "Äá»™ rá»™ng tab (cá»™t)" #: tool/mlconfig/mc_unicode_areas.c:131 msgid "" "Set unicode area in the following format.\n" "Format: U+XXXX-XXXX or U+XXXX (U+ is optional)" msgstr "" #: tool/mlconfig/mc_wordsep.c:111 msgid "Word separators" msgstr "" #, fuzzy #~ msgid "Transparent" #~ msgstr "Ảnh/Trong suốt" #~ msgid "ISCII language" #~ msgstr "Ngôn ngữ ISCII" mlterm-3.8.9/tool/mlconfig/po/zh_TW.po010064400017600000144000000357071356600660700163420ustar kenusers# Chinese Translation of mlconfig # Copyright (C) 2003 Free Software Foundation, Inc. # Yuan-Chen Cheng , 2003. # msgid "" msgstr "" "Project-Id-Version: mlconfig\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-03-03 22:12+0900\n" "PO-Revision-Date: 2003-02-09 21:26+0800\n" "Last-Translator: Ambrose Li \n" "Language-Team: Chinese (Traditional) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=Big5\n" "Content-Transfer-Encoding: 8bit\n" "Language: \n" #: tool/mlconfig/gtkxlfdsel.c:225 #, fuzzy msgid "Foundry:" msgstr "­µ®Ä" #: tool/mlconfig/gtkxlfdsel.c:226 msgid "Family:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:227 #, fuzzy msgid "Weight:" msgstr "°ª«×" #: tool/mlconfig/gtkxlfdsel.c:228 msgid "Slant:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:229 #, fuzzy msgid "Set Width:" msgstr "Áï«×" #: tool/mlconfig/gtkxlfdsel.c:230 msgid "Add Style:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:231 msgid "Pixel Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:232 msgid "Point Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:233 msgid "Resolution X:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:234 msgid "Resolution Y:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:235 msgid "Spacing:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:236 msgid "Average Width:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:237 msgid "Charset:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:469 msgid "Font Property" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:470 msgid "Requested Value" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:471 msgid "Actual Value" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:504 tool/mlconfig/main.c:551 msgid "Font" msgstr "¦r«¬" #: tool/mlconfig/gtkxlfdsel.c:514 tool/mlconfig/gtkxlfdsel.c:2156 #: tool/mlconfig/gtkxlfdsel.c:2386 #, fuzzy msgid "Font:" msgstr "¦r«¬" #: tool/mlconfig/gtkxlfdsel.c:519 msgid "Font Style:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:524 msgid "Size:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:656 tool/mlconfig/gtkxlfdsel.c:878 msgid "Reset Filter" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:670 msgid "Metric:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:674 msgid "Points" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:681 msgid "Pixels" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:697 msgid "Preview:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:726 msgid "Font Information" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:759 msgid "Requested Font Name:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:770 msgid "Actual Font Name:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:781 #, c-format msgid "%i fonts available with a total of %i styles." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:796 msgid "Filter" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:809 msgid "Font Types:" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:817 msgid "Bitmap" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:823 msgid "Scalable" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:829 msgid "Scaled Bitmap" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:897 msgid "*" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1224 msgid "(nil)" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1224 msgid "regular" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1229 tool/mlconfig/gtkxlfdsel.c:1985 msgid "italic" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1230 tool/mlconfig/gtkxlfdsel.c:1986 msgid "oblique" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1231 tool/mlconfig/gtkxlfdsel.c:1987 msgid "reverse italic" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1232 tool/mlconfig/gtkxlfdsel.c:1988 msgid "reverse oblique" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1233 tool/mlconfig/gtkxlfdsel.c:1989 #, fuzzy msgid "other" msgstr "¨ä¥L" #: tool/mlconfig/gtkxlfdsel.c:1240 msgid "[M]" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1241 msgid "[C]" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1803 msgid "The selected font is not available." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1809 msgid "The selected font is not a valid font." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1866 msgid "This is a 2-byte font and may not be displayed correctly." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1973 msgid "(unknown)" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1984 msgid "roman" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1996 msgid "proportional" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1997 msgid "monospaced" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:1998 msgid "char cell" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:2161 #, fuzzy msgid "Font: (Filter Applied)" msgstr "¦r«¬¤j¤p (¹³¯À­È)" #: tool/mlconfig/gtkxlfdsel.c:2637 msgid "MAX_FONTS exceeded. Some fonts may be missing." msgstr "" #: tool/mlconfig/gtkxlfdsel.c:3477 msgid "OK" msgstr "" #: tool/mlconfig/gtkxlfdsel.c:3484 tool/mlconfig/main.c:372 msgid "Apply" msgstr "®M¥Î" #: tool/mlconfig/gtkxlfdsel.c:3490 tool/mlconfig/main.c:373 msgid "Cancel" msgstr "¨ú®ø" #: tool/mlconfig/gtkxlfdsel.c:3506 #, fuzzy msgid "Font Selection" msgstr "¿ï¾Ü" #: tool/mlconfig/main.c:216 msgid "Send" msgstr "" #: tool/mlconfig/main.c:217 msgid "Recv" msgstr "" #: tool/mlconfig/main.c:218 msgid "Return" msgstr "" #: tool/mlconfig/main.c:219 #, fuzzy msgid "Exit" msgstr "Àx¦s" #: tool/mlconfig/main.c:230 msgid "Local" msgstr "" #: tool/mlconfig/main.c:247 msgid "Remote" msgstr "" #: tool/mlconfig/main.c:370 msgid "Save&Exit" msgstr "Àx¦s" # NOTE: "Apply&Exit" is usually just written "OK"... #: tool/mlconfig/main.c:371 msgid "Apply&Exit" msgstr "½T©w" # FIXME incomplete translation (but still makes sense) #: tool/mlconfig/main.c:382 msgid "Font size (temporary)" msgstr "¦r«¬¤j¤p" #: tool/mlconfig/main.c:390 msgid "Larger" msgstr "¤j¤@ÂI" #: tool/mlconfig/main.c:391 msgid "Smaller" msgstr "¤p¤@ÂI" #: tool/mlconfig/main.c:406 msgid "Command" msgstr "" #: tool/mlconfig/main.c:414 msgid "Full reset" msgstr "§¹¥þ­«¸m" #: tool/mlconfig/main.c:415 msgid "Snapshot" msgstr "" #: tool/mlconfig/main.c:417 msgid "SCP" msgstr "" #: tool/mlconfig/main.c:433 msgid "PTY List" msgstr "PTY ²M³æ" #: tool/mlconfig/main.c:441 msgid " New " msgstr "·s¼W" #: tool/mlconfig/main.c:442 tool/mlconfig/mc_font.c:1264 #: tool/mlconfig/mc_wall_pic.c:62 #, fuzzy msgid "Select" msgstr "¿ï¾Ü" #: tool/mlconfig/main.c:467 msgid "mlterm configuration" msgstr "mlterm ³]©w" #: tool/mlconfig/main.c:502 tool/mlconfig/mc_char_encoding.c:157 msgid "Encoding" msgstr "½s½X" #: tool/mlconfig/main.c:588 msgid "Background" msgstr "­I´º" #: tool/mlconfig/main.c:599 msgid "Picture/Transparent" msgstr "¹Ï®×¢¬³z©ú«×¿ï¶µ" #: tool/mlconfig/main.c:637 tool/mlconfig/mc_bgtype.c:105 msgid "Color" msgstr "ÃC¦â" #: tool/mlconfig/main.c:658 msgid "Scrollbar" msgstr "" #: tool/mlconfig/main.c:689 msgid "Others" msgstr "¨ä¥L" #: tool/mlconfig/mc_alpha.c:49 msgid "Alpha" msgstr "" #: tool/mlconfig/mc_auto_detect.c:65 msgid "Auto detect" msgstr "" #: tool/mlconfig/mc_auto_detect.c:70 #, fuzzy msgid "Encoding list" msgstr "½s½X" #: tool/mlconfig/mc_bgtype.c:98 msgid "Background type" msgstr "­I´ºÃþ«¬" #: tool/mlconfig/mc_bgtype.c:117 tool/mlconfig/mc_wall_pic.c:52 msgid "Picture" msgstr "¹Ï®×" #: tool/mlconfig/mc_bgtype.c:129 msgid "Pseudo transparent" msgstr "³z©ú" #: tool/mlconfig/mc_char_encoding.c:24 msgid "auto" msgstr "¦Û°Ê" #: tool/mlconfig/mc_char_encoding.c:26 msgid "--- Unicode ---" msgstr "--- Unicode ---" #: tool/mlconfig/mc_char_encoding.c:28 msgid "--- ISO 8859 encodings ---" msgstr "--- ¦UºØ ISO 8859 ½s½X ---" #: tool/mlconfig/mc_char_encoding.c:35 msgid "--- Other 8bit ---" msgstr "--- ¨ä¥L 8bit ---" #: tool/mlconfig/mc_char_encoding.c:43 msgid "--- Japanese ---" msgstr "--- ¤é¤å ---" #: tool/mlconfig/mc_char_encoding.c:46 msgid "--- Korean ---" msgstr "--- Áú¤å ---" #: tool/mlconfig/mc_char_encoding.c:48 msgid "--- traditional Chinese ---" msgstr "--- ¥¿Å餤¤å ---" #: tool/mlconfig/mc_char_encoding.c:50 msgid "--- simplified Chinese ---" msgstr "--- ²Å餤¤å ---" #: tool/mlconfig/mc_char_encoding.c:151 tool/mlconfig/mc_im.c:309 #: tool/mlconfig/mc_im.c:358 tool/mlconfig/mc_im.c:430 #: tool/mlconfig/mc_im.c:433 #, c-format msgid "auto (currently %s)" msgstr "¦Û°Ê (¥Ø«e¬° %s)" #: tool/mlconfig/mc_char_width.c:85 msgid "Add full width areas" msgstr "" #: tool/mlconfig/mc_char_width.c:90 msgid "Add half width areas" msgstr "" #: tool/mlconfig/mc_click.c:49 msgid "Double click interval (msec)" msgstr "" #: tool/mlconfig/mc_color.c:36 tool/mlconfig/mc_color.c:37 msgid "Foreground color" msgstr "¤å¦rÃC¦â" #: tool/mlconfig/mc_color.c:36 tool/mlconfig/mc_color.c:37 msgid "Background color" msgstr "­I´ºÃC¦â" #: tool/mlconfig/mc_color.c:37 msgid "Bold " msgstr "" #: tool/mlconfig/mc_color.c:37 msgid "Italic" msgstr "" #: tool/mlconfig/mc_color.c:37 msgid "Underline" msgstr "" #: tool/mlconfig/mc_color.c:38 msgid "Blink" msgstr "" #: tool/mlconfig/mc_color.c:38 msgid "Cross out" msgstr "" #: tool/mlconfig/mc_color.c:138 msgid "Cursor color" msgstr "" #: tool/mlconfig/mc_color.c:161 msgid "Substituting color" msgstr "" #: tool/mlconfig/mc_color.c:208 msgid "VT basic 16 colors" msgstr "" #: tool/mlconfig/mc_ctl.c:59 msgid "Bidi separators" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Xft" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Cairo" msgstr "" #: tool/mlconfig/mc_flags.c:30 msgid "Anti Alias" msgstr "¶ê·Æ¦r«¬" #: tool/mlconfig/mc_flags.c:30 msgid "Variable column width" msgstr "¥iÅܦæ¼e" #: tool/mlconfig/mc_flags.c:30 msgid "Combining" msgstr "¥Î²Õ¦X¥Î¦r²Å" # FIXME perhaps a bit weird #: tool/mlconfig/mc_flags.c:31 msgid "Combining = 1 (or 0) logical column(s)" msgstr "²Õ¦X¥Î¦r²Å¦û¤@­ÓÅ޿誽¦æ (§_«h¤£¦ûÅ޿誽¦æ)" #: tool/mlconfig/mc_flags.c:31 msgid "Process received strings via Unicode" msgstr "³z¹L Unicode ´À¦¬¨ìªº¦r¦êÂà´«½s½X" # FIXME perhaps a bit weird #: tool/mlconfig/mc_flags.c:32 msgid "Fullwidth = 2 (or 1) logical column(s)" msgstr "¥þ§Î¦r¦û¨â­ÓÅ޿誽¦æ (§_«h¥u¦û¤@­Ó)" # FIXME #: tool/mlconfig/mc_flags.c:32 msgid "Complex Text Layout" msgstr "Complex Text Layout" #: tool/mlconfig/mc_flags.c:33 msgid "Ambiguouswidth = fullwidth" msgstr "" #: tool/mlconfig/mc_flags.c:33 msgid "CLIPBOARD Selection" msgstr "" #: tool/mlconfig/mc_flags.c:33 msgid "Local echo" msgstr "" #: tool/mlconfig/mc_flags.c:34 msgid "Blink cursor" msgstr "" #: tool/mlconfig/mc_flags.c:34 msgid "Don't scroll automatically in scrolling back" msgstr "" #: tool/mlconfig/mc_flags.c:35 msgid "Scroll by Shift+Up or Shift+Down" msgstr "" #: tool/mlconfig/mc_flags.c:35 msgid "Select URI by double click" msgstr "" # FIXME #: tool/mlconfig/mc_flags.c:35 #, fuzzy msgid "OpenType Layout" msgstr "Complex Text Layout" #: tool/mlconfig/mc_flags.c:36 msgid "Trim trailing CR/LF in pasting" msgstr "" #: tool/mlconfig/mc_flags.c:36 msgid "Send keys to all windows" msgstr "" #: tool/mlconfig/mc_font.c:1186 msgid "Font size (pixels)" msgstr "¦r«¬¤j¤p (¹³¯À­È)" #: tool/mlconfig/mc_font.c:1248 #, fuzzy msgid "Font name" msgstr "¦r«¬" #: tool/mlconfig/mc_font.c:1274 msgid "Font width" msgstr "" #: tool/mlconfig/mc_font.c:1278 msgid "Narrow" msgstr "" #: tool/mlconfig/mc_font.c:1283 msgid "Widen" msgstr "" #: tool/mlconfig/mc_font.c:1288 msgid "Default" msgstr "" #: tool/mlconfig/mc_font.c:1303 msgid "Unicode areas you won't convert to other charsets" msgstr "" #: tool/mlconfig/mc_font.c:1306 msgid " Edit " msgstr "" #: tool/mlconfig/mc_geometry.c:36 msgid "Columns" msgstr "" #: tool/mlconfig/mc_geometry.c:36 msgid "Rows" msgstr "" #: tool/mlconfig/mc_im.c:364 msgid "XIM Server" msgstr "" #: tool/mlconfig/mc_im.c:367 msgid "XIM locale" msgstr "¿é¤Jªk¦a°ì" #: tool/mlconfig/mc_im.c:442 #, fuzzy msgid "Option" msgstr "¯»¬õ" #: tool/mlconfig/mc_im.c:534 msgid "Dictionary" msgstr "" #: tool/mlconfig/mc_im.c:535 msgid "Sticky shift key" msgstr "" #: tool/mlconfig/mc_im.c:584 msgid "Server" msgstr "" #: tool/mlconfig/mc_im.c:719 #, fuzzy msgid "Input Method" msgstr "¿é¤Jªk¥Dµ{¦¡" #: tool/mlconfig/mc_im.c:743 tool/mlconfig/mc_radio.c:55 #: tool/mlconfig/mc_radio.c:58 tool/mlconfig/mc_radio.c:61 #: tool/mlconfig/mc_radio.c:64 msgid "None" msgstr "µL" #: tool/mlconfig/mc_logsize.c:50 msgid "Backlog size (lines)" msgstr "¾ú¥v¤j¤p (¦æ¼Æ)" #: tool/mlconfig/mc_opentype.c:92 msgid "Select opentype features" msgstr "" #: tool/mlconfig/mc_opentype.c:178 msgid "Select opentype scripts" msgstr "" #: tool/mlconfig/mc_opentype.c:254 msgid "Features" msgstr "" #: tool/mlconfig/mc_opentype.c:259 msgid "Script" msgstr "" #: tool/mlconfig/mc_radio.c:55 #, fuzzy msgid "Meta key outputs" msgstr "Meta Áä¿é¥X¡G" #: tool/mlconfig/mc_radio.c:55 msgid "Esc" msgstr "Esc" #: tool/mlconfig/mc_radio.c:55 msgid "8bit" msgstr "" #: tool/mlconfig/mc_radio.c:58 #, fuzzy msgid "Bell mode" msgstr "Bell ¼Ò¦¡" #: tool/mlconfig/mc_radio.c:58 msgid "Sound" msgstr "­µ®Ä" # XXX from Japanese, may need retranslation #: tool/mlconfig/mc_radio.c:58 msgid "Visual" msgstr "Åã¥Ü" #: tool/mlconfig/mc_radio.c:58 msgid "Both" msgstr "" #: tool/mlconfig/mc_radio.c:61 msgid "Position" msgstr "¦ì¸m" #: tool/mlconfig/mc_radio.c:61 msgid "Left" msgstr "¥ª°¼" #: tool/mlconfig/mc_radio.c:61 msgid "Right" msgstr "¥k°¼" #: tool/mlconfig/mc_radio.c:61 msgid "Auto hide" msgstr "" #: tool/mlconfig/mc_radio.c:64 msgid "Vertical mode" msgstr "ª½¦æ¼Ò¦¡" #: tool/mlconfig/mc_radio.c:64 msgid "CJK" msgstr "¤¤¤éÁú" #: tool/mlconfig/mc_radio.c:64 msgid "Mongol" msgstr "»X¥j" #: tool/mlconfig/mc_radio.c:67 msgid "Box drawing" msgstr "" #: tool/mlconfig/mc_radio.c:67 tool/mlconfig/mc_radio.c:70 msgid "As it is" msgstr "" #: tool/mlconfig/mc_radio.c:67 #, fuzzy msgid "Unicode" msgstr "--- Unicode ---" #: tool/mlconfig/mc_radio.c:67 msgid "DEC Special" msgstr "" #: tool/mlconfig/mc_radio.c:70 msgid "Font policy" msgstr "" #: tool/mlconfig/mc_radio.c:70 msgid "Always unicode" msgstr "" #: tool/mlconfig/mc_radio.c:70 msgid "Never unicode" msgstr "" #: tool/mlconfig/mc_radio.c:73 msgid "Save log" msgstr "" #: tool/mlconfig/mc_radio.c:73 #, fuzzy msgid "No" msgstr "µL" #: tool/mlconfig/mc_radio.c:73 msgid "Raw format" msgstr "" #: tool/mlconfig/mc_radio.c:73 msgid "Ttyrec format" msgstr "" #: tool/mlconfig/mc_ratio.c:31 #, fuzzy msgid "Contrast " msgstr "¹ï¤ñ" #: tool/mlconfig/mc_ratio.c:31 msgid "Gamma" msgstr "¦÷º¿" #: tool/mlconfig/mc_ratio.c:31 msgid "Brightness" msgstr "¥ú·t" # FIXME weird translation #: tool/mlconfig/mc_ratio.c:31 msgid "Fade ratio on unfocus" msgstr "¥¢¥hµJÂI®Éµøµ¡ªº«G«×" #: tool/mlconfig/mc_ratio.c:32 msgid "Screen size ratio against font size" msgstr "µøµ¡¤j¤p»P¦r«¬¤j¤p¶¡¤§¤ñ¨Ò" #: tool/mlconfig/mc_sb_view.c:119 msgid "View" msgstr "¼Ë¦¡" #: tool/mlconfig/mc_space.c:31 msgid "Line space (pixels)" msgstr "¦æ¶Z¡@¡@ (¹³¯À­È)" #: tool/mlconfig/mc_space.c:31 #, fuzzy msgid "Letter space (pixels)" msgstr "¦æ¶Z¡@¡@ (¹³¯À­È)" #: tool/mlconfig/mc_space.c:31 #, fuzzy msgid "Baseline position (pixels)" msgstr "¦æ¶Z¡@¡@ (¹³¯À­È)" #: tool/mlconfig/mc_space.c:32 #, fuzzy msgid "Underline position (pixels)" msgstr "¦æ¶Z¡@¡@ (¹³¯À­È)" #: tool/mlconfig/mc_tabsize.c:50 msgid "Tab width (columns)" msgstr "Tab ¤j¤p (¦r¼Æ)" #: tool/mlconfig/mc_unicode_areas.c:131 msgid "" "Set unicode area in the following format.\n" "Format: U+XXXX-XXXX or U+XXXX (U+ is optional)" msgstr "" #: tool/mlconfig/mc_wordsep.c:111 msgid "Word separators" msgstr "" #, fuzzy #~ msgid "Transparent" #~ msgstr "¹Ï®×¢¬³z©ú«×¿ï¶µ" #~ msgid "ISCII language" #~ msgstr "ISCII »y¤å" mlterm-3.8.9/tool/mlconfig/po/Makefile.in.in010064400017600000144000000157101356600660700174110ustar kenusers# Makefile for PO directory in any package using GNU gettext. # Copyright (C) 1995-1997, 2000-2002 by Ulrich Drepper # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU General Public # License but which still want to provide support for the GNU gettext # functionality. # Please note that the actual code of GNU gettext is covered by the GNU # General Public License and is *not* in the public domain. PACKAGE = mlconfig VERSION = @VERSION@ DOMAIN = $(PACKAGE) COPYRIGHT_HOLDER = Free Software Foundation, Inc. SHELL = /bin/sh @SET_MAKE@ top_builddir = @top_builddir@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ subdir = tool/mlconfig/po prefix = @prefix@ exec_prefix = @exec_prefix@ datadir = @datadir@ localedir = $(datadir)/locale INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ MKINSTALLDIRS = $(top_srcdir)/script/mkinstalldirs GMSGFMT = @GMSGFMT@ MSGFMT = @MSGFMT@ XGETTEXT = @XGETTEXT@ MSGMERGE = msgmerge MSGMERGE_UPDATE = msgmerge --update # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ POFILES = $(srcdir)/ar.po $(srcdir)/de.po $(srcdir)/ja.po $(srcdir)/vi.po $(srcdir)/zh_TW.po GMOFILES = $(POFILES:.po=.gmo) UPDATEPOFILES = ar.po-update de.po-update ja.po-update vi.po-update zh_TW.po-update DUMMYPOFILES = $(UPDATEPOFILES:.po-update=.nop) POTFILES = \ CATALOGS = ar.gmo de.gmo ja.gmo vi.gmo zh_TW.gmo .SUFFIXES: .SUFFIXES: .po .gmo .mo .sed .sin .nop .po-update .po.mo: @echo "$(MSGFMT) -c -o $@ $<"; \ $(MSGFMT) -c -o t-$@ $< && mv t-$@ $@ .po.gmo: @lang=`echo $* | sed -e 's,.*/,,'`; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o $${lang}.gmo $${lang}.po"; \ cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo .sin.sed: sed -e '/^#/d' $< > t-$@ mv t-$@ $@ all: all-@USE_NLS@ all-yes: $(CATALOGS) all-no: # Note: Target 'all' must not depend on target '$(DOMAIN).pot-update', # otherwise packages like GCC can not be built if only parts of the source # have been downloaded. $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ --add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) \ --files-from=$(srcdir)/POTFILES.in \ --copyright-holder='$(COPYRIGHT_HOLDER)' test ! -f $(DOMAIN).po || { \ if test -f $(srcdir)/$(DOMAIN).pot; then \ sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \ sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \ if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \ rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \ else \ rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \ mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ fi; \ else \ mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \ fi; \ } $(srcdir)/$(DOMAIN).pot: $(MAKE) $(DOMAIN).pot-update $(POFILES): $(srcdir)/$(DOMAIN).pot @lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot"; \ cd $(srcdir) && $(MSGMERGE_UPDATE) $${lang}.po $(DOMAIN).pot install: install-@USE_NLS@ install-no: install-yes: all $(MKINSTALLDIRS) $(DESTDIR)$(datadir) @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ dir=$(localedir)/$$lang/LC_MESSAGES; \ $(MKINSTALLDIRS) $(DESTDIR)$$dir; \ if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \ $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \ echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \ if test -n "$$lc"; then \ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \ link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \ mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ (cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \ for file in *; do \ if test -f $$file; then \ ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \ fi; \ done); \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \ else \ if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \ :; \ else \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \ mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \ fi; \ fi; \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \ cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \ fi; \ done; \ done uninstall: catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \ for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \ rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \ done; \ done clean: rm -f remove-potcdate.sed rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po \ $(POFILES:.po=.po~) distclean: clean rm -f Makefile Makefile.in POTFILES *.mo rm -f $(GMOFILES) update-po: Makefile $(MAKE) $(DOMAIN).pot-update $(MAKE) $(UPDATEPOFILES) $(MAKE) update-gmo # General rule for updating PO files. .nop.po-update: @lang=`echo $@ | sed -e 's/\.po-update$$//'`; \ if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; fi; \ tmpdir=`pwd`; \ echo "$$lang:"; \ test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \ echo "$${cdcmd}$(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \ cd $(srcdir); \ if $(MSGMERGE) $$lang.po $(DOMAIN).pot -o $$tmpdir/$$lang.new.po; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$lang.po failed!" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ fi $(DUMMYPOFILES): update-gmo: $(GMOFILES) @: # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mlterm-3.8.9/tool/mlconfig/gtkxlfdsel.c010064400017600000144000003427261356600660700166460ustar kenusers/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * GtkFontSelection widget for Gtk+, by Damon Chaplin, May 1998. * Based on the GnomeFontSelector widget, by Elliot Lee, but major changes. * The GnomeFontSelector was derived from app/text_tool.c in the GIMP. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ /* * Modified by Araki Ken(arakiken@users.sf.net). * GtkFontSelection => GtkXlfdSelection */ /* * Limits: * * Fontnames - A maximum of MAX_FONTS (32767) fontnames will be retrieved * from X Windows with XListFonts(). Any more are ignored. * I think this limit may have been set because of a limit in * GtkList. It could possibly be increased since we are using * GtkClists now, but I'd be surprised if it was reached. * Field length - XLFD_MAX_FIELD_LEN is the maximum length that any field of a * fontname can be for it to be considered valid. Others are * ignored. * Properties - Maximum of 65535 choices for each font property - guint16's * are used as indices, e.g. in the FontInfo struct. * Combinations - Maximum of 65535 combinations of properties for each font * family - a guint16 is used in the FontInfo struct. * Font size - Minimum font size of 2 pixels/points, since trying to load * some fonts with a size of 1 can cause X to hang. * (e.g. the Misc Fixed fonts). */ /* * Possible Improvements: * * Font Styles - could sort the styles into a reasonable order - regular * first, then bold, bold italic etc. * * I18N - the default preview text is not useful for international * fonts. Maybe the first few characters of the font could be * displayed instead. * - fontsets? should these be handled by the font dialog? */ /* * Debugging: compile with -DFONTSEL_DEBUG for lots of debugging output. */ #include "gtkxlfdsel.h" #ifndef G_PLATFORM_WIN32 /* In case of compiling with cygwin + X11 + win32 native gtk+. */ #include #include #include #include #include #include #include #if 0 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* include in GTK 1.2 */ #else #include #endif #include /* The maximum number of fontnames requested with XListFonts(). */ #define MAX_FONTS 32767 /* This is the largest field length we will accept. If a fontname has a field larger than this we will skip it. */ #define XLFD_MAX_FIELD_LEN 64 /* These are what we use as the standard font sizes, for the size clist. Note that when using points we still show these integer point values but we work internally in decipoints (and decipoint values can be typed in). */ static const guint16 font_sizes[] = { 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28, 32, 36, 40, 48, 56, 64, 72 }; /* Initial font metric & size (Remember point sizes are in decipoints). The font size should match one of those in the font_sizes array. */ #define INITIAL_METRIC GTK_XLFD_METRIC_POINTS #define INITIAL_FONT_SIZE 140 /* This is the default text shown in the preview entry, though the user can set it. Remember that some fonts only have capital letters. */ #define PREVIEW_TEXT "abcdefghijk ABCDEFGHIJK" /* This is the initial and maximum height of the preview entry (it expands when large font sizes are selected). Initial height is also the minimum. */ #define INITIAL_PREVIEW_HEIGHT 44 #define MAX_PREVIEW_HEIGHT 300 /* These are the sizes of the font, style & size clists. */ #define FONT_LIST_HEIGHT 136 #define FONT_LIST_WIDTH 190 #define FONT_STYLE_LIST_WIDTH 170 #define FONT_SIZE_LIST_WIDTH 60 /* This is the number of fields in an X Logical Font Description font name. Note that we count the registry & encoding as 1. */ #define GTK_XLFD_NUM_FIELDS 13 typedef struct _GtkXlfdSelInfo GtkXlfdSelInfo; typedef struct _FontInfo FontInfo; typedef struct _FontStyle FontStyle; /* This struct represents one family of fonts (with one foundry), e.g. adobe courier or sony fixed. It stores the family name, the index of the foundry name, and the index of and number of available styles. */ struct _FontInfo { gchar *family; guint16 foundry; gint style_index; guint16 nstyles; }; /* This represents one style, as displayed in the Font Style clist. It can have a number of available pixel sizes and point sizes. The indexes point into the two big fontsel_info->pixel_sizes & fontsel_info->point_sizes arrays. The displayed flag is used when displaying styles to remember which styles have already been displayed. Note that it is combined with the GtkXlfdType in the flags field. */ #define GTK_XLFD_DISPLAYED (1 << 7) struct _FontStyle { guint16 properties[GTK_NUM_STYLE_PROPERTIES]; gint pixel_sizes_index; guint16 npixel_sizes; gint point_sizes_index; guint16 npoint_sizes; guint8 flags; }; struct _GtkXlfdSelInfo { /* This is a table with each FontInfo representing one font family+foundry */ FontInfo *font_info; gint nfonts; /* This stores all the valid combinations of properties for every family. Each FontInfo holds an index into its own space in this one big array. */ FontStyle *font_styles; gint nstyles; /* This stores all the font sizes available for every style. Each style holds an index into these arrays. */ guint16 *pixel_sizes; guint16 *point_sizes; /* These are the arrays of strings of all possible weights, slants, set widths, spacings, charsets & foundries, and the amount of space allocated for each array. */ gchar **properties[GTK_NUM_FONT_PROPERTIES]; guint16 nproperties[GTK_NUM_FONT_PROPERTIES]; guint16 space_allocated[GTK_NUM_FONT_PROPERTIES]; }; /* These are the field numbers in the X Logical Font Description fontnames, e.g. -adobe-courier-bold-o-normal--25-180-100-100-m-150-iso8859-1 */ typedef enum { XLFD_FOUNDRY = 0, XLFD_FAMILY = 1, XLFD_WEIGHT = 2, XLFD_SLANT = 3, XLFD_SET_WIDTH = 4, XLFD_ADD_STYLE = 5, XLFD_PIXELS = 6, XLFD_POINTS = 7, XLFD_RESOLUTION_X = 8, XLFD_RESOLUTION_Y = 9, XLFD_SPACING = 10, XLFD_AVERAGE_WIDTH = 11, XLFD_CHARSET = 12 } FontField; /* These are the names of the fields, used on the info & filter page. */ static const gchar *xlfd_field_names[GTK_XLFD_NUM_FIELDS] = { N_("Foundry:"), N_("Family:"), N_("Weight:"), N_("Slant:"), N_("Set Width:"), N_("Add Style:"), N_("Pixel Size:"), N_("Point Size:"), N_("Resolution X:"), N_("Resolution Y:"), N_("Spacing:"), N_("Average Width:"), N_("Charset:"), }; /* These are the array indices of the font properties used in several arrays, and should match the xlfd_index array below. */ typedef enum { WEIGHT = 0, SLANT = 1, SET_WIDTH = 2, SPACING = 3, CHARSET = 4, FOUNDRY = 5 } PropertyIndexType; /* This is used to look up a field in a fontname given one of the above property indices. */ static const FontField xlfd_index[GTK_NUM_FONT_PROPERTIES] = { XLFD_WEIGHT, XLFD_SLANT, XLFD_SET_WIDTH, XLFD_SPACING, XLFD_CHARSET, XLFD_FOUNDRY }; /* These are the positions of the properties in the filter table - x, y. */ static const gint filter_positions[GTK_NUM_FONT_PROPERTIES][2] = { { 1, 0 }, { 0, 2 }, { 1, 2 }, { 2, 2 }, { 2, 0 }, { 0, 0 } }; static const gint filter_heights[GTK_NUM_FONT_PROPERTIES] = { 100, 70, 70, 40, 100, 100 }; /* This is returned by gtk_xlfd_selection_filter_state to describe if a property value is filtered. e.g. if 'bold' has been selected on the filter page, then that will return 'FILTERED' and 'black' will be 'NOT_FILTERED'. If none of the weight values are selected, they all return 'NOT_SET'. */ typedef enum { FILTERED, NOT_FILTERED, NOT_SET } GtkXlfdPropertyFilterState; static GtkXlfdSelInfo *fontsel_info = NULL; /* The initial size and increment of each of the arrays of property values. */ #define PROPERTY_ARRAY_INCREMENT 16 static void gtk_xlfd_selection_class_init (GtkXlfdSelectionClass *klass); static void gtk_xlfd_selection_init (GtkXlfdSelection *fontsel); static void gtk_xlfd_selection_destroy (GtkObject *object); /* These are all used for class initialization - loading in the fonts etc. */ static void gtk_xlfd_selection_get_fonts (void); static void gtk_xlfd_selection_insert_font (GSList *fontnames[], gint *ntable, gchar *fontname); static gint gtk_xlfd_selection_insert_field (gchar *fontname, gint prop); /* These are the callbacks & related functions. */ static void gtk_xlfd_selection_select_font (GtkWidget *w, gint row, gint column, GdkEventButton *bevent, gpointer data); static gint gtk_xlfd_selection_on_clist_key_press (GtkWidget *clist, GdkEventKey *event, GtkXlfdSelection *fs); static gboolean gtk_xlfd_selection_select_next (GtkXlfdSelection *fs, GtkWidget *clist, gint step); static void gtk_xlfd_selection_show_available_styles (GtkXlfdSelection *fs); static void gtk_xlfd_selection_select_best_style (GtkXlfdSelection *fs, gboolean use_first); static void gtk_xlfd_selection_select_style (GtkWidget *w, gint row, gint column, GdkEventButton *bevent, gpointer data); static void gtk_xlfd_selection_show_available_sizes (GtkXlfdSelection *fs); static void gtk_xlfd_selection_size_activate (GtkWidget *w, gpointer data); static void gtk_xlfd_selection_select_best_size (GtkXlfdSelection *fs); static void gtk_xlfd_selection_select_size (GtkWidget *w, gint row, gint column, GdkEventButton *bevent, gpointer data); static void gtk_xlfd_selection_metric_callback (GtkWidget *w, gpointer data); static void gtk_xlfd_selection_expose_list (GtkWidget *w, GdkEventExpose *event, gpointer data); static void gtk_xlfd_selection_realize_list (GtkWidget *widget, gpointer data); static void gtk_xlfd_selection_switch_page (GtkWidget *w, GtkNotebookPage *page, gint page_num, gpointer data); static void gtk_xlfd_selection_show_font_info (GtkXlfdSelection *fs); static void gtk_xlfd_selection_select_filter (GtkWidget *w, gint row, gint column, GdkEventButton *bevent, GtkXlfdSelection *fs); static void gtk_xlfd_selection_update_filter (GtkXlfdSelection *fs); static gboolean gtk_xlfd_selection_style_visible (GtkXlfdSelection *fs, FontInfo *font, gint style); static void gtk_xlfd_selection_reset_filter (GtkWidget *w, GtkXlfdSelection *fs); static void gtk_xlfd_selection_on_clear_filter (GtkWidget *w, GtkXlfdSelection *fs); static void gtk_xlfd_selection_show_available_fonts (GtkXlfdSelection *fs); static void gtk_xlfd_selection_clear_filter (GtkXlfdSelection *fs); static void gtk_xlfd_selection_update_filter_lists(GtkXlfdSelection *fs); static GtkXlfdPropertyFilterState gtk_xlfd_selection_filter_state (GtkXlfdSelection *fs, GtkXlfdFilterType filter_type, gint property, gint index); /* Misc. utility functions. */ static gboolean gtk_xlfd_selection_load_font (GtkXlfdSelection *fs); static void gtk_xlfd_selection_update_preview (GtkXlfdSelection *fs); static gint gtk_xlfd_selection_find_font (GtkXlfdSelection *fs, gchar *family, guint16 foundry); static guint16 gtk_xlfd_selection_field_to_index (gchar **table, gint ntable, gchar *field); static gchar* gtk_xlfd_selection_expand_slant_code (gchar *slant); static gchar* gtk_xlfd_selection_expand_spacing_code(gchar *spacing); /* Functions for handling X Logical Font Description fontnames. */ static gboolean gtk_xlfd_selection_is_xlfd_font_name (const gchar *fontname); static char* gtk_xlfd_selection_get_xlfd_field (const gchar *fontname, FontField field_num, gchar *buffer); static gchar * gtk_xlfd_selection_create_xlfd (gint size, GtkXlfdMetricType metric, gchar *foundry, gchar *family, gchar *weight, gchar *slant, gchar *set_width, gchar *spacing, gchar *charset); /* FontSelectionDialog */ static void gtk_xlfd_selection_dialog_class_init (GtkXlfdSelectionDialogClass *klass); static void gtk_xlfd_selection_dialog_init (GtkXlfdSelectionDialog *fontseldiag); static gint gtk_xlfd_selection_dialog_on_configure(GtkWidget *widget, GdkEventConfigure *event, GtkXlfdSelectionDialog *fsd); static GtkWindowClass *font_selection_parent_class = NULL; static GtkNotebookClass *font_selection_dialog_parent_class = NULL; GtkType gtk_xlfd_selection_get_type() { static GtkType font_selection_type = 0; if(!font_selection_type) { static const GtkTypeInfo fontsel_type_info = { "GtkXlfdSelection", sizeof (GtkXlfdSelection), sizeof (GtkXlfdSelectionClass), (GtkClassInitFunc) gtk_xlfd_selection_class_init, (GtkObjectInitFunc) gtk_xlfd_selection_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; font_selection_type = gtk_type_unique (GTK_TYPE_NOTEBOOK, &fontsel_type_info); } return font_selection_type; } static void gtk_xlfd_selection_class_init(GtkXlfdSelectionClass *klass) { GtkObjectClass *object_class; object_class = (GtkObjectClass *) klass; font_selection_parent_class = gtk_type_class (GTK_TYPE_NOTEBOOK); object_class->destroy = gtk_xlfd_selection_destroy; gtk_xlfd_selection_get_fonts (); } static void gtk_xlfd_selection_init(GtkXlfdSelection *fontsel) { GtkWidget *scrolled_win; GtkWidget *text_frame; GtkWidget *text_box, *frame; GtkWidget *table, *label, *hbox, *hbox2, *clist, *button, *vbox, *alignment; gint i, prop, row; gchar *titles[] = { NULL, NULL, NULL }; gchar buffer[128]; gchar *size; gint size_to_match; gchar *row_text[3]; gchar *property, *text; gboolean inserted; /* Number of internationalized titles here must match number of NULL initializers above */ titles[0] = _("Font Property"); titles[1] = _("Requested Value"); titles[2] = _("Actual Value"); /* Initialize the GtkXlfdSelection struct. We do this here in case any callbacks are triggered while creating the interface. */ fontsel->font = NULL; fontsel->font_index = -1; fontsel->style = -1; fontsel->metric = INITIAL_METRIC; fontsel->size = INITIAL_FONT_SIZE; fontsel->selected_size = INITIAL_FONT_SIZE; fontsel->filters[GTK_XLFD_FILTER_BASE].font_type = GTK_XLFD_ALL; fontsel->filters[GTK_XLFD_FILTER_USER].font_type = GTK_XLFD_BITMAP | GTK_XLFD_SCALABLE; for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) { fontsel->filters[GTK_XLFD_FILTER_BASE].property_filters[prop] = NULL; fontsel->filters[GTK_XLFD_FILTER_BASE].property_nfilters[prop] = 0; fontsel->filters[GTK_XLFD_FILTER_USER].property_filters[prop] = NULL; fontsel->filters[GTK_XLFD_FILTER_USER].property_nfilters[prop] = 0; } for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) fontsel->property_values[prop] = 0; /* Create the main notebook page. */ gtk_notebook_set_homogeneous_tabs (GTK_NOTEBOOK (fontsel), TRUE); gtk_notebook_set_tab_hborder (GTK_NOTEBOOK (fontsel), 8); fontsel->main_vbox = gtk_vbox_new (FALSE, 4); gtk_widget_show (fontsel->main_vbox); gtk_container_set_border_width (GTK_CONTAINER (fontsel->main_vbox), 6); label = gtk_label_new(_("Font")); gtk_notebook_append_page (GTK_NOTEBOOK (fontsel), fontsel->main_vbox, label); /* Create the table of font, style & size. */ table = gtk_table_new (3, 3, FALSE); gtk_widget_show (table); gtk_table_set_col_spacings(GTK_TABLE(table), 8); gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), table, TRUE, TRUE, 0); fontsel->font_label = gtk_label_new(_("Font:")); gtk_misc_set_alignment (GTK_MISC (fontsel->font_label), 0.0, 0.5); gtk_widget_show (fontsel->font_label); gtk_table_attach (GTK_TABLE (table), fontsel->font_label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); label = gtk_label_new(_("Font Style:")); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_widget_show (label); gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1, GTK_FILL, 0, 0, 0); label = gtk_label_new(_("Size:")); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_widget_show (label); gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1, GTK_FILL, 0, 0, 0); fontsel->font_entry = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(fontsel->font_entry), FALSE); gtk_widget_set_usize (fontsel->font_entry, 20, -1); gtk_widget_show (fontsel->font_entry); gtk_table_attach (GTK_TABLE (table), fontsel->font_entry, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); fontsel->font_style_entry = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(fontsel->font_style_entry), FALSE); gtk_widget_set_usize (fontsel->font_style_entry, 20, -1); gtk_widget_show (fontsel->font_style_entry); gtk_table_attach (GTK_TABLE (table), fontsel->font_style_entry, 1, 2, 1, 2, GTK_FILL, 0, 0, 0); fontsel->size_entry = gtk_entry_new(); gtk_widget_set_usize (fontsel->size_entry, 20, -1); gtk_widget_show (fontsel->size_entry); gtk_table_attach (GTK_TABLE (table), fontsel->size_entry, 2, 3, 1, 2, GTK_FILL, 0, 0, 0); gtk_signal_connect (GTK_OBJECT (fontsel->size_entry), "activate", GTK_SIGNAL_FUNC (gtk_xlfd_selection_size_activate), fontsel); /* Create the clists */ fontsel->font_clist = gtk_clist_new(1); gtk_clist_column_titles_hide (GTK_CLIST(fontsel->font_clist)); gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_clist), 0, TRUE); scrolled_win = gtk_scrolled_window_new (NULL, NULL); gtk_widget_set_usize (scrolled_win, FONT_LIST_WIDTH, FONT_LIST_HEIGHT); gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_clist); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_widget_show(fontsel->font_clist); gtk_widget_show(scrolled_win); gtk_table_attach (GTK_TABLE (table), scrolled_win, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); fontsel->font_style_clist = gtk_clist_new(1); gtk_clist_column_titles_hide (GTK_CLIST(fontsel->font_style_clist)); gtk_clist_set_column_auto_resize (GTK_CLIST (fontsel->font_style_clist), 0, TRUE); scrolled_win = gtk_scrolled_window_new (NULL, NULL); gtk_widget_set_usize (scrolled_win, FONT_STYLE_LIST_WIDTH, -1); gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->font_style_clist); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_widget_show(fontsel->font_style_clist); gtk_widget_show(scrolled_win); gtk_table_attach (GTK_TABLE (table), scrolled_win, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); fontsel->size_clist = gtk_clist_new(1); gtk_clist_column_titles_hide (GTK_CLIST(fontsel->size_clist)); gtk_clist_set_column_width (GTK_CLIST(fontsel->size_clist), 0, 20); scrolled_win = gtk_scrolled_window_new (NULL, NULL); gtk_widget_set_usize (scrolled_win, FONT_SIZE_LIST_WIDTH, -1); gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->size_clist); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_widget_show(fontsel->size_clist); gtk_widget_show(scrolled_win); gtk_table_attach (GTK_TABLE (table), scrolled_win, 2, 3, 2, 3, GTK_FILL, GTK_FILL, 0, 0); /* Insert the fonts. If there exist fonts with the same family but different foundries, then the foundry name is appended in brackets. */ gtk_xlfd_selection_show_available_fonts(fontsel); gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "select_row", GTK_SIGNAL_FUNC(gtk_xlfd_selection_select_font), fontsel); GTK_WIDGET_SET_FLAGS (fontsel->font_clist, GTK_CAN_FOCUS); gtk_signal_connect (GTK_OBJECT (fontsel->font_clist), "key_press_event", GTK_SIGNAL_FUNC(gtk_xlfd_selection_on_clist_key_press), fontsel); gtk_signal_connect_after (GTK_OBJECT (fontsel->font_clist), "map_event", GTK_SIGNAL_FUNC(gtk_xlfd_selection_expose_list), fontsel); gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist), "select_row", GTK_SIGNAL_FUNC(gtk_xlfd_selection_select_style), fontsel); GTK_WIDGET_SET_FLAGS (fontsel->font_style_clist, GTK_CAN_FOCUS); gtk_signal_connect (GTK_OBJECT (fontsel->font_style_clist), "key_press_event", GTK_SIGNAL_FUNC(gtk_xlfd_selection_on_clist_key_press), fontsel); gtk_signal_connect_after (GTK_OBJECT (fontsel->font_style_clist), "realize", GTK_SIGNAL_FUNC(gtk_xlfd_selection_realize_list), fontsel); /* Insert the standard font sizes */ gtk_clist_freeze (GTK_CLIST(fontsel->size_clist)); size_to_match = INITIAL_FONT_SIZE; if (INITIAL_METRIC == GTK_XLFD_METRIC_POINTS) size_to_match = size_to_match / 10; for (i = 0; i < sizeof(font_sizes) / sizeof(font_sizes[0]); i++) { sprintf(buffer, "%i", font_sizes[i]); size = buffer; gtk_clist_append(GTK_CLIST(fontsel->size_clist), &size); if (font_sizes[i] == size_to_match) { gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), i, 0); gtk_entry_set_text(GTK_ENTRY(fontsel->size_entry), buffer); } } gtk_clist_thaw (GTK_CLIST(fontsel->size_clist)); gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "select_row", GTK_SIGNAL_FUNC(gtk_xlfd_selection_select_size), fontsel); GTK_WIDGET_SET_FLAGS (fontsel->size_clist, GTK_CAN_FOCUS); gtk_signal_connect (GTK_OBJECT (fontsel->size_clist), "key_press_event", GTK_SIGNAL_FUNC(gtk_xlfd_selection_on_clist_key_press), fontsel); /* create the Reset Filter & Metric buttons */ hbox = gtk_hbox_new(FALSE, 8); gtk_widget_show (hbox); gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), hbox, FALSE, TRUE, 0); fontsel->filter_button = gtk_button_new_with_label(_("Reset Filter")); gtk_misc_set_padding (GTK_MISC (GTK_BIN (fontsel->filter_button)->child), 16, 0); gtk_widget_show(fontsel->filter_button); gtk_box_pack_start (GTK_BOX (hbox), fontsel->filter_button, FALSE, FALSE, 0); gtk_widget_set_sensitive (fontsel->filter_button, FALSE); gtk_signal_connect (GTK_OBJECT (fontsel->filter_button), "clicked", GTK_SIGNAL_FUNC(gtk_xlfd_selection_on_clear_filter), fontsel); hbox2 = gtk_hbox_new(FALSE, 0); gtk_widget_show (hbox2); gtk_box_pack_end (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0); label = gtk_label_new(_("Metric:")); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 8); fontsel->points_button = gtk_radio_button_new_with_label(NULL, _("Points")); gtk_widget_show (fontsel->points_button); gtk_box_pack_start (GTK_BOX (hbox2), fontsel->points_button, FALSE, TRUE, 0); if (INITIAL_METRIC == GTK_XLFD_METRIC_POINTS) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->points_button), TRUE); fontsel->pixels_button = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(fontsel->points_button), _("Pixels")); gtk_widget_show (fontsel->pixels_button); gtk_box_pack_start (GTK_BOX (hbox2), fontsel->pixels_button, FALSE, TRUE, 0); if (INITIAL_METRIC == GTK_XLFD_METRIC_PIXELS) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->pixels_button), TRUE); gtk_signal_connect(GTK_OBJECT(fontsel->points_button), "toggled", (GtkSignalFunc) gtk_xlfd_selection_metric_callback, fontsel); gtk_signal_connect(GTK_OBJECT(fontsel->pixels_button), "toggled", (GtkSignalFunc) gtk_xlfd_selection_metric_callback, fontsel); /* create the text entry widget */ text_frame = gtk_frame_new (_("Preview:")); gtk_widget_show (text_frame); gtk_frame_set_shadow_type(GTK_FRAME(text_frame), GTK_SHADOW_ETCHED_IN); gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), text_frame, FALSE, TRUE, 0); /* This is just used to get a 4-pixel space around the preview entry. */ text_box = gtk_hbox_new (FALSE, 0); gtk_widget_show (text_box); gtk_container_add (GTK_CONTAINER (text_frame), text_box); gtk_container_set_border_width (GTK_CONTAINER (text_box), 4); fontsel->preview_entry = gtk_entry_new (); gtk_widget_show (fontsel->preview_entry); gtk_widget_set_usize (fontsel->preview_entry, -1, INITIAL_PREVIEW_HEIGHT); gtk_box_pack_start (GTK_BOX (text_box), fontsel->preview_entry, TRUE, TRUE, 0); /* Create the message area */ fontsel->message_label = gtk_label_new(""); gtk_widget_show (fontsel->message_label); gtk_box_pack_start (GTK_BOX (fontsel->main_vbox), fontsel->message_label, FALSE, FALSE, 0); /* Create the font info page */ fontsel->info_vbox = gtk_vbox_new (FALSE, 4); gtk_widget_show (fontsel->info_vbox); gtk_container_set_border_width (GTK_CONTAINER (fontsel->info_vbox), 2); label = gtk_label_new(_("Font Information")); gtk_notebook_append_page (GTK_NOTEBOOK (fontsel), fontsel->info_vbox, label); fontsel->info_clist = gtk_clist_new_with_titles (3, titles); gtk_widget_set_usize (fontsel->info_clist, 390, 150); gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 0, 130); gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 1, 130); gtk_clist_set_column_width(GTK_CLIST(fontsel->info_clist), 2, 130); gtk_clist_column_titles_passive(GTK_CLIST(fontsel->info_clist)); scrolled_win = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (scrolled_win), fontsel->info_clist); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_show(fontsel->info_clist); gtk_widget_show(scrolled_win); gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), scrolled_win, TRUE, TRUE, 0); /* Insert the property names */ gtk_clist_freeze (GTK_CLIST(fontsel->info_clist)); row_text[1] = ""; row_text[2] = ""; for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++) { row_text[0] = _(xlfd_field_names[i]); gtk_clist_append(GTK_CLIST(fontsel->info_clist), row_text); gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 0, 0, 4); gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 1, 0, 4); gtk_clist_set_shift(GTK_CLIST(fontsel->info_clist), i, 2, 0, 4); } gtk_clist_thaw (GTK_CLIST(fontsel->info_clist)); label = gtk_label_new(_("Requested Font Name:")); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, TRUE, 0); fontsel->requested_font_name = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(fontsel->requested_font_name), FALSE); gtk_widget_show (fontsel->requested_font_name); gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), fontsel->requested_font_name, FALSE, TRUE, 0); label = gtk_label_new(_("Actual Font Name:")); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, TRUE, 0); fontsel->actual_font_name = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(fontsel->actual_font_name), FALSE); gtk_widget_show (fontsel->actual_font_name); gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), fontsel->actual_font_name, FALSE, TRUE, 0); sprintf(buffer, _("%i fonts available with a total of %i styles."), fontsel_info->nfonts, fontsel_info->nstyles); label = gtk_label_new(buffer); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (fontsel->info_vbox), label, FALSE, FALSE, 0); gtk_signal_connect (GTK_OBJECT (fontsel), "switch_page", GTK_SIGNAL_FUNC(gtk_xlfd_selection_switch_page), fontsel); /* Create the Filter page. */ fontsel->filter_vbox = gtk_vbox_new (FALSE, 4); gtk_widget_show (fontsel->filter_vbox); gtk_container_set_border_width (GTK_CONTAINER (fontsel->filter_vbox), 2); label = gtk_label_new(_("Filter")); gtk_notebook_append_page (GTK_NOTEBOOK (fontsel), fontsel->filter_vbox, label); /* Create the font type checkbuttons. */ frame = gtk_frame_new (NULL); gtk_widget_show (frame); gtk_box_pack_start (GTK_BOX (fontsel->filter_vbox), frame, FALSE, TRUE, 0); hbox = gtk_hbox_new (FALSE, 20); gtk_widget_show (hbox); gtk_container_add (GTK_CONTAINER (frame), hbox); label = gtk_label_new(_("Font Types:")); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 10); hbox2 = gtk_hbox_new (TRUE, 0); gtk_widget_show (hbox2); gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, TRUE, 0); fontsel->type_bitmaps_button = gtk_check_button_new_with_label (_("Bitmap")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), TRUE); gtk_widget_show (fontsel->type_bitmaps_button); gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_bitmaps_button, FALSE, TRUE, 0); fontsel->type_scalable_button = gtk_check_button_new_with_label (_("Scalable")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), TRUE); gtk_widget_show (fontsel->type_scalable_button); gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_scalable_button, FALSE, TRUE, 0); fontsel->type_scaled_bitmaps_button = gtk_check_button_new_with_label (_("Scaled Bitmap")); gtk_widget_show (fontsel->type_scaled_bitmaps_button); gtk_box_pack_start (GTK_BOX (hbox2), fontsel->type_scaled_bitmaps_button, FALSE, TRUE, 0); table = gtk_table_new (4, 3, FALSE); gtk_table_set_col_spacings(GTK_TABLE(table), 2); gtk_widget_show (table); gtk_box_pack_start (GTK_BOX (fontsel->filter_vbox), table, TRUE, TRUE, 0); for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) { gint left = filter_positions[prop][0]; gint top = filter_positions[prop][1]; label = gtk_label_new(_(xlfd_field_names[xlfd_index[prop]])); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 1.0); gtk_misc_set_padding (GTK_MISC (label), 0, 2); gtk_widget_show(label); gtk_table_attach (GTK_TABLE (table), label, left, left + 1, top, top + 1, GTK_FILL, GTK_FILL, 0, 0); clist = gtk_clist_new(1); gtk_widget_set_usize (clist, 100, filter_heights[prop]); gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_MULTIPLE); gtk_clist_column_titles_hide(GTK_CLIST(clist)); gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE); scrolled_win = gtk_scrolled_window_new (NULL, NULL); gtk_container_add (GTK_CONTAINER (scrolled_win), clist); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_show(clist); gtk_widget_show(scrolled_win); /* For the bottom-right cell we add the 'Reset Filter' button. */ if (top == 2 && left == 2) { vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox); gtk_table_attach (GTK_TABLE (table), vbox, left, left + 1, top + 1, top + 2, GTK_FILL, GTK_FILL, 0, 0); gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0); alignment = gtk_alignment_new(0.5, 0.0, 0.8, 0.0); gtk_widget_show(alignment); gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, TRUE, 4); button = gtk_button_new_with_label(_("Reset Filter")); gtk_widget_show(button); gtk_container_add(GTK_CONTAINER(alignment), button); gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC(gtk_xlfd_selection_reset_filter), fontsel); } else gtk_table_attach (GTK_TABLE (table), scrolled_win, left, left + 1, top + 1, top + 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_signal_connect (GTK_OBJECT (clist), "select_row", GTK_SIGNAL_FUNC(gtk_xlfd_selection_select_filter), fontsel); /* Insert the property names, expanded, and in sorted order. But we make sure that the wildcard '*' is first. */ gtk_clist_freeze (GTK_CLIST(clist)); property = N_("*"); gtk_clist_append(GTK_CLIST(clist), &property); for (i = 1; i < fontsel_info->nproperties[prop]; i++) { property = _(fontsel_info->properties[prop][i]); if (prop == SLANT) property = gtk_xlfd_selection_expand_slant_code(property); else if (prop == SPACING) property = gtk_xlfd_selection_expand_spacing_code(property); inserted = FALSE; for (row = 1; row < GTK_CLIST(clist)->rows; row++) { gtk_clist_get_text(GTK_CLIST(clist), row, 0, &text); if (strcmp(property, text) < 0) { inserted = TRUE; gtk_clist_insert(GTK_CLIST(clist), row, &property); break; } } if (!inserted) row = gtk_clist_append(GTK_CLIST(clist), &property); gtk_clist_set_row_data(GTK_CLIST(clist), row, GINT_TO_POINTER (i)); } gtk_clist_select_row(GTK_CLIST(clist), 0, 0); gtk_clist_thaw (GTK_CLIST(clist)); fontsel->filter_clists[prop] = clist; } } GtkWidget * gtk_xlfd_selection_new() { GtkXlfdSelection *fontsel; fontsel = gtk_type_new (GTK_TYPE_XLFD_SELECTION); return GTK_WIDGET (fontsel); } static void gtk_xlfd_selection_destroy (GtkObject *object) { GtkXlfdSelection *fontsel; g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_XLFD_SELECTION (object)); fontsel = GTK_XLFD_SELECTION (object); #if 0 /* All we have to do is unref the font, if we have one. */ if (fontsel->font) gdk_font_unref (fontsel->font); #endif if (GTK_OBJECT_CLASS (font_selection_parent_class)->destroy) (* GTK_OBJECT_CLASS (font_selection_parent_class)->destroy) (object); } /* This is called when the clist is exposed. Here we scroll to the current font if necessary. */ static void gtk_xlfd_selection_expose_list (GtkWidget *widget, GdkEventExpose *event, gpointer data) { GtkXlfdSelection *fontsel; FontInfo *font_info; GList *selection; gint index; #ifdef FONTSEL_DEBUG g_message("In expose_list\n"); #endif fontsel = GTK_XLFD_SELECTION(data); font_info = fontsel_info->font_info; /* Try to scroll the font family clist to the selected item */ selection = GTK_CLIST(fontsel->font_clist)->selection; if (selection) { index = GPOINTER_TO_INT (selection->data); if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), index) != GTK_VISIBILITY_FULL) gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), index, -1, 0.5, 0); } /* Try to scroll the font style clist to the selected item */ selection = GTK_CLIST(fontsel->font_style_clist)->selection; if (selection) { index = GPOINTER_TO_INT (selection->data); if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), index) != GTK_VISIBILITY_FULL) gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), index, -1, 0.5, 0); } /* Try to scroll the font size clist to the selected item */ selection = GTK_CLIST(fontsel->size_clist)->selection; if (selection) { index = GPOINTER_TO_INT (selection->data); if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->size_clist), index) != GTK_VISIBILITY_FULL) gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), index, -1, 0.5, 0); } } /* This is called when the style clist is realized. We need to set any charset rows to insensitive colours. */ static void gtk_xlfd_selection_realize_list (GtkWidget *widget, gpointer data) { GtkXlfdSelection *fontsel; gint row; GdkColor *inactive_fg, *inactive_bg; #ifdef FONTSEL_DEBUG g_message("In realize_list\n"); #endif fontsel = GTK_XLFD_SELECTION (data); /* Set the colours for any charset rows to insensitive. */ inactive_fg = &fontsel->font_style_clist->style->fg[GTK_STATE_INSENSITIVE]; inactive_bg = &fontsel->font_style_clist->style->bg[GTK_STATE_INSENSITIVE]; for (row = 0; row < GTK_CLIST (fontsel->font_style_clist)->rows; row++) { if (GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_style_clist), row)) == -1) { gtk_clist_set_foreground (GTK_CLIST (fontsel->font_style_clist), row, inactive_fg); gtk_clist_set_background (GTK_CLIST (fontsel->font_style_clist), row, inactive_bg); } } } /* This is called when a family is selected in the list. */ static void gtk_xlfd_selection_select_font (GtkWidget *w, gint row, gint column, GdkEventButton *bevent, gpointer data) { GtkXlfdSelection *fontsel; FontInfo *font_info; FontInfo *font; #ifdef FONTSEL_DEBUG g_message("In select_font\n"); #endif fontsel = GTK_XLFD_SELECTION(data); font_info = fontsel_info->font_info; if (bevent && !GTK_WIDGET_HAS_FOCUS (w)) gtk_widget_grab_focus (w); row = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_clist), row)); font = &font_info[row]; gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), font->family); /* If it is already the current font, just return. */ if (fontsel->font_index == row) return; fontsel->font_index = row; gtk_xlfd_selection_show_available_styles (fontsel); gtk_xlfd_selection_select_best_style (fontsel, TRUE); } static gint gtk_xlfd_selection_on_clist_key_press (GtkWidget *clist, GdkEventKey *event, GtkXlfdSelection *fontsel) { #ifdef FONTSEL_DEBUG g_message("In on_clist_key_press\n"); #endif if (event->keyval == GDK_Up) return gtk_xlfd_selection_select_next (fontsel, clist, -1); else if (event->keyval == GDK_Down) return gtk_xlfd_selection_select_next (fontsel, clist, 1); else return FALSE; } static gboolean gtk_xlfd_selection_select_next (GtkXlfdSelection *fontsel, GtkWidget *clist, gint step) { GList *selection; gint current_row, row; selection = GTK_CLIST(clist)->selection; if (!selection) return FALSE; current_row = GPOINTER_TO_INT (selection->data); /* Stop the normal clist key handler from being run. */ gtk_signal_emit_stop_by_name (GTK_OBJECT (clist), "key_press_event"); for (row = current_row + step; row >= 0 && row < GTK_CLIST(clist)->rows; row += step) { /* If this is the style clist, make sure that the item is not a charset entry. */ if (clist == fontsel->font_style_clist) if (GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist), row)) == -1) continue; /* Now we've found the row to select. */ if (gtk_clist_row_is_visible(GTK_CLIST(clist), row) != GTK_VISIBILITY_FULL) gtk_clist_moveto(GTK_CLIST(clist), row, -1, (step < 0) ? 0 : 1, 0); gtk_clist_select_row(GTK_CLIST(clist), row, 0); break; } return TRUE; } /* This fills the font style clist with all the possible style combinations for the current font family. */ static void gtk_xlfd_selection_show_available_styles (GtkXlfdSelection *fontsel) { FontInfo *font; FontStyle *styles; gint style, tmpstyle, row; gint weight_index, slant_index, set_width_index, spacing_index; gint charset_index; gchar *weight, *slant, *set_width, *spacing; gchar *charset = NULL; gchar *new_item; gchar buffer[XLFD_MAX_FIELD_LEN * 6 + 2]; GdkColor *inactive_fg, *inactive_bg; gboolean show_charset; #ifdef FONTSEL_DEBUG g_message("In show_available_styles\n"); #endif font = &fontsel_info->font_info[fontsel->font_index]; styles = &fontsel_info->font_styles[font->style_index]; gtk_clist_freeze (GTK_CLIST(fontsel->font_style_clist)); gtk_clist_clear (GTK_CLIST(fontsel->font_style_clist)); /* First we mark all visible styles as not having been displayed yet, and check if every style has the same charset. If not then we will display the charset in the list before the styles. */ show_charset = FALSE; charset_index = -1; for (style = 0; style < font->nstyles; style++) { if (gtk_xlfd_selection_style_visible(fontsel, font, style)) { styles[style].flags &= ~GTK_XLFD_DISPLAYED; if (charset_index == -1) charset_index = styles[style].properties[CHARSET]; else if (charset_index != styles[style].properties[CHARSET]) show_charset = TRUE; } else styles[style].flags |= GTK_XLFD_DISPLAYED; } /* Step through the undisplayed styles, finding the next charset which hasn't been displayed yet. Then display the charset on one line, if necessary, and the visible styles indented beneath it. */ inactive_fg = &fontsel->font_style_clist->style->fg[GTK_STATE_INSENSITIVE]; inactive_bg = &fontsel->font_style_clist->style->bg[GTK_STATE_INSENSITIVE]; for (style = 0; style < font->nstyles; style++) { if (styles[style].flags & GTK_XLFD_DISPLAYED) continue; if (show_charset) { charset_index = styles[style].properties[CHARSET]; charset = fontsel_info->properties[CHARSET] [charset_index]; row = gtk_clist_append(GTK_CLIST(fontsel->font_style_clist), &charset); gtk_clist_set_row_data(GTK_CLIST(fontsel->font_style_clist), row, (gpointer) -1); if (GTK_WIDGET_REALIZED (fontsel->font_style_clist)) { gtk_clist_set_foreground(GTK_CLIST(fontsel->font_style_clist), row, inactive_fg); gtk_clist_set_background(GTK_CLIST(fontsel->font_style_clist), row, inactive_bg); } } for (tmpstyle = style; tmpstyle < font->nstyles; tmpstyle++) { if (styles[tmpstyle].flags & GTK_XLFD_DISPLAYED || charset_index != styles[tmpstyle].properties[CHARSET]) continue; styles[tmpstyle].flags |= GTK_XLFD_DISPLAYED; weight_index = styles[tmpstyle].properties[WEIGHT]; slant_index = styles[tmpstyle].properties[SLANT]; set_width_index = styles[tmpstyle].properties[SET_WIDTH]; spacing_index = styles[tmpstyle].properties[SPACING]; weight = fontsel_info->properties[WEIGHT] [weight_index]; slant = fontsel_info->properties[SLANT] [slant_index]; set_width = fontsel_info->properties[SET_WIDTH][set_width_index]; spacing = fontsel_info->properties[SPACING] [spacing_index]; /* Convert '(nil)' weights to 'regular', since it looks nicer. */ if (!g_strcasecmp(weight, N_("(nil)"))) weight = N_("regular"); /* We don't show default values or (nil) in the other properties. */ if (!g_strcasecmp(slant, "r")) slant = NULL; else if (!g_strcasecmp(slant, "(nil)")) slant = NULL; else if (!g_strcasecmp(slant, "i")) slant = N_("italic"); else if (!g_strcasecmp(slant, "o")) slant = N_("oblique"); else if (!g_strcasecmp(slant, "ri")) slant = N_("reverse italic"); else if (!g_strcasecmp(slant, "ro")) slant = N_("reverse oblique"); else if (!g_strcasecmp(slant, "ot")) slant = N_("other"); if (!g_strcasecmp(set_width, "normal")) set_width = NULL; else if (!g_strcasecmp(set_width, "(nil)")) set_width = NULL; if (!g_strcasecmp(spacing, "p")) spacing = NULL; else if (!g_strcasecmp(spacing, "(nil)")) spacing = NULL; else if (!g_strcasecmp(spacing, "m")) spacing = N_("[M]"); else if (!g_strcasecmp(spacing, "c")) spacing = N_("[C]"); /* Add the strings together, making sure there is 1 space between them */ strcpy(buffer, _(weight)); if (slant) { strcat(buffer, " "); strcat(buffer, _(slant)); } if (set_width) { strcat(buffer, " "); strcat(buffer, _(set_width)); } if (spacing) { strcat(buffer, " "); strcat(buffer, _(spacing)); } new_item = buffer; row = gtk_clist_append(GTK_CLIST(fontsel->font_style_clist), &new_item); if (show_charset) gtk_clist_set_shift(GTK_CLIST(fontsel->font_style_clist), row, 0, 0, 4); gtk_clist_set_row_data(GTK_CLIST(fontsel->font_style_clist), row, GINT_TO_POINTER (tmpstyle)); } } gtk_clist_thaw (GTK_CLIST(fontsel->font_style_clist)); } /* This selects a style when the user selects a font. It just uses the first available style at present. I was thinking of trying to maintain the selected style, e.g. bold italic, when the user selects different fonts. However, the interface is so easy to use now I'm not sure it's worth it. Note: This will load a font. */ static void gtk_xlfd_selection_select_best_style(GtkXlfdSelection *fontsel, gboolean use_first) { FontInfo *font; FontStyle *styles; gint row, prop, style, matched; gint best_matched = -1, best_style = -1, best_row = -1; #ifdef FONTSEL_DEBUG g_message("In select_best_style\n"); #endif font = &fontsel_info->font_info[fontsel->font_index]; styles = &fontsel_info->font_styles[font->style_index]; for (row = 0; row < GTK_CLIST(fontsel->font_style_clist)->rows; row++) { style = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (fontsel->font_style_clist), row)); /* Skip charset rows. */ if (style == -1) continue; /* If we just want the first style, we've got it. */ if (use_first) { best_style = style; best_row = row; break; } matched = 0; for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) { if (fontsel->property_values[prop] == styles[style].properties[prop]) matched++; } if (matched > best_matched) { best_matched = matched; best_style = style; best_row = row; } } g_return_if_fail (best_style != -1); g_return_if_fail (best_row != -1); fontsel->style = best_style; for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) fontsel->property_values[prop] = styles[fontsel->style].properties[prop]; gtk_clist_select_row(GTK_CLIST(fontsel->font_style_clist), best_row, 0); if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_style_clist), best_row) != GTK_VISIBILITY_FULL) gtk_clist_moveto(GTK_CLIST(fontsel->font_style_clist), best_row, -1, 0.5, 0); gtk_xlfd_selection_show_available_sizes (fontsel); gtk_xlfd_selection_select_best_size (fontsel); } /* This is called when a style is selected in the list. */ static void gtk_xlfd_selection_select_style (GtkWidget *w, gint row, gint column, GdkEventButton *bevent, gpointer data) { GtkXlfdSelection *fontsel; FontInfo *font_info; FontInfo *font; FontStyle *styles; gint style, prop; gchar *text; #ifdef FONTSEL_DEBUG g_message("In select_style\n"); #endif fontsel = GTK_XLFD_SELECTION(data); font_info = fontsel_info->font_info; font = &font_info[fontsel->font_index]; styles = &fontsel_info->font_styles[font->style_index]; if (bevent && !GTK_WIDGET_HAS_FOCUS (w)) gtk_widget_grab_focus (w); /* The style index is stored in the row data, so we just need to copy the style values into the fontsel and reload the font. */ style = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(fontsel->font_style_clist), row)); /* Don't allow selection of charset rows. */ if (style == -1) { gtk_clist_unselect_row(GTK_CLIST(fontsel->font_style_clist), row, 0); return; } gtk_clist_get_text(GTK_CLIST(fontsel->font_style_clist), row, 0, &text); gtk_entry_set_text(GTK_ENTRY(fontsel->font_style_entry), text); for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) fontsel->property_values[prop] = styles[style].properties[prop]; if (fontsel->style == style) return; fontsel->style = style; gtk_xlfd_selection_show_available_sizes (fontsel); gtk_xlfd_selection_select_best_size (fontsel); } /* This shows all the available sizes in the size clist, according to the current metric and the current font & style. */ static void gtk_xlfd_selection_show_available_sizes (GtkXlfdSelection *fontsel) { FontInfo *font; FontStyle *styles, *style; const guint16 *standard_sizes; guint16 *bitmapped_sizes; gint nstandard_sizes, nbitmapped_sizes; gchar buffer[16], *size; gfloat bitmap_size_float = 0.; guint16 bitmap_size = 0; gboolean can_match; gint type_filter; #ifdef FONTSEL_DEBUG g_message("In show_available_sizes\n"); #endif font = &fontsel_info->font_info[fontsel->font_index]; styles = &fontsel_info->font_styles[font->style_index]; style = &styles[fontsel->style]; standard_sizes = font_sizes; nstandard_sizes = sizeof(font_sizes) / sizeof(font_sizes[0]); if (fontsel->metric == GTK_XLFD_METRIC_POINTS) { bitmapped_sizes = &fontsel_info->point_sizes[style->point_sizes_index]; nbitmapped_sizes = style->npoint_sizes; } else { bitmapped_sizes = &fontsel_info->pixel_sizes[style->pixel_sizes_index]; nbitmapped_sizes = style->npixel_sizes; } /* Only show the standard sizes if a scalable font is available. */ type_filter = fontsel->filters[GTK_XLFD_FILTER_BASE].font_type & fontsel->filters[GTK_XLFD_FILTER_USER].font_type; if (!((style->flags & GTK_XLFD_SCALABLE_BITMAP && type_filter & GTK_XLFD_SCALABLE_BITMAP) || (style->flags & GTK_XLFD_SCALABLE && type_filter & GTK_XLFD_SCALABLE))) nstandard_sizes = 0; gtk_clist_freeze (GTK_CLIST(fontsel->size_clist)); gtk_clist_clear (GTK_CLIST(fontsel->size_clist)); /* Interleave the standard sizes with the bitmapped sizes so we get a list of ascending sizes. If the metric is points, we have to convert the decipoints to points. */ while (nstandard_sizes || nbitmapped_sizes) { can_match = TRUE; if (nbitmapped_sizes) { if (fontsel->metric == GTK_XLFD_METRIC_POINTS) { if (*bitmapped_sizes % 10 != 0) can_match = FALSE; bitmap_size = *bitmapped_sizes / 10; bitmap_size_float = *bitmapped_sizes / 10; } else { bitmap_size = *bitmapped_sizes; bitmap_size_float = *bitmapped_sizes; } } if (can_match && nstandard_sizes && nbitmapped_sizes && *standard_sizes == bitmap_size) { sprintf(buffer, "%i *", *standard_sizes); standard_sizes++; nstandard_sizes--; bitmapped_sizes++; nbitmapped_sizes--; } else if (nstandard_sizes && (!nbitmapped_sizes || (gfloat)*standard_sizes < bitmap_size_float)) { sprintf(buffer, "%i", *standard_sizes); standard_sizes++; nstandard_sizes--; } else { if (fontsel->metric == GTK_XLFD_METRIC_POINTS) { if (*bitmapped_sizes % 10 == 0) sprintf(buffer, "%i *", *bitmapped_sizes / 10); else sprintf(buffer, "%i.%i *", *bitmapped_sizes / 10, *bitmapped_sizes % 10); } else { sprintf(buffer, "%i *", *bitmapped_sizes); } bitmapped_sizes++; nbitmapped_sizes--; } size = buffer; gtk_clist_append(GTK_CLIST(fontsel->size_clist), &size); } gtk_clist_thaw (GTK_CLIST(fontsel->size_clist)); } static void gtk_xlfd_selection_update_size (GtkXlfdSelection *fontsel) { gint new_size; gfloat new_size_float; gchar *text; #ifdef FONTSEL_DEBUG g_message("In update_size\n"); #endif text = gtk_entry_get_text (GTK_ENTRY (fontsel->size_entry)); if (fontsel->metric == GTK_XLFD_METRIC_PIXELS) { new_size = atoi (text); if (new_size < 2) new_size = 2; } else { new_size_float = atof (text) * 10; new_size = (gint) new_size_float; if (new_size < 20) new_size = 20; } /* Remember that this size was set explicitly. */ fontsel->selected_size = new_size; /* Check if the font size has changed, and return if it hasn't. */ if (fontsel->size == new_size) return; fontsel->size = new_size; gtk_xlfd_selection_select_best_size (fontsel); } /* If the user hits return in the font size entry, we change to the new font size. */ static void gtk_xlfd_selection_size_activate (GtkWidget *w, gpointer data) { gtk_xlfd_selection_update_size (data); } /* This tries to select the closest size to the current size, though it may have to change the size if only unscaled bitmaps are available. Note: this will load a font. */ static void gtk_xlfd_selection_select_best_size(GtkXlfdSelection *fontsel) { FontInfo *font; FontStyle *styles, *style; gchar *text; gint row, best_row = 0, size, size_fraction, best_size = 0, nmatched; gboolean found = FALSE; gchar buffer[32]; GList *selection; gint type_filter; #ifdef FONTSEL_DEBUG g_message("In select_best_size\n"); #endif if (fontsel->font_index == -1) return; font = &fontsel_info->font_info[fontsel->font_index]; styles = &fontsel_info->font_styles[font->style_index]; style = &styles[fontsel->style]; /* Find the closest size available in the size clist. If the exact size is in the list set found to TRUE. */ for (row = 0; row < GTK_CLIST(fontsel->size_clist)->rows; row++) { gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text); nmatched = sscanf(text, "%i.%i", &size, &size_fraction); if (fontsel->metric == GTK_XLFD_METRIC_POINTS) { size *= 10; if (nmatched == 2) size += size_fraction; } if (size == fontsel->selected_size) { found = TRUE; best_size = size; best_row = row; break; } else if (best_size == 0 || abs(size - fontsel->selected_size) < (abs(best_size - fontsel->selected_size))) { best_size = size; best_row = row; } } /* If we aren't scaling bitmapped fonts and this is a bitmapped font, we need to use the closest size found. */ type_filter = fontsel->filters[GTK_XLFD_FILTER_BASE].font_type & fontsel->filters[GTK_XLFD_FILTER_USER].font_type; if (!((style->flags & GTK_XLFD_SCALABLE_BITMAP && type_filter & GTK_XLFD_SCALABLE_BITMAP) || (style->flags & GTK_XLFD_SCALABLE && type_filter & GTK_XLFD_SCALABLE))) found = TRUE; if (found) { fontsel->size = best_size; gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), best_row, -1, 0.5, 0); gtk_clist_select_row(GTK_CLIST(fontsel->size_clist), best_row, 0); } else { fontsel->size = fontsel->selected_size; selection = GTK_CLIST(fontsel->size_clist)->selection; if (selection) gtk_clist_unselect_row(GTK_CLIST(fontsel->size_clist), GPOINTER_TO_INT (selection->data), 0); gtk_clist_moveto(GTK_CLIST(fontsel->size_clist), best_row, -1, 0.5, 0); /* Show the size in the size entry. */ if (fontsel->metric == GTK_XLFD_METRIC_PIXELS) sprintf(buffer, "%i", fontsel->size); else { if (fontsel->size % 10 == 0) sprintf(buffer, "%i", fontsel->size / 10); else sprintf(buffer, "%i.%i", fontsel->size / 10, fontsel->size % 10); } gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer); } gtk_xlfd_selection_load_font (fontsel); } /* This is called when a size is selected in the list. */ static void gtk_xlfd_selection_select_size (GtkWidget *w, gint row, gint column, GdkEventButton *bevent, gpointer data) { GtkXlfdSelection *fontsel; gdouble new_size; gchar *text; gchar buffer[16]; gint i; #ifdef FONTSEL_DEBUG g_message("In select_size\n"); #endif fontsel = GTK_XLFD_SELECTION(data); if (bevent && !GTK_WIDGET_HAS_FOCUS (w)) gtk_widget_grab_focus (w); /* Copy the size from the clist to the size entry, but without the bitmapped marker ('*'). */ gtk_clist_get_text(GTK_CLIST(fontsel->size_clist), row, 0, &text); i = 0; while (i < 15 && (text[i] == '.' || (text[i] >= '0' && text[i] <= '9'))) { buffer[i] = text[i]; i++; } buffer[i] = '\0'; gtk_entry_set_text(GTK_ENTRY(fontsel->size_entry), buffer); /* Check if the font size has changed, and return if it hasn't. */ new_size = atof(text); if (fontsel->metric == GTK_XLFD_METRIC_POINTS) new_size *= 10; if (fontsel->size == (gint)new_size) return; /* If the size was selected by the user we set the selected_size. */ fontsel->selected_size = new_size; fontsel->size = new_size; gtk_xlfd_selection_load_font (fontsel); } /* This is called when the pixels or points radio buttons are pressed. */ static void gtk_xlfd_selection_metric_callback (GtkWidget *w, gpointer data) { GtkXlfdSelection *fontsel = GTK_XLFD_SELECTION(data); #ifdef FONTSEL_DEBUG g_message("In metric_callback\n"); #endif if (GTK_TOGGLE_BUTTON(fontsel->pixels_button)->active) { if (fontsel->metric == GTK_XLFD_METRIC_PIXELS) return; fontsel->metric = GTK_XLFD_METRIC_PIXELS; fontsel->size = (fontsel->size + 5) / 10; fontsel->selected_size = (fontsel->selected_size + 5) / 10; } else { if (fontsel->metric == GTK_XLFD_METRIC_POINTS) return; fontsel->metric = GTK_XLFD_METRIC_POINTS; fontsel->size *= 10; fontsel->selected_size *= 10; } if (fontsel->font_index != -1) { gtk_xlfd_selection_show_available_sizes (fontsel); gtk_xlfd_selection_select_best_size (fontsel); } } /* This searches the given property table and returns the index of the given string, or 0, which is the wildcard '*' index, if it's not found. */ static guint16 gtk_xlfd_selection_field_to_index (gchar **table, gint ntable, gchar *field) { gint i; for (i = 0; i < ntable; i++) if (strcmp (field, table[i]) == 0) return i; return 0; } /* This attempts to load the current font, and returns TRUE if it succeeds. */ static gboolean gtk_xlfd_selection_load_font (GtkXlfdSelection *fontsel) { GdkFont *font; gchar *fontname, *label_text; XFontStruct *xfs; #if 0 if (fontsel->font) gdk_font_unref (fontsel->font); #endif fontsel->font = NULL; /* If no family has been selected yet, just return FALSE. */ if (fontsel->font_index == -1) return FALSE; fontname = gtk_xlfd_selection_get_font_name (fontsel); if (fontname) { #ifdef FONTSEL_DEBUG g_message("Loading: %s\n", fontname); #endif font = gdk_font_load (fontname); xfs = font ? GDK_FONT_XFONT (font) : NULL; if (xfs && (xfs->min_byte1 != 0 || xfs->max_byte1 != 0)) { gchar *tmp_name; gdk_font_unref (font); tmp_name = g_strconcat (fontname, ",*", NULL); font = gdk_fontset_load (tmp_name); g_free (tmp_name); } g_free (fontname); if (font) { fontsel->font = font; /* Make sure the message label is empty, but don't change it unless it's necessary as it results in a resize of the whole window! */ gtk_label_get(GTK_LABEL(fontsel->message_label), &label_text); if (strcmp(label_text, "")) gtk_label_set_text(GTK_LABEL(fontsel->message_label), ""); gtk_xlfd_selection_update_preview (fontsel); return TRUE; } else { gtk_label_set_text(GTK_LABEL(fontsel->message_label), _("The selected font is not available.")); } } else { gtk_label_set_text(GTK_LABEL(fontsel->message_label), _("The selected font is not a valid font.")); } return FALSE; } /* This sets the font in the preview entry to the selected font, and tries to make sure that the preview entry is a reasonable size, i.e. so that the text can be seen with a bit of space to spare. But it tries to avoid resizing the entry every time the font changes. This also used to shrink the preview if the font size was decreased, but that made it awkward if the user wanted to resize the window themself. */ static void gtk_xlfd_selection_update_preview (GtkXlfdSelection *fontsel) { GtkWidget *preview_entry; GtkStyle *style; gint text_height, new_height; gchar *text; XFontStruct *xfs; #ifdef FONTSEL_DEBUG g_message("In update_preview\n"); #endif style = gtk_style_new (); gtk_style_set_font( style , fontsel->font) ; preview_entry = fontsel->preview_entry; gtk_widget_set_style (preview_entry, style); gtk_style_unref(style); text_height = gtk_style_get_font( preview_entry->style)->ascent + gtk_style_get_font( preview_entry->style)->descent; /* We don't ever want to be over MAX_PREVIEW_HEIGHT pixels high. */ new_height = text_height + 20; if (new_height < INITIAL_PREVIEW_HEIGHT) new_height = INITIAL_PREVIEW_HEIGHT; if (new_height > MAX_PREVIEW_HEIGHT) new_height = MAX_PREVIEW_HEIGHT; if ((preview_entry->requisition.height < text_height + 10) || (preview_entry->requisition.height > text_height + 40)) gtk_widget_set_usize(preview_entry, -1, new_height); /* This sets the preview text, if it hasn't been set already. */ text = gtk_entry_get_text(GTK_ENTRY(fontsel->preview_entry)); if (strlen(text) == 0) gtk_entry_set_text(GTK_ENTRY(fontsel->preview_entry), PREVIEW_TEXT); gtk_entry_set_position(GTK_ENTRY(fontsel->preview_entry), 0); /* If this is a 2-byte font display a message to say it may not be displayed properly. */ xfs = GDK_FONT_XFONT(fontsel->font); if (xfs->min_byte1 != 0 || xfs->max_byte1 != 0) gtk_label_set_text(GTK_LABEL(fontsel->message_label), _("This is a 2-byte font and may not be displayed correctly.")); } static void gtk_xlfd_selection_switch_page (GtkWidget *w, GtkNotebookPage *page, gint page_num, gpointer data) { GtkXlfdSelection *fontsel = GTK_XLFD_SELECTION(data); /* This function strangely gets called when the window is destroyed, so we check here to see if the notebook is visible. */ if (!GTK_WIDGET_VISIBLE(w)) return; if (page_num == 0) gtk_xlfd_selection_update_filter(fontsel); else if (page_num == 1) gtk_xlfd_selection_show_font_info(fontsel); } static void gtk_xlfd_selection_show_font_info (GtkXlfdSelection *fontsel) { Atom font_atom, atom; Bool status; char *name; gchar *fontname; gchar field_buffer[XLFD_MAX_FIELD_LEN]; gchar *field; gint i; gboolean shown_actual_fields = FALSE; fontname = gtk_xlfd_selection_get_font_name(fontsel); gtk_entry_set_text(GTK_ENTRY(fontsel->requested_font_name), fontname ? fontname : ""); gtk_clist_freeze (GTK_CLIST(fontsel->info_clist)); for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++) { if (fontname) field = gtk_xlfd_selection_get_xlfd_field (fontname, i, field_buffer); else field = NULL; if (field) { if (i == XLFD_SLANT) field = gtk_xlfd_selection_expand_slant_code(field); else if (i == XLFD_SPACING) field = gtk_xlfd_selection_expand_spacing_code(field); } gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 1, field ? field : ""); } if (fontsel->font) { font_atom = gdk_x11_atom_to_xatom_for_display (gtk_widget_get_display (GTK_WIDGET(fontsel)) , gdk_atom_intern ("FONT", FALSE)) ; if (fontsel->font->type == GDK_FONT_FONTSET) { XFontStruct **font_structs; gint num_fonts; gchar **font_names; num_fonts = XFontsOfFontSet (GDK_FONT_XFONT(fontsel->font), &font_structs, &font_names); status = XGetFontProperty(font_structs[0], font_atom, &atom); } else { status = XGetFontProperty(GDK_FONT_XFONT(fontsel->font), font_atom, &atom); } if (status == True) { name = gdk_atom_name (gdk_x11_xatom_to_atom_for_display ( gtk_widget_get_display(GTK_WIDGET(fontsel)), atom)); gtk_entry_set_text(GTK_ENTRY(fontsel->actual_font_name), name); for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++) { field = gtk_xlfd_selection_get_xlfd_field (name, i, field_buffer); if (i == XLFD_SLANT) field = gtk_xlfd_selection_expand_slant_code(field); else if (i == XLFD_SPACING) field = gtk_xlfd_selection_expand_spacing_code(field); gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2, field ? field : ""); } shown_actual_fields = TRUE; g_free (name); } } if (!shown_actual_fields) { gtk_entry_set_text(GTK_ENTRY(fontsel->actual_font_name), ""); for (i = 0; i < GTK_XLFD_NUM_FIELDS; i++) { gtk_clist_set_text(GTK_CLIST(fontsel->info_clist), i, 2, fontname ? _("(unknown)") : ""); } } gtk_clist_thaw (GTK_CLIST(fontsel->info_clist)); g_free(fontname); } static gchar* gtk_xlfd_selection_expand_slant_code(gchar *slant) { if (!g_strcasecmp(slant, "r")) return(_("roman")); else if (!g_strcasecmp(slant, "i")) return(_("italic")); else if (!g_strcasecmp(slant, "o")) return(_("oblique")); else if (!g_strcasecmp(slant, "ri")) return(_("reverse italic")); else if (!g_strcasecmp(slant, "ro")) return(_("reverse oblique")); else if (!g_strcasecmp(slant, "ot")) return(_("other")); return slant; } static gchar* gtk_xlfd_selection_expand_spacing_code(gchar *spacing) { if (!g_strcasecmp(spacing, "p")) return(_("proportional")); else if (!g_strcasecmp(spacing, "m")) return(_("monospaced")); else if (!g_strcasecmp(spacing, "c")) return(_("char cell")); return spacing; } /***************************************************************************** * These functions all deal with the Filter page and filtering the fonts. *****************************************************************************/ /* This is called when an item is selected in one of the filter clists. We make sure that the first row of the clist, i.e. the wildcard '*', is selected if and only if none of the other items are selected. Also doesn't allow selections of values filtered out by base filter. We may need to be careful about triggering other signals. */ static void gtk_xlfd_selection_select_filter (GtkWidget *w, gint row, gint column, GdkEventButton *bevent, GtkXlfdSelection *fontsel) { gint i, prop, index; if (row == 0) { for (i = 1; i < GTK_CLIST(w)->rows; i++) gtk_clist_unselect_row(GTK_CLIST(w), i, 0); } else { /* Find out which property this is. */ for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) if (fontsel->filter_clists[prop] == w) break; index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(w), row)); if (gtk_xlfd_selection_filter_state (fontsel, GTK_XLFD_FILTER_BASE, prop, index) == NOT_FILTERED) { gtk_clist_unselect_row(GTK_CLIST(w), row, 0); } else { gtk_clist_unselect_row(GTK_CLIST(w), 0, 0); } } } /* This is called when the main notebook page is selected. It checks if the filter has changed, an if so it creates the filter settings, and filters the fonts shown. If an empty filter (all '*'s) is applied, then filtering is turned off. */ static void gtk_xlfd_selection_update_filter (GtkXlfdSelection *fontsel) { GtkWidget *clist; GList *selection; gboolean default_filter = TRUE, filter_changed = FALSE; gint prop, nselected, i, row, index; GtkXlfdFilter *filter = &fontsel->filters[GTK_XLFD_FILTER_USER]; gint base_font_type, user_font_type, new_font_type; #ifdef FONTSEL_DEBUG g_message("In update_filter\n"); #endif /* Check if the user filter has changed, and also if it is the default filter, i.e. bitmap & scalable fonts and all '*'s selected. We only look at the bits which are not already filtered out by the base filter, since that overrides the user filter. */ base_font_type = fontsel->filters[GTK_XLFD_FILTER_BASE].font_type & GTK_XLFD_ALL; user_font_type = fontsel->filters[GTK_XLFD_FILTER_USER].font_type & GTK_XLFD_ALL; new_font_type = GTK_TOGGLE_BUTTON(fontsel->type_bitmaps_button)->active ? GTK_XLFD_BITMAP : 0; new_font_type |= (GTK_TOGGLE_BUTTON(fontsel->type_scalable_button)->active ? GTK_XLFD_SCALABLE : 0); new_font_type |= (GTK_TOGGLE_BUTTON(fontsel->type_scaled_bitmaps_button)->active ? GTK_XLFD_SCALABLE_BITMAP : 0); new_font_type &= base_font_type; new_font_type |= (~base_font_type & user_font_type); if (new_font_type != (GTK_XLFD_BITMAP | GTK_XLFD_SCALABLE)) default_filter = FALSE; if (new_font_type != user_font_type) filter_changed = TRUE; fontsel->filters[GTK_XLFD_FILTER_USER].font_type = new_font_type; for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) { clist = fontsel->filter_clists[prop]; selection = GTK_CLIST(clist)->selection; nselected = g_list_length(selection); if (nselected != 1 || GPOINTER_TO_INT (selection->data) != 0) { default_filter = FALSE; if (filter->property_nfilters[prop] != nselected) filter_changed = TRUE; else { for (i = 0; i < nselected; i++) { row = GPOINTER_TO_INT (selection->data); index = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row)); if (filter->property_filters[prop][i] != index) filter_changed = TRUE; selection = selection->next; } } } else { if (filter->property_nfilters[prop] != 0) filter_changed = TRUE; } } /* If the filter hasn't changed we just return. */ if (!filter_changed) return; #ifdef FONTSEL_DEBUG g_message(" update_fonts: filter has changed\n"); #endif /* Free the old filter data and create the new arrays. */ for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) { g_free(filter->property_filters[prop]); clist = fontsel->filter_clists[prop]; selection = GTK_CLIST(clist)->selection; nselected = g_list_length(selection); if (nselected == 1 && GPOINTER_TO_INT (selection->data) == 0) { filter->property_filters[prop] = NULL; filter->property_nfilters[prop] = 0; } else { filter->property_filters[prop] = g_new(guint16, nselected); filter->property_nfilters[prop] = nselected; for (i = 0; i < nselected; i++) { row = GPOINTER_TO_INT (selection->data); index = GPOINTER_TO_INT (gtk_clist_get_row_data (GTK_CLIST (clist), row)); filter->property_filters[prop][i] = index; selection = selection->next; } } } /* Set the 'Reset Filter' button sensitive if a filter is in effect, and also set the label above the font list to show this as well. */ if (default_filter) { gtk_widget_set_sensitive(fontsel->filter_button, FALSE); gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font:")); } else { gtk_widget_set_sensitive(fontsel->filter_button, TRUE); gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font: (Filter Applied)")); } gtk_xlfd_selection_show_available_fonts(fontsel); } /* This shows all the available fonts in the font clist. */ static void gtk_xlfd_selection_show_available_fonts (GtkXlfdSelection *fontsel) { FontInfo *font_info, *font; GtkXlfdFilter *filter; gint nfonts, i, j, k, row, style, font_row = -1; gchar font_buffer[XLFD_MAX_FIELD_LEN * 2 + 4]; gchar *font_item; gboolean matched, matched_style; #ifdef FONTSEL_DEBUG g_message("In show_available_fonts\n"); #endif font_info = fontsel_info->font_info; nfonts = fontsel_info->nfonts; /* Filter the list of fonts. */ gtk_clist_freeze (GTK_CLIST(fontsel->font_clist)); gtk_clist_clear (GTK_CLIST(fontsel->font_clist)); for (i = 0; i < nfonts; i++) { font = &font_info[i]; /* Check if the foundry passes through all filters. */ matched = TRUE; for (k = 0; k < GTK_NUM_FONT_FILTERS; k++) { filter = &fontsel->filters[k]; if (filter->property_nfilters[FOUNDRY] != 0) { matched = FALSE; for (j = 0; j < filter->property_nfilters[FOUNDRY]; j++) { if (font->foundry == filter->property_filters[FOUNDRY][j]) { matched = TRUE; break; } } if (!matched) break; } } if (!matched) continue; /* Now check if the other properties are matched in at least one style.*/ matched_style = FALSE; for (style = 0; style < font->nstyles; style++) { if (gtk_xlfd_selection_style_visible(fontsel, font, style)) { matched_style = TRUE; break; } } if (!matched_style) continue; /* Insert the font in the clist. */ if ((i > 0 && font->family == font_info[i-1].family) || (i < nfonts - 1 && font->family == font_info[i+1].family)) { sprintf(font_buffer, "%s (%s)", font->family, fontsel_info->properties[FOUNDRY][font->foundry]); font_item = font_buffer; row = gtk_clist_append(GTK_CLIST(fontsel->font_clist), &font_item); } else { row = gtk_clist_append(GTK_CLIST(fontsel->font_clist), &font->family); } gtk_clist_set_row_data(GTK_CLIST(fontsel->font_clist), row, GINT_TO_POINTER (i)); if (fontsel->font_index == i) font_row = row; } gtk_clist_thaw (GTK_CLIST(fontsel->font_clist)); /* If the currently-selected font isn't in the new list, reset the selection. */ if (font_row == -1) { fontsel->font_index = -1; if (fontsel->font) gdk_font_unref(fontsel->font); fontsel->font = NULL; gtk_entry_set_text(GTK_ENTRY(fontsel->font_entry), ""); gtk_clist_clear (GTK_CLIST(fontsel->font_style_clist)); gtk_entry_set_text(GTK_ENTRY(fontsel->font_style_entry), ""); return; } gtk_clist_select_row(GTK_CLIST(fontsel->font_clist), font_row, 0); if (gtk_clist_row_is_visible(GTK_CLIST(fontsel->font_clist), font_row) != GTK_VISIBILITY_FULL) gtk_clist_moveto(GTK_CLIST(fontsel->font_clist), font_row, -1, 0.5, 0); gtk_xlfd_selection_show_available_styles (fontsel); gtk_xlfd_selection_select_best_style (fontsel, FALSE); } /* Returns TRUE if the style is not currently filtered out. */ static gboolean gtk_xlfd_selection_style_visible(GtkXlfdSelection *fontsel, FontInfo *font, gint style_index) { FontStyle *styles, *style; GtkXlfdFilter *filter; guint16 value; gint prop, i, j; gboolean matched; gint type_filter; styles = &fontsel_info->font_styles[font->style_index]; style = &styles[style_index]; /* Check if font_type of style is filtered. */ type_filter = fontsel->filters[GTK_XLFD_FILTER_BASE].font_type & fontsel->filters[GTK_XLFD_FILTER_USER].font_type; if (!(style->flags & type_filter)) return FALSE; for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) { value = style->properties[prop]; /* Check each filter. */ for (i = 0; i < GTK_NUM_FONT_FILTERS; i++) { filter = &fontsel->filters[i]; if (filter->property_nfilters[prop] != 0) { matched = FALSE; for (j = 0; j < filter->property_nfilters[prop]; j++) { if (value == filter->property_filters[prop][j]) { matched = TRUE; break; } } if (!matched) return FALSE; } } } return TRUE; } /* This resets the font type to bitmap or scalable, and sets all the filter clists to the wildcard '*' options. */ static void gtk_xlfd_selection_reset_filter (GtkWidget *w, GtkXlfdSelection *fontsel) { gint prop, base_font_type; fontsel->filters[GTK_XLFD_FILTER_USER].font_type = GTK_XLFD_BITMAP | GTK_XLFD_SCALABLE; base_font_type = fontsel->filters[GTK_XLFD_FILTER_BASE].font_type; if (base_font_type & GTK_XLFD_BITMAP) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), TRUE); if (base_font_type & GTK_XLFD_SCALABLE) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), TRUE); if (base_font_type & GTK_XLFD_SCALABLE_BITMAP) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), FALSE); for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) gtk_clist_select_row(GTK_CLIST(fontsel->filter_clists[prop]), 0, 0); } /* This clears the filter, showing all fonts and styles again. */ static void gtk_xlfd_selection_on_clear_filter (GtkWidget *w, GtkXlfdSelection *fontsel) { gtk_xlfd_selection_clear_filter(fontsel); } /* This resets the user filter, showing all fonts and styles which pass the base filter again. Note that the font type is set to bitmaps and scalable fonts - scaled bitmaps are not shown. */ static void gtk_xlfd_selection_clear_filter (GtkXlfdSelection *fontsel) { GtkXlfdFilter *filter; gint prop; #ifdef FONTSEL_DEBUG g_message("In clear_filter\n"); #endif /* Clear the filter data. */ filter = &fontsel->filters[GTK_XLFD_FILTER_USER]; filter->font_type = GTK_XLFD_BITMAP | GTK_XLFD_SCALABLE; for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) { g_free(filter->property_filters[prop]); filter->property_filters[prop] = NULL; filter->property_nfilters[prop] = 0; } /* Select all the '*'s on the filter page. */ gtk_xlfd_selection_reset_filter(NULL, fontsel); /* Update the main notebook page. */ gtk_widget_set_sensitive(fontsel->filter_button, FALSE); gtk_label_set_text(GTK_LABEL(fontsel->font_label), _("Font:")); gtk_xlfd_selection_show_available_fonts(fontsel); } void gtk_xlfd_selection_set_filter (GtkXlfdSelection *fontsel, GtkXlfdFilterType filter_type, GtkXlfdType font_type, gchar **foundries, gchar **weights, gchar **slants, gchar **setwidths, gchar **spacings, gchar **charsets) { GtkXlfdFilter *filter; gchar **filter_strings [GTK_NUM_FONT_PROPERTIES]; gchar *filter_string; gchar *property, *property_alt; gint prop, nfilters, i, j, num_found; gint base_font_type, user_font_type; gboolean filter_set; /* Put them into an array so we can use a simple loop. */ filter_strings[FOUNDRY] = foundries; filter_strings[WEIGHT] = weights; filter_strings[SLANT] = slants; filter_strings[SET_WIDTH] = setwidths; filter_strings[SPACING] = spacings; filter_strings[CHARSET] = charsets; filter = &fontsel->filters[filter_type]; filter->font_type = font_type; /* Free the old filter data, and insert the new. */ for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) { g_free(filter->property_filters[prop]); filter->property_filters[prop] = NULL; filter->property_nfilters[prop] = 0; if (filter_strings[prop]) { /* Count how many items in the new array. */ nfilters = 0; while (filter_strings[prop][nfilters]) nfilters++; filter->property_filters[prop] = g_new(guint16, nfilters); filter->property_nfilters[prop] = 0; /* Now convert the strings to property indices. */ num_found = 0; for (i = 0; i < nfilters; i++) { filter_string = filter_strings[prop][i]; for (j = 0; j < fontsel_info->nproperties[prop]; j++) { property = _(fontsel_info->properties[prop][j]); property_alt = NULL; if (prop == SLANT) property_alt = gtk_xlfd_selection_expand_slant_code(property); else if (prop == SPACING) property_alt = gtk_xlfd_selection_expand_spacing_code(property); if (!strcmp (filter_string, property) || (property_alt && !strcmp (filter_string, property_alt))) { filter->property_filters[prop][num_found] = j; num_found++; break; } } } filter->property_nfilters[prop] = num_found; } } /* Now set the clists on the filter page according to the new filter. */ gtk_xlfd_selection_update_filter_lists (fontsel); if (filter_type == GTK_XLFD_FILTER_BASE) { user_font_type = fontsel->filters[GTK_XLFD_FILTER_USER].font_type; if (font_type & GTK_XLFD_BITMAP) { gtk_widget_set_sensitive (fontsel->type_bitmaps_button, TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), user_font_type & GTK_XLFD_BITMAP); } else { gtk_widget_set_sensitive (fontsel->type_bitmaps_button, FALSE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), FALSE); } if (font_type & GTK_XLFD_SCALABLE) { gtk_widget_set_sensitive (fontsel->type_scalable_button, TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), user_font_type & GTK_XLFD_SCALABLE); } else { gtk_widget_set_sensitive (fontsel->type_scalable_button, FALSE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), FALSE); } if (font_type & GTK_XLFD_SCALABLE_BITMAP) { gtk_widget_set_sensitive (fontsel->type_scaled_bitmaps_button, TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), user_font_type & GTK_XLFD_SCALABLE_BITMAP); } else { gtk_widget_set_sensitive (fontsel->type_scaled_bitmaps_button, FALSE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), FALSE); } } else { base_font_type = fontsel->filters[GTK_XLFD_FILTER_BASE].font_type; if (base_font_type & GTK_XLFD_BITMAP) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_bitmaps_button), font_type & GTK_XLFD_BITMAP); if (base_font_type & GTK_XLFD_SCALABLE) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scalable_button), font_type & GTK_XLFD_SCALABLE); if (base_font_type & GTK_XLFD_SCALABLE_BITMAP) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fontsel->type_scaled_bitmaps_button), font_type & GTK_XLFD_SCALABLE_BITMAP); /* If the user filter is not the default, make the 'Reset Filter' button sensitive. */ filter_set = FALSE; if (font_type != (GTK_XLFD_BITMAP | GTK_XLFD_SCALABLE)) filter_set = TRUE; for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) { if (filter->property_nfilters[prop] != 0) filter_set = TRUE; } if (filter_set) gtk_widget_set_sensitive (fontsel->filter_button, TRUE); } gtk_xlfd_selection_show_available_fonts (fontsel); } /* This sets the colour of each property in the filter clists according to the base filter. i.e. Filtered properties are shown as insensitive. */ static void gtk_xlfd_selection_update_filter_lists (GtkXlfdSelection *fontsel) { GtkWidget *clist; GdkColor *inactive_fg, *inactive_bg, *fg, *bg; gint prop, row, index; /* We have to make sure the clist is realized to use the colours. */ for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) { clist = fontsel->filter_clists[prop]; gtk_widget_realize (clist); inactive_fg = &clist->style->fg[GTK_STATE_INSENSITIVE]; inactive_bg = &clist->style->bg[GTK_STATE_INSENSITIVE]; for (row = 1; row < GTK_CLIST(clist)->rows; row++) { index = GPOINTER_TO_INT (gtk_clist_get_row_data(GTK_CLIST(clist), row)); /* Set the colour according to the base filter. */ if (gtk_xlfd_selection_filter_state (fontsel, GTK_XLFD_FILTER_BASE, prop, index) == NOT_FILTERED) { fg = inactive_fg; bg = inactive_bg; } else { fg = NULL; bg = NULL; } gtk_clist_set_foreground(GTK_CLIST(clist), row, fg); gtk_clist_set_background(GTK_CLIST(clist), row, bg); /* Set the selection state according to the user filter. */ if (gtk_xlfd_selection_filter_state (fontsel, GTK_XLFD_FILTER_USER, prop, index) == FILTERED && fg == NULL) gtk_clist_select_row (GTK_CLIST (clist), row, 0); else gtk_clist_unselect_row (GTK_CLIST (clist), row, 0); } } } /* Returns whether a property value is in the filter or not, or if the property has no filter set. */ static GtkXlfdPropertyFilterState gtk_xlfd_selection_filter_state (GtkXlfdSelection *fontsel, GtkXlfdFilterType filter_type, gint property, gint index) { GtkXlfdFilter *filter; gint i; filter = &fontsel->filters[filter_type]; if (filter->property_nfilters[property] == 0) return NOT_SET; for (i = 0; i < filter->property_nfilters[property]; i++) { if (filter->property_filters[property][i] == index) return FILTERED; } return NOT_FILTERED; } /***************************************************************************** * These functions all deal with creating the main class arrays containing * the data about all available fonts. *****************************************************************************/ static void gtk_xlfd_selection_get_fonts (void) { gchar **xfontnames; GSList **fontnames; gchar *fontname; GSList * temp_list; gint num_fonts; gint i, prop, style, size; gint npixel_sizes = 0, npoint_sizes = 0; FontInfo *font; FontStyle *current_style, *prev_style, *tmp_style; gboolean matched_style, found_size; gint pixels, points, res_x, res_y; gchar field_buffer[XLFD_MAX_FIELD_LEN]; gchar *field; guint8 flags; guint16 *pixel_sizes, *point_sizes, *tmp_sizes; fontsel_info = g_new (GtkXlfdSelInfo, 1); /* Get a maximum of MAX_FONTS fontnames from the X server. Use "-*" as the pattern rather than "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" since the latter may result in fonts being returned which don't actually exist. xlsfonts also uses "*" so I think it's OK. "-*" gets rid of aliases. */ xfontnames = XListFonts (GDK_DISPLAY(), "-*", MAX_FONTS, &num_fonts); /* Output a warning if we actually get MAX_FONTS fonts. */ if (num_fonts == MAX_FONTS) g_warning(_("MAX_FONTS exceeded. Some fonts may be missing.")); /* The maximum size of all these tables is the number of font names returned. We realloc them later when we know exactly how many unique entries there are. */ fontsel_info->font_info = g_new (FontInfo, num_fonts); fontsel_info->font_styles = g_new (FontStyle, num_fonts); fontsel_info->pixel_sizes = g_new (guint16, num_fonts); fontsel_info->point_sizes = g_new (guint16, num_fonts); fontnames = g_new (GSList*, num_fonts); /* Create the initial arrays for the property value strings, though they may be realloc'ed later. Put the wildcard '*' in the first elements. */ for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) { fontsel_info->properties[prop] = g_new(gchar*, PROPERTY_ARRAY_INCREMENT); fontsel_info->space_allocated[prop] = PROPERTY_ARRAY_INCREMENT; fontsel_info->nproperties[prop] = 1; fontsel_info->properties[prop][0] = "*"; } /* Insert the font families into the main table, sorted by family and foundry (fonts with different foundries are placed in seaparate FontInfos. All fontnames in each family + foundry are placed into the fontnames array of lists. */ fontsel_info->nfonts = 0; for (i = 0; i < num_fonts; i++) { #ifdef FONTSEL_DEBUG g_message("%s\n", xfontnames[i]); #endif if (gtk_xlfd_selection_is_xlfd_font_name (xfontnames[i])) gtk_xlfd_selection_insert_font (fontnames, &fontsel_info->nfonts, xfontnames[i]); else { #ifdef FONTSEL_DEBUG g_warning("Skipping invalid font: %s", xfontnames[i]); #endif } } /* Since many font names will be in the same FontInfo not all of the allocated FontInfo table will be used, so we will now reallocate it with the real size. */ fontsel_info->font_info = g_realloc(fontsel_info->font_info, sizeof(FontInfo) * fontsel_info->nfonts); /* Now we work out which choices of weight/slant etc. are valid for each font. */ fontsel_info->nstyles = 0; current_style = fontsel_info->font_styles; for (i = 0; i < fontsel_info->nfonts; i++) { font = &fontsel_info->font_info[i]; /* Use the next free position in the styles array. */ font->style_index = fontsel_info->nstyles; /* Now step through each of the fontnames with this family, and create a style for each fontname. Each style contains the index into the weights/slants etc. arrays, and a number of pixel/point sizes. */ style = 0; temp_list = fontnames[i]; while (temp_list) { fontname = temp_list->data; temp_list = temp_list->next; for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) { current_style->properties[prop] = gtk_xlfd_selection_insert_field (fontname, prop); } current_style->pixel_sizes_index = npixel_sizes; current_style->npixel_sizes = 0; current_style->point_sizes_index = npoint_sizes; current_style->npoint_sizes = 0; current_style->flags = 0; field = gtk_xlfd_selection_get_xlfd_field (fontname, XLFD_PIXELS, field_buffer); pixels = atoi(field); field = gtk_xlfd_selection_get_xlfd_field (fontname, XLFD_POINTS, field_buffer); points = atoi(field); field = gtk_xlfd_selection_get_xlfd_field (fontname, XLFD_RESOLUTION_X, field_buffer); res_x = atoi(field); field = gtk_xlfd_selection_get_xlfd_field (fontname, XLFD_RESOLUTION_Y, field_buffer); res_y = atoi(field); if (pixels == 0 && points == 0) { if (res_x == 0 && res_y == 0) flags = GTK_XLFD_SCALABLE; else flags = GTK_XLFD_SCALABLE_BITMAP; } else flags = GTK_XLFD_BITMAP; /* Now we check to make sure that the style is unique. If it isn't we forget it. */ prev_style = fontsel_info->font_styles + font->style_index; matched_style = FALSE; while (prev_style < current_style) { matched_style = TRUE; for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) { if (prev_style->properties[prop] != current_style->properties[prop]) { matched_style = FALSE; break; } } if (matched_style) break; prev_style++; } /* If we matched an existing style, we need to add the pixels & point sizes to the style. If not, we insert the pixel & point sizes into our new style. Note that we don't add sizes for scalable fonts. */ if (matched_style) { prev_style->flags |= flags; if (flags == GTK_XLFD_BITMAP) { pixel_sizes = fontsel_info->pixel_sizes + prev_style->pixel_sizes_index; found_size = FALSE; for (size = 0; size < prev_style->npixel_sizes; size++) { if (pixels == *pixel_sizes) { found_size = TRUE; break; } else if (pixels < *pixel_sizes) break; pixel_sizes++; } /* We need to move all the following pixel sizes up, and also update the indexes of any following styles. */ if (!found_size) { for (tmp_sizes = fontsel_info->pixel_sizes + npixel_sizes; tmp_sizes > pixel_sizes; tmp_sizes--) *tmp_sizes = *(tmp_sizes - 1); *pixel_sizes = pixels; npixel_sizes++; prev_style->npixel_sizes++; tmp_style = prev_style + 1; while (tmp_style < current_style) { tmp_style->pixel_sizes_index++; tmp_style++; } } point_sizes = fontsel_info->point_sizes + prev_style->point_sizes_index; found_size = FALSE; for (size = 0; size < prev_style->npoint_sizes; size++) { if (points == *point_sizes) { found_size = TRUE; break; } else if (points < *point_sizes) break; point_sizes++; } /* We need to move all the following point sizes up, and also update the indexes of any following styles. */ if (!found_size) { for (tmp_sizes = fontsel_info->point_sizes + npoint_sizes; tmp_sizes > point_sizes; tmp_sizes--) *tmp_sizes = *(tmp_sizes - 1); *point_sizes = points; npoint_sizes++; prev_style->npoint_sizes++; tmp_style = prev_style + 1; while (tmp_style < current_style) { tmp_style->point_sizes_index++; tmp_style++; } } } } else { current_style->flags = flags; if (flags == GTK_XLFD_BITMAP) { fontsel_info->pixel_sizes[npixel_sizes++] = pixels; current_style->npixel_sizes = 1; fontsel_info->point_sizes[npoint_sizes++] = points; current_style->npoint_sizes = 1; } style++; fontsel_info->nstyles++; current_style++; } } g_slist_free(fontnames[i]); /* Set nstyles to the real value, minus duplicated fontnames. Note that we aren't using all the allocated memory if fontnames are duplicated. */ font->nstyles = style; } /* Since some repeated styles may be skipped we won't have used all the allocated space, so we will now reallocate it with the real size. */ fontsel_info->font_styles = g_realloc(fontsel_info->font_styles, sizeof(FontStyle) * fontsel_info->nstyles); fontsel_info->pixel_sizes = g_realloc(fontsel_info->pixel_sizes, sizeof(guint16) * npixel_sizes); fontsel_info->point_sizes = g_realloc(fontsel_info->point_sizes, sizeof(guint16) * npoint_sizes); g_free(fontnames); XFreeFontNames (xfontnames); /* Debugging Output */ /* This outputs all FontInfos. */ #ifdef FONTSEL_DEBUG g_message("\n\n Font Family Weight Slant Set Width Spacing Charset\n\n"); for (i = 0; i < fontsel_info->nfonts; i++) { FontInfo *font = &fontsel_info->font_info[i]; FontStyle *styles = fontsel_info->font_styles + font->style_index; for (style = 0; style < font->nstyles; style++) { g_message("%5i %-16.16s ", i, font->family); for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) g_message("%-9.9s ", fontsel_info->properties[prop][styles->properties[prop]]); g_message("\n "); if (styles->flags & GTK_XLFD_BITMAP) g_message("Bitmapped font "); if (styles->flags & GTK_XLFD_SCALABLE) g_message("Scalable font "); if (styles->flags & GTK_XLFD_SCALABLE_BITMAP) g_message("Scalable-Bitmapped font "); g_message("\n"); if (styles->npixel_sizes) { g_message(" Pixel sizes: "); tmp_sizes = fontsel_info->pixel_sizes + styles->pixel_sizes_index; for (size = 0; size < styles->npixel_sizes; size++) g_message("%i ", *tmp_sizes++); g_message("\n"); } if (styles->npoint_sizes) { g_message(" Point sizes: "); tmp_sizes = fontsel_info->point_sizes + styles->point_sizes_index; for (size = 0; size < styles->npoint_sizes; size++) g_message("%i ", *tmp_sizes++); g_message("\n"); } g_message("\n"); styles++; } } /* This outputs all available properties. */ for (prop = 0; prop < GTK_NUM_FONT_PROPERTIES; prop++) { g_message("Property: %s\n", xlfd_field_names[xlfd_index[prop]]); for (i = 0; i < fontsel_info->nproperties[prop]; i++) g_message(" %s\n", fontsel_info->properties[prop][i]); } #endif } /* This inserts the given fontname into the FontInfo table. If a FontInfo already exists with the same family and foundry, then the fontname is added to the FontInfos list of fontnames, else a new FontInfo is created and inserted in alphabetical order in the table. */ static void gtk_xlfd_selection_insert_font (GSList *fontnames[], gint *ntable, gchar *fontname) { FontInfo *table; FontInfo temp_info; GSList *temp_fontname; gchar *family; gboolean family_exists = FALSE; gint foundry; gint lower, upper; gint middle, cmp; gchar family_buffer[XLFD_MAX_FIELD_LEN]; table = fontsel_info->font_info; /* insert a fontname into a table */ family = gtk_xlfd_selection_get_xlfd_field (fontname, XLFD_FAMILY, family_buffer); if (!family) return; foundry = gtk_xlfd_selection_insert_field (fontname, FOUNDRY); lower = 0; if (*ntable > 0) { /* Do a binary search to determine if we have already encountered * a font with this family & foundry. */ upper = *ntable; while (lower < upper) { middle = (lower + upper) >> 1; cmp = strcmp (family, table[middle].family); /* If the family matches we sort by the foundry. */ if (cmp == 0) { family_exists = TRUE; family = table[middle].family; cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry], fontsel_info->properties[FOUNDRY][table[middle].foundry]); } if (cmp == 0) { fontnames[middle] = g_slist_prepend (fontnames[middle], fontname); return; } else if (cmp < 0) upper = middle; else lower = middle+1; } } /* Add another entry to the table for this new font family */ temp_info.family = family_exists ? family : g_strdup(family); temp_info.foundry = foundry; temp_fontname = g_slist_prepend (NULL, fontname); (*ntable)++; /* Quickly insert the entry into the table in sorted order * using a modification of insertion sort and the knowledge * that the entries proper position in the table was determined * above in the binary search and is contained in the "lower" * variable. */ if (*ntable > 1) { upper = *ntable - 1; while (lower != upper) { table[upper] = table[upper-1]; fontnames[upper] = fontnames[upper-1]; upper--; } } table[lower] = temp_info; fontnames[lower] = temp_fontname; } /* This checks that the specified field of the given fontname is in the appropriate properties array. If not it is added. Thus eventually we get arrays of all possible weights/slants etc. It returns the array index. */ static gint gtk_xlfd_selection_insert_field (gchar *fontname, gint prop) { gchar field_buffer[XLFD_MAX_FIELD_LEN]; gchar *field; guint16 index; field = gtk_xlfd_selection_get_xlfd_field (fontname, xlfd_index[prop], field_buffer); if (!field) return 0; /* If the field is already in the array just return its index. */ for (index = 0; index < fontsel_info->nproperties[prop]; index++) if (!strcmp(field, fontsel_info->properties[prop][index])) return index; /* Make sure we have enough space to add the field. */ if (fontsel_info->nproperties[prop] == fontsel_info->space_allocated[prop]) { fontsel_info->space_allocated[prop] += PROPERTY_ARRAY_INCREMENT; fontsel_info->properties[prop] = g_realloc(fontsel_info->properties[prop], sizeof(gchar*) * fontsel_info->space_allocated[prop]); } /* Add the new field. */ index = fontsel_info->nproperties[prop]; fontsel_info->properties[prop][index] = g_strdup(field); fontsel_info->nproperties[prop]++; return index; } /***************************************************************************** * These functions are the main public interface for getting/setting the font. *****************************************************************************/ GdkFont* gtk_xlfd_selection_get_font (GtkXlfdSelection *fontsel) { g_return_val_if_fail (GTK_IS_XLFD_SELECTION (fontsel), NULL); gtk_xlfd_selection_update_size (fontsel); return fontsel->font; } gchar * gtk_xlfd_selection_get_font_name (GtkXlfdSelection *fontsel) { FontInfo *font; gchar *family_str, *foundry_str; gchar *property_str[GTK_NUM_STYLE_PROPERTIES]; gint prop; g_return_val_if_fail (fontsel != NULL, NULL); g_return_val_if_fail (GTK_IS_XLFD_SELECTION (fontsel), NULL); gtk_xlfd_selection_update_size (fontsel); /* If no family has been selected return NULL. */ if (fontsel->font_index == -1) return NULL; font = &fontsel_info->font_info[fontsel->font_index]; family_str = font->family; foundry_str = fontsel_info->properties[FOUNDRY][font->foundry]; /* some fonts have a (nil) foundry */ if (strcmp (foundry_str, "(nil)") == 0) foundry_str = ""; for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) { property_str[prop] = fontsel_info->properties[prop][fontsel->property_values[prop]]; if (strcmp (property_str[prop], "(nil)") == 0) property_str[prop] = ""; } return gtk_xlfd_selection_create_xlfd (fontsel->size, fontsel->metric, foundry_str, family_str, property_str[WEIGHT], property_str[SLANT], property_str[SET_WIDTH], property_str[SPACING], property_str[CHARSET]); } /* This sets the current font, selecting the appropriate clist rows. First we check the fontname is valid and try to find the font family - i.e. the name in the main list. If we can't find that, then just return. Next we try to set each of the properties according to the fontname. Finally we select the font family & style in the clists. */ gboolean gtk_xlfd_selection_set_font_name (GtkXlfdSelection *fontsel, const gchar *fontname) { gchar *family, *field; gint index, prop, size, row; guint16 foundry, value; gchar family_buffer[XLFD_MAX_FIELD_LEN]; gchar field_buffer[XLFD_MAX_FIELD_LEN]; gchar buffer[16]; g_return_val_if_fail (fontsel != NULL, FALSE); g_return_val_if_fail (GTK_IS_XLFD_SELECTION (fontsel), FALSE); g_return_val_if_fail (fontname != NULL, FALSE); /* Check it is a valid fontname. */ if (!gtk_xlfd_selection_is_xlfd_font_name(fontname)) return FALSE; family = gtk_xlfd_selection_get_xlfd_field (fontname, XLFD_FAMILY, family_buffer); if (!family) return FALSE; field = gtk_xlfd_selection_get_xlfd_field (fontname, XLFD_FOUNDRY, field_buffer); foundry = gtk_xlfd_selection_field_to_index (fontsel_info->properties[FOUNDRY], fontsel_info->nproperties[FOUNDRY], field); index = gtk_xlfd_selection_find_font(fontsel, family, foundry); if (index == -1) return FALSE; /* Convert the property fields into indices and set them. */ for (prop = 0; prop < GTK_NUM_STYLE_PROPERTIES; prop++) { field = gtk_xlfd_selection_get_xlfd_field (fontname, xlfd_index[prop], field_buffer); value = gtk_xlfd_selection_field_to_index (fontsel_info->properties[prop], fontsel_info->nproperties[prop], field); fontsel->property_values[prop] = value; } field = gtk_xlfd_selection_get_xlfd_field (fontname, XLFD_POINTS, field_buffer); size = atoi(field); if (size > 0) { if (size < 20) size = 20; fontsel->size = fontsel->selected_size = size; fontsel->metric = GTK_XLFD_METRIC_POINTS; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->points_button), TRUE); if (size % 10 == 0) sprintf (buffer, "%i", size / 10); else sprintf (buffer, "%i.%i", size / 10, size % 10); } else { field = gtk_xlfd_selection_get_xlfd_field (fontname, XLFD_PIXELS, field_buffer); size = atoi(field); if (size < 2) size = 2; fontsel->size = fontsel->selected_size = size; fontsel->metric = GTK_XLFD_METRIC_PIXELS; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fontsel->pixels_button), TRUE); sprintf (buffer, "%i", size); } gtk_entry_set_text (GTK_ENTRY (fontsel->size_entry), buffer); /* Clear any current filter. */ gtk_xlfd_selection_clear_filter(fontsel); /* Now find the best style match. */ fontsel->font_index = index; row = gtk_clist_find_row_from_data (GTK_CLIST (fontsel->font_clist), GINT_TO_POINTER (index)); if (row != -1) { gtk_clist_select_row (GTK_CLIST (fontsel->font_clist), row, 0); if (GTK_WIDGET_MAPPED (fontsel->font_clist)) gtk_clist_moveto (GTK_CLIST (fontsel->font_clist), row, -1, 0.5, 0); } gtk_xlfd_selection_show_available_styles (fontsel); /* This will load the font. */ gtk_xlfd_selection_select_best_style (fontsel, FALSE); return TRUE; } /* Returns the index of the given family, or -1 if not found */ static gint gtk_xlfd_selection_find_font (GtkXlfdSelection *fontsel, gchar *family, guint16 foundry) { FontInfo *font_info; gint lower, upper, middle = -1, cmp, nfonts; gint found_family = -1; font_info = fontsel_info->font_info; nfonts = fontsel_info->nfonts; if (nfonts == 0) return -1; /* Do a binary search to find the font family. */ lower = 0; upper = nfonts; while (lower < upper) { middle = (lower + upper) >> 1; cmp = strcmp (family, font_info[middle].family); if (cmp == 0) { found_family = middle; cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry], fontsel_info->properties[FOUNDRY][font_info[middle].foundry]); } if (cmp == 0) return middle; else if (cmp < 0) upper = middle; else if (cmp > 0) lower = middle+1; } /* We couldn't find the family and foundry, but we may have just found the family, so we return that. */ return found_family; } /* This returns the text in the preview entry. You should copy the returned text if you need it. */ gchar* gtk_xlfd_selection_get_preview_text (GtkXlfdSelection *fontsel) { return gtk_entry_get_text(GTK_ENTRY(fontsel->preview_entry)); } /* This sets the text in the preview entry. */ void gtk_xlfd_selection_set_preview_text (GtkXlfdSelection *fontsel, const gchar *text) { gtk_entry_set_text(GTK_ENTRY(fontsel->preview_entry), text); } /***************************************************************************** * These functions all deal with X Logical Font Description (XLFD) fontnames. * See the freely available documentation about this. *****************************************************************************/ /* * Returns TRUE if the fontname is a valid XLFD. * (It just checks if the number of dashes is 14, and that each * field < XLFD_MAX_FIELD_LEN characters long - that's not in the XLFD but it * makes it easier for me). */ static gboolean gtk_xlfd_selection_is_xlfd_font_name (const gchar *fontname) { gint i = 0; gint field_len = 0; while (*fontname) { if (*fontname++ == '-') { if (field_len > XLFD_MAX_FIELD_LEN) return FALSE; field_len = 0; i++; } else field_len++; } return (i == 14) ? TRUE : FALSE; } /* * This fills the buffer with the specified field from the X Logical Font * Description name, and returns it. If fontname is NULL or the field is * longer than XFLD_MAX_FIELD_LEN it returns NULL. * Note: For the charset field, we also return the encoding, e.g. 'iso8859-1'. */ static gchar* gtk_xlfd_selection_get_xlfd_field (const gchar *fontname, FontField field_num, gchar *buffer) { const gchar *t1, *t2; gint countdown, len, num_dashes; if (!fontname) return NULL; /* we assume this is a valid fontname...that is, it has 14 fields */ countdown = field_num; t1 = fontname; while (*t1 && (countdown >= 0)) if (*t1++ == '-') countdown--; num_dashes = (field_num == XLFD_CHARSET) ? 2 : 1; for (t2 = t1; *t2; t2++) { if (*t2 == '-' && --num_dashes == 0) break; } if (t1 != t2) { /* Check we don't overflow the buffer */ len = (long) t2 - (long) t1; if (len > XLFD_MAX_FIELD_LEN - 1) return NULL; strncpy (buffer, t1, len); buffer[len] = 0; /* Convert to lower case. */ g_strdown (buffer); } else strcpy(buffer, "(nil)"); return buffer; } /* * This returns a X Logical Font Description font name, given all the pieces. * Note: this retval must be freed by the caller. */ static gchar * gtk_xlfd_selection_create_xlfd (gint size, GtkXlfdMetricType metric, gchar *foundry, gchar *family, gchar *weight, gchar *slant, gchar *set_width, gchar *spacing, gchar *charset) { gchar buffer[16]; gchar *pixel_size = "*", *point_size = "*", *fontname; if (size <= 0) return NULL; sprintf (buffer, "%d", (int) size); if (metric == GTK_XLFD_METRIC_PIXELS) pixel_size = buffer; else point_size = buffer; fontname = g_strdup_printf("-%s-%s-%s-%s-%s-*-%s-%s-*-*-%s-*-%s", foundry, family, weight, slant, set_width, pixel_size, point_size, spacing, charset); return fontname; } /***************************************************************************** * GtkXlfdSelectionDialog *****************************************************************************/ guint gtk_xlfd_selection_dialog_get_type (void) { static guint font_selection_dialog_type = 0; if (!font_selection_dialog_type) { GtkTypeInfo fontsel_diag_info = { "GtkXlfdSelectionDialog", sizeof (GtkXlfdSelectionDialog), sizeof (GtkXlfdSelectionDialogClass), (GtkClassInitFunc) gtk_xlfd_selection_dialog_class_init, (GtkObjectInitFunc) gtk_xlfd_selection_dialog_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; font_selection_dialog_type = gtk_type_unique (GTK_TYPE_WINDOW, &fontsel_diag_info); } return font_selection_dialog_type; } static void gtk_xlfd_selection_dialog_class_init (GtkXlfdSelectionDialogClass *klass) { GtkObjectClass *object_class; object_class = (GtkObjectClass*) klass; font_selection_dialog_parent_class = gtk_type_class (GTK_TYPE_WINDOW); } static void gtk_xlfd_selection_dialog_init (GtkXlfdSelectionDialog *fontseldiag) { fontseldiag->dialog_width = -1; fontseldiag->auto_resize = TRUE; gtk_widget_set_events(GTK_WIDGET(fontseldiag), GDK_STRUCTURE_MASK); gtk_signal_connect (GTK_OBJECT (fontseldiag), "configure_event", (GtkSignalFunc) gtk_xlfd_selection_dialog_on_configure, fontseldiag); gtk_container_set_border_width (GTK_CONTAINER (fontseldiag), 4); gtk_window_set_policy(GTK_WINDOW(fontseldiag), FALSE, TRUE, TRUE); fontseldiag->main_vbox = gtk_vbox_new (FALSE, 4); gtk_widget_show (fontseldiag->main_vbox); gtk_container_add (GTK_CONTAINER (fontseldiag), fontseldiag->main_vbox); fontseldiag->fontsel = gtk_xlfd_selection_new(); gtk_widget_show (fontseldiag->fontsel); gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox), fontseldiag->fontsel, TRUE, TRUE, 0); /* Create the action area */ fontseldiag->action_area = gtk_hbutton_box_new (); gtk_button_box_set_layout(GTK_BUTTON_BOX(fontseldiag->action_area), GTK_BUTTONBOX_END); gtk_button_box_set_spacing(GTK_BUTTON_BOX(fontseldiag->action_area), 5); gtk_box_pack_start (GTK_BOX (fontseldiag->main_vbox), fontseldiag->action_area, FALSE, FALSE, 0); gtk_widget_show (fontseldiag->action_area); fontseldiag->ok_button = gtk_button_new_with_label(_("OK")); GTK_WIDGET_SET_FLAGS (fontseldiag->ok_button, GTK_CAN_DEFAULT); gtk_widget_show(fontseldiag->ok_button); gtk_box_pack_start (GTK_BOX (fontseldiag->action_area), fontseldiag->ok_button, TRUE, TRUE, 0); gtk_widget_grab_default (fontseldiag->ok_button); fontseldiag->apply_button = gtk_button_new_with_label(_("Apply")); GTK_WIDGET_SET_FLAGS (fontseldiag->apply_button, GTK_CAN_DEFAULT); /*gtk_widget_show(fontseldiag->apply_button);*/ gtk_box_pack_start (GTK_BOX(fontseldiag->action_area), fontseldiag->apply_button, TRUE, TRUE, 0); fontseldiag->cancel_button = gtk_button_new_with_label(_("Cancel")); GTK_WIDGET_SET_FLAGS (fontseldiag->cancel_button, GTK_CAN_DEFAULT); gtk_widget_show(fontseldiag->cancel_button); gtk_box_pack_start (GTK_BOX(fontseldiag->action_area), fontseldiag->cancel_button, TRUE, TRUE, 0); } GtkWidget* gtk_xlfd_selection_dialog_new (const gchar *title) { GtkXlfdSelectionDialog *fontseldiag; fontseldiag = gtk_type_new (GTK_TYPE_XLFD_SELECTION_DIALOG); gtk_window_set_title (GTK_WINDOW (fontseldiag), title ? title : _("Font Selection")); return GTK_WIDGET (fontseldiag); } gchar* gtk_xlfd_selection_dialog_get_font_name (GtkXlfdSelectionDialog *fsd) { return gtk_xlfd_selection_get_font_name(GTK_XLFD_SELECTION(fsd->fontsel)); } GdkFont* gtk_xlfd_selection_dialog_get_font (GtkXlfdSelectionDialog *fsd) { return gtk_xlfd_selection_get_font(GTK_XLFD_SELECTION(fsd->fontsel)); } gboolean gtk_xlfd_selection_dialog_set_font_name (GtkXlfdSelectionDialog *fsd, const gchar *fontname) { return gtk_xlfd_selection_set_font_name(GTK_XLFD_SELECTION(fsd->fontsel), fontname); } void gtk_xlfd_selection_dialog_set_filter (GtkXlfdSelectionDialog *fsd, GtkXlfdFilterType filter_type, GtkXlfdType font_type, gchar **foundries, gchar **weights, gchar **slants, gchar **setwidths, gchar **spacings, gchar **charsets) { gtk_xlfd_selection_set_filter (GTK_XLFD_SELECTION (fsd->fontsel), filter_type, font_type, foundries, weights, slants, setwidths, spacings, charsets); } gchar* gtk_xlfd_selection_dialog_get_preview_text (GtkXlfdSelectionDialog *fsd) { return gtk_xlfd_selection_get_preview_text(GTK_XLFD_SELECTION(fsd->fontsel)); } void gtk_xlfd_selection_dialog_set_preview_text (GtkXlfdSelectionDialog *fsd, const gchar *text) { gtk_xlfd_selection_set_preview_text(GTK_XLFD_SELECTION(fsd->fontsel), text); } /* This turns auto-shrink off if the user resizes the width of the dialog. It also turns it back on again if the user resizes it back to its normal width. */ static gint gtk_xlfd_selection_dialog_on_configure (GtkWidget *widget, GdkEventConfigure *event, GtkXlfdSelectionDialog *fsd) { /* This sets the initial width. */ if (fsd->dialog_width == -1) fsd->dialog_width = event->width; else if (fsd->auto_resize && fsd->dialog_width != event->width) { fsd->auto_resize = FALSE; gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, FALSE); } else if (!fsd->auto_resize && fsd->dialog_width == event->width) { fsd->auto_resize = TRUE; gtk_window_set_policy(GTK_WINDOW(fsd), FALSE, TRUE, TRUE); } return FALSE; } #endif /* G_PLATFORM_WIN32 */ mlterm-3.8.9/tool/mlconfig/gtkxlfdsel.h010064400017600000144000000252521356600660700166430ustar kenusers/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * GtkFontSelection widget for Gtk+, by Damon Chaplin, May 1998. * Based on the GnomeFontSelector widget, by Elliot Lee, but major changes. * The GnomeFontSelector was derived from app/text_tool.c in the GIMP. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ /* * Modified by Araki Ken(arakiken@users.sf.net). * GtkFontSelection => GtkXlfdSelection */ #ifndef __GTK_XLFDSEL_H__ #define __GTK_XLFDSEL_H__ #include #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define GTK_TYPE_XLFD_SELECTION (gtk_xlfd_selection_get_type ()) #define GTK_XLFD_SELECTION(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_XLFD_SELECTION, GtkXlfdSelection)) #define GTK_XLFD_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_XLFD_SELECTION, GtkXlfdSelectionClass)) #define GTK_IS_XLFD_SELECTION(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_XLFD_SELECTION)) #define GTK_IS_XLFD_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_XLFD_SELECTION)) #define GTK_TYPE_XLFD_SELECTION_DIALOG (gtk_xlfd_selection_dialog_get_type ()) #define GTK_XLFD_SELECTION_DIALOG(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_XLFD_SELECTION_DIALOG, GtkXlfdSelectionDialog)) #define GTK_XLFD_SELECTION_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_XLFD_SELECTION_DIALOG, GtkXlfdSelectionDialogClass)) #define GTK_IS_XLFD_SELECTION_DIALOG(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_XLFD_SELECTION_DIALOG)) #define GTK_IS_XLFD_SELECTION_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_XLFD_SELECTION_DIALOG)) typedef struct _GtkXlfdSelection GtkXlfdSelection; typedef struct _GtkXlfdSelectionClass GtkXlfdSelectionClass; typedef struct _GtkXlfdSelectionDialog GtkXlfdSelectionDialog; typedef struct _GtkXlfdSelectionDialogClass GtkXlfdSelectionDialogClass; /* This is the number of properties which we keep in the properties array, i.e. Weight, Slant, Set Width, Spacing, Charset & Foundry. */ #define GTK_NUM_FONT_PROPERTIES 6 /* This is the number of properties each style has i.e. Weight, Slant, Set Width, Spacing & Charset. Note that Foundry is not included, since it is the same for all styles of the same FontInfo. */ #define GTK_NUM_STYLE_PROPERTIES 5 /* Used to determine whether we are using point or pixel sizes. */ typedef enum { GTK_XLFD_METRIC_PIXELS, GTK_XLFD_METRIC_POINTS } GtkXlfdMetricType; /* Used for determining the type of a font style, and also for setting filters. These can be combined if a style has bitmaps and scalable fonts available.*/ typedef enum { GTK_XLFD_BITMAP = 1 << 0, GTK_XLFD_SCALABLE = 1 << 1, GTK_XLFD_SCALABLE_BITMAP = 1 << 2, GTK_XLFD_ALL = 0x07 } GtkXlfdType; /* These are the two types of filter available - base and user. The base filter is set by the application and can't be changed by the user. */ #define GTK_NUM_FONT_FILTERS 2 typedef enum { GTK_XLFD_FILTER_BASE, GTK_XLFD_FILTER_USER } GtkXlfdFilterType; /* These hold the arrays of current filter settings for each property. If nfilters is 0 then all values of the property are OK. If not the filters array contains the indexes of the valid property values. */ typedef struct _GtkXlfdFilter GtkXlfdFilter; struct _GtkXlfdFilter { gint font_type; guint16 *property_filters[GTK_NUM_FONT_PROPERTIES]; guint16 property_nfilters[GTK_NUM_FONT_PROPERTIES]; }; struct _GtkXlfdSelection { GtkNotebook notebook; /* These are on the font page. */ GtkWidget *main_vbox; GtkWidget *font_label; GtkWidget *font_entry; GtkWidget *font_clist; GtkWidget *font_style_entry; GtkWidget *font_style_clist; GtkWidget *size_entry; GtkWidget *size_clist; GtkWidget *pixels_button; GtkWidget *points_button; GtkWidget *filter_button; GtkWidget *preview_entry; GtkWidget *message_label; /* These are on the font info page. */ GtkWidget *info_vbox; GtkWidget *info_clist; GtkWidget *requested_font_name; GtkWidget *actual_font_name; /* These are on the filter page. */ GtkWidget *filter_vbox; GtkWidget *type_bitmaps_button; GtkWidget *type_scalable_button; GtkWidget *type_scaled_bitmaps_button; GtkWidget *filter_clists[GTK_NUM_FONT_PROPERTIES]; GdkFont *font; gint font_index; gint style; GtkXlfdMetricType metric; /* The size is either in pixels or deci-points, depending on the metric. */ gint size; /* This is the last size explicitly selected. When the user selects different fonts we try to find the nearest size to this. */ gint selected_size; /* These are the current property settings. They are indexes into the strings in the GtkXlfdSelInfo properties array. */ guint16 property_values[GTK_NUM_STYLE_PROPERTIES]; /* These are the base and user font filters. */ GtkXlfdFilter filters[GTK_NUM_FONT_FILTERS]; }; struct _GtkXlfdSelectionClass { GtkNotebookClass parent_class; }; struct _GtkXlfdSelectionDialog { GtkWindow window; GtkWidget *fontsel; GtkWidget *main_vbox; GtkWidget *action_area; GtkWidget *ok_button; /* The 'Apply' button is not shown by default but you can show/hide it. */ GtkWidget *apply_button; GtkWidget *cancel_button; /* If the user changes the width of the dialog, we turn auto-shrink off. */ gint dialog_width; gboolean auto_resize; }; struct _GtkXlfdSelectionDialogClass { GtkWindowClass parent_class; }; /***************************************************************************** * GtkXlfdSelection functions. * see the comments in the GtkXlfdSelectionDialog functions. *****************************************************************************/ GtkType gtk_xlfd_selection_get_type (void); GtkWidget *gtk_xlfd_selection_new (void); gchar* gtk_xlfd_selection_get_font_name (GtkXlfdSelection *fontsel); GdkFont* gtk_xlfd_selection_get_font (GtkXlfdSelection *fontsel); gboolean gtk_xlfd_selection_set_font_name (GtkXlfdSelection *fontsel, const gchar *fontname); void gtk_xlfd_selection_set_filter (GtkXlfdSelection *fontsel, GtkXlfdFilterType filter_type, GtkXlfdType font_type, gchar **foundries, gchar **weights, gchar **slants, gchar **setwidths, gchar **spacings, gchar **charsets); gchar* gtk_xlfd_selection_get_preview_text (GtkXlfdSelection *fontsel); void gtk_xlfd_selection_set_preview_text (GtkXlfdSelection *fontsel, const gchar *text); /***************************************************************************** * GtkXlfdSelectionDialog functions. * most of these functions simply call the corresponding function in the * GtkXlfdSelection. *****************************************************************************/ guint gtk_xlfd_selection_dialog_get_type (void); GtkWidget *gtk_xlfd_selection_dialog_new (const gchar *title); /* This returns the X Logical Font Description fontname, or NULL if no font is selected. Note that there is a slight possibility that the font might not have been loaded OK. You should call gtk_xlfd_selection_dialog_get_font() to see if it has been loaded OK. You should g_free() the returned font name after you're done with it. */ gchar* gtk_xlfd_selection_dialog_get_font_name (GtkXlfdSelectionDialog *fsd); /* This will return the current GdkFont, or NULL if none is selected or there was a problem loading it. Remember to use gdk_font_ref/unref() if you want to use the font (in a style, for example). */ GdkFont *gtk_xlfd_selection_dialog_get_font (GtkXlfdSelectionDialog *fsd); /* This sets the currently displayed font. It should be a valid X Logical Font Description font name (anything else will be ignored), e.g. "-adobe-courier-bold-o-normal--25-*-*-*-*-*-*-*" It returns TRUE on success. */ gboolean gtk_xlfd_selection_dialog_set_font_name (GtkXlfdSelectionDialog *fsd, const gchar *fontname); /* This sets one of the font filters, to limit the fonts shown. The filter_type is GTK_XLFD_FILTER_BASE or GTK_XLFD_FILTER_USER. The font type is a combination of the bit flags GTK_XLFD_BITMAP, GTK_XLFD_SCALABLE and GTK_XLFD_SCALABLE_BITMAP (or GTK_XLFD_ALL for all font types). The foundries, weights etc. are arrays of strings containing property values, e.g. 'bold', 'demibold', and *MUST* finish with a NULL. Standard long names are also accepted, e.g. 'italic' instead of 'i'. e.g. to allow only fixed-width fonts ('char cell' or 'monospaced') to be selected use: gchar *spacings[] = { "c", "m", NULL }; gtk_xlfd_selection_dialog_set_filter (GTK_XLFD_SELECTION_DIALOG (fontsel), GTK_XLFD_FILTER_BASE, GTK_XLFD_ALL, NULL, NULL, NULL, NULL, spacings, NULL); to allow only true scalable fonts to be selected use: gtk_xlfd_selection_dialog_set_filter (GTK_XLFD_SELECTION_DIALOG (fontsel), GTK_XLFD_FILTER_BASE, GTK_XLFD_SCALABLE, NULL, NULL, NULL, NULL, NULL, NULL); */ void gtk_xlfd_selection_dialog_set_filter (GtkXlfdSelectionDialog *fsd, GtkXlfdFilterType filter_type, GtkXlfdType font_type, gchar **foundries, gchar **weights, gchar **slants, gchar **setwidths, gchar **spacings, gchar **charsets); /* This returns the text in the preview entry. You should copy the returned text if you need it. */ gchar* gtk_xlfd_selection_dialog_get_preview_text (GtkXlfdSelectionDialog *fsd); /* This sets the text in the preview entry. It will be copied by the entry, so there's no need to g_strdup() it first. */ void gtk_xlfd_selection_dialog_set_preview_text (GtkXlfdSelectionDialog *fsd, const gchar *text); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __GTK_XLFDSEL_H__ */ mlterm-3.8.9/tool/mlconfig/main.c010064400017600000144000000602561356600660700154160ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include /* sprintf */ #include #include #include #include #include #include #include "mc_char_encoding.h" #include "mc_auto_detect.h" #include "mc_ctl.h" #include "mc_color.h" #include "mc_bgtype.h" #include "mc_alpha.h" #include "mc_tabsize.h" #include "mc_logsize.h" #include "mc_wordsep.h" #include "mc_font.h" #include "mc_space.h" #include "mc_im.h" #include "mc_sb_view.h" #include "mc_io.h" #include "mc_pty.h" #include "mc_flags.h" #include "mc_ratio.h" #include "mc_radio.h" #include "mc_char_width.h" #include "mc_geometry.h" #include "mc_click.h" #include "mc_opentype.h" #if 0 #define __DEBUG #endif /* --- static functions --- */ #ifdef DEBUG static void check_mem_leak(void) { bl_mem_free_all(); } #endif static void end_application(GtkWidget *widget, gpointer data) { gtk_main_quit(); } /* * ******** procedures when buttons are clicked ******** */ static int update(mc_io_t io) { const char *gui = mc_get_gui(); mc_update_char_encoding(); mc_update_auto_detect(); mc_update_color(MC_COLOR_FG); if (mc_is_color_bg()) { mc_update_bgtype(); mc_update_alpha(); } else { /* * alpha must be updated before bgtype because transparent or wall picture * bgtype could change alpha from 255 to 0. */ mc_update_alpha(); mc_update_bgtype(); } mc_update_tabsize(); mc_update_logsize(); mc_update_wordsep(); mc_update_geometry(); mc_update_font_misc(); mc_update_space(MC_SPACE_LINE); mc_update_space(MC_SPACE_LETTER); mc_update_space(MC_SPACE_UNDERLINE); mc_update_space(MC_SPACE_BASELINE); mc_update_ratio(MC_RATIO_SCREEN_WIDTH); mc_update_radio(MC_RADIO_MOD_META_MODE); mc_update_radio(MC_RADIO_BELL_MODE); mc_update_radio(MC_RADIO_LOG_VTSEQ); mc_update_ratio(MC_RATIO_BRIGHTNESS); mc_update_ratio(MC_RATIO_CONTRAST); mc_update_ratio(MC_RATIO_GAMMA); mc_update_ratio(MC_RATIO_FADE); mc_update_im(); mc_update_cursor_color(); mc_update_substitute_color(); mc_update_ctl(); mc_update_char_width(); mc_update_click_interval(); mc_update_opentype(); mc_update_flag_mode(MC_FLAG_COMB); mc_update_flag_mode(MC_FLAG_DYNCOMB); mc_update_flag_mode(MC_FLAG_RECVUCS); if (strcmp(gui, "xlib") == 0) { mc_update_flag_mode(MC_FLAG_CLIPBOARD); } mc_update_flag_mode(MC_FLAG_LOCALECHO); mc_update_flag_mode(MC_FLAG_BLINKCURSOR); mc_update_flag_mode(MC_FLAG_STATICBACKSCROLL); mc_update_flag_mode(MC_FLAG_EXTSCROLLSHORTCUT); mc_update_flag_mode(MC_FLAG_REGARDURIASWORD); mc_update_flag_mode(MC_FLAG_OTLAYOUT); mc_update_radio(MC_RADIO_SB_MODE); if (strcmp(gui, "quartz") != 0) { mc_update_color(MC_COLOR_SBFG); mc_update_color(MC_COLOR_SBBG); mc_update_sb_view_name(); } mc_flush(io); if (io == mc_io_set) { mc_update_font_name(mc_io_set_font); mc_update_vtcolor(mc_io_set_color); } else if (io == mc_io_set_save) { mc_update_font_name(mc_io_set_save_font); mc_update_vtcolor(mc_io_set_save_color); } return 1; } static gint cancel_clicked(GtkWidget *widget, gpointer data) { gtk_main_quit(); return FALSE; } static gint apply_clicked(GtkWidget *widget, gpointer data) { update(mc_io_set); return 1; } static gint saveexit_clicked(GtkWidget *widget, gpointer data) { update(mc_io_set_save); gtk_main_quit(); return 1; } static gint applyexit_clicked(GtkWidget *widget, gpointer data) { update(mc_io_set); gtk_main_quit(); return 1; } static gint larger_clicked(GtkWidget *widget, gpointer data) { mc_set_str_value("fontsize", "larger"); mc_flush(mc_io_set); return 1; } static gint smaller_clicked(GtkWidget *widget, gpointer data) { mc_set_str_value("fontsize", "smaller"); mc_flush(mc_io_set); return 1; } static gint full_reset_clicked(GtkWidget *widget, gpointer data) { mc_exec("full_reset"); return 1; } static gint snapshot_clicked(GtkWidget *widget, gpointer data) { mc_exec("snapshot"); return 1; } #ifdef USE_LIBSSH2 #define MY_RESPONSE_RETURN 1 #define MY_RESPONSE_EXIT 2 #define MY_RESPONSE_SEND 3 #define MY_RESPONSE_RECV 4 static void drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint time) { gchar **uris; gchar *filename; #if GTK_CHECK_VERSION(2, 14, 0) uris = g_uri_list_extract_uris(gtk_selection_data_get_data(data)); #else uris = g_uri_list_extract_uris(data->data); #endif filename = g_filename_from_uri(uris[0], NULL, NULL); gtk_entry_set_text(GTK_ENTRY(widget), filename); g_free(filename); g_strfreev(uris); } static gint ssh_scp_clicked(GtkWidget *widget, gpointer data) { GtkWidget *dialog; GtkWidget *content_area; GtkWidget *hbox; GtkWidget *label; GtkWidget *local_entry; GtkWidget *remote_entry; gint res; GtkTargetEntry local_targets[] = { {"text/uri-list", 0, 0}, }; gtk_widget_hide(gtk_widget_get_toplevel(widget)); dialog = gtk_dialog_new(); gtk_window_set_title(GTK_WINDOW(dialog), "mlconfig"); gtk_dialog_add_button(GTK_DIALOG(dialog), _("Send"), MY_RESPONSE_SEND); gtk_dialog_add_button(GTK_DIALOG(dialog), _("Recv"), MY_RESPONSE_RECV); gtk_dialog_add_button(GTK_DIALOG(dialog), _("Return"), MY_RESPONSE_RETURN); gtk_dialog_add_button(GTK_DIALOG(dialog), _("Exit"), MY_RESPONSE_EXIT); #if GTK_CHECK_VERSION(2, 14, 0) content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); #else content_area = GTK_DIALOG(dialog)->vbox; #endif hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); label = gtk_label_new(_("Local")); gtk_widget_show(label); gtk_widget_set_size_request(label, 70, -1); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 1); local_entry = gtk_entry_new(); gtk_widget_show(local_entry); gtk_widget_set_size_request(local_entry, 280, -1); gtk_drag_dest_set(local_entry, GTK_DEST_DEFAULT_ALL, local_targets, 1, GDK_ACTION_COPY); g_signal_connect(local_entry, "drag-data-received", G_CALLBACK(drag_data_received), NULL); gtk_box_pack_start(GTK_BOX(hbox), local_entry, FALSE, FALSE, 1); gtk_container_add(GTK_CONTAINER(content_area), hbox); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); label = gtk_label_new(_("Remote")); gtk_widget_show(label); gtk_widget_set_size_request(label, 70, -1); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 1); remote_entry = gtk_entry_new(); gtk_widget_show(remote_entry); gtk_widget_set_size_request(remote_entry, 280, -1); gtk_box_pack_start(GTK_BOX(hbox), remote_entry, FALSE, FALSE, 1); gtk_container_add(GTK_CONTAINER(content_area), hbox); while ((res = gtk_dialog_run(GTK_DIALOG(dialog))) >= MY_RESPONSE_SEND) { char *cmd; const gchar *local_path; const gchar *remote_path; local_path = gtk_entry_get_text(GTK_ENTRY(local_entry)); remote_path = gtk_entry_get_text(GTK_ENTRY(remote_entry)); if ((cmd = alloca(28 + strlen(local_path) + strlen(remote_path)))) { char *p; if (res == MY_RESPONSE_SEND) { if (!*local_path) { bl_msg_printf( "Local file path to send " "is not specified.\n"); continue; } sprintf(cmd, "scp \"local:%s\" \"remote:%s\" UTF8", local_path, remote_path); } else /* if( res == MY_RESPONSE_RECV) */ { if (!*remote_path) { bl_msg_printf( "Remote file path to receive " "is not specified.\n"); continue; } sprintf(cmd, "scp \"remote:%s\" \"local:%s\" UTF8", remote_path, local_path); } p = cmd + strlen(cmd) - 2; if (*p == '\\') { /* * Avoid to be parsed as follows. * "local:c:\foo\bar\" => local:c:\foo\bar" */ *(p++) = '\"'; *p = '\0'; } mc_exec(cmd); } } if (res == MY_RESPONSE_EXIT) { gtk_main_quit(); return FALSE; } else /* if (res == MY_RESPONSE_RETURN) */ { gtk_widget_destroy(dialog); gtk_widget_show_all(gtk_widget_get_toplevel(widget)); return TRUE; } } #endif /* USE_LIBSSH2 */ static gint pty_new_button_clicked(GtkWidget *widget, gpointer data) { mc_exec("open_pty"); mc_flush(mc_io_set); gtk_main_quit(); return 1; } static gint pty_button_clicked(GtkWidget *widget, gpointer data) { mc_select_pty(); /* * As soon as pty changed, stdout is also changed, but mlconfig couldn't * follow it. */ gtk_main_quit(); return 1; } static gboolean event(GtkWidget *widget, GdkEvent *event, gpointer data) { if (event->type == GDK_FOCUS_CHANGE && !((GdkEventFocus*)event)->in) { gtk_window_set_keep_above(GTK_WINDOW(widget), FALSE); g_signal_handlers_disconnect_by_func(widget, event, NULL); } return FALSE; } /* * ******** Building GUI (lower part, independent buttons) ******** */ static void addbutton(const char *label, gint(func)(GtkWidget*, gpointer), GtkWidget *box) { GtkWidget *button; button = gtk_button_new_with_label(label); g_signal_connect(button, "clicked", G_CALLBACK(func), NULL); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0); } static GtkWidget *apply_cancel_button(void) { GtkWidget *hbox; hbox = gtk_hbox_new(FALSE, 5); gtk_widget_show(hbox); addbutton(_("Save&Exit"), saveexit_clicked, hbox); addbutton(_("Apply&Exit"), applyexit_clicked, hbox); addbutton(_("Apply"), apply_clicked, hbox); addbutton(_("Cancel"), cancel_clicked, hbox); return hbox; } static GtkWidget *font_large_small(void) { GtkWidget *frame; GtkWidget *hbox; frame = gtk_frame_new(_("Font size (temporary)")); gtk_widget_show(frame); hbox = gtk_hbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); gtk_widget_show(hbox); gtk_container_add(GTK_CONTAINER(frame), hbox); addbutton(_("Larger"), larger_clicked, hbox); addbutton(_("Smaller"), smaller_clicked, hbox); #if GTK_CHECK_VERSION(2, 12, 0) gtk_widget_set_tooltip_text(frame, "If you change fonts from \"Select\" button in \"Font\" tab, " "it is not recommended to change font size here."); #endif return frame; } static GtkWidget *command(void) { GtkWidget *frame; GtkWidget *hbox; frame = gtk_frame_new(_("Command")); gtk_widget_show(frame); hbox = gtk_hbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); gtk_widget_show(hbox); gtk_container_add(GTK_CONTAINER(frame), hbox); addbutton(_("Full reset"), full_reset_clicked, hbox); addbutton(_("Snapshot"), snapshot_clicked, hbox); #ifdef USE_LIBSSH2 addbutton(_("SCP"), ssh_scp_clicked, hbox); #endif return frame; } static GtkWidget *pty_list(void) { GtkWidget *frame; GtkWidget *hbox; GtkWidget *config_widget; if ((config_widget = mc_pty_config_widget_new()) == NULL) { return NULL; } gtk_widget_show(config_widget); frame = gtk_frame_new(_("PTY List")); gtk_widget_show(frame); hbox = gtk_hbox_new(FALSE, 5); gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); gtk_widget_show(hbox); gtk_container_add(GTK_CONTAINER(frame), hbox); addbutton(_(" New "), pty_new_button_clicked, hbox); addbutton(_("Select"), pty_button_clicked, hbox); gtk_box_pack_start(GTK_BOX(hbox), config_widget, TRUE, TRUE, 0); return frame; } /* * ******** Building GUI (main part, page (tab)-separated widgets) ******** */ static int show(void) { GtkWidget *window; GtkWidget *vbox; GtkWidget *vbox2; GtkWidget *hbox; GtkWidget *notebook; GtkWidget *frame; GtkWidget *label; GtkWidget *config_widget; GtkWidget *separator; const char *gui = mc_get_gui(); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(window, "destroy", G_CALLBACK(end_application), NULL); gtk_window_set_title(GTK_WINDOW(window), _("mlterm configuration")); gtk_container_set_border_width(GTK_CONTAINER(window), 0); vbox = gtk_vbox_new(FALSE, 10); gtk_widget_show(vbox); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_container_add(GTK_CONTAINER(window), vbox); /* whole screen (except for the contents of notebook) */ notebook = gtk_notebook_new(); gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP); gtk_widget_show(notebook); gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); separator = gtk_hseparator_new(); gtk_widget_show(separator); gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, FALSE, 0); hbox = apply_cancel_button(); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); frame = font_large_small(); gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5); frame = command(); gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 5); frame = pty_list(); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); /* contents of the "Encoding" tab */ label = gtk_label_new(_("Encoding")); gtk_widget_show(label); vbox = gtk_vbox_new(FALSE, 3); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label); gtk_widget_show(vbox); config_widget = mc_char_encoding_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_auto_detect_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_im_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_ctl_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); config_widget = mc_flag_config_widget_new(MC_FLAG_COMB); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_flag_config_widget_new(MC_FLAG_DYNCOMB); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_flag_config_widget_new(MC_FLAG_RECVUCS); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_opentype_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_char_width_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); /* contents of the "Font" tab */ label = gtk_label_new(_("Font")); gtk_widget_show(label); vbox = gtk_vbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label); gtk_widget_show(vbox); config_widget = mc_font_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); config_widget = mc_space_config_widget_new(MC_SPACE_LINE); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_space_config_widget_new(MC_SPACE_LETTER); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_space_config_widget_new(MC_SPACE_UNDERLINE); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_space_config_widget_new(MC_SPACE_BASELINE); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_ratio_config_widget_new(MC_RATIO_SCREEN_WIDTH); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); /* contents of the "Background" tab */ label = gtk_label_new(_("Background")); gtk_widget_show(label); vbox = gtk_vbox_new(FALSE, 3); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label); gtk_widget_show(vbox); config_widget = mc_bgtype_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); frame = gtk_frame_new(_("Picture/Transparent")); gtk_widget_show(frame); gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0); vbox2 = gtk_vbox_new(FALSE, 3); gtk_widget_show(vbox2); gtk_container_add(GTK_CONTAINER(frame), vbox2); hbox = gtk_hbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0); config_widget = mc_ratio_config_widget_new(MC_RATIO_BRIGHTNESS); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_ratio_config_widget_new(MC_RATIO_GAMMA); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_container_set_border_width(GTK_CONTAINER(hbox), 2); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, FALSE, 0); config_widget = mc_ratio_config_widget_new(MC_RATIO_CONTRAST); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_alpha_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_ratio_config_widget_new(MC_RATIO_FADE); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); /* contents of the "Color" tab */ label = gtk_label_new(_("Color")); gtk_widget_show(label); vbox = gtk_vbox_new(FALSE, 3); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label); gtk_widget_show(vbox); config_widget = mc_cursor_color_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_substitute_color_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_vtcolor_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); /* contents of the "Scrollbar" tab */ label = gtk_label_new(_("Scrollbar")); gtk_widget_show(label); vbox = gtk_vbox_new(FALSE, 3); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label); gtk_widget_show(vbox); config_widget = mc_radio_config_widget_new(MC_RADIO_SB_MODE); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); if (strcmp(gui, "quartz") != 0) { config_widget = mc_sb_view_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); config_widget = mc_color_config_widget_new(MC_COLOR_SBFG); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 5); config_widget = mc_color_config_widget_new(MC_COLOR_SBBG); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); } /* contents of the "Others" tab */ label = gtk_label_new(_("Others")); gtk_widget_show(label); vbox = gtk_vbox_new(FALSE, 3); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label); gtk_widget_show(vbox); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); config_widget = mc_tabsize_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_logsize_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); config_widget = mc_geometry_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_wordsep_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_click_interval_config_widget_new(); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_radio_config_widget_new(MC_RADIO_MOD_META_MODE); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_radio_config_widget_new(MC_RADIO_BELL_MODE); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_radio_config_widget_new(MC_RADIO_LOG_VTSEQ); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); if (strcmp(gui, "xlib") == 0) { config_widget = mc_flag_config_widget_new(MC_FLAG_CLIPBOARD); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); } config_widget = mc_flag_config_widget_new(MC_FLAG_LOCALECHO); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_flag_config_widget_new(MC_FLAG_BLINKCURSOR); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_flag_config_widget_new(MC_FLAG_STATICBACKSCROLL); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); config_widget = mc_flag_config_widget_new(MC_FLAG_EXTSCROLLSHORTCUT); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); config_widget = mc_flag_config_widget_new(MC_FLAG_REGARDURIASWORD); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_flag_config_widget_new(MC_FLAG_BROADCAST); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(hbox), config_widget, FALSE, FALSE, 0); config_widget = mc_flag_config_widget_new(MC_FLAG_TRIMNEWLINE); gtk_widget_show(config_widget); gtk_box_pack_start(GTK_BOX(vbox), config_widget, FALSE, FALSE, 0); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_MOUSE); #if !GTK_CHECK_VERSION(2, 90, 0) gtk_window_set_policy(GTK_WINDOW(window), 0, 0, 0); #endif gtk_widget_show(window); if (strcmp(gui, "win32") == 0 || strcmp(gui, "quartz") == 0) { gtk_window_set_keep_above(GTK_WINDOW(window), TRUE); g_signal_connect(window, "event", G_CALLBACK(event), NULL); } gtk_main(); return 1; } /* --- global functions --- */ int main(int argc, char **argv) { #ifdef DEBUG atexit(check_mem_leak); #endif /* * Loading libim-*.so after gtk im module is loaded might break internal states * in gtk or input method library. */ mc_im_init(); #if !GTK_CHECK_VERSION(2, 90, 0) gtk_set_locale(); #endif bindtextdomain("mlconfig", LOCALEDIR); bind_textdomain_codeset("mlconfig", "UTF-8"); textdomain("mlconfig"); #ifdef __DEBUG { int count; for (count = 0; count < argc; count++) { fprintf(stderr, "%s\n", argv[count]); } } #endif bl_set_msg_log_file_name("mlterm/msg.log"); gtk_init(&argc, &argv); if (show() == 0) { bl_msg_printf("Starting mlconfig failed.\n"); return 1; } else { return 0; } } mlterm-3.8.9/tool/mlconfig/mc_alpha.c010064400017600000144000000026501356600660700162300ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_alpha.h" #include #include /* free */ #include #include #include #include "mc_combo.h" #include "mc_io.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static char *new_alpha = NULL; static char *old_alpha = NULL; static int is_changed; /* --- static functions --- */ static gint alpha_selected(GtkWidget *widget, gpointer data) { g_free(new_alpha); new_alpha = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s alpha is selected.\n", new_alpha); #endif return 1; } /* --- global functions --- */ GtkWidget *mc_alpha_config_widget_new(void) { GtkWidget *combo; GtkWidget *entry; char *alphas[] = { "255", "223", "191", "159", "127", "95", "63", "31", "0", }; new_alpha = strdup(old_alpha = mc_get_str_value("alpha")); is_changed = 0; combo = mc_combo_new_with_width(_("Alpha"), alphas, sizeof(alphas) / sizeof(alphas[0]), new_alpha, 0, 50, &entry); g_signal_connect(entry, "changed", G_CALLBACK(alpha_selected), NULL); return combo; } void mc_update_alpha(void) { if (strcmp(new_alpha, old_alpha)) { is_changed = 1; } if (is_changed) { mc_set_str_value("alpha", new_alpha); free(old_alpha); old_alpha = strdup(new_alpha); } } mlterm-3.8.9/tool/mlconfig/mc_alpha.h010064400017600000144000000003321356600660700162300ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_ALPHA_H__ #define __MC_ALPHA_H__ #include GtkWidget *mc_alpha_config_widget_new(void); void mc_update_alpha(void); #endif mlterm-3.8.9/tool/mlconfig/mc_auto_detect.c010064400017600000144000000047041356600660700174450ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_auto_detect.h" #include #include #include /* free */ #include #include #include #include #include "mc_io.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static int new_flag; static int old_flag; static GtkWidget *entry; static char *old_encodings; static int is_changed; /* --- static functions --- */ static char *get_default_encodings(void) { #if 0 if ((bl_compare_str(bl_get_lang(), "ja")) == 0) #endif { return strdup("UTF-8,EUC-JP,SJIS"); } } static gint checked(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { if (*old_encodings == '\0') { if ((old_encodings = get_default_encodings())) { gtk_entry_set_text(GTK_ENTRY(entry), old_encodings); } } gtk_widget_set_sensitive(entry, TRUE); new_flag = 1; } else { gtk_widget_set_sensitive(entry, FALSE); new_flag = 0; } return 1; } /* -- global functions --- */ GtkWidget *mc_auto_detect_config_widget_new(void) { GtkWidget *hbox; GtkWidget *check; GtkWidget *label; hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); old_flag = mc_get_flag_value("use_auto_detect"); check = gtk_check_button_new_with_label(_("Auto detect")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), old_flag); gtk_widget_show(check); gtk_box_pack_start(GTK_BOX(hbox), check, FALSE, FALSE, 0); label = gtk_label_new(_("Encoding list")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); entry = gtk_entry_new(); old_encodings = mc_get_str_value("auto_detect_encodings"); gtk_entry_set_text(GTK_ENTRY(entry), old_encodings); gtk_widget_show(entry); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 1); if (!old_flag) gtk_widget_set_sensitive(entry, 0); g_signal_connect(check, "toggled", G_CALLBACK(checked), NULL); return hbox; } void mc_update_auto_detect(void) { char *new_encodings; new_encodings = strdup(gtk_entry_get_text(GTK_ENTRY(entry))); if (old_flag != new_flag || bl_compare_str(new_encodings, old_encodings) != 0) { is_changed = 1; } if (is_changed) { mc_set_flag_value("use_auto_detect", new_flag); mc_set_str_value("auto_detect_encodings", new_encodings); free(old_encodings); old_encodings = new_encodings; } } mlterm-3.8.9/tool/mlconfig/mc_auto_detect.h010064400017600000144000000003621356600660700174460ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_AUTO_DETECT_H__ #define __MC_AUTO_DETECT_H__ #include GtkWidget *mc_auto_detect_config_widget_new(void); void mc_update_auto_detect(void); #endif mlterm-3.8.9/tool/mlconfig/mc_bgtype.c010064400017600000144000000115531356600660700164370ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_bgtype.h" #include #include #include "mc_color.h" #include "mc_wall_pic.h" #include "mc_io.h" #if 0 #define __DEBUG #endif #define MC_BG_TRANSPARENT 0 #define MC_BG_WALLPICTURE 1 #define MC_BG_COLOR 2 /* --- static variables --- */ static int bgtype; static int is_changed; static GtkWidget *bg_color; static GtkWidget *wall_picture; /* --- static functions --- */ static int get_bgtype(void) { char *val; if (mc_get_flag_value("use_transbg")) return MC_BG_TRANSPARENT; else if ((val = mc_get_str_value("wall_picture")) && *val != '\0') return MC_BG_WALLPICTURE; else return MC_BG_COLOR; } static void set_sensitive(void) { if (bgtype == MC_BG_COLOR) { gtk_widget_set_sensitive(bg_color, 1); gtk_widget_set_sensitive(wall_picture, 0); } else if (bgtype == MC_BG_WALLPICTURE) { gtk_widget_set_sensitive(bg_color, 0); gtk_widget_set_sensitive(wall_picture, 1); } else { gtk_widget_set_sensitive(bg_color, 0); gtk_widget_set_sensitive(wall_picture, 0); } } static gint button_color_checked(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { bgtype = MC_BG_COLOR; is_changed = 1; set_sensitive(); } return 1; } static gint button_transparent_checked(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { bgtype = MC_BG_TRANSPARENT; is_changed = 1; set_sensitive(); } return 1; } static gint button_picture_checked(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { bgtype = MC_BG_WALLPICTURE; is_changed = 1; set_sensitive(); } return 1; } /* --- global functions --- */ GtkWidget *mc_bgtype_config_widget_new(void) { GtkWidget *frame; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *radio; GSList *group; bgtype = get_bgtype(); bg_color = mc_color_config_widget_new(MC_COLOR_BG); gtk_widget_show(bg_color); wall_picture = mc_wall_pic_config_widget_new(); gtk_widget_show(wall_picture); group = NULL; frame = gtk_frame_new(_("Background type")); vbox = gtk_vbox_new(TRUE, 2); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_container_add(GTK_CONTAINER(frame), vbox); gtk_widget_show(vbox); /* color button */ radio = gtk_radio_button_new_with_label(group, _("Color")); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); g_signal_connect(radio, "toggled", G_CALLBACK(button_color_checked), NULL); gtk_widget_show(GTK_WIDGET(radio)); if (bgtype == MC_BG_COLOR) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); hbox = gtk_hbox_new(FALSE, 2); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), bg_color, TRUE, TRUE, 0); /* picture button */ radio = gtk_radio_button_new_with_label(group, _("Picture")); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); g_signal_connect(radio, "toggled", G_CALLBACK(button_picture_checked), NULL); gtk_widget_show(GTK_WIDGET(radio)); if (bgtype == MC_BG_WALLPICTURE) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); hbox = gtk_hbox_new(FALSE, 2); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), wall_picture, TRUE, TRUE, 0); /* transparent button */ radio = gtk_radio_button_new_with_label(group, _("Pseudo transparent")); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); g_signal_connect(radio, "toggled", G_CALLBACK(button_transparent_checked), NULL); gtk_widget_show(GTK_WIDGET(radio)); if (bgtype == MC_BG_TRANSPARENT) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); #if GTK_CHECK_VERSION(2, 12, 0) gtk_widget_set_tooltip_text(radio, "If you want true translucence, toggle this " "button off and start mlterm with depth=32."); #endif hbox = gtk_hbox_new(FALSE, 2); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, FALSE, 0); set_sensitive(); return frame; } void mc_update_bgtype(void) { if (bgtype == MC_BG_COLOR) { if (is_changed) { mc_set_flag_value("use_transbg", 0); mc_wall_pic_none(); } mc_update_color(MC_COLOR_BG); } else if (bgtype == MC_BG_WALLPICTURE) { if (is_changed) { mc_set_flag_value("use_transbg", 0); } mc_update_wall_pic(); } else if (bgtype == MC_BG_TRANSPARENT) { if (is_changed) { mc_set_flag_value("use_transbg", 1); mc_wall_pic_none(); } } } int mc_is_color_bg(void) { return bgtype == MC_BG_COLOR; } mlterm-3.8.9/tool/mlconfig/mc_bgtype.h010064400017600000144000000003711356600660700164400ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_BGTYPE_H__ #define __MC_BGTYPE_H__ #include GtkWidget *mc_bgtype_config_widget_new(void); void mc_update_bgtype(void); int mc_is_color_bg(void); #endif mlterm-3.8.9/tool/mlconfig/mc_char_encoding.c010064400017600000144000000120171356600660700177240ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_char_encoding.h" #include #include #include /* free */ #include #include #include #include #include "mc_combo.h" #include "mc_io.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static int new_encoding_idx; /* remember encoding as index in encodings[] */ static int old_encoding_idx; static int is_changed; static char *encodings[] = { N_("auto"), N_("--- Unicode ---"), "UTF-8", N_("--- ISO 8859 encodings ---"), "ISO-8859-1 (Latin-1)", "ISO-8859-2 (Latin-2)", "ISO-8859-3 (Latin-3)", "ISO-8859-4 (Latin-4)", "ISO-8859-5 (Latin/Cyrillic)", "ISO-8859-6 (Latin/Arabic)", "ISO-8859-7 (Latin/Greek)", "ISO-8859-8 (Latin/Hebrew)", "ISO-8859-9 (Latin-5)", "ISO-8859-10 (Latin-6)", "ISO-8859-11 (TIS-620 Thai)", "ISO-8859-13 (Latin-7)", "ISO-8859-14 (Latin-8)", "ISO-8859-15 (Latin-9)", "ISO-8859-16 (Latin-10)", N_("--- Other 8bit ---"), "KOI8-R (Russian)", "KOI8-U (Ukrainian)", "KOI8-T (Tajik)", "GEORGIAN-PS (Georgian)", "TCVN5712 (Vietnamese)", "VISCII (Vietnamese)", "CP1250 (EastEurope)", "CP1251 (Bulgarian,Belarusian)", "CP1252 (Latin-1)", "CP1253 (Greek)", "CP1254 (Turkish)", "CP1255 (Hebrew)", "CP1256 (Arabic)", "CP1257 (Baltic)", "CP1258 (Vietnamese)", "ISCII-ASSAMESE (Indics)", "ISCII-BENGALI (Indics)", "ISCII-GUJARATI (Indics)", "ISCII-HINDI (Indics)", "ISCII-KANNAdA (Indics)", "ISCII-MALAYALAM (Indics)", "ISCII-ORIYA (Indics)", "ISCII-PUNJABI (Indics)", "ISCII-TELUGU (Indics)", N_("--- Japanese ---"), "EUC-JP", "EUC-JISX0213", "ISO-2022-JP", "ISO-2022-JP2", "ISO-2022-JP3", "SJIS", "SJISX0213", N_("--- Korean ---"), "EUC-KR", "UHC", "JOHAB", "ISO-2022-KR", N_("--- traditional Chinese ---"), "BIG-5", "EUC-TW", "BIG5HKSCS", N_("--- simplified Chinese ---"), "EUC-CN (GB2312)", "GBK", "GB18030", "HZ", "ISO-2022-CN", NULL}; static char *encodings_l10n[sizeof(encodings) / sizeof(encodings[0])]; /* --- static functions --- */ /* translate combobox items (encodings) * - the top item ("auto") and * - items which start with "-" (explanations) */ static void prepare_encodings_l10n(void) { int j; encodings_l10n[0] = strdup(_(encodings[0])); for (j = 1; encodings[j]; j++) { if (encodings[j][0] == '-') { encodings_l10n[j] = strdup(_(encodings[j])); if (encodings_l10n[j][0] != '-') { free(encodings_l10n[j]); encodings_l10n[j] = encodings[j]; } } else { encodings_l10n[j] = encodings[j]; } } encodings_l10n[j] = NULL; } /* compare two encoding names, returns non-zero if equal */ static int compare(const char *e1, const char *e2) { while (1) { if (*e1 == '_' || *e1 == '-') { e1++; continue; } if (*e2 == '_' || *e2 == '-') { e2++; continue; } if ((*e1 == 0 || *e1 == ' ') && (*e2 == 0 || *e2 == ' ')) return 1; if (toupper(*e1) != toupper(*e2)) return 0; e1++; e2++; } } static int get_index(const char *encoding) { int j; for (j = 0; encodings[j]; j++) if (compare(encodings[j], encoding)) return j; /* Returns "auto" for unknown encoding names. * Also, there is a possibility of translated "auto". */ return 0; } static char *savename(int index) { static char buf[256]; char *p; if (index == -1) return "UNKNOWN"; strncpy(buf, encodings[index], 255); buf[255] = 0; p = strchr(buf, ' '); if (p) *p = 0; return buf; } static gint encoding_selected(GtkWidget *widget, gpointer data) { const char *p; p = gtk_entry_get_text(GTK_ENTRY(widget)); if (*p == '-') return 1; new_encoding_idx = get_index(p); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s encoding is selected.\n", new_encoding); #endif return 1; } /* -- global functions --- */ GtkWidget *mc_char_encoding_config_widget_new(void) { int isauto, idx; char *encoding; GtkWidget *widget; GtkWidget *entry; isauto = mc_get_flag_value("is_auto_encoding"); encoding = mc_get_str_value("encoding"); if (isauto) { static char autostr[256]; idx = 0; sprintf(autostr, _("auto (currently %s)"), savename(get_index(encoding))); encodings[0] = autostr; } else idx = get_index(encoding); prepare_encodings_l10n(); widget = mc_combo_new(_("Encoding"), encodings_l10n, sizeof(encodings) / sizeof(encodings[0]) - 1, encodings_l10n[idx], 1, &entry); g_signal_connect(entry, "changed", G_CALLBACK(encoding_selected), NULL); new_encoding_idx = old_encoding_idx = idx; is_changed = 0; return widget; } void mc_update_char_encoding(void) { if (new_encoding_idx != old_encoding_idx) is_changed = 1; if (is_changed) { mc_set_str_value("encoding", savename(new_encoding_idx)); old_encoding_idx = new_encoding_idx; } } char *mc_get_char_encoding(void) { if (strncmp(encodings[new_encoding_idx], "auto", 4) == 0) { return encodings[new_encoding_idx] + 16; } else { return encodings[new_encoding_idx]; } } mlterm-3.8.9/tool/mlconfig/mc_char_encoding.h010064400017600000144000000004351356600660700177320ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_CHAR_ENCODING_H__ #define __MC_CHAR_ENCODING_H__ #include GtkWidget *mc_char_encoding_config_widget_new(void); void mc_update_char_encoding(void); char *mc_get_char_encoding(void); #endif mlterm-3.8.9/tool/mlconfig/mc_char_width.c010064400017600000144000000052711356600660700172610ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_char_width.h" #include #include /* free */ #include #include #include #include "mc_unicode_areas.h" #include "mc_flags.h" #include "mc_io.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static char *full_width_areas; static char *half_width_areas; /* --- static functions --- */ static void edit_full_width_areas(GtkWidget *widget, gpointer data) { char *cur_areas; char *new_areas; if (full_width_areas) { cur_areas = strdup(full_width_areas); } else { cur_areas = mc_get_str_value("unicode_full_width_areas"); } if ((new_areas = mc_get_unicode_areas(cur_areas)) && bl_compare_str(full_width_areas, new_areas) != 0) { free(full_width_areas); full_width_areas = new_areas; } free(cur_areas); } static void edit_half_width_areas(GtkWidget *widget, gpointer data) { char *cur_areas; char *new_areas; if (half_width_areas) { cur_areas = strdup(half_width_areas); } else { cur_areas = mc_get_str_value("unicode_half_width_areas"); } if ((new_areas = mc_get_unicode_areas(cur_areas)) && bl_compare_str(half_width_areas, new_areas) != 0) { free(half_width_areas); half_width_areas = new_areas; } free(cur_areas); } /* --- global functions --- */ GtkWidget *mc_char_width_config_widget_new(void) { GtkWidget *hbox; GtkWidget *vbox; GtkWidget *widget; vbox = gtk_vbox_new(FALSE, 0); widget = mc_flag_config_widget_new(MC_FLAG_AWIDTH); gtk_widget_show(widget); gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0); widget = mc_flag_config_widget_new(MC_FLAG_MCOL); gtk_widget_show(widget); gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); widget = gtk_button_new_with_label(_("Add full width areas")); gtk_widget_show(widget); gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 4); g_signal_connect(widget, "clicked", G_CALLBACK(edit_full_width_areas), NULL); widget = gtk_button_new_with_label(_("Add half width areas")); gtk_widget_show(widget); gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 4); g_signal_connect(widget, "clicked", G_CALLBACK(edit_half_width_areas), NULL); return vbox; } void mc_update_char_width(void) { mc_update_flag_mode(MC_FLAG_MCOL); mc_update_flag_mode(MC_FLAG_AWIDTH); if (full_width_areas) { mc_set_str_value("unicode_full_width_areas", full_width_areas); } if (half_width_areas) { mc_set_str_value("unicode_half_width_areas", half_width_areas); } } mlterm-3.8.9/tool/mlconfig/mc_char_width.h010064400017600000144000000003561356600660700172650ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_CHAR_WIDTH_H__ #define __MC_CHAR_WIDTH_H__ #include GtkWidget *mc_char_width_config_widget_new(void); void mc_update_char_width(void); #endif mlterm-3.8.9/tool/mlconfig/mc_click.c010064400017600000144000000032461356600660700162320ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_click.h" #include #include /* free */ #include #include #include #include "mc_combo.h" #include "mc_io.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static char *new_click_interval = NULL; static char *old_click_interval = NULL; static int is_changed; /* --- static functions --- */ static gint click_interval_selected(GtkWidget *widget, gpointer data) { g_free(new_click_interval); new_click_interval = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s click interval is selected.\n", new_click_interval); #endif return 1; } /* --- global functions --- */ GtkWidget *mc_click_interval_config_widget_new(void) { GtkWidget *combo; GtkWidget *entry; char *click_intervals[] = { "250", "300", "350", "400", "450", "500", }; new_click_interval = strdup(old_click_interval = mc_get_str_value("click_interval")); is_changed = 0; combo = mc_combo_new_with_width(_("Double click interval (msec)"), click_intervals, sizeof(click_intervals) / sizeof(click_intervals[0]), new_click_interval, 0, 50, &entry); g_signal_connect(entry, "changed", G_CALLBACK(click_interval_selected), NULL); return combo; } void mc_update_click_interval(void) { if (strcmp(new_click_interval, old_click_interval)) is_changed = 1; if (is_changed) { mc_set_str_value("click_interval", new_click_interval); free(old_click_interval); old_click_interval = strdup(new_click_interval); } } mlterm-3.8.9/tool/mlconfig/mc_click.h010064400017600000144000000003541356600660700162340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_CLICK_H__ #define __MC_CLICK_H__ #include GtkWidget *mc_click_interval_config_widget_new(void); void mc_update_click_interval(void); #endif mlterm-3.8.9/tool/mlconfig/mc_color.c010064400017600000144000000164701356600660700162660ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_color.h" #include #include /* free */ #include #include #include #include "mc_io.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ /* "rgba:rrrr/gggg/bbbb/aaaa" == 25 bytes */ #define MC_COLOR_LEN 32 /* colors are stored in untranslated forms */ static char new_color[MC_COLOR_MODES][MC_COLOR_LEN]; static char old_color[MC_COLOR_MODES][MC_COLOR_LEN]; static int is_changed[MC_COLOR_MODES]; static char new_vtcolor[16][MC_COLOR_LEN]; static char old_vtcolor[16][MC_COLOR_LEN]; static int is_changed_vt[16]; static char *configname[MC_COLOR_MODES] = { "fg_color", "bg_color", "sb_fg_color", "sb_bg_color", "cursor_fg_color", "cursor_bg_color", "bd_color", "it_color", "ul_color", "bl_color", "co_color"}; static char *labelname[MC_COLOR_MODES] = { N_("Foreground color"), N_("Background color"), N_("Foreground color"), N_("Background color"), N_("Foreground color"), N_("Background color"), N_("Bold "), N_("Italic"), N_("Underline"), N_("Blink"), N_("Cross out")}; /* --- static functions --- */ #if !GTK_CHECK_VERSION(2, 12, 0) /* gdk_color_to_string() was not supported by gtk+ < 2.12. */ static gchar *gdk_color_to_string(const GdkColor *color) { gchar *str; if ((str = g_malloc(14)) == NULL) { return NULL; } sprintf(str, "#%04x%04x%04x", color->red, color->green, color->blue); return str; } #endif static char *color_strncpy(char *dst, const char *src) { strncpy(dst, src, MC_COLOR_LEN); dst[MC_COLOR_LEN - 1] = 0; return dst; } static void color_selected(GtkWidget *button, gpointer data) { GdkColor color; gchar *str; gtk_color_button_get_color(GTK_COLOR_BUTTON(button), &color); str = gdk_color_to_string(&color); color_strncpy(g_object_get_data(G_OBJECT(button), "color"), str); g_free(str); } static void checked(GtkWidget *check, gpointer data) { GtkWidget *button; button = data; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check))) { gtk_widget_set_sensitive(button, 1); } else { gtk_widget_set_sensitive(button, 0); color_strncpy(g_object_get_data(G_OBJECT(button), "color"), ""); } } /* --- global functions --- */ GtkWidget *mc_color_config_widget_new(int id) { char *value; GtkWidget *hbox; GtkWidget *label; GtkWidget *button; GdkColor color; value = mc_get_str_value(configname[id]); color_strncpy(new_color[id], value); color_strncpy(old_color[id], value); hbox = gtk_hbox_new(FALSE, 0); if (id <= MC_COLOR_SBBG) { label = gtk_label_new(_(labelname[id])); } else { label = gtk_check_button_new_with_label(_(labelname[id])); if (*value) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(label), TRUE); } } gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 1); memset(&color, 0, sizeof(color)); gdk_color_parse(value, &color); button = gtk_color_button_new_with_color(&color); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); g_object_set_data(G_OBJECT(button), "color", &new_color[id]); g_signal_connect(button, "color-set", G_CALLBACK(color_selected), NULL); if (id > MC_COLOR_SBBG) { if (*value == '\0') { gtk_widget_set_sensitive(button, 0); } g_signal_connect(label, "toggled", G_CALLBACK(checked), button); } return hbox; } GtkWidget *mc_cursor_color_config_widget_new(void) { GtkWidget *hbox; GtkWidget *frame; GtkWidget *color; frame = gtk_frame_new(_("Cursor color")); hbox = gtk_hbox_new(FALSE, 1); gtk_widget_show(hbox); gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); gtk_container_add(GTK_CONTAINER(frame), hbox); color = mc_color_config_widget_new(MC_COLOR_CURSOR_FG); gtk_widget_show(color); gtk_box_pack_start(GTK_BOX(hbox), color, FALSE, FALSE, 1); color = mc_color_config_widget_new(MC_COLOR_CURSOR_BG); gtk_widget_show(color); gtk_box_pack_start(GTK_BOX(hbox), color, FALSE, FALSE, 1); return frame; } GtkWidget *mc_substitute_color_config_widget_new(void) { GtkWidget *vbox; GtkWidget *hbox; GtkWidget *frame; GtkWidget *color; frame = gtk_frame_new(_("Substituting color")); vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_container_add(GTK_CONTAINER(frame), vbox); hbox = gtk_hbox_new(FALSE, 1); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); color = mc_color_config_widget_new(MC_COLOR_BD); gtk_widget_show(color); gtk_box_pack_start(GTK_BOX(hbox), color, FALSE, FALSE, 1); color = mc_color_config_widget_new(MC_COLOR_UL); gtk_widget_show(color); gtk_box_pack_start(GTK_BOX(hbox), color, FALSE, FALSE, 1); color = mc_color_config_widget_new(MC_COLOR_IT); gtk_widget_show(color); gtk_box_pack_start(GTK_BOX(hbox), color, FALSE, FALSE, 1); hbox = gtk_hbox_new(FALSE, 1); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); color = mc_color_config_widget_new(MC_COLOR_BL); gtk_widget_show(color); gtk_box_pack_start(GTK_BOX(hbox), color, FALSE, FALSE, 1); color = mc_color_config_widget_new(MC_COLOR_CO); gtk_widget_show(color); gtk_box_pack_start(GTK_BOX(hbox), color, FALSE, FALSE, 1); return frame; } GtkWidget *mc_vtcolor_config_widget_new(void) { int id; char id_str[3]; char *value; GtkWidget *frame; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *button; GdkColor color; frame = gtk_frame_new(_("VT basic 16 colors")); vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_container_add(GTK_CONTAINER(frame), vbox); for (id = 0; id < 16; id++) { sprintf(id_str, "%d", id); value = mc_get_color_name(id_str); color_strncpy(new_vtcolor[id], value); color_strncpy(old_vtcolor[id], value); if (id % 8 == 0) { hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); } memset(&color, 0, sizeof(color)); gdk_color_parse(value, &color); button = gtk_color_button_new_with_color(&color); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); g_object_set_data(G_OBJECT(button), "color", &new_vtcolor[id]); g_signal_connect(button, "color-set", G_CALLBACK(color_selected), NULL); } return frame; } void mc_update_color(int id) { if (strcmp(new_color[id], old_color[id]) != 0) is_changed[id] = 1; if (is_changed[id]) { mc_set_str_value(configname[id], new_color[id]); strcpy(old_color[id], new_color[id]); } } void mc_update_cursor_color(void) { mc_update_color(MC_COLOR_CURSOR_FG); mc_update_color(MC_COLOR_CURSOR_BG); } void mc_update_substitute_color(void) { mc_update_color(MC_COLOR_BD); mc_update_color(MC_COLOR_IT); mc_update_color(MC_COLOR_UL); mc_update_color(MC_COLOR_BL); mc_update_color(MC_COLOR_CO); } void mc_update_vtcolor(mc_io_t io) { int id; char id_str[3]; for (id = 0; id < 16; id++) { if (strcmp(new_vtcolor[id], old_vtcolor[id]) != 0) { is_changed_vt[id] = 1; } if (is_changed_vt[id]) { sprintf(id_str, "%d", id); mc_set_color_name(io, id_str, new_vtcolor[id]); strcpy(old_vtcolor[id], new_vtcolor[id]); } } } mlterm-3.8.9/tool/mlconfig/mc_color.h010064400017600000144000000014421356600660700162640ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_COLOR_H__ #define __MC_COLOR_H__ #include #include "mc_io.h" #define MC_COLOR_MODES 11 #define MC_COLOR_FG 0 #define MC_COLOR_BG 1 #define MC_COLOR_SBFG 2 #define MC_COLOR_SBBG 3 #define MC_COLOR_CURSOR_FG 4 #define MC_COLOR_CURSOR_BG 5 #define MC_COLOR_BD 6 #define MC_COLOR_IT 7 #define MC_COLOR_UL 8 #define MC_COLOR_BL 9 #define MC_COLOR_CO 10 GtkWidget *mc_color_config_widget_new(int id); GtkWidget *mc_cursor_color_config_widget_new(void); GtkWidget *mc_substitute_color_config_widget_new(void); GtkWidget *mc_vtcolor_config_widget_new(void); void mc_update_color(int id); void mc_update_cursor_color(void); void mc_update_substitute_color(void); void mc_update_vtcolor(mc_io_t io); #endif mlterm-3.8.9/tool/mlconfig/mc_combo.c010064400017600000144000000053171356600660700162450ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include "mc_combo.h" #define CHAR_WIDTH 10 /* --- global functions --- */ GtkWidget *mc_combo_new(const char *label_name, char **item_names, u_int item_num, char *selected_item_name, int is_readonly, GtkWidget **entry) { return mc_combo_new_with_width(label_name, item_names, item_num, selected_item_name, is_readonly, 0, entry); } GtkWidget *mc_combo_new_with_width(const char *label_name, char **item_names, u_int item_num, char *selected_item_name, int is_readonly, int entry_width, GtkWidget **entry) { GtkWidget *hbox; GtkWidget *label; GtkWidget *combo; int item_found; u_int count; hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); label = gtk_label_new(label_name); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); #if GTK_CHECK_VERSION(2, 90, 0) combo = gtk_combo_box_text_new_with_entry(); #else combo = gtk_combo_box_entry_new_text(); #endif gtk_widget_show(combo); item_found = 0; for (count = 0; count < item_num; count++) { if (strcmp(selected_item_name, item_names[count]) == 0) { #if GTK_CHECK_VERSION(2, 90, 0) gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(combo), item_names[count]); #else gtk_combo_box_prepend_text(GTK_COMBO_BOX(combo), item_names[count]); #endif item_found = 1; } else { #if GTK_CHECK_VERSION(2, 90, 0) gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), item_names[count]); #else gtk_combo_box_append_text(GTK_COMBO_BOX(combo), item_names[count]); #endif } } if (!item_found && !is_readonly) { #if GTK_CHECK_VERSION(2, 90, 0) gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(combo), selected_item_name); #else gtk_combo_box_prepend_text(GTK_COMBO_BOX(combo), selected_item_name); #endif } gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); if (entry) { *entry = gtk_bin_get_child(GTK_BIN(combo)); } if (is_readonly) { gtk_editable_set_editable(GTK_EDITABLE(gtk_bin_get_child(GTK_BIN(combo))), FALSE); } if (entry_width) { #if GTK_CHECK_VERSION(2, 90, 0) gint width_chars; if (entry_width < CHAR_WIDTH) { width_chars = 1; } else { width_chars = entry_width / CHAR_WIDTH; } gtk_entry_set_width_chars(gtk_bin_get_child(GTK_BIN(combo)), width_chars); #else gtk_widget_set_size_request(gtk_bin_get_child(GTK_BIN(combo)), entry_width, -1); #endif gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 0); } else { gtk_box_pack_start(GTK_BOX(hbox), combo, TRUE, TRUE, 0); } return hbox; } mlterm-3.8.9/tool/mlconfig/mc_combo.h010064400017600000144000000012331356600660700162430ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_COMBO_H__ #define __MC_COMBO_H__ #include #include #include #define MC_COMBO_LABEL_WIDTH 1 #define MC_COMBO_TOTAL_WIDTH 2 GtkWidget *mc_combo_new(const char *label_name, char **item_names, u_int item_num, char *selected_item_name, int is_readonly, GtkWidget **entry); GtkWidget *mc_combo_new_with_width(const char *label_name, char **item_names, u_int item_num, char *selected_item_name, int is_readonly, int entry_width, GtkWidget **entry); #endif mlterm-3.8.9/tool/mlconfig/mc_ctl.c010064400017600000144000000042521356600660700157250ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_ctl.h" #include #include /* free */ #include #include #include #include "mc_io.h" #include "mc_flags.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static GtkWidget *entry; static char *old_bidisep; static int is_changed; /* --- static funcitons --- */ static void set_str_value(const char *value) { char *replaced; if ((replaced = bl_str_replace(value, "\\", "\\\\"))) { value = replaced; } mc_set_str_value("bidi_separators", value); free(replaced); } static gint toggled(GtkWidget *widget, gpointer data) { gtk_widget_set_sensitive(entry, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))); return 1; } /* --- global functions --- */ GtkWidget *mc_ctl_config_widget_new(void) { GtkWidget *hbox; GtkWidget *check; GtkWidget *label; hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); check = mc_flag_config_widget_new(MC_FLAG_CTL); gtk_widget_show(check); gtk_box_pack_start(GTK_BOX(hbox), check, FALSE, FALSE, 0); g_signal_connect(check, "toggled", G_CALLBACK(toggled), NULL); label = gtk_label_new(_("Bidi separators")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); entry = gtk_entry_new(); gtk_widget_set_size_request(entry, 50, -1); old_bidisep = mc_get_str_value("bidi_separators"); gtk_entry_set_text(GTK_ENTRY(entry), old_bidisep); gtk_widget_show(entry); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 1); #if GTK_CHECK_VERSION(2, 12, 0) gtk_widget_set_tooltip_text(entry, "Separator characters (ASCII only) to reorder " "every separated area by bidi algorithm " "respectively."); #endif return hbox; } void mc_update_ctl(void) { const char *new_bidisep; mc_update_flag_mode(MC_FLAG_CTL); new_bidisep = gtk_entry_get_text(GTK_ENTRY(entry)); if (strcmp(new_bidisep, old_bidisep)) { is_changed = 1; } if (is_changed) { free(old_bidisep); set_str_value((old_bidisep = strdup(new_bidisep))); } } mlterm-3.8.9/tool/mlconfig/mc_ctl.h010064400017600000144000000003221356600660700157240ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_CTL_H__ #define __MC_CTL_H__ #include GtkWidget *mc_ctl_config_widget_new(void); void mc_update_ctl(void); #endif mlterm-3.8.9/tool/mlconfig/mc_flags.c010064400017600000144000000065361356600660700162460ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_flags.h" #include #include /* free */ #include #include #include "mc_io.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static int old_flag_modes[MC_FLAG_MODES]; static int new_flag_modes[MC_FLAG_MODES]; static int is_changed[MC_FLAG_MODES]; static char *config_keys[MC_FLAG_MODES] = { "type_engine", "type_engine", "use_anti_alias", "use_variable_column_width", "use_combining", "use_dynamic_comb", "receive_string_via_ucs", "use_multi_column_char", "use_ctl", "col_size_of_width_a", "use_clipboard", "use_local_echo", "blink_cursor", "static_backscroll_mode", "use_extended_scroll_shortcut", "regard_uri_as_word", "use_ot_layout", "trim_trailing_newline_in_pasting", "broadcast", }; static char *labels[MC_FLAG_MODES] = { N_("Xft"), N_("Cairo"), N_("Anti Alias"), N_("Variable column width"), N_("Combining"), N_("Combining = 1 (or 0) logical column(s)"), N_("Process received strings via Unicode"), N_("Fullwidth = 2 (or 1) logical column(s)"), N_("Complex Text Layout"), N_("Ambiguouswidth = fullwidth"), N_("CLIPBOARD Selection"), N_("Local echo"), N_("Blink cursor"), N_("Don't scroll automatically in scrolling back"), N_("Scroll by Shift+Up or Shift+Down"), N_("Select URI by double click"), N_("OpenType Layout"), N_("Trim trailing CR/LF in pasting"), N_("Send keys to all windows"), }; static GtkWidget *widgets[MC_FLAG_MODES]; /* --- global functions --- */ GtkWidget *mc_flag_config_widget_new(int id) { if (id == MC_FLAG_XFT) { old_flag_modes[id] = new_flag_modes[id] = (strcmp(mc_get_str_value(config_keys[id]), "xft") == 0); } else if (id == MC_FLAG_CAIRO) { old_flag_modes[id] = new_flag_modes[id] = (strcmp(mc_get_str_value(config_keys[id]), "cairo") == 0); } else if (id == MC_FLAG_AWIDTH) { old_flag_modes[id] = new_flag_modes[id] = (strcmp(mc_get_str_value(config_keys[id]), "2") == 0); } else { old_flag_modes[id] = new_flag_modes[id] = mc_get_flag_value(config_keys[id]); } widgets[id] = gtk_check_button_new_with_label(_(labels[id])); if (old_flag_modes[id]) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widgets[id]), TRUE); } return widgets[id]; } void mc_update_flag_mode(int id) { new_flag_modes[id] = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets[id])); if (old_flag_modes[id] != new_flag_modes[id]) { is_changed[id] = 1; } if (is_changed[id]) { if (id == MC_FLAG_XFT) { if (new_flag_modes[id]) { mc_set_str_value(config_keys[id], "xft"); } else if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets[MC_FLAG_CAIRO]))) { mc_set_str_value(config_keys[id], "xcore"); } } else if (id == MC_FLAG_CAIRO) { if (new_flag_modes[id]) { mc_set_str_value(config_keys[id], "cairo"); } else if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets[MC_FLAG_XFT]))) { mc_set_str_value(config_keys[id], "xcore"); } } else if (id == MC_FLAG_AWIDTH) { if (new_flag_modes[id]) { mc_set_str_value(config_keys[id], "2"); } else { mc_set_str_value(config_keys[id], "1"); } } else { mc_set_flag_value(config_keys[id], new_flag_modes[id]); } old_flag_modes[id] = new_flag_modes[id]; } } mlterm-3.8.9/tool/mlconfig/mc_flags.h010064400017600000144000000014041356600660700162400ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_FLAGS_H__ #define __MC_FLAGS_H__ #include #define MC_FLAG_MODES 19 #define MC_FLAG_XFT 0 #define MC_FLAG_CAIRO 1 #define MC_FLAG_AA 2 #define MC_FLAG_VCOL 3 #define MC_FLAG_COMB 4 #define MC_FLAG_DYNCOMB 5 #define MC_FLAG_RECVUCS 6 #define MC_FLAG_MCOL 7 #define MC_FLAG_CTL 8 #define MC_FLAG_AWIDTH 9 #define MC_FLAG_CLIPBOARD 10 #define MC_FLAG_LOCALECHO 11 #define MC_FLAG_BLINKCURSOR 12 #define MC_FLAG_STATICBACKSCROLL 13 #define MC_FLAG_EXTSCROLLSHORTCUT 14 #define MC_FLAG_REGARDURIASWORD 15 #define MC_FLAG_OTLAYOUT 16 #define MC_FLAG_TRIMNEWLINE 17 #define MC_FLAG_BROADCAST 18 GtkWidget *mc_flag_config_widget_new(int id); void mc_update_flag_mode(int id); #endif mlterm-3.8.9/tool/mlconfig/mc_font.c010064400017600000144000000733141356600660700161160ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_font.h" #include #include #include #include /* free */ #include #include #include #if defined(GDK_WINDOWING_X11) && !GTK_CHECK_VERSION(2, 90, 0) #include "gtkxlfdsel.c" #endif #include "mc_combo.h" #include "mc_flags.h" #include "mc_radio.h" #include "mc_char_encoding.h" #include "mc_color.h" #include "mc_unicode_areas.h" #if 0 #define __DEBUG #endif typedef struct cs_info { char *cs; /* * Default font encoding name. * This used only if xcore font is used. * * !! Notice !! * The last element must be NULL. * (Conforming to the specification of 'charsets' argument of * gtk_xlfd_selection_dialog_set_filter()). */ char *encoding_names[3]; } cs_info_t; /* --- static variables --- */ /* * Combination of x_font_config.c:cs_table and x_font.c:cs_info_table */ static cs_info_t cs_info_table[] = { { "DEFAULT", { NULL, NULL, NULL, }, }, /* * UNICODE => ISO10646_UCS4_1 or U+XXXX-XXXX in get_correct_cs(). */ { "UNICODE", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Full Width)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Emoji)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Hankaku Kana)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Hebrew)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Arabic)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Hindi)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Bengali)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Punjabi)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Gujarati)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Oriya)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Tamil)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Telugu)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Kannada)", { "iso10646-1", NULL, NULL, }, }, { "UNICODE (Malayalam)", { "iso10646-1", NULL, NULL, }, }, { "DEC_SPECIAL", { "iso8859-1", NULL, NULL, }, }, { "ISO8859_1", { "iso8859-1", NULL, NULL, }, }, { "ISO8859_2", { "iso8859-2", NULL, NULL, }, }, { "ISO8859_3", { "iso8859-3", NULL, NULL, }, }, { "ISO8859_4", { "iso8859-4", NULL, NULL, }, }, { "ISO8859_5", { "iso8859-5", NULL, NULL, }, }, { "ISO8859_6", { "iso8859-6", NULL, NULL, }, }, { "ISO8859_7", { "iso8859-7", NULL, NULL, }, }, { "ISO8859_8", { "iso8859-8", NULL, NULL, }, }, { "ISO8859_9", { "iso8859-9", NULL, NULL, }, }, { "ISO8859_10", { "iso8859-10", NULL, NULL, }, }, { "TIS620", { "tis620.2533-1", "tis620.2529-1", NULL, }, }, { "ISO8859_13", { "iso8859-13", NULL, NULL, }, }, { "ISO8859_14", { "iso8859-14", NULL, NULL, }, }, { "ISO8859_15", { "iso8859-15", NULL, NULL, }, }, { "ISO8859_16", { "iso8859-16", NULL, NULL, }, }, /* * XXX * The encoding of TCVN font is iso8859-1, and its font family is .VnTime or * .VnTimeH... How to deal with it ? */ { "TCVN5712", { NULL, NULL, NULL, }, }, { "ISCII_ASSAMESE", { NULL, NULL, NULL, }, }, { "ISCII_BENGALI", { NULL, NULL, NULL, }, }, { "ISCII_GUJARATI", { NULL, NULL, NULL, }, }, { "ISCII_HINDI", { NULL, NULL, NULL, }, }, { "ISCII_KANNADA", { NULL, NULL, NULL, }, }, { "ISCII_MALAYALAM", { NULL, NULL, NULL, }, }, { "ISCII_ORIYA", { NULL, NULL, NULL, }, }, { "ISCII_PUNJABI", { NULL, NULL, NULL, }, }, { "ISCII_TAMIL", { NULL, NULL, NULL, }, }, { "ISCII_TELUGU", { NULL, NULL, NULL, }, }, { "VISCII", { "viscii-1", NULL, NULL, }, }, { "KOI8_R", { "koi8-r", NULL, NULL, }, }, { "KOI8_U", { "koi8-u", NULL, NULL, }, }, #if 0 /* * XXX * KOI8_T, GEORGIAN_PS and CP125X charset can be shown by unicode font only. */ { "KOI8_T", { NULL, NULL, NULL, }, }, { "GEORGIAN_PS", { NULL, NULL, NULL, }, }, #endif #ifdef USE_WIN32GUI { "CP1250", { NULL, NULL, NULL, }, }, { "CP1251", { NULL, NULL, NULL, }, }, { "CP1252", { NULL, NULL, NULL, }, }, { "CP1253", { NULL, NULL, NULL, }, }, { "CP1254", { NULL, NULL, NULL, }, }, { "CP1255", { NULL, NULL, NULL, }, }, { "CP1256", { NULL, NULL, NULL, }, }, { "CP1257", { NULL, NULL, NULL, }, }, { "CP1258", { NULL, NULL, NULL, }, }, { "CP874", { NULL, NULL, NULL, }, }, #endif { "JISX0201_KATA", { "jisx0201.1976-0", NULL, NULL, }, }, { "JISX0201_ROMAN", { "jisx0201.1976-0", NULL, NULL, }, }, { "JISX0208_1978", { "jisx0208.1978-0", "jisx0208.1983-0", NULL, }, }, { "JISX0208_1983", { "jisx0208.1983-0", "jisx0208.1990-0", NULL, }, }, { "JISX0208_1990", { "jisx0208.1990-0", "jisx0208.1983-0", NULL, }, }, { "JISX0212_1990", { "jisx0212.1990-0", NULL, NULL, }, }, { "JISX0213_2000_1", { "jisx0213.2000-1", "jisx0208.1983-0", NULL, }, }, { "JISX0213_2000_2", { "jisx0213.2000-2", NULL, NULL, }, }, { "KSX1001_1997", { "ksc5601.1987-0", "ksx1001.1997-0", NULL, }, }, #if 0 /* * XXX * UHC and JOHAB fonts are not used at the present time. * see vt_vt100_parser.c:vt_parse_vt100_sequence(). */ { "UHC", { NULL, NULL, NULL, }, }, { "JOHAB", { "johabsh-1", /* "johabs-1" , */ "johab-1", NULL, }, }, #endif { "GB2312_80", { "gb2312.1980-0", NULL, NULL, }, }, { "GBK", { "gbk-0", NULL, NULL, }, }, { "BIG5", { "big5.eten-0", "big5.hku-0", NULL, }, }, { "HKSCS", { "big5hkscs-0", "big5-0", NULL, }, }, { "CNS11643_1992_1", { "cns11643.1992-1", "cns11643.1992.1-0", NULL, }, }, { "CNS11643_1992_2", { "cns11643.1992-2", "cns11643.1992.2-0", NULL, }, }, { "CNS11643_1992_3", { "cns11643.1992-3", "cns11643.1992.3-0", NULL, }, }, { "CNS11643_1992_4", { "cns11643.1992-4", "cns11643.1992.4-0", NULL, }, }, { "CNS11643_1992_5", { "cns11643.1992-5", "cns11643.1992.5-0", NULL, }, }, { "CNS11643_1992_6", { "cns11643.1992-6", "cns11643.1992.6-0", NULL, }, }, { "CNS11643_1992_7", { "cns11643.1992-7", "cns11643.1992.7-0", NULL, }, }, }; static char *new_fontsize = NULL; static char *old_fontsize = NULL; static int is_fontsize_changed; static char *new_fontname_list[sizeof(cs_info_table) / sizeof(cs_info_table[0])]; static int dont_change_new_fontname_list = 0; static int selected_cs = 0; /* 0 = DEFAULT */ static GtkWidget *fontcs_entry; static GtkWidget *fontname_entry; static GtkWidget *select_font_button; static GtkWidget *xft_flag; static GtkWidget *cairo_flag; static GtkWidget *aa_flag; static GtkWidget *vcol_flag; static int dont_change_type_engine; static GtkWidget *noconv_areas_button; static char *noconv_areas; /* --- static functions --- */ static void reset_fontname_list(void) { int count; for (count = 0; count < sizeof(cs_info_table) / sizeof(cs_info_table[0]); count++) { free(new_fontname_list[count]); new_fontname_list[count] = NULL; } } /* * If you use functions in mc_io.c, use this function instead of direct * access to cs_info_t::cs. */ static const char *get_correct_cs(int idx) { const char *unicode_names[] = { "ISO10646_UCS4_1", "ISO10646_UCS4_1_FULLWIDTH", "U+1F000-1F77F", /* Emoji */ "U+FF61-FF9F", /* Hankaku Kana */ "U+0590-05FF", /* Hebrew */ "U+0600-06FF", /* Arabic */ "U+0900-097F", /* Hindi */ "U+0980-09FF", /* Bengali */ "U+0A00-0A7F", /* Punjabi */ "U+0A80-0AFF", /* Gujarati */ "U+0B00-0B7F", /* Oriya */ "U+0B80-0BFF", /* Tamil */ "U+0C00-0C7F", /* Telugu */ "U+0C80-0CFF", /* Kannada */ "U+0D00-0D7F", /* Malayalam */ }; if (idx < 0) { return NULL; } else if (1 <= idx && idx <= 15) { return unicode_names[idx - 1]; } else if (idx < sizeof(cs_info_table) / sizeof(cs_info_table[0])) { return cs_info_table[idx].cs; } else { return NULL; } } static char *get_font_file(void) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xft_flag)) || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cairo_flag)) || mc_get_flag_value("use_aafont")) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(vcol_flag))) { return "vaafont"; } else if (mc_radio_get_value(MC_RADIO_VERTICAL_MODE)) { return "taafont"; } else { return "aafont"; } } else { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(vcol_flag))) { return "vfont"; } else if (mc_radio_get_value(MC_RADIO_VERTICAL_MODE)) { return "tfont"; } else { return "font"; } } } static gint aa_flag_checked(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xft_flag)) && !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cairo_flag))) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xft_flag), 1); reset_fontname_list(); gtk_entry_set_text( GTK_ENTRY(fontname_entry), g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL, NULL, NULL)); } } return 1; } static gint xft_flag_checked(GtkWidget *widget, gpointer data) { if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) && !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cairo_flag))) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(aa_flag), 0); } else if (!dont_change_type_engine) { dont_change_type_engine = 1; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cairo_flag), 0); dont_change_type_engine = 0; } reset_fontname_list(); gtk_entry_set_text( GTK_ENTRY(fontname_entry), g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL, NULL, NULL)); return 1; } static gint cairo_flag_checked(GtkWidget *widget, gpointer data) { if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) && !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xft_flag))) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(aa_flag), 0); } else if (!dont_change_type_engine) { dont_change_type_engine = 1; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xft_flag), 0); dont_change_type_engine = 0; } reset_fontname_list(); gtk_entry_set_text( GTK_ENTRY(fontname_entry), g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL, NULL, NULL)); return 1; } static gint vcol_flag_checked(GtkWidget *widget, gpointer data) { reset_fontname_list(); gtk_entry_set_text( GTK_ENTRY(fontname_entry), g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL, NULL, NULL)); return 1; } static void vertical_mode_changed(void) { reset_fontname_list(); gtk_entry_set_text( GTK_ENTRY(fontname_entry), g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL, NULL, NULL)); if (mc_radio_get_value(MC_RADIO_VERTICAL_MODE)) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vcol_flag), 0); gtk_widget_set_sensitive(vcol_flag, 0); } else { gtk_widget_set_sensitive(vcol_flag, 1); } } static gint fontsize_selected(GtkWidget *widget, gpointer data) { g_free(new_fontsize); new_fontsize = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s font size is selected.\n", new_fontsize); #endif return 1; } static void specify_width(GtkWidget *widget, int flag) { gchar *fontname; if (((fontname = new_fontname_list[selected_cs]) || (fontname = gtk_entry_get_text(GTK_ENTRY(fontname_entry)))) && *fontname) { gchar *p; int percent; size_t len; if (!(p = strrchr(fontname, ':')) || (percent = atoi(p + 1)) == 0) { if (flag == 0) { return; } len = strlen(fontname); percent = (flag < 0 ? 100 : 110); } else { len = p - fontname; if (flag == 0) { percent = 0; } else { percent += (flag < 0 ? -10 : 10); if (percent <= 0 || 200 < percent) { return; } } } if ((p = malloc(len + 5))) { strncpy(p, fontname, len); if (percent == 0) { p[len] = '\0'; } else { sprintf(p + len, ":%d", percent); } free(new_fontname_list[selected_cs]); new_fontname_list[selected_cs] = p; dont_change_new_fontname_list = 1; gtk_entry_set_text(GTK_ENTRY(fontname_entry), p); dont_change_new_fontname_list = 0; } } } static void widen_width(GtkWidget *widget, gpointer data) { specify_width(widget, 1); } static void narrow_width(GtkWidget *widget, gpointer data) { specify_width(widget, -1); } static void default_width(GtkWidget *widget, gpointer data) { specify_width(widget, 0); } static void fontcs_changed(void) { dont_change_new_fontname_list = 1; if (new_fontname_list[selected_cs]) { gtk_entry_set_text(GTK_ENTRY(fontname_entry), new_fontname_list[selected_cs]); } else { gtk_entry_set_text( GTK_ENTRY(fontname_entry), g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL, NULL, NULL)); } dont_change_new_fontname_list = 0; } /* compare two encoding names, returns non-zero if equal */ static int compare(const char *e1, const char *e2) { while (1) { /* ')' is for "auto (currently EUC-JP)" */ if (*e1 == '-' || *e1 == '_' || *e1 == ')') { e1++; continue; } if (*e2 == '-' || *e2 == '_' || *e2 == ')') { e2++; continue; } if ((*e1 == 0 || *e1 == ' ') && (*e2 == 0 || *e2 == ' ')) { return 1; } if (toupper(*e1) != toupper(*e2)) { return 0; } e1++; e2++; } } static void fontcs_map(GtkWidget *widget, gpointer data) { char *encoding; int count; encoding = mc_get_char_encoding(); if ((strstr(encoding, "UTF") && mc_radio_get_value(MC_RADIO_FONT_POLICY) != 2) || mc_radio_get_value(MC_RADIO_FONT_POLICY) == 1) { if (selected_cs == 1) { return; } selected_cs = 1; /* UNICODE */ } else { for (count = 0; count < sizeof(cs_info_table) / sizeof(cs_info_table[0]); count++) { if (strcmp(cs_info_table[count].cs, "JISX0201_KATA") == 0) { break; } else if (compare(encoding, cs_info_table[count].cs)) { if (selected_cs == count) { return; } selected_cs = count; goto update_cs; } } if (selected_cs == 0) { return; } selected_cs = 0; /* DEFAULT */ } update_cs: gtk_entry_set_text(GTK_ENTRY(widget), cs_info_table[selected_cs].cs); fontcs_changed(); } static void font_policy_changed(void) { fontcs_map(fontcs_entry, NULL); if (noconv_areas_button) { gtk_widget_set_sensitive(noconv_areas_button, (mc_radio_get_value(MC_RADIO_FONT_POLICY) == 2)); } } static gint fontcs_selected(GtkWidget *widget, gpointer data) { const char *cs; int count; cs = gtk_entry_get_text(GTK_ENTRY(widget)); for (count = 0; count < sizeof(cs_info_table) / sizeof(cs_info_table[0]); count++) { if (strcmp(cs, cs_info_table[count].cs) == 0) { if (selected_cs != count) { #if 0 bl_debug_printf("Before: cs %s fontname %s => ", cs_info_table[selected_cs].cs, new_fontname_list[selected_cs]); #endif selected_cs = count; fontcs_changed(); #if 0 bl_debug_printf("After: cs %s fontname %s\n", cs, new_fontname_list[selected_cs]); #endif return 1; } } } return 0; } #if defined(GDK_WINDOWING_X11) && !GTK_CHECK_VERSION(2, 90, 0) static gchar *get_xlfd_font_name(gpointer dialog) { char *name; name = gtk_xlfd_selection_dialog_get_font_name(GTK_XLFD_SELECTION_DIALOG(dialog)); if (selected_cs == 0 && name && *name) /* DEFAULT */ { /* * Removing font encoding such as "iso8859-1". */ char *p; if ((p = strrchr(name, '-'))) { *p = '\0'; if ((p = strrchr(name, '-'))) { *(p + 1) = '\0'; } } } return name; } static void ok_pressed(GtkWidget *widget, gpointer dialog) { gchar *name; name = get_xlfd_font_name(dialog); gtk_entry_set_text(GTK_ENTRY(fontname_entry), name); g_free(name); gtk_widget_destroy(GTK_WIDGET(dialog)); } static void apply_pressed(GtkWidget *widget, gpointer dialog) { gchar *name; name = get_xlfd_font_name(dialog); gtk_entry_set_text(GTK_ENTRY(fontname_entry), name); g_free(name); } static void cancel_pressed(GtkWidget *widget, gpointer dialog) { gtk_widget_destroy(GTK_WIDGET(dialog)); } static int set_current_font_name(GtkWidget *dialog) { const gchar *font_name; font_name = gtk_entry_get_text(GTK_ENTRY(fontname_entry)); if (font_name && *font_name) { char *p; /* * Modify DEFAULT font name. "-*-...-*-" => "-*-...-*-*-*" */ if (selected_cs == 0 && (p = alloca(strlen(font_name) + 4))) { sprintf(p, "%s*-*", font_name); font_name = p; } return gtk_xlfd_selection_dialog_set_font_name(GTK_XLFD_SELECTION_DIALOG(dialog), font_name); } else { return 0; } } static void select_xlfd_font(GtkWidget *widget, gpointer label) { GtkWidget *dialog; dialog = gtk_xlfd_selection_dialog_new("Select Font"); if (!set_current_font_name(dialog)) { char *encoding; char *font_name; char format[] = "-misc-fixed-medium-*-normal-*-%s-*-*-*-*-*-%s"; if ((encoding = cs_info_table[selected_cs].encoding_names[0]) == NULL) { encoding = "*-*"; } if ((font_name = alloca(sizeof(format) + strlen(new_fontsize) + strlen(encoding)))) { sprintf(font_name, format, new_fontsize, encoding); gtk_xlfd_selection_dialog_set_font_name(GTK_XLFD_SELECTION_DIALOG(dialog), font_name); } } if (cs_info_table[selected_cs].encoding_names[0]) { gtk_xlfd_selection_dialog_set_filter(GTK_XLFD_SELECTION_DIALOG(dialog), GTK_XLFD_FILTER_USER, GTK_XLFD_ALL, NULL, NULL, NULL, NULL, NULL, cs_info_table[selected_cs].encoding_names); } g_signal_connect(GTK_XLFD_SELECTION_DIALOG(dialog)->ok_button, "clicked", G_CALLBACK(ok_pressed), dialog); g_signal_connect(GTK_XLFD_SELECTION_DIALOG(dialog)->apply_button, "clicked", G_CALLBACK(apply_pressed), dialog); g_signal_connect(GTK_XLFD_SELECTION_DIALOG(dialog)->cancel_button, "clicked", G_CALLBACK(cancel_pressed), dialog); gtk_widget_show_all(dialog); } #endif static char *my_gtk_font_selection_dialog_get_font_name(GtkFontSelectionDialog *dialog) { char *str; int count; char *p; char *dup_str; str = gtk_font_selection_dialog_get_font_name(dialog); if ((dup_str = malloc(strlen(str) * 2 + 1)) == NULL) { free(str); return NULL; } /* Escape '-' in Xft. */ count = 0; p = str; while (*p) { #ifndef USE_WIN32GUI if (*p == '-') { dup_str[count++] = '\\'; } #endif dup_str[count++] = *(p++); } dup_str[count] = '\0'; g_free(str); return dup_str; } static char *get_gtk_font_name(const char *font_name) { int count; char *str; if ((str = malloc(strlen(font_name) + 1)) == NULL) { return NULL; } count = 0; while (*font_name && *font_name != '-') { if (*font_name == '\\') { font_name++; } str[count++] = *(font_name++); } str[count] = '\0'; return str; } static void fontname_entry_edit(GtkWidget *widget, gpointer p) { /* In case fontname is editted in text entry widget. */ if (!dont_change_new_fontname_list) { const char *name; if (!(name = gtk_entry_get_text(GTK_ENTRY(fontname_entry)))) { if (new_fontname_list[selected_cs]) { /* * Font name for selected_cs was specfied, but now * font name for selected_cs is cleared. */ name = ""; } } if (name) { free(new_fontname_list[selected_cs]); new_fontname_list[selected_cs] = strdup(name); } } } static void select_fc_font(GtkWidget *widget, gpointer p) { GtkWidget *dialog; char *font_name; GtkResponseType result; dialog = gtk_font_selection_dialog_new("Select Font"); font_name = get_gtk_font_name(gtk_entry_get_text(GTK_ENTRY(fontname_entry))); if (!font_name || !*font_name || !gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog), font_name)) { free(font_name); if ((font_name = malloc(6 + strlen(new_fontsize))) == NULL) { return; } sprintf(font_name, "Sans %s", new_fontsize); gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog), font_name); } free(font_name); result = gtk_dialog_run(GTK_DIALOG(dialog)); if (result == GTK_RESPONSE_OK) { gtk_entry_set_text(GTK_ENTRY(fontname_entry), my_gtk_font_selection_dialog_get_font_name( GTK_FONT_SELECTION_DIALOG(dialog))); } gtk_widget_destroy(dialog); } static void select_font(GtkWidget *widget, gpointer p) { #if defined(GDK_WINDOWING_X11) && !GTK_CHECK_VERSION(2, 90, 0) if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xft_flag)) && !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cairo_flag)) && strcmp(mc_get_gui(), "xlib") == 0) { select_xlfd_font(widget, p); } else #endif { select_fc_font(widget, p); } } static void edit_noconv_areas(GtkWidget *widget, gpointer data) { char *cur_areas; char *new_areas; if (noconv_areas) { cur_areas = strdup(noconv_areas); } else { cur_areas = mc_get_str_value("unicode_noconv_areas"); } if ((new_areas = mc_get_unicode_areas(cur_areas)) && bl_compare_str(noconv_areas, new_areas) != 0) { free(noconv_areas); noconv_areas = new_areas; } free(cur_areas); } /* --- global functions --- */ GtkWidget *mc_font_config_widget_new(void) { GtkWidget *vbox; GtkWidget *hbox; GtkWidget *fgcolor; GtkWidget *combo; GtkWidget *entry; GtkWidget *radio; GtkWidget *label; GtkWidget *button; char *fontlist[] = { "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", }; char **cslist; new_fontsize = strdup(old_fontsize = mc_get_str_value("fontsize")); is_fontsize_changed = 0; vbox = gtk_vbox_new(FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); combo = mc_combo_new_with_width(_("Font size (pixels)"), fontlist, sizeof(fontlist) / sizeof(fontlist[0]), new_fontsize, 1, 30, &entry); g_signal_connect(entry, "changed", G_CALLBACK(fontsize_selected), NULL); gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 0); #if GTK_CHECK_VERSION(2, 12, 0) gtk_widget_set_tooltip_text(combo, "If you change fonts from \"Select\" button, " "it is not recommended to change font size here."); #endif fgcolor = mc_color_config_widget_new(MC_COLOR_FG); gtk_widget_show(fgcolor); gtk_box_pack_start(GTK_BOX(hbox), fgcolor, FALSE, FALSE, 5); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); xft_flag = mc_flag_config_widget_new(MC_FLAG_XFT); gtk_widget_show(xft_flag); gtk_box_pack_start(GTK_BOX(hbox), xft_flag, FALSE, FALSE, 0); g_signal_connect(xft_flag, "toggled", G_CALLBACK(xft_flag_checked), NULL); if (strcmp(mc_get_gui(), "xlib") != 0) { gtk_widget_set_sensitive(xft_flag, 0); } cairo_flag = mc_flag_config_widget_new(MC_FLAG_CAIRO); gtk_widget_show(cairo_flag); gtk_box_pack_start(GTK_BOX(hbox), cairo_flag, FALSE, FALSE, 0); g_signal_connect(cairo_flag, "toggled", G_CALLBACK(cairo_flag_checked), NULL); if (strcmp(mc_get_gui(), "xlib") != 0) { gtk_widget_set_sensitive(cairo_flag, 0); } aa_flag = mc_flag_config_widget_new(MC_FLAG_AA); gtk_widget_show(aa_flag); gtk_box_pack_start(GTK_BOX(hbox), aa_flag, FALSE, FALSE, 0); g_signal_connect(aa_flag, "toggled", G_CALLBACK(aa_flag_checked), NULL); vcol_flag = mc_flag_config_widget_new(MC_FLAG_VCOL); gtk_widget_show(vcol_flag); gtk_box_pack_start(GTK_BOX(hbox), vcol_flag, FALSE, FALSE, 0); g_signal_connect(vcol_flag, "toggled", G_CALLBACK(vcol_flag_checked), NULL); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); radio = mc_radio_config_widget_new(MC_RADIO_VERTICAL_MODE); gtk_widget_show(radio); gtk_box_pack_start(GTK_BOX(vbox), radio, FALSE, FALSE, 0); mc_radio_set_callback(MC_RADIO_VERTICAL_MODE, vertical_mode_changed); if (mc_radio_get_value(MC_RADIO_VERTICAL_MODE)) { gtk_widget_set_sensitive(vcol_flag, 0); } hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); if ((cslist = alloca(sizeof(char*) * sizeof(cs_info_table) / sizeof(cs_info_table[0])))) { int count; for (count = 0; count < sizeof(cs_info_table) / sizeof(cs_info_table[0]); count++) { cslist[count] = cs_info_table[count].cs; } combo = mc_combo_new_with_width(_("Font name"), cslist, count, cslist[selected_cs], 1, 90, &fontcs_entry); g_signal_connect(fontcs_entry, "changed", G_CALLBACK(fontcs_selected), NULL); g_signal_connect(fontcs_entry, "map", G_CALLBACK(fontcs_map), NULL); gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 0); } fontname_entry = gtk_entry_new(); gtk_entry_set_text( GTK_ENTRY(fontname_entry), g_locale_to_utf8(mc_get_font_name(get_font_file(), get_correct_cs(selected_cs)), -1, NULL, NULL, NULL)); gtk_widget_show(fontname_entry); gtk_box_pack_start(GTK_BOX(hbox), fontname_entry, TRUE, TRUE, 1); g_signal_connect(fontname_entry, "changed", G_CALLBACK(fontname_entry_edit), NULL); select_font_button = gtk_button_new_with_label(_("Select")); gtk_widget_show(select_font_button); gtk_box_pack_start(GTK_BOX(hbox), select_font_button, FALSE, FALSE, 1); g_signal_connect(select_font_button, "clicked", G_CALLBACK(select_font), NULL); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); label = gtk_label_new(_("Font width")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); button = gtk_button_new_with_label(_("Narrow")); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5); g_signal_connect(button, "clicked", G_CALLBACK(narrow_width), NULL); button = gtk_button_new_with_label(_("Widen")); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5); g_signal_connect(button, "clicked", G_CALLBACK(widen_width), NULL); button = gtk_button_new_with_label(_("Default")); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 5); g_signal_connect(button, "clicked", G_CALLBACK(default_width), NULL); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); radio = mc_radio_config_widget_new(MC_RADIO_FONT_POLICY); gtk_widget_show(radio); gtk_box_pack_start(GTK_BOX(vbox), radio, FALSE, FALSE, 0); mc_radio_set_callback(MC_RADIO_FONT_POLICY, font_policy_changed); hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); label = gtk_label_new(_("Unicode areas you won't convert to other charsets")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); noconv_areas_button = gtk_button_new_with_label(_(" Edit ")); gtk_widget_show(noconv_areas_button); gtk_box_pack_start(GTK_BOX(hbox), noconv_areas_button, FALSE, FALSE, 0); g_signal_connect(noconv_areas_button, "clicked", G_CALLBACK(edit_noconv_areas), NULL); if (mc_radio_get_value(MC_RADIO_FONT_POLICY) != 2) { gtk_widget_set_sensitive(noconv_areas_button, 0); } gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); radio = mc_radio_config_widget_new(MC_RADIO_BOX_DRAWING); gtk_widget_show(radio); gtk_box_pack_start(GTK_BOX(vbox), radio, FALSE, FALSE, 0); return vbox; } void mc_update_font_misc(void) { if (strcmp(new_fontsize, old_fontsize)) is_fontsize_changed = 1; if (is_fontsize_changed) { mc_set_str_value("fontsize", new_fontsize); free(old_fontsize); old_fontsize = strdup(new_fontsize); } /* * MC_FLAG_{XFT|CAIRO} should be updated last because MC_FLAG_{XFT|CAIRO} are * invalid in some environments. */ mc_update_flag_mode(MC_FLAG_AA); mc_update_radio(MC_RADIO_VERTICAL_MODE); /* vcol is forcibly disabled in vertical mode, so update after vertical mode. */ mc_update_flag_mode(MC_FLAG_VCOL); mc_update_flag_mode(MC_FLAG_XFT); mc_update_flag_mode(MC_FLAG_CAIRO); mc_update_radio(MC_RADIO_BOX_DRAWING); mc_update_radio(MC_RADIO_FONT_POLICY); if (noconv_areas) { mc_set_str_value("unicode_noconv_areas", noconv_areas); } } void mc_update_font_name(mc_io_t io) { size_t count; for (count = 0; count < sizeof(cs_info_table) / sizeof(cs_info_table[0]); count++) { if (new_fontname_list[count]) { mc_set_font_name(io, get_font_file(), get_correct_cs(count), new_fontname_list[count]); if (count == 6) { /* Arabic Supplement */ mc_set_font_name(io, get_font_file(), "U+0750-77F", new_fontname_list[count]); /* Arabic Extended-A */ mc_set_font_name(io, get_font_file(), "U+08A0-8FF", new_fontname_list[count]); /* Arabic Presentation Forms-A */ mc_set_font_name(io, get_font_file(), "U+FB50-FDFF", new_fontname_list[count]); /* Arabic Presentation Forms-B */ mc_set_font_name(io, get_font_file(), "U+FE70-FEFF", new_fontname_list[count]); /* Arabic Mathematical Alphabetic Symbols */ mc_set_font_name(io, get_font_file(), "U+1EE00-1EEFF", new_fontname_list[count]); } } } } mlterm-3.8.9/tool/mlconfig/mc_font.h010064400017600000144000000004261356600660700161150ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_FONT_H__ #define __MC_FONT_H__ #include #include "mc_io.h" GtkWidget *mc_font_config_widget_new(void); void mc_update_font_misc(void); void mc_update_font_name(mc_io_t io); #endif mlterm-3.8.9/tool/mlconfig/mc_geometry.c010064400017600000144000000052141356600660700167750ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_geometry.h" #include #include /* free */ #include #include #include #include "mc_io.h" #if 0 #define __DEBUG #endif #define MC_GEOMETRIES 2 #define MC_GEOMETRY_COLUMNS 0 #define MC_GEOMETRY_ROWS 1 #define MAX_VALUE_LEN 4 #define CHAR_WIDTH 10 /* --- static variables --- */ static char new_values[MC_GEOMETRIES][MAX_VALUE_LEN + 1]; /* 0 - 9999 */ static char old_values[MC_GEOMETRIES][MAX_VALUE_LEN + 1]; /* 0 - 9999 */ static int is_changed; static char *config_keys[MC_GEOMETRIES] = { "cols", "rows", }; static char *labels[MC_GEOMETRIES] = { N_("Columns"), N_("Rows"), }; /* --- static functions --- */ static gint geometry_selected(GtkWidget *widget, gpointer data) { gchar *text; text = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1); if (strlen(text) <= MAX_VALUE_LEN) { strcpy(data, text); } g_free(text); return 1; } /* --- global functions --- */ GtkWidget *mc_geometry_config_widget_new(void) { GtkWidget *hbox; GtkWidget *label; GtkWidget *entry; char *value; int count; hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); for (count = 0; count < MC_GEOMETRIES; count++) { label = gtk_label_new(labels[count]); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); value = mc_get_str_value(config_keys[count]); if (strlen(value) <= MAX_VALUE_LEN) { strcpy(new_values[count], value); strcpy(old_values[count], value); } entry = gtk_entry_new(); gtk_entry_set_text(GTK_ENTRY(entry), value); gtk_widget_show(entry); free(value); #if GTK_CHECK_VERSION(2, 90, 0) gtk_entry_set_width_chars(GTK_ENTRY(entry), MAX_VALUE_LEN); #else gtk_widget_set_size_request(entry, MAX_VALUE_LEN * CHAR_WIDTH, -1); #endif gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 1); g_signal_connect(entry, "changed", G_CALLBACK(geometry_selected), &new_values[count]); } return hbox; } void mc_update_geometry(void) { if (!is_changed) { int count; for (count = 0; count < MC_GEOMETRIES; count++) { if (strcmp(new_values[count], old_values[count])) { is_changed = 1; break; } } } if (is_changed) { char value[MAX_VALUE_LEN + 1 + MAX_VALUE_LEN + 1]; sprintf(value, "%sx%s", new_values[MC_GEOMETRY_COLUMNS], new_values[MC_GEOMETRY_ROWS]); mc_set_str_value("geometry", value); strcpy(old_values[MC_GEOMETRY_COLUMNS], new_values[MC_GEOMETRY_COLUMNS]); strcpy(old_values[MC_GEOMETRY_ROWS], new_values[MC_GEOMETRY_ROWS]); } } mlterm-3.8.9/tool/mlconfig/mc_geometry.h010064400017600000144000000003461356600660700170030ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_GEOMETRY_H__ #define __MC_GEOMETRY_H__ #include GtkWidget *mc_geometry_config_widget_new(void); void mc_update_geometry(void); #endif mlterm-3.8.9/tool/mlconfig/mc_im.c010064400017600000144000000512121356600660700155460ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_im.h" #include /* free */ #include #include #include #include #include #include #include /* USE_WIN32API */ #include #include #include #include #include "mc_combo.h" #include "mc_io.h" #if 0 #define __DEBUG #endif #if defined(USE_WIN32API) #define CONFIG_PATH "." #elif defined(SYSCONFDIR) #define CONFIG_PATH SYSCONFDIR #else #define CONFIG_PATH "/etc" #endif #ifndef LIBDIR #define IM_DIR "/usr/local/lib/mlterm/" #else #define IM_DIR LIBDIR "/mlterm/" #endif #define STR_LEN 256 BL_MAP_TYPEDEF(xim_locale, char *, char *); #define IM_MAX 20 typedef enum im_type { IM_NONE = 0, IM_XIM = 1, IM_OTHER = 2, IM_TYPE_MAX = IM_MAX } im_type_t; typedef im_info_t *(*im_get_info_func_t)(char *, char *); /* --- static variables --- */ static char *cur_locale; static im_type_t im_type; static im_type_t cur_im_type; static char **xims; static char **locales; static u_int num_xims; static int is_changed = 0; static char xim_auto_str[STR_LEN] = ""; static char current_locale_str[STR_LEN] = ""; static char selected_xim_name[STR_LEN] = ""; static char selected_xim_locale[STR_LEN] = ""; static im_info_t *im_info_table[IM_MAX]; static u_int num_info = 0; static im_info_t *selected_im = NULL; static int selected_im_arg = -1; static GtkWidget **im_opt_widget; static GtkWidget *skk_dict_entry; static GtkWidget *skk_sskey_entry; static GtkWidget *wnn_serv_entry; /* --- static functions --- */ static int is_im_plugin(char *file_name) { if (bl_dl_is_module(file_name) && strstr(file_name, "im-")) { return 1; } return 0; } #ifdef USE_WIN32API static im_info_t *get_kbd_info(char *locale, char *encoding) { im_info_t *result; if (!(result = malloc(sizeof(im_info_t)))) { return NULL; } result->num_args = 13; if (!(result->args = malloc(sizeof(char *) * result->num_args))) { free(result); return NULL; } if (!(result->readable_args = malloc(sizeof(char *) * result->num_args))) { free(result->args); free(result); return NULL; } result->readable_args[0] = strdup("Unknown"); result->readable_args[1] = strdup("Arabic"); result->readable_args[2] = strdup("Hebrew"); result->readable_args[3] = strdup("Indic (ASSAMESE)"); result->readable_args[4] = strdup("Indic (BENGALI)"); result->readable_args[5] = strdup("Indic (GUJARATI)"); result->readable_args[6] = strdup("Indic (HINDI)"); result->readable_args[7] = strdup("Indic (KANNADA)"); result->readable_args[8] = strdup("Indic (MALAYALAM)"); result->readable_args[9] = strdup("Indic (ORIYA)"); result->readable_args[10] = strdup("Indic (PUNJABI)"); result->readable_args[11] = strdup("Indic (TAMIL)"); result->readable_args[12] = strdup("Indic (TELUGU)"); result->args[0] = strdup(""); result->args[1] = strdup("arabic"); result->args[2] = strdup("hebrew"); result->args[3] = strdup("isciiassamese"); result->args[4] = strdup("isciibengali"); result->args[5] = strdup("isciigujarati"); result->args[6] = strdup("isciihindi"); result->args[7] = strdup("isciikannada"); result->args[8] = strdup("isciimalayalam"); result->args[9] = strdup("isciioriya"); result->args[10] = strdup("isciipunjabi"); result->args[11] = strdup("isciitamil"); result->args[12] = strdup("isciitelugu"); result->id = strdup("kbd"); result->name = strdup("keyboard"); return result; } #endif static int get_im_info(char *locale, char *encoding) { char *im_dir_path; DIR *dir; struct dirent *d; const char *gui; if ((dir = opendir(IM_DIR))) { im_dir_path = IM_DIR; #if 0 } else if ((dir = opendir("."))) { im_dir_path = ""; #endif } else { #ifdef USE_WIN32API if ((im_info_table[num_info] = get_kbd_info(locale, encoding))) { num_info++; return 1; } #endif return 0; } gui = mc_get_gui(); while ((d = readdir(dir))) { im_info_t *info; char symname[100]; char *p; char *end; bl_dl_handle_t handle; if (d->d_name[0] == '.' || !is_im_plugin(d->d_name)) continue; /* libim-foo.so -> libim-foo */ if (!(p = strchr(d->d_name, '.'))) continue; *p = '\0'; /* libim-foo -> im-foo */ if (!(p = strstr(d->d_name, "im-"))) continue; end = p + strlen(p); if (strcmp(gui, "sdl2") == 0) { end -= 5; if (strcmp(end, "-sdl2") != 0) { continue; } } else if (strcmp(gui, "fb") == 0 || strcmp(gui, "console") == 0 || strcmp(gui, "wayland") == 0) { end -= 3; if (strcmp(end, *gui == 'w' ? "-wl" : "-fb") != 0) { continue; } } if ((handle = bl_dl_open(im_dir_path, p))) { im_get_info_func_t func; *end = '\0'; snprintf(symname, 100, "im_%s_get_info", &p[3]); if ((func = (im_get_info_func_t)bl_dl_func_symbol(handle, symname))) { if ((info = (*func)(locale, encoding))) { im_info_table[num_info] = info; num_info++; } } bl_dl_close(handle); } } return 0; } /* * XIM */ static char *get_xim_locale(char *xim) { int count; for (count = 0; count < num_xims; count++) { if (strcmp(xims[count], xim) == 0) { return locales[count]; } } return NULL; } static gint xim_selected(GtkWidget *widget, gpointer data) { char *locale; snprintf(selected_xim_name, STR_LEN, "%s", gtk_entry_get_text(GTK_ENTRY(widget))); if ((locale = get_xim_locale(selected_xim_name))) { gtk_entry_set_text(GTK_ENTRY(data), locale); } else { gtk_entry_set_text(GTK_ENTRY(data), current_locale_str); } snprintf(selected_xim_locale, STR_LEN, "%s", gtk_entry_get_text(GTK_ENTRY(data))); is_changed = 1; return 1; } static int read_xim_conf(BL_MAP(xim_locale) xim_locale_table, char *filename) { bl_file_t *from; char *key; char *value; BL_PAIR(xim_locale) pair; int result; if (!(from = bl_file_open(filename, "r"))) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " %s couldn't be opened.\n", filename); #endif return 0; } while (bl_conf_io_read(from, &key, &value)) { bl_map_get(xim_locale_table, key, pair); if (pair) { free(pair->value); pair->value = strdup(value); } else { key = strdup(key); value = strdup(value); bl_map_set(result, xim_locale_table, key, value); } } bl_file_close(from); return 1; } static GtkWidget *xim_widget_new(const char *xim_name, const char *xim_locale, const char *cur_locale) { BL_MAP(xim_locale) xim_locale_table; BL_PAIR(xim_locale) * array; u_int size; char *rcpath; char *default_xim_name; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *label; GtkWidget *entry; GtkWidget *combo; GtkWidget *combo_entry; int count; default_xim_name = mc_get_str_value("default_xim_name"); snprintf(xim_auto_str, STR_LEN, _("auto (currently %s)"), default_xim_name); free(default_xim_name); /* * create known xim list from /etc/mlterm/xim and/or * ~/.mlterm/xim. */ bl_map_new_with_size(char *, char *, xim_locale_table, bl_map_hash_str, bl_map_compare_str, 16); bl_set_sys_conf_dir(CONFIG_PATH); if ((rcpath = bl_get_sys_rc_path("mlterm/xim"))) { read_xim_conf(xim_locale_table, rcpath); free(rcpath); } if ((rcpath = bl_get_user_rc_path("mlterm/xim"))) { read_xim_conf(xim_locale_table, rcpath); free(rcpath); } bl_map_get_pairs_array(xim_locale_table, array, size); if ((xims = malloc(sizeof(char *) * (size + 1))) == NULL) return NULL; if ((locales = malloc(sizeof(char *) * (size + 1))) == NULL) { free(xims); return NULL; } for (count = 0; count < size; count++) { xims[count] = array[count]->key; locales[count] = array[count]->value; } xims[count] = xim_auto_str; locales[count] = NULL; num_xims = size + 1; bl_map_destroy(xim_locale_table); /* * create widgets */ vbox = gtk_vbox_new(FALSE, 5); snprintf(current_locale_str, STR_LEN, _("auto (currently %s)"), cur_locale); entry = gtk_entry_new(); snprintf(selected_xim_locale, STR_LEN, "%s", xim_locale ? xim_locale : current_locale_str); gtk_entry_set_text(GTK_ENTRY(entry), selected_xim_locale); snprintf(selected_xim_name, STR_LEN, "%s", xim_name ? xim_name : xim_auto_str); combo = mc_combo_new(_("XIM Server"), xims, num_xims, selected_xim_name, 0, &combo_entry); g_signal_connect(combo_entry, "changed", G_CALLBACK(xim_selected), entry); label = gtk_label_new(_("XIM locale")); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(vbox), combo, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); gtk_widget_show(combo); gtk_widget_show(entry); gtk_widget_show(label); gtk_widget_show(hbox); return vbox; } /* * pluggable ims */ static gint im_selected(GtkWidget *widget, gpointer data) { const char *str; int i; if (selected_im == NULL) return 1; str = (const char *)gtk_entry_get_text(GTK_ENTRY(widget)); for (i = 0; i < selected_im->num_args; i++) if (strcmp(selected_im->readable_args[i], str) == 0) selected_im_arg = i; is_changed = 1; return 1; } static GtkWidget *im_widget_new(int nth_im, const char *value, char *locale) { GtkWidget *combo; GtkWidget *entry; im_info_t *info; int i; int selected = 0; size_t len; info = im_info_table[nth_im]; if (value) { for (i = 1; i < info->num_args; i++) { if (strcmp(info->args[i], value) == 0) { selected = i; } } } if (!info->num_args) return NULL; if (!value || (value && selected)) { char *auto_str; /* * replace gettextized string */ len = strlen(_("auto (currently %s)")) + strlen(info->readable_args[0]) + 1; if ((auto_str = malloc(len))) { snprintf(auto_str, len, _("auto (currently %s)"), info->readable_args[0]); free(info->readable_args[0]); info->readable_args[0] = auto_str; } } else { free(info->readable_args[0]); info->readable_args[0] = strdup(value); } combo = mc_combo_new(_("Option"), info->readable_args, info->num_args, info->readable_args[selected], 1, &entry); g_signal_connect(entry, "changed", G_CALLBACK(im_selected), NULL); return combo; } static gint entry_selected(GtkWidget *widget, gpointer data) { is_changed = 1; return 1; } static GtkWidget *entry_with_label_new(GtkWidget *parent, const char *text, const char *value) { GtkWidget *hbox; GtkWidget *label; GtkWidget *entry; hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(parent), hbox, TRUE, TRUE, 0); gtk_widget_show(hbox); label = gtk_label_new(text); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); entry = gtk_entry_new(); gtk_entry_set_text(GTK_ENTRY(entry), value); g_signal_connect(entry, "changed", G_CALLBACK(entry_selected), entry); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); gtk_widget_show(entry); return entry; } static GtkWidget *combo_with_label_new(GtkWidget *parent, const char *label_name, char **item_names, u_int item_num, const char *value) { GtkWidget *hbox; GtkWidget *combo; GtkWidget *entry; hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(parent), hbox, TRUE, TRUE, 0); gtk_widget_show(hbox); combo = mc_combo_new(label_name, item_names, item_num, value, 0, &entry); gtk_box_pack_start(GTK_BOX(hbox), combo, TRUE, TRUE, 0); gtk_widget_show(combo); g_signal_connect(entry, "changed", G_CALLBACK(entry_selected), entry); return entry; } static GtkWidget *skk_widget_new(char *value) { GtkWidget *vbox; char *dict = NULL; char *sskey = NULL; char buf[2]; char *cands[] = { ";", ":", "Muhenkan", "Henkan", }; /* Same processing as im_skk_new() in im_skk.c */ if (value) { #if 1 /* XXX Compat with 3.8.3 or before. */ if (!strchr(value, '=')) { dict = value; } else #endif { char *next; do { if ((next = strchr(value, ','))) { *(next++) = '\0'; } if (strncmp(value, "sskey=", 6) == 0) { int digit; sskey = value + 6; if (sscanf(sskey, "\\x%x", &digit) == 1) { buf[0] = digit; buf[1] = '\0'; sskey = buf; } } else if (strncmp(value, "dict=", 5) == 0) { dict = value + 5; } } while ((value = next)); } } vbox = gtk_vbox_new(FALSE, 5); skk_dict_entry = entry_with_label_new(vbox, _("Dictionary"), dict ? dict : ""); skk_sskey_entry = combo_with_label_new(vbox, _("Sticky shift key"), cands, sizeof(cands) / sizeof(cands[0]), sskey ? sskey : ""); return vbox; } static char *skk_current_value(void) { const char *dict; const char *sskey; size_t len = 4; char *value; char *p; dict = gtk_entry_get_text(GTK_ENTRY(skk_dict_entry)); if (*dict) { len += (strlen(dict) + 5 + 1); } sskey = gtk_entry_get_text(GTK_ENTRY(skk_sskey_entry)); if (*sskey) { len += (strlen(sskey) + 6 + 1); } value = p = malloc(len); strcpy(p, "skk"); p += 3; if (*dict) { sprintf(p, ":dict=%s", dict); p += strlen(p); } if (*sskey) { char sep = *dict ? ',' : ':'; if (strlen(sskey) == 1) { sprintf(p, "%csskey=\\x%.2x", sep, *sskey); } else { sprintf(p, "%csskey=%s", sep, sskey); } } return value; } static GtkWidget *wnn_widget_new(char *value) { GtkWidget *vbox; vbox = gtk_vbox_new(FALSE, 5); wnn_serv_entry = entry_with_label_new(vbox, _("Server"), value); return vbox; } static char *wnn_current_value(void) { const char *serv; size_t len = 4; char *value; serv = gtk_entry_get_text(GTK_ENTRY(wnn_serv_entry)); if (*serv) { len += (strlen(serv) + 1); } value = malloc(len); if (*serv) { sprintf(value, "wnn:%s", serv); } else { strcpy(value, "wnn"); } return value; } /* * callbacks for radio buttons of im type. */ static gint button_xim_checked(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { if (data) gtk_widget_show(GTK_WIDGET(data)); im_type = IM_XIM; } else { if (data) gtk_widget_hide(GTK_WIDGET(data)); } is_changed = 1; return 1; } static gint button_im_checked(GtkWidget *widget, gpointer data) { int i; int idx = 0; if (data == NULL || num_info == 0) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { im_type = IM_NONE; } } else { for (i = 0; i < num_info; i++) if (im_info_table[i] == data) idx = i; if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { im_type = IM_OTHER + idx; selected_im = data; if (im_opt_widget[idx]) gtk_widget_show(GTK_WIDGET(im_opt_widget[idx])); } else { if (im_opt_widget[idx]) gtk_widget_hide(GTK_WIDGET(im_opt_widget[idx])); } } is_changed = 1; return 1; } /* --- global functions --- */ void mc_im_init(void) { char *encoding = mc_get_str_value("encoding"); cur_locale = mc_get_str_value("locale"); /* XXX leaked */ get_im_info(cur_locale, encoding); free(encoding); } GtkWidget *mc_im_config_widget_new(void) { char *xim_name = NULL; char *xim_locale = NULL; char *value; char *im_name; int i; int index = -1; GtkWidget *xim; GtkWidget *frame; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *radio; GSList *group; value = mc_get_str_value("input_method"); im_name = bl_str_sep(&value, ":"); im_type = IM_NONE; if (strncmp(im_name, "xim", 3) == 0) { im_type = IM_XIM; xim_name = bl_str_sep(&value, ":"); xim_locale = bl_str_sep(&value, ":"); } else if (strncmp(im_name, "none", 4) == 0) { /* do nothing */ } else { for (i = 0; i < num_info; i++) { if (strcmp(im_name, im_info_table[i]->id) == 0) { index = i; im_type = IM_OTHER + i; break; } } } cur_im_type = im_type; if (strcmp(mc_get_gui(), "xlib") != 0) { xim = NULL; } else { xim = xim_widget_new(xim_name, xim_locale, cur_locale); } im_opt_widget = malloc(sizeof(GtkWidget*) * num_info); for (i = 0; i < num_info; i++) { if (strcmp(im_info_table[i]->id, "skk") == 0) im_opt_widget[i] = skk_widget_new(index == i ? value : ""); else if (strcmp(im_info_table[i]->id, "wnn") == 0) im_opt_widget[i] = wnn_widget_new(index == i ? value : ""); else im_opt_widget[i] = im_widget_new(i, index == i ? value : NULL, cur_locale); } free(im_name); frame = gtk_frame_new(_("Input Method")); vbox = gtk_vbox_new(FALSE, 5); gtk_widget_show(vbox); hbox = gtk_hbox_new(FALSE, 5); radio = gtk_radio_button_new_with_label(NULL, xim ? "XIM" : "Default"); g_signal_connect(radio, "toggled", G_CALLBACK(button_xim_checked), xim); gtk_widget_show(GTK_WIDGET(radio)); gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, FALSE, 0); if (im_type == IM_XIM) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); for (i = 0; i < num_info; i++) { group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); radio = gtk_radio_button_new_with_label(group, im_info_table[i]->name); g_signal_connect(radio, "toggled", G_CALLBACK(button_im_checked), im_info_table[i]); gtk_widget_show(GTK_WIDGET(radio)); gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, FALSE, 0); if (index == i) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); } if (strcmp(mc_get_gui(), "xlib") == 0) { group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); radio = gtk_radio_button_new_with_label(group, _("None")); g_signal_connect(radio, "toggled", G_CALLBACK(button_im_checked), NULL); gtk_widget_show(GTK_WIDGET(radio)); gtk_box_pack_start(GTK_BOX(hbox), radio, FALSE, FALSE, 0); if (im_type == IM_NONE) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); } gtk_widget_show(GTK_WIDGET(hbox)); gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); switch (im_type) { case IM_XIM: if (xim) gtk_widget_show(xim); for (i = 0; i < num_info; i++) if (im_opt_widget[i]) gtk_widget_hide(im_opt_widget[i]); break; case IM_NONE: if (xim) gtk_widget_hide(xim); for (i = 0; i < num_info; i++) if (im_opt_widget[i]) gtk_widget_hide(im_opt_widget[i]); break; default: /* OTHER */ if (xim) gtk_widget_hide(xim); for (i = 0; i < num_info; i++) { if (!im_opt_widget[i]) continue; if (i == index) gtk_widget_show(im_opt_widget[i]); else gtk_widget_hide(im_opt_widget[i]); } break; } if (xim) gtk_box_pack_start(GTK_BOX(vbox), xim, TRUE, TRUE, 0); for (i = 0; i < num_info; i++) if (im_opt_widget[i]) gtk_box_pack_start(GTK_BOX(vbox), im_opt_widget[i], TRUE, TRUE, 0); gtk_container_set_border_width(GTK_CONTAINER(vbox), 5); gtk_container_add(GTK_CONTAINER(frame), vbox); is_changed = 0; return frame; } void mc_update_im(void) { char *p; size_t len; if (!is_changed) return; if (strcmp(selected_im->id, "skk") == 0) { p = skk_current_value(); goto end; } else if (strcmp(selected_im->id, "wnn") == 0) { p = wnn_current_value(); goto end; } if (im_type == cur_im_type && selected_im_arg == -1) { is_changed = 0; return; } if (selected_im_arg == -1) { is_changed = 0; selected_im_arg = 0; } switch (im_type) { case IM_XIM: if (strcmp(selected_xim_name, xim_auto_str) == 0) { p = strdup("xim"); } else if (strcmp(selected_xim_locale, current_locale_str) == 0) { len = 3 + 1 + strlen(selected_xim_name) + 1; if (!(p = malloc(sizeof(char) * len))) return; sprintf(p, "xim:%s", selected_xim_name); } else { len = 3 + 1 + strlen(selected_xim_name) + 1 + strlen(selected_xim_locale) + 1; if (!(p = malloc(sizeof(char) * len))) return; sprintf(p, "xim:%s:%s", selected_xim_name, selected_xim_locale); } break; case IM_NONE: p = strdup("none"); break; /* case IM_OTHER: */ default: if (selected_im == NULL) return; if (selected_im_arg == 0) { /* auto */ p = strdup(selected_im->id); } else { len = strlen(selected_im->id) + strlen(selected_im->args[selected_im_arg]) + 2; if (!(p = malloc(len))) return; sprintf(p, "%s:%s", selected_im->id, selected_im->args[selected_im_arg]); } break; } end: mc_set_str_value("input_method", p); selected_im_arg = -1; cur_im_type = im_type; is_changed = 0; free(p); } mlterm-3.8.9/tool/mlconfig/mc_im.h010064400017600000144000000003461356600660700155550ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_IM_H__ #define __MC_IM_H__ #include void mc_im_init(void); GtkWidget *mc_im_config_widget_new(void); void mc_update_im(void); #endif mlterm-3.8.9/tool/mlconfig/mc_io.c010064400017600000144000000130401356600660700155450ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_io.h" #include #include /* malloc */ #include /* STDIN_FILENO */ #include #include #include /* USE_WIN32API */ /* --- static variables --- */ static char *message; static const char *gui; /* --- static functions --- */ static int append_value(const char *key, const char *value) { if (message == NULL) { if ((message = malloc(strlen(key) + 1 + strlen(value) + 1)) == NULL) { return 0; } sprintf(message, "%s=%s", key, value); } else { void *p; int len; len = strlen(message); if ((p = realloc(message, len + 1 + strlen(key) + 1 + strlen(value) + 1)) == NULL) { return 0; } message = p; sprintf(message + len, ";%s=%s", key, value); } return 1; } static char *get_value(const char *key, mc_io_t io) { #define RET_SIZE 1024 int count; char ret[RET_SIZE]; char c; char *p; printf("\x1b]%d;%s\x07", io, key); fflush(stdout); for (count = 0; count < RET_SIZE; count++) { if (read(STDIN_FILENO, &c, 1) == 1) { if (c != '\n') { ret[count] = c; } else { break; } } else { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " %s return from mlterm is illegal.\n", key); #endif return NULL; } } if (count == RET_SIZE) return NULL; ret[count] = '\0'; p = strchr(ret, '='); if (p == NULL || strcmp(ret, "#error") == 0) return NULL; /* #key=value */ return strdup(p + 1); #undef RET_SIZE } /* --- global functions --- */ int mc_exec(const char *cmd) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s\n", cmd); #endif printf("\x1b]%d;%s\x07", mc_io_exec, cmd); fflush(stdout); return 1; } int mc_set_str_value(const char *key, const char *value) { if (value == NULL) { return 0; } if (strcmp(key, "font_policy") == 0) { if (strcmp(value, "unicode") == 0) { return mc_set_flag_value("only_use_unicode_font", 1); } else if (strcmp(value, "nounicode") == 0) { return mc_set_flag_value("not_use_unicode_font", 1); } else { return mc_set_flag_value("only_use_unicode_font", 0) && mc_set_flag_value("not_use_unicode_font", 0); } } else if (strcmp(key, "logging_vt_seq") == 0) { if (strcmp(key, "no") == 0) { return mc_set_flag_value("logging_vt_seq", 0); } else { return mc_set_flag_value("logging_vt_seq", 1) && mc_set_str_value("vt_seq_format", value); } } #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s=%s\n", key, value); #endif return append_value(key, value); } int mc_set_flag_value(const char *key, int flag_val) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s=%s\n", key, value); #endif return append_value(key, (flag_val ? "true" : "false")); } int mc_flush(mc_io_t io) { char *chal; if (message == NULL) { return 1; } if (io == mc_io_set_save && (chal = get_value("challenge", mc_io_get))) { printf("\x1b]%d;%s;%s\x07", io, chal, message); } else { printf("\x1b]%d;%s\x07", io, message); } fflush(stdout); #if 0 fprintf(stderr, "%s\n", message); #endif free(message); message = NULL; return 1; } char *mc_get_str_value(const char *key) { char *value; if (strcmp(key, "font_policy") == 0) { if (mc_get_flag_value("only_use_unicode_font")) { return strdup("unicode"); } else if (mc_get_flag_value("not_use_unicode_font")) { return strdup("nounicode"); } else { return strdup("noconv"); } } else if (strcmp(key, "logging_vt_seq") == 0) { if (mc_get_flag_value("logging_vt_seq")) { return mc_get_str_value("vt_seq_format"); } else { return strdup("no"); } } if ((value = get_value(key, mc_io_get)) == NULL) { return strdup("error"); } else { return value; } } int mc_get_flag_value(const char *key) { char *value; if ((value = get_value(key, mc_io_get)) == NULL) { return 0; } if (strcmp(value, "true") == 0) { free(value); return 1; } else { free(value); return 0; } } const char *mc_get_gui(void) { if (!gui && !(gui = get_value("gui", mc_io_get))) { return "xlib"; } return gui; } int mc_set_font_name(mc_io_t io, const char *file, const char *cs, const char *font_name) { char *chal; if (io == mc_io_set_save_font && (chal = get_value("challenge", mc_io_get))) { printf("\x1b]%d;%s;%s:%s=%s\x07", io, chal, file, cs, font_name); } else { printf("\x1b]%d;%s:%s=%s\x07", io, file, cs, font_name); } fflush(stdout); return 1; } char *mc_get_font_name(const char *file, const char *cs) { size_t len; char *value; char *key; len = strlen(cs) + 1; if (file) { len += (strlen(file) + 2); } if ((key = alloca(len))) { sprintf(key, "%s%s%s", file ? file : "", file ? ":" : "", cs); if ((value = get_value(key, mc_io_get_font))) { return value; } } return strdup("error"); } int mc_set_color_name(mc_io_t io, const char *color, const char *value) { char *chal; if (io == mc_io_set_save_font && (chal = get_value("challenge", mc_io_get))) { printf("\x1b]%d;%s;color:%s=%s\x07", io, chal, color, value); } else { printf("\x1b]%d;color:%s=%s\x07", io, color, value); } fflush(stdout); return 1; } char *mc_get_color_name(const char *color) { char *key; char *value; if ((key = alloca(6 + strlen(color) + 1))) { sprintf(key, "color:%s", color); if ((value = get_value(key, mc_io_get_color))) { return value; } } return strdup("error"); } mlterm-3.8.9/tool/mlconfig/mc_io.h010064400017600000144000000016631356600660700155620ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_IO_H__ #define __MC_IO_H__ typedef enum { mc_io_exec = 5379, mc_io_set = 5379, mc_io_get = 5381, mc_io_set_save = 5383, mc_io_set_font = 5379, mc_io_get_font = 5381, mc_io_set_save_font = 5383, mc_io_set_color = 5379, mc_io_get_color = 5381, mc_io_set_save_color = 5383, } mc_io_t; int mc_exec(const char *cmd); int mc_set_str_value(const char *key, const char *value); int mc_set_flag_value(const char *key, int flag_val); int mc_flush(mc_io_t io); char *mc_get_str_value(const char *key); int mc_get_flag_value(const char *key); const char *mc_get_gui(void); int mc_set_font_name(mc_io_t io, const char *file, const char *cs, const char *font_name); char *mc_get_font_name(const char *file, const char *cs); int mc_set_color_name(mc_io_t io, const char *color, const char *value); char *mc_get_color_name(const char *color); #endif mlterm-3.8.9/tool/mlconfig/mc_logsize.c010064400017600000144000000027231356600660700166200ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_logsize.h" #include #include /* free */ #include #include #include #include "mc_combo.h" #include "mc_io.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static char *new_logsize = NULL; static char *old_logsize = NULL; static int is_changed; /* --- static functions --- */ static gint logsize_selected(GtkWidget *widget, gpointer data) { g_free(new_logsize); new_logsize = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s logsize is selected.\n", new_logsize); #endif return 1; } /* --- global functions --- */ GtkWidget *mc_logsize_config_widget_new(void) { GtkWidget *combo; GtkWidget *entry; char *logsizes[] = { "128", "256", "512", "1024", "unlimited", }; new_logsize = strdup(old_logsize = mc_get_str_value("logsize")); is_changed = 0; combo = mc_combo_new_with_width(_("Backlog size (lines)"), logsizes, sizeof(logsizes) / sizeof(logsizes[0]), new_logsize, 0, 50, &entry); g_signal_connect(entry, "changed", G_CALLBACK(logsize_selected), NULL); return combo; } void mc_update_logsize(void) { if (strcmp(new_logsize, old_logsize)) is_changed = 1; if (is_changed) { mc_set_str_value("logsize", new_logsize); free(old_logsize); old_logsize = strdup(new_logsize); } } mlterm-3.8.9/tool/mlconfig/mc_logsize.h010064400017600000144000000003421356600660700166200ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_LOGSIZE_H__ #define __MC_LOGSIZE_H__ #include GtkWidget *mc_logsize_config_widget_new(void); void mc_update_logsize(void); #endif mlterm-3.8.9/tool/mlconfig/mc_opentype.c010064400017600000144000000217461356600660700170150ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_unicode_areas.h" #include #include #include #include #include #include /* bl_str_sep */ #include "mc_io.h" #include "mc_flags.h" #if GTK_CHECK_VERSION(2, 14, 0) #define FEATURE_LEN 4 #define SCRIPT_LEN 4 /* --- static variables --- */ static char *features; static char *script; static GtkWidget *features_button; static GtkWidget *script_button; /* --- static functions --- */ static char *ascii_strcasestr(const char *str1 /* separated by ',' */, const char *str2 /* 4 bytes/Lower case */) { const char *p1 = str1; const char *p2 = str2; while (1) { if ((*p1|0x20) == *p2) { if (*(++p2) == '\0') { return p1 - 3; } if (*(++p1) == '\0') { return NULL; } } else { do { if (*p1 == '\0') { return NULL; } } while (*(p1++) != ','); p2 = str2; } } } static int contains(char *values, char *value) { char *p; if ((p = ascii_strcasestr(values, value))) { if (p == values || *(p - 1) == ',') { p += strlen(value); if (*p == '\0' || *p == ',') { return 1; } } } return 0; } static void edit_features(GtkWidget *widget, gpointer data) { static char *features_tbl[] = { "c2pc", "c2sc", "calt", "case", "clig", "cpsp", "cswh", "dlig", "expt", "frac", "fwid", "halt", "hist", "hkna", "hlig", "hngl", "hojo", "hwid", "ital", "jp04", "jp78", "jp83", "jp90", "liga", "lnum", "mgrk", "nlck", "onum", "ordn", "palt", "pcap", "pkna", "pnum", "pwid", "qwid", "ruby", "sinf", "smcp", "smpl", "ss01", "ss02", "ss03", "ss04", "ss05", "ss06", "ss07", "ss08", "ss09", "ss10", "ss11", "ss12", "ss13", "ss14", "ss15", "ss16", "ss17", "ss18", "ss19", "ss20", "subs", "sups", "swsh", "titl", "tnam", "tnum", "trad", "twid", "unic", "valt", "vert", "vhal", "vkna", "vpal", "vrt2", "zero", }; GtkWidget *buttons[sizeof(features_tbl) / sizeof(features_tbl[0])]; GtkWidget *dialog; GtkWidget *vbox; GtkWidget *hbox; u_int count; char *value; if (features) { value = strdup(features); } else { value = mc_get_str_value("ot_features"); } dialog = gtk_dialog_new_with_buttons(_("Select opentype features"), NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox); gtk_box_pack_start(gtk_dialog_get_content_area(GTK_DIALOG(dialog)), vbox, FALSE, FALSE, 0); for (count = 0; count < sizeof(features_tbl) / sizeof(features_tbl[0]); count++) { if (count % 8 == 0) { hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(vbox, hbox, FALSE, FALSE, 0); } buttons[count] = gtk_check_button_new_with_label(features_tbl[count]); if (contains(value, features_tbl[count])) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(buttons[count]), TRUE); } gtk_widget_show(buttons[count]); gtk_box_pack_start(hbox, buttons[count], FALSE, FALSE, 0); } if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { char *new_value; if ((new_value = malloc((FEATURE_LEN + 1) * (sizeof(features_tbl) / sizeof(features_tbl[0]))))) { char *p = new_value; for (count = 0; count < sizeof(features_tbl) / sizeof(features_tbl[0]); count++) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[count]))) { strcpy(p, features_tbl[count]); p += FEATURE_LEN; *(p++) = ','; } } if (p != new_value) { p--; } *p = '\0'; } if (g_ascii_strcasecmp(value, new_value) != 0) { free(features); features = new_value; } else { free(new_value); } } free(value); gtk_widget_destroy(dialog); } static void edit_script(GtkWidget *widget, gpointer data) { static char *scripts_tbl[] = { "zyyy", "zinh", "zzzz", "arab", "armn", "beng", "cyrl", "deva", "geor", "grek", "gujr", "guru", "hang", "hani", "hebr", "hira", "knda", "kana", "laoo", "latn", "mlym", "orya", "taml", "telu", "thai", "tibt", "bopo", "brai", "cans", "cher", "ethi", "khmr", "mong", "mymr", "ogam", "runr", "sinh", "syrc", "thaa", "yiii", "dsrt", "goth", "ital", "buhd", "hano", "tglg", "tagb", "cprt", "limb", "linb", "osma", "shaw", "tale", "ugar", "bugi", "copt", "glag", "khar", "talu", "xpeo", "sylo", "tfng", "bali", "xsux", "nkoo", "phag", "phnx", "cari", "cham", "kali", "lepc", "lyci", "lydi", "olck", "rjng", "saur", "sund", "vaii", "avst", "bamu", "egyp", "armi", "phli", "prti", "java", "kthi", "lisu", "mtei", "sarb", "orkh", "samr", "lana", "tavt", "batk", "brah", "mand", "cakm", "merc", "mero", "plrd", "shrd", "sora", "takr", "bass", "aghb", "dupl", "elba", "gran", "khoj", "sind", "lina", "mahj", "mani", "mend", "modi", "mroo", "nbat", "narb", "perm", "hmng", "palm", "pauc", "phlp", "sidd", "tirh", "wara", "ahom", "hluw", "hatr", "mult", "hung", "sgnw", }; GtkWidget *buttons[sizeof(scripts_tbl) / sizeof(scripts_tbl[0])]; GtkWidget *dialog; GtkWidget *vbox; GtkWidget *hbox; GtkWidget *group = NULL; u_int count; char *value; if (script) { value = strdup(script); } else { value = mc_get_str_value("ot_script"); } dialog = gtk_dialog_new_with_buttons(_("Select opentype scripts"), NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); vbox = gtk_vbox_new(FALSE, 0); gtk_widget_show(vbox); gtk_box_pack_start(gtk_dialog_get_content_area(GTK_DIALOG(dialog)), vbox, FALSE, FALSE, 0); for (count = 0; count < sizeof(scripts_tbl) / sizeof(scripts_tbl[0]); count++) { if (count % 8 == 0) { hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); gtk_box_pack_start(vbox, hbox, FALSE, FALSE, 0); } buttons[count] = gtk_radio_button_new_with_label(group, scripts_tbl[count]); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(buttons[count])); if (g_ascii_strcasecmp(value, scripts_tbl[count]) == 0) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(buttons[count]), TRUE); } gtk_widget_show(buttons[count]); gtk_box_pack_start(hbox, buttons[count], FALSE, FALSE, 0); } if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { char *new_value; if ((new_value = malloc(SCRIPT_LEN + 1))) { for (count = 0; count < sizeof(scripts_tbl) / sizeof(scripts_tbl[0]); count++) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(buttons[count]))) { strcpy(new_value, scripts_tbl[count]); break; } } } if (g_ascii_strcasecmp(value, new_value) != 0) { free(script); script = new_value; } else { free(new_value); } } free(value); gtk_widget_destroy(dialog); } static gint button_checked(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { gtk_widget_set_sensitive(features_button, 1); gtk_widget_set_sensitive(script_button, 1); } else { gtk_widget_set_sensitive(features_button, 0); gtk_widget_set_sensitive(script_button, 0); } return 1; } /* --- global functions --- */ GtkWidget *mc_opentype_config_widget_new(void) { GtkWidget *hbox; GtkWidget *widget; hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); widget = mc_flag_config_widget_new(MC_FLAG_OTLAYOUT); gtk_widget_show(widget); gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0); g_signal_connect(widget, "toggled", G_CALLBACK(button_checked), NULL); features_button = gtk_button_new_with_label(_("Features")); gtk_widget_show(features_button); gtk_box_pack_start(GTK_BOX(hbox), features_button, FALSE, FALSE, 4); g_signal_connect(features_button, "clicked", G_CALLBACK(edit_features), NULL); script_button = gtk_button_new_with_label(_("Script")); gtk_widget_show(script_button); gtk_box_pack_start(GTK_BOX(hbox), script_button, FALSE, FALSE, 4); g_signal_connect(script_button, "clicked", G_CALLBACK(edit_script), NULL); button_checked(widget, NULL); return hbox; } void mc_update_opentype(void) { if (features) { mc_set_str_value("ot_features", features); } if (script) { mc_set_str_value("ot_script", script); } } #else GtkWidget *mc_opentype_config_widget_new(void) { GtkWidget *dialog; dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "This dialog requires GTK+-2.14 or later"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return NULL; } void mc_update_opentype(void) { } #endif mlterm-3.8.9/tool/mlconfig/mc_opentype.h010064400017600000144000000003461356600660700170130ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_OPENTYPE_H__ #define __MC_OPENTYPE_H__ #include GtkWidget *mc_opentype_config_widget_new(void); void mc_update_opentype(void); #endif mlterm-3.8.9/tool/mlconfig/mc_pty.c010064400017600000144000000047571356600660700157710ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_pty.h" #include #include #include /* malloc */ #include /* bl_str_sep */ #include "mc_combo.h" #include "mc_io.h" #define MAX_TERMS (sizeof(long) * 8) /* this must coincide with xwindow/x_term_manager.c */ /* --- static variables --- */ static char *new_pty = NULL; static char *old_pty = NULL; /* --- static functions --- */ static gint selected(GtkWidget *widget, gpointer data) { g_free(new_pty); new_pty = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1); return 1; } static char *get_pty_title(char *dev) { char query[256], *name; if (strlen(dev) > 256 - 10) return strdup(""); sprintf(query, "%s:pty_name", dev); name = mc_get_str_value(query); return name; } static char *get_pty_entry(char *dev) { char *title, *entry; title = get_pty_title(dev); /* Assumed that dev always starts with "/dev/". */ if (title == NULL) return dev + 5; if (strcmp(title, dev) == 0 || strlen(title) == 0) { free(title); return dev + 5; } entry = malloc(strlen(dev + 5) + strlen(title) + 4); if (entry) { sprintf(entry, "%s (%s)", dev + 5, title); free(title); return entry; } else { free(title); return dev + 5; } } /* --- global functions --- */ GtkWidget *mc_pty_config_widget_new(void) { char *my_pty; char *pty_list; char *ptys[MAX_TERMS]; int num; GtkWidget *combo; GtkWidget *entry; my_pty = mc_get_str_value("pty_name"); pty_list = mc_get_str_value("pty_list"); if (my_pty == NULL) return NULL; ptys[0] = get_pty_entry(my_pty); num = 1; while (pty_list) { char *p; if (strlen(pty_list) <= 5) break; p = strchr(pty_list, ':'); if (!p) break; if (*(p + 1) == '0') { *p = 0; ptys[num] = get_pty_entry(pty_list); num++; } pty_list = strchr(p + 1, ';'); if (pty_list) pty_list++; } new_pty = strdup(old_pty = strdup(my_pty + 5)); combo = mc_combo_new("", ptys, num, new_pty, 1, &entry); g_signal_connect(entry, "changed", G_CALLBACK(selected), NULL); return combo; } void mc_select_pty(void) { if (strcmp(new_pty, old_pty) != 0) { char *cmd; char *space; if ((cmd = alloca(11 + 5 + strlen(new_pty) + 1)) == NULL) { return; } sprintf(cmd, "select_pty /dev/%s", new_pty); space = strchr(cmd + 11, ' '); if (space) *space = 0; mc_exec(cmd); free(old_pty); old_pty = strdup(new_pty); } } mlterm-3.8.9/tool/mlconfig/mc_pty.h010064400017600000144000000003221356600660700157560ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_PTY_H__ #define __MC_PTY_H__ #include GtkWidget *mc_pty_config_widget_new(void); void mc_select_pty(void); #endif mlterm-3.8.9/tool/mlconfig/mc_radio.c010064400017600000144000000133671356600660700162500ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_radio.h" #include #include /* free */ #include #include #include #include "mc_io.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static int new_values[MC_RADIOS]; static int old_values[MC_RADIOS]; static int is_changed[MC_RADIOS]; static void (*funcs[MC_RADIOS])(void); static char *config_keys[MC_RADIOS] = { "mod_meta_mode", "bel_mode", "scrollbar_mode", "vertical_mode", "box_drawing_font", "font_policy", "logging_vt_seq", }; static char *config_values[MC_RADIOS][4] = { { "none", "esc", "8bit", NULL, }, { "none", "sound", "visual", "sound|visual", }, { "none", "left", "right", "autohide", }, { "none", "cjk", "mongol", NULL, }, { "noconv", "unicode", "decsp", NULL, }, { "noconv", "unicode", "nounicode", NULL, }, { "no", "raw", "ttyrec", }, }; static char *labels[MC_RADIOS][5] = { { N_("Meta key outputs"), N_("None"), N_("Esc"), N_("8bit"), NULL, }, { N_("Bell mode"), N_("None"), N_("Sound"), N_("Visual"), N_("Both"), }, { N_("Position"), N_("None"), N_("Left"), N_("Right"), N_("Auto hide"), }, { N_("Vertical mode"), N_("None"), N_("CJK"), N_("Mongol"), NULL, }, { N_("Box drawing"), N_("As it is"), N_("Unicode"), N_("DEC Special"), NULL, }, { N_("Font policy"), N_("As it is"), N_("Always unicode"), N_("Never unicode"), NULL, }, { N_("Save log"), N_("No"), N_("Raw format"), N_("Ttyrec format"), NULL, }, }; /* --- static functions --- */ static void update_value(int *data, int num) { int id; id = data - new_values; *data = num; if (funcs[id]) { (*funcs[id])(); } } static gint button1_checked(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { update_value(data, 0); } return 1; } static gint button2_checked(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { update_value(data, 1); } return 1; } static gint button3_checked(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { update_value(data, 2); } return 1; } static gint button4_checked(GtkWidget *widget, gpointer data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { update_value(data, 3); } return 1; } /* --- global functions --- */ GtkWidget *mc_radio_config_widget_new(int id) { GtkWidget *label; GtkWidget *hbox; GtkWidget *radio; GSList *group; char *value; value = mc_get_str_value(config_keys[id]); hbox = gtk_hbox_new(FALSE, 0); label = gtk_label_new(_(labels[id][0])); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); group = NULL; radio = gtk_radio_button_new_with_label(group, _(labels[id][1])); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); g_signal_connect(radio, "toggled", G_CALLBACK(button1_checked), &new_values[id]); gtk_widget_show(GTK_WIDGET(radio)); gtk_box_pack_start(GTK_BOX(hbox), radio, TRUE, FALSE, 0); if (strcmp(value, config_values[id][0]) == 0) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); new_values[id] = old_values[id] = 0; } radio = gtk_radio_button_new_with_label(group, _(labels[id][2])); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); g_signal_connect(radio, "toggled", G_CALLBACK(button2_checked), &new_values[id]); gtk_widget_show(GTK_WIDGET(radio)); gtk_box_pack_start(GTK_BOX(hbox), radio, TRUE, FALSE, 0); if (strcmp(value, config_values[id][1]) == 0) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); new_values[id] = old_values[id] = 1; } radio = gtk_radio_button_new_with_label(group, _(labels[id][3])); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); g_signal_connect(radio, "toggled", G_CALLBACK(button3_checked), &new_values[id]); gtk_widget_show(GTK_WIDGET(radio)); gtk_box_pack_start(GTK_BOX(hbox), radio, TRUE, FALSE, 0); if (strcmp(value, config_values[id][2]) == 0) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); new_values[id] = old_values[id] = 2; } if (config_values[id][3]) { radio = gtk_radio_button_new_with_label(group, _(labels[id][4])); group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); g_signal_connect(radio, "toggled", G_CALLBACK(button4_checked), &new_values[id]); gtk_widget_show(GTK_WIDGET(radio)); gtk_box_pack_start(GTK_BOX(hbox), radio, TRUE, FALSE, 0); if (strcmp(value, config_values[id][3]) == 0) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), TRUE); new_values[id] = old_values[id] = 3; } } #if GTK_CHECK_VERSION(2, 12, 0) if (id == MC_RADIO_LOG_VTSEQ) { char *pty; if ((pty = mc_get_str_value("pty_name"))) { char *p; char *msg; for (p = pty; *p; p++) { if (*p == '/') { *p = '_'; } } /* 35 is "You can do 'ttyplay ~/.mlterm/.log'" */ if (strcmp(pty, "error") != 0 && (msg = malloc(35 + strlen(pty + 5) + 1))) { sprintf(msg, "Log VT sequence in ~/.mlterm/%s.log", pty + 5); gtk_widget_set_tooltip_text(label, msg); sprintf(msg, "You can do \'ttyplay ~/.mlterm/%s.log\'", pty + 5); gtk_widget_set_tooltip_text(radio, msg); free(msg); } free(pty); } } #endif return hbox; } void mc_update_radio(int id) { if (new_values[id] != old_values[id]) { is_changed[id] = 1; } if (is_changed[id]) { mc_set_str_value(config_keys[id], config_values[id][new_values[id]]); old_values[id] = new_values[id]; } } int mc_radio_get_value(int id) { return new_values[id]; } void mc_radio_set_callback(int id, void (*func)(void)) { funcs[id] = func; } mlterm-3.8.9/tool/mlconfig/mc_radio.h010064400017600000144000000010431356600660700162410ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_RADIO_H__ #define __MC_RADIO_H__ #include #define MC_RADIOS 7 #define MC_RADIO_MOD_META_MODE 0 #define MC_RADIO_BELL_MODE 1 #define MC_RADIO_SB_MODE 2 #define MC_RADIO_VERTICAL_MODE 3 #define MC_RADIO_BOX_DRAWING 4 #define MC_RADIO_FONT_POLICY 5 #define MC_RADIO_LOG_VTSEQ 6 GtkWidget *mc_radio_config_widget_new(int id); void mc_update_radio(int id); void mc_radio_set_callback(int id, void (*func)(void)); int mc_radio_get_value(int id); #endif mlterm-3.8.9/tool/mlconfig/mc_ratio.c010064400017600000144000000040151356600660700162560ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_ratio.h" #include #include /* free */ #include #include #include #include "mc_combo.h" #include "mc_io.h" #if 0 #define __DEBUG #endif #define MAX_VALUE_LEN 3 /* --- static variables --- */ static char new_values[MC_RATIOS][MAX_VALUE_LEN + 1]; /* 0 - 100 */ static char old_values[MC_RATIOS][MAX_VALUE_LEN + 1]; /* 0 - 100 */ static int is_changed[MC_RATIOS]; static char *config_keys[MC_RATIOS] = { "contrast", "gamma", "brightness", "fade_ratio", "screen_width_ratio", }; static char *labels[MC_RATIOS] = { N_("Contrast "), N_("Gamma"), N_("Brightness"), N_("Fade ratio on unfocus"), N_("Screen size ratio against font size") }; /* --- static functions --- */ static gint ratio_selected(GtkWidget *widget, gpointer data) { gchar *text; text = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1); if (strlen(text) <= MAX_VALUE_LEN) { strcpy(data, text); } g_free(text); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s ratio is selected.\n", text); #endif return 1; } /* --- global functions --- */ GtkWidget *mc_ratio_config_widget_new(int id) { char *value; GtkWidget *combo; GtkWidget *entry; char *ratios[] = { "100", "90", "80", "70", "60", "50", "40", "30", "20", "10", }; value = mc_get_str_value(config_keys[id]); if (strlen(value) <= MAX_VALUE_LEN) { strcpy(new_values[id], value); strcpy(old_values[id], value); } free(value); combo = mc_combo_new_with_width(_(labels[id]), ratios, sizeof(ratios) / sizeof(ratios[0]), new_values[id], 0, 50, &entry); g_signal_connect(entry, "changed", G_CALLBACK(ratio_selected), &new_values[id]); return combo; } void mc_update_ratio(int id) { if (strcmp(new_values[id], old_values[id])) { is_changed[id] = 1; } if (is_changed[id]) { mc_set_str_value(config_keys[id], new_values[id]); strcpy(old_values[id], new_values[id]); } } mlterm-3.8.9/tool/mlconfig/mc_ratio.h010064400017600000144000000005771356600660700162740ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_RATIO_H__ #define __MC_RATIO_H__ #include #define MC_RATIOS 5 #define MC_RATIO_CONTRAST 0 #define MC_RATIO_GAMMA 1 #define MC_RATIO_BRIGHTNESS 2 #define MC_RATIO_FADE 3 #define MC_RATIO_SCREEN_WIDTH 4 GtkWidget *mc_ratio_config_widget_new(int id); void mc_update_ratio(int id); #endif mlterm-3.8.9/tool/mlconfig/mc_sb_view.c010064400017600000144000000057011356600660700166010ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_sb_view.h" #include #include /* free */ #include #include #include #include #include #include #include "mc_combo.h" #include "mc_io.h" #ifndef XDATADIR #define SB_DIR "/usr/local/share/mlterm/scrollbars" #else #define SB_DIR XDATADIR "/mlterm/scrollbars" #endif #define MAX_SCROLLBARS 100 #if 0 #define __DEBUG #endif /* --- static variables --- */ static char *new_sb_view_name = NULL; static char *old_sb_view_name = NULL; static int is_changed; /* --- static functions --- */ static gint sb_view_name_selected(GtkWidget *widget, gpointer data) { free(new_sb_view_name); new_sb_view_name = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s sb_view_name is selected.\n", new_sb_view_name); #endif return 1; } static int has_rc_file(char *dirname, char *sbdirname) { DIR *d; struct dirent *e; char path[PATH_MAX]; int result = 0; snprintf(path, PATH_MAX, "%s/%s", dirname, sbdirname); if (!(d = opendir(path))) return 0; while ((e = readdir(d))) { if (strcmp("rc", e->d_name) == 0) { result = 1; break; } } closedir(d); return result; } static int read_sb_names(char *dirname, char **sbnames, int n) { int n0, j; DIR *d; struct dirent *e; d = opendir(dirname); if (!d) return n; n0 = n; while (n < MAX_SCROLLBARS) { ignore: e = readdir(d); if (!e) break; if (e->d_name[0] == '.' || !has_rc_file(dirname, e->d_name)) continue; sbnames[n] = strdup(e->d_name); if (!sbnames[n]) break; for (j = 0; j < n0; j++) { if (!strcmp(sbnames[n], sbnames[j])) goto ignore; } n++; } closedir(d); return n; } /* --- global functions --- */ GtkWidget *mc_sb_view_config_widget_new(void) { char *sb_view0[] = {"simple", "sample", "sample3", "athena", "motif", "mozmodern", "next"}; char *sb_view_names[MAX_SCROLLBARS]; char *userdir; int n; GtkWidget *combo; GtkWidget *entry; for (n = 0; n < sizeof(sb_view0) / sizeof(sb_view0[0]); n++) { sb_view_names[n] = sb_view0[n]; } userdir = bl_get_user_rc_path("mlterm/scrollbars"); if (userdir) { n = read_sb_names(userdir, sb_view_names, n); free(userdir); } n = read_sb_names(SB_DIR, sb_view_names, n); new_sb_view_name = strdup(old_sb_view_name = mc_get_str_value("scrollbar_view_name")); is_changed = 0; combo = mc_combo_new(_("View"), sb_view_names, n, new_sb_view_name, 0, &entry); g_signal_connect(entry, "changed", G_CALLBACK(sb_view_name_selected), NULL); return combo; } void mc_update_sb_view_name(void) { if (strcmp(new_sb_view_name, old_sb_view_name)) is_changed = 1; if (is_changed) { mc_set_str_value("scrollbar_view_name", new_sb_view_name); free(old_sb_view_name); old_sb_view_name = strdup(new_sb_view_name); } } mlterm-3.8.9/tool/mlconfig/mc_sb_view.h010064400017600000144000000003471356600660700166070ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_SB_VIEW_H__ #define __MC_SB_VIEW_H__ #include GtkWidget *mc_sb_view_config_widget_new(void); void mc_update_sb_view_name(void); #endif mlterm-3.8.9/tool/mlconfig/mc_space.c010064400017600000144000000044071356600660700162400ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_space.h" #include #include /* free */ #include #include #include #include "mc_combo.h" #include "mc_io.h" #if 0 #define __DEBUG #endif #define MAX_VALUE_LEN 2 /* --- static variables --- */ static char new_values[MC_SPACES][MAX_VALUE_LEN + 1]; /* -9...99 */ static char old_values[MC_SPACES][MAX_VALUE_LEN + 1]; /* -9...99 */ static int is_changed[MC_SPACES]; static char *config_keys[MC_SPACES] = { "line_space", "letter_space", "baseline_offset", "underline_offset", }; static char *labels[MC_SPACES] = { N_("Line space (pixels)"), N_("Letter space (pixels)"), N_("Baseline position (pixels)"), N_("Underline position (pixels)"), }; /* --- static functions --- */ static gint space_selected(GtkWidget *widget, gpointer data) { gchar *text; text = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1); if (strlen(text) <= MAX_VALUE_LEN) { strcpy(data, text); } g_free(text); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s space is selected.\n", text); #endif return 1; } /* --- global functions --- */ GtkWidget *mc_space_config_widget_new(int id) { char *value; GtkWidget *combo; GtkWidget *entry; char *spaces[] = { "3", "2", "1", "0", "-1", "-2", }; char *spaces2[] = { "5", "4", "3", "2", "1", "0", }; value = mc_get_str_value(config_keys[id]); if (strlen(value) <= MAX_VALUE_LEN) { strcpy(new_values[id], value); strcpy(old_values[id], value); } free(value); if (id == MC_SPACE_LETTER) { combo = mc_combo_new_with_width(_(labels[id]), spaces2, sizeof(spaces2) / sizeof(spaces2[0]), new_values[id], 0, 20, &entry); } else { combo = mc_combo_new_with_width(_(labels[id]), spaces, sizeof(spaces) / sizeof(spaces[0]), new_values[id], 0, 20, &entry); } g_signal_connect(entry, "changed", G_CALLBACK(space_selected), &new_values[id]); return combo; } void mc_update_space(int id) { if (strcmp(new_values[id], old_values[id])) { is_changed[id] = 1; } if (is_changed[id]) { mc_set_str_value(config_keys[id], new_values[id]); strcpy(old_values[id], new_values[id]); } } mlterm-3.8.9/tool/mlconfig/mc_space.h010064400017600000144000000005361356600660700162440ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_SPACE_H__ #define __MC_SPACE_H__ #include #define MC_SPACES 4 #define MC_SPACE_LINE 0 #define MC_SPACE_LETTER 1 #define MC_SPACE_BASELINE 2 #define MC_SPACE_UNDERLINE 3 GtkWidget *mc_space_config_widget_new(int id); void mc_update_space(int id); #endif mlterm-3.8.9/tool/mlconfig/mc_tabsize.c010064400017600000144000000026671356600660700166140ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_tabsize.h" #include #include /* free */ #include #include #include #include "mc_combo.h" #include "mc_io.h" #if 0 #define __DEBUG #endif /* --- static variables --- */ static char *new_tabsize = NULL; static char *old_tabsize = NULL; static int is_changed; /* --- static functions --- */ static gint tabsize_selected(GtkWidget *widget, gpointer data) { g_free(new_tabsize); new_tabsize = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1); #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " %s tabsize is selected.\n", new_tabsize); #endif return 1; } /* --- global functions --- */ GtkWidget *mc_tabsize_config_widget_new(void) { GtkWidget *combo; GtkWidget *entry; char *tabsizes[] = { "8", "4", "2", }; new_tabsize = strdup(old_tabsize = mc_get_str_value("tabsize")); is_changed = 0; combo = mc_combo_new_with_width(_("Tab width (columns)"), tabsizes, sizeof(tabsizes) / sizeof(tabsizes[0]), new_tabsize, 0, 20, &entry); g_signal_connect(entry, "changed", G_CALLBACK(tabsize_selected), NULL); return combo; } void mc_update_tabsize(void) { if (strcmp(new_tabsize, old_tabsize)) is_changed = 1; if (is_changed) { mc_set_str_value("tabsize", new_tabsize); free(old_tabsize); old_tabsize = strdup(new_tabsize); } } mlterm-3.8.9/tool/mlconfig/mc_tabsize.h010064400017600000144000000003421356600660700166050ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_TABSIZE_H__ #define __MC_TABSIZE_H__ #include GtkWidget *mc_tabsize_config_widget_new(void); void mc_update_tabsize(void); #endif mlterm-3.8.9/tool/mlconfig/mc_unicode_areas.c010064400017600000144000000136771356600660700177570ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_unicode_areas.h" #include #include #include #include #include #include /* bl_str_sep */ #include "mc_io.h" #if GTK_CHECK_VERSION(2, 14, 0) /* --- static functions --- */ static void add_row(GtkWidget *widget, gpointer p) { GtkListStore *store; GtkTreeIter iter; store = p; gtk_list_store_append(store, &iter); } static void delete_row(GtkWidget *widget, gpointer p) { GtkTreeView *view; GtkTreeModel *store; GtkTreeIter itr; view = p; gtk_tree_selection_get_selected(gtk_tree_view_get_selection(view), &store, &itr); gtk_list_store_remove(GTK_LIST_STORE(store), &itr); } static int check_hex(const gchar *text) { const gchar *p; int count; for (count = 0, p = text; *p; p++) { if (++count > 17 || /* 17: XXXXXXXX-XXXXXXXX */ (*p != '-' && (*p < '0' || ('9' < *p && *p < 'A') || ('F' < *p && *p < 'a') || 'f' < *p))) { return 0; } } return 1; } static void edited(GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer data) { int min; int max; int num; GtkListStore *store; GtkTreeIter itr; GtkTreePath *treepath; GtkWidget *dialog; if (*new_text == '\0') { /* do nothing */ } else if ((num = sscanf(new_text, "%x-%x", &min, &max)) == 2 || (num = sscanf(new_text, "%x", &min)) == 1) { if (!check_hex(new_text)) { goto error1; } else if (num == 2 && min > max) { goto error2; } else { gchar *prepended; prepended = alloca(strlen(new_text) + 3); sprintf(prepended, "U+%s", new_text); new_text = prepended; } } else if ((num = sscanf(new_text, "U+%x-%x", &min, &max)) == 2 || (num = sscanf(new_text, "U+%x", &min)) == 1) { if (!check_hex(new_text + 2)) { goto error1; } else if (num == 2 && min > max) { goto error2; } } else { goto error1; } store = data; treepath = gtk_tree_path_new_from_string(path); gtk_tree_model_get_iter(GTK_TREE_MODEL(store), &itr, treepath); gtk_tree_path_free(treepath); gtk_list_store_set(store, &itr, 0, new_text, -1); return; error1: dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "\'%s\' is illegal", new_text); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; error2: dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "U+%x is larger than U+%x", min, max); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } /* --- global functions --- */ char *mc_get_unicode_areas(char *areas) { GtkWidget *dialog; GtkWidget *label; GtkListStore *store; GtkCellRenderer *renderer; GtkWidget *view; GtkWidget *hbox; GtkWidget *button; GtkTreeIter itr; char *strp; char *area; dialog = gtk_dialog_new_with_buttons( "Edit unicode areas", NULL, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); label = gtk_label_new( _("Set unicode area in the following format.\n" "Format: U+XXXX-XXXX or U+XXXX (U+ is optional)")); gtk_widget_show(label); gtk_box_pack_start(gtk_dialog_get_content_area(GTK_DIALOG(dialog)), label, TRUE, TRUE, 1); store = gtk_list_store_new(1, G_TYPE_STRING); strp = areas; while ((area = bl_str_sep(&strp, ","))) { gtk_list_store_append(store, &itr); gtk_list_store_set(store, &itr, 0, area, -1); } view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); g_object_unref(G_OBJECT(store)); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_append_column(GTK_TREE_VIEW(view), gtk_tree_view_column_new_with_attributes( NULL, renderer, "text", 0, NULL)); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); g_object_set(renderer, "editable", TRUE, NULL); g_signal_connect(renderer, "edited", G_CALLBACK(edited), store); gtk_widget_show(view); gtk_box_pack_start(gtk_dialog_get_content_area(GTK_DIALOG(dialog)), view, TRUE, TRUE, 1); hbox = gtk_hbox_new(TRUE, 0); gtk_widget_show(hbox); button = gtk_button_new_with_label("Add"); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 1); g_signal_connect(button, "clicked", G_CALLBACK(add_row), store); button = gtk_button_new_with_label("Delete"); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 1); g_signal_connect(button, "clicked", G_CALLBACK(delete_row), view); gtk_box_pack_start(gtk_dialog_get_content_area(GTK_DIALOG(dialog)), hbox, TRUE, TRUE, 1); if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) { areas = NULL; } else if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &itr)) { char *p; /* 20: U+XXXXXXXX-XXXXXXXX, */ p = areas = g_malloc(20 * gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL)); do { GValue gval = {0}; const char *str; gtk_tree_model_get_value(GTK_TREE_MODEL(store), &itr, 0, &gval); str = g_value_get_string(&gval); if (str && *str) { if (p > areas) { *(p++) = ','; } strcpy(p, str); p += strlen(p); } else { *p = '\0'; } g_value_unset(&gval); } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &itr)); } else { areas = strdup(""); } gtk_widget_destroy(dialog); return areas; } #else char *mc_get_unicode_areas(char *areas) { GtkWidget *dialog; dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "This dialog requires GTK+-2.14 or later"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return NULL; } #endif mlterm-3.8.9/tool/mlconfig/mc_unicode_areas.h010064400017600000144000000002631356600660700177470ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_UNICODE_AREAS_H__ #define __MC_UNICODE_AREAS_H__ char *mc_get_unicode_areas(char *areas); #endif mlterm-3.8.9/tool/mlconfig/mc_wall_pic.c010064400017600000144000000043461356600660700167410ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_wall_pic.h" #include #include /* free */ #include #include #include "mc_io.h" /* --- static functions --- */ static GtkWidget *entry; static char *old_wall_pic = NULL; static int is_changed; /* --- static functions --- */ static gint button_clicked(GtkWidget *widget, gpointer data) { GtkWidget *dialog; dialog = gtk_file_chooser_dialog_new("Wall Paper", NULL, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { gchar *filename; filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); gtk_entry_set_text(GTK_ENTRY(entry), filename); g_free(filename); } gtk_widget_destroy(dialog); return TRUE; } /* --- global functions --- */ GtkWidget *mc_wall_pic_config_widget_new(void) { GtkWidget *hbox; GtkWidget *button; char *wall_pic; wall_pic = mc_get_str_value("wall_picture"); hbox = gtk_hbox_new(FALSE, 0); #if 0 label = gtk_label_new(_("Picture")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); #endif entry = gtk_entry_new(); gtk_widget_show(entry); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 2); gtk_entry_set_text(GTK_ENTRY(entry), wall_pic); button = gtk_button_new_with_label(_("Select")); gtk_widget_show(button); g_signal_connect(button, "clicked", G_CALLBACK(button_clicked), NULL); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); old_wall_pic = wall_pic; is_changed = 0; return hbox; } void mc_update_wall_pic(void) { char *new_wall_pic; new_wall_pic = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1); if (strcmp(old_wall_pic, new_wall_pic) != 0) is_changed = 1; if (is_changed) { mc_set_str_value("wall_picture", new_wall_pic); g_free(old_wall_pic); old_wall_pic = new_wall_pic; } else { g_free(new_wall_pic); } } void mc_wall_pic_none(void) { g_free(old_wall_pic); old_wall_pic = strdup(""); mc_set_str_value("wall_picture", ""); } mlterm-3.8.9/tool/mlconfig/mc_wall_pic.h010064400017600000144000000004041356600660700167350ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_WALL_PIC_H__ #define __MC_WALL_PIC_H__ #include GtkWidget *mc_wall_pic_config_widget_new(void); void mc_update_wall_pic(void); void mc_wall_pic_none(void); #endif mlterm-3.8.9/tool/mlconfig/mc_wordsep.c010064400017600000144000000063551356600660700166340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "mc_wordsep.h" #include #include /* free */ #include #include #include #include "mc_io.h" #if 0 #define __DEBUG #endif #define CHAR_WIDTH 10 /* --- static variables --- */ static GtkWidget *entry; static char *old_wordsep; static int is_changed; /* --- static funcitons --- */ static void set_str_value(const char *value) { size_t len; if ((len = strlen(value)) > 0) { char *value2; char *p; if (len < 3 && strchr(value, ' ')) { /* len must be more than 2 to hold ' ' between other characters. */ if ((value2 = alloca(4))) { value = strcpy(value2, value); for (; len < 3; len++) { value2[len] = '\xff'; } value2[len] = '\0'; } else { return; } } if (((*value == ' ' && strchr(value + 1, ' ') == NULL) || (value[len - 1] == ' ' && strchr(value, ' ') == value + len - 1)) && (value2 = alloca(len + 1))) { /* Hold ' ' between other characters. */ if (*value == ' ') { value2[0] = value[1]; value2[1] = value[0]; strcpy(value2 + 2, value + 2); } else { strncpy(value2, value, len - 2); value2[len - 1] = value[len - 2]; value2[len - 2] = value[len - 1]; value2[len] = '\0'; } value = value2; } /* ';' => \x3b */ if ((p = strchr(value, ';'))) { if ((value2 = alloca(len + 3 + 1))) { strncpy(value2, value, p - value); strcpy(value2 + (p - value), "\\x3b"); strcpy(value2 + (p - value) + 4, p + 1); p = value2 + (p - value) + 4; while ((p = strchr(p, ';'))) { memmove(p, p + 1, strlen(p + 1)); p++; } value = value2; } } } mc_set_str_value("word_separators", value); } static char *remove_ff_mark(char *value) { size_t len; if ((len = strlen(value)) > 0) { if (*value == '\xff') { memmove(value, value + 1, --len); } if (value[len - 1] == '\xff') { value[len - 1] = '\0'; } } return value; } /* --- global functions --- */ GtkWidget *mc_wordsep_config_widget_new(void) { GtkWidget *hbox; GtkWidget *label; hbox = gtk_hbox_new(FALSE, 0); gtk_widget_show(hbox); label = gtk_label_new(_("Word separators")); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5); entry = gtk_entry_new(); old_wordsep = remove_ff_mark(mc_get_str_value("word_separators")); gtk_entry_set_text(GTK_ENTRY(entry), old_wordsep); gtk_widget_show(entry); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 1); #if GTK_CHECK_VERSION(2, 90, 0) gtk_entry_set_width_chars(GTK_ENTRY(entry), 10); #else gtk_widget_set_size_request(entry, 10 * CHAR_WIDTH, -1); #endif #if GTK_CHECK_VERSION(2, 12, 0) gtk_widget_set_tooltip_text(entry, "ASCII characters only"); #endif return hbox; } void mc_update_wordsep(void) { const char *new_wordsep; new_wordsep = gtk_entry_get_text(GTK_ENTRY(entry)); if (strcmp(new_wordsep, old_wordsep)) { is_changed = 1; } if (is_changed) { free(old_wordsep); set_str_value((old_wordsep = strdup(new_wordsep))); } } mlterm-3.8.9/tool/mlconfig/Makefile.in010064400017600000144000000051461356600660700163700ustar kenuserstop_builddir = ../.. top_srcdir = @top_srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datadir = @datadir@ bindir = @bindir@ libdir = @libdir@ libexecdir = @libexecdir@ sysconfdir = @sysconfdir@ datadir = @datadir@ VPATH = ${top_srcdir}/tool/mlconfig CC = @CC@ LIBTOOL = @LIBTOOL@ INSTALL = @INSTALL@ LIBEXECDIR = $(DESTDIR)$(libexecdir)/mlterm LIBEXECDIR_win32 = $(DESTDIR)$(bindir) LPOBL = @LPOBL@ # XDATADIR is to avoid conflicting with DATADIR structure in w32api/objidl.h. CFLAGS = $(CFLAGS_LOCAL) @GTK_CFLAGS@ @IMAGELIB_CFLAGS@ @DEB_CFLAGS@ \ @POBL_CFLAGS@ @GUI_CFLAGS@ @SSH2_CFLAGS@ @CFLAGS@ @CPPFLAGS@ \ -I${top_srcdir}/xwindow -I${top_srcdir}/vtemu \ -I${top_builddir}/common -I${top_srcdir}/common \ -I${top_srcdir}/inputmethod \ -I/usr/local/include \ -DSYSCONFDIR=\"$(sysconfdir)\" -DLOCALEDIR=\"$(datadir)/locale\" \ -DXDATADIR=\"$(datadir)\" -DLIBDIR=\"$(libdir)\" LIBS1 = $(LIBS_LOCAL) @INTL_LIBS@ @DL_SELF@ @DL_LIBS_IM@ @GTK_LIBS@ # -lX11 is for http://fedoraproject.org/wiki/Features/ChangeInImplicitDSOLinking LIBS2_xlib = $(LPOBL) -lX11 -L/usr/local/lib -R/usr/local/lib LIBS2_wayland = $(LPOBL) LIBS2_sdl2 = $(LPOBL) # mlconfig is statically linked with libpobl. # Then it works if installed libpobl.dll is compiled with USE_WIN32API or not. LIBS2_win32 = -mwindows ${top_builddir}/baselib/src/.libs/libpobl.a LIBS2_quartz = $(LPOBL) LIBS = $(LIBS1) $(LIBS2_@GUI@) LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) PACKAGE = @PACKAGE@ VERSION = @VERSION@ OBJ = main.o mc_combo.o mc_char_encoding.o mc_im.o mc_tabsize.o mc_logsize.o \ mc_font.o mc_color.o mc_radio.o mc_space.o mc_alpha.o mc_ctl.o \ mc_sb_view.o mc_wall_pic.o mc_bgtype.o mc_io.o mc_pty.o mc_char_width.o \ mc_flags.o mc_auto_detect.o mc_ratio.o mc_wordsep.o mc_unicode_areas.o \ mc_geometry.o mc_click.o mc_opentype.o LPOBL_DEB=-lpobl_deb all: mlconfig debug: $(MAKE) LPOBL="$(LPOBL_DEB)" all mlconfig: $(OBJ) $(LIBTOOL_LINK) $(OBJ) $(CFLAGS) -o mlconfig $(LIBS) # "cd po" must be enclosed by () because it may not return # to the $(top_builddir)/tool/mlconfig at the next line. (cd po ; $(MAKE) update-gmo) # cd po ; $(MAKE) update-po .c.o: $(CC) $(DEFS) $(CFLAGS) -c $< install: $(LIBEXECDIR@WIN32TAG@) $(LIBTOOL_INSTALL) -m 755 mlconfig $(LIBEXECDIR@WIN32TAG@) cd po ; $(MAKE) install uninstall: rm -f $(LIBEXECDIR@WIN32TAG@)/mlconfig cd po ; $(MAKE) uninstall $(LIBEXECDIR@WIN32TAG@): mkdir -p $(LIBEXECDIR@WIN32TAG@) clean: rm -rf $(OBJ) mlconfig mlconfig.exe *.core .libs cd po ; $(MAKE) clean distclean: clean rm -f Makefile cd po ; $(MAKE) distclean mlterm-3.8.9/tool/mlconfig/mc_wordsep.h010064400017600000144000000003421356600660700166270ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __MC_WORDSEP_H__ #define __MC_WORDSEP_H__ #include GtkWidget *mc_wordsep_config_widget_new(void); void mc_update_wordsep(void); #endif mlterm-3.8.9/tool/mlfc004075500017600000144000000000001356600660700133645ustar kenusersmlterm-3.8.9/tool/mlfc/Makefile.in010064400017600000144000000017601356600660700155110ustar kenuserstop_builddir = ../.. top_srcdir = @top_srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ CC = @CC@ LIBTOOL = @LIBTOOL@ INSTALL = @INSTALL@ BINDIR = $(DESTDIR)$(bindir) VPATH = $(top_srcdir)/tool/mlfc OBJ = main.o CFLAGS = $(CFLAGS_LOCAL) @CFLAGS@ @CPPFLAGS@ @FONTCONFIG_CFLAGS@ -I/usr/local/include LIBS = $(LIBS_LOCAL) @FONTCONFIG_LIBS@ -L/usr/local/lib -R/usr/local/lib PROG = mlfc LIBTOOL_CC = $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) all: $(PROG) $(PROG): $(OBJ) $(LIBTOOL_LINK) $(CFLAGS) -o $(PROG) $(OBJ:.o=.lo) $(LIBS) .SUFFIXES: .c .o .c.o: $(LIBTOOL_CC) -c $< $(BINDIR): mkdir -p $(BINDIR) install: $(BINDIR) $(LIBTOOL_INSTALL) $(PROG) $(BINDIR) uninstall: rm -f $(BINDIR)/$(PROG) wc: find . -name "*.[ch]" -a \! -name "test_*" | xargs wc -l clean: rm -rf $(PROG) $(PROG).exe *core $(OBJ) $(OBJ:.o=.lo) .libs distclean: clean rm -f Makefile mlterm-3.8.9/tool/mlfc/main.c010064400017600000144000000474221356600660700145410ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include #include #include /* alloca */ #include #ifdef __sunos #include #endif #define MAX_AREAS 256 #define HEADER "# Permit mlfc to ovewrite this file.\n" #ifndef u_int #define u_int unsigned int #endif static struct unicode_block { u_int beg; u_int end; } blocks[] = { {0x0100, 0x024F}, /* Latin Extended */ {0x0250, 0x02AF}, /* IPA Extensions */ {0x02B0, 0x02FF}, /* Spacing Modifier Letters */ {0x0300, 0x036F}, /* Combining Diacritical Marks */ {0x0370, 0x03FF}, /* Greek and Coptic */ {0x0400, 0x04FF}, /* Cyrillic */ {0x0500, 0x052F}, /* Cyrillic Supplement */ {0x0530, 0x058F}, /* Armenian */ {0x0590, 0x05FF}, /* Hebrew */ {0x0600, 0x06FF}, /* Arabic */ {0x0700, 0x074F}, /* Syriac */ {0x0750, 0x077F}, /* Arabic Supplement */ {0x0780, 0x07BF}, /* Thaana */ {0x07C0, 0x07FF}, /* NKo */ {0x0800, 0x083F}, /* Samaritan */ {0x0840, 0x085F}, /* Mandaic */ {0x08A0, 0x08FF}, /* Arabic Extended-A */ {0x0900, 0x097F}, /* Devanagari */ {0x0980, 0x09FF}, /* Bengali */ {0x0A00, 0x0A7F}, /* Gurmukhi */ {0x0A80, 0x0AFF}, /* Gujarati */ {0x0B00, 0x0B7F}, /* Oriya */ {0x0B80, 0x0BFF}, /* Tamil */ {0x0C00, 0x0C7F}, /* Telugu */ {0x0C80, 0x0CFF}, /* Kannada */ {0x0D00, 0x0D7F}, /* Malayalam */ {0x0D80, 0x0DFF}, /* Sinhala */ {0x0E00, 0x0E7F}, /* Thai */ {0x0E80, 0x0EFF}, /* Lao */ {0x0F00, 0x0FFF}, /* Tibetan */ {0x1000, 0x109F}, /* Myanmar */ {0x10A0, 0x10FF}, /* Georgian */ {0x1100, 0x11FF}, /* Hangul Jamo */ {0x1200, 0x137F}, /* Ethiopic */ {0x1380, 0x139F}, /* Ethiopic Supplement */ {0x13A0, 0x13FF}, /* Cherokee */ {0x1400, 0x167F}, /* Unified Canadian Aboriginal */ {0x1680, 0x169F}, /* Ogham */ {0x16A0, 0x16FF}, /* Runic */ {0x1700, 0x171F}, /* Tagalog */ {0x1720, 0x173F}, /* Hanunoo */ {0x1740, 0x175F}, /* Buhid */ {0x1760, 0x177F}, /* Tagbanwa */ {0x1780, 0x17FF}, /* Khmer */ {0x1800, 0x18AF}, /* Mongolian */ {0x18B0, 0x18FF}, /* Unified Canadian Aboriginal Syllabics Extended */ {0x1900, 0x194F}, /* Limbu */ {0x1950, 0x197F}, /* Tai Le */ {0x1980, 0x19DF}, /* New Tai Lue */ {0x19E0, 0x19FF}, /* Khmer Symbols */ {0x1A00, 0x1A1F}, /* Buginese */ {0x1A20, 0x1AAF}, /* Tai Tham */ {0x1AB0, 0x1AFF}, /* Combining Diacritical Marks Extended */ {0x1B00, 0x1B7F}, /* Balinese */ {0x1B80, 0x1BBF}, /* Sundanese */ {0x1BC0, 0x1BFF}, /* Batak */ {0x1C00, 0x1C4F}, /* Lepcha */ {0x1C50, 0x1C7F}, /* Ol Chiki */ {0x1CC0, 0x1CCF}, /* Sundanese Supplement */ {0x1CD0, 0x1CFF}, /* Vedic Extensions */ {0x1D00, 0x1D7F}, /* Phonetic Extensions */ {0x1D80, 0x1DBF}, /* Phonetic Extensions Supplement */ {0x1DC0, 0x1DFF}, /* Combining Diacritical Marks Supplement */ {0x1E00, 0x1EFF}, /* Latin Extended Additional */ {0x1F00, 0x1FFF}, /* Greek Extended */ {0x2000, 0x206F}, /* General Punctuation */ {0x2070, 0x209F}, /* Superscripts and Subscripts */ {0x20A0, 0x20CF}, /* Currency Symbols */ {0x20D0, 0x20FF}, /* Combining Diacritical Marks for Symbols */ {0x2100, 0x214F}, /* Letterlike Symbols */ {0x2150, 0x218F}, /* Number Forms */ {0x2190, 0x21FF}, /* Arrows */ {0x2200, 0x22FF}, /* Mathematical Operators */ {0x2300, 0x23FF}, /* Miscellaneous Technical */ {0x2400, 0x243F}, /* Control Pictures */ {0x2440, 0x245F}, /* Optical Character Recognition */ {0x2460, 0x24FF}, /* Enclosed Alphanumerics */ {0x2500, 0x257F}, /* Box Drawing */ {0x2580, 0x259F}, /* Block Elements */ {0x25A0, 0x25FF}, /* Geometric Shapes */ {0x2600, 0x26FF}, /* Miscellaneous Symbols */ {0x2700, 0x27BF}, /* Dingbats */ {0x27C0, 0x27EF}, /* Miscellaneous Mathematical Symbols-A */ {0x27F0, 0x27FF}, /* Supplemental Arrows-A */ {0x2800, 0x28FF}, /* Braille Patterns */ {0x2900, 0x297F}, /* Supplemental Arrows-B */ {0x2980, 0x29FF}, /* Miscellaneous Mathematical Symbols-B */ {0x2A00, 0x2AFF}, /* Supplemental Mathematical Operators */ {0x2B00, 0x2BFF}, /* Miscellaneous Symbols and Arrows */ {0x2C00, 0x2C5F}, /* Glagolitic */ {0x2C60, 0x2C7F}, /* Latin Extended-C */ {0x2C80, 0x2CFF}, /* Coptic */ {0x2D00, 0x2D2F}, /* Georgian Supplement */ {0x2D30, 0x2D7F}, /* Tifinagh */ {0x2D80, 0x2DDF}, /* Ethiopic Extended */ {0x2DE0, 0x2DFF}, /* Cyrillic Extended-A */ {0x2E00, 0x2E7F}, /* Supplemental Punctuation */ {0x2E80, 0x2EFF}, /* CJK Radicals Supplement */ {0x2F00, 0x2FDF}, /* Kangxi Radicals */ {0x2FF0, 0x2FFF}, /* Ideographic Description Characters */ {0x3000, 0x303F}, /* CJK Symbols and Punctuation */ {0x3040, 0x309F}, /* Hiragana */ {0x30A0, 0x30FF}, /* Katakana */ {0x3100, 0x312F}, /* Bopomofo */ {0x3130, 0x318F}, /* Hangul Compatibility Jamo */ {0x3190, 0x319F}, /* Kanbun */ {0x31A0, 0x31BF}, /* Bopomofo Extended */ {0x31C0, 0x31EF}, /* CJK Strokes */ {0x31F0, 0x31FF}, /* Katakana Phonetic Extensions */ {0x3200, 0x32FF}, /* Enclosed CJK Letters and Months */ {0x3300, 0x33FF}, /* CJK Compatibility */ {0x3400, 0x4DBF}, /* CJK Unified Ideographs Extension A */ {0x4DC0, 0x4DFF}, /* Yijing Hexagram Symbols */ {0x4E00, 0x9FFF}, /* CJK Unified Ideographs */ {0xA000, 0xA48F}, /* Yi Syllables */ {0xA490, 0xA4CF}, /* Yi Radicals */ {0xA4D0, 0xA4FF}, /* Lisu */ {0xA500, 0xA63F}, /* Vai */ {0xA640, 0xA69F}, /* Cyrillic Extended-B */ {0xA6A0, 0xA6FF}, /* Bamum */ {0xA700, 0xA71F}, /* Modifier Tone Letters */ {0xA720, 0xA7FF}, /* Latin Extended-D */ {0xA800, 0xA82F}, /* Syloti Nagri */ {0xA830, 0xA83F}, /* Common Indic Number Forms */ {0xA840, 0xA87F}, /* Phags-pa */ {0xA880, 0xA8DF}, /* Saurashtra */ {0xA8E0, 0xA8FF}, /* Devanagari Extended */ {0xA900, 0xA92F}, /* Kayah Li */ {0xA930, 0xA95F}, /* Rejang */ {0xA960, 0xA97F}, /* Hangul Jamo Extended-A */ {0xA980, 0xA9DF}, /* Javanese */ {0xA9E0, 0xA9FF}, /* Myanmar Extended-B */ {0xAA00, 0xAA5F}, /* Cham */ {0xAA60, 0xAA7F}, /* Myanmar Extended-A */ {0xAA80, 0xAADF}, /* Tai Viet */ {0xAAE0, 0xAAFF}, /* Meetei Mayek Extensions */ {0xAB00, 0xAB2F}, /* Ethiopic Extended-A */ {0xAB30, 0xAB6F}, /* Latin Extended-E */ {0xAB70, 0xABBF}, /* Cherokee Supplement */ {0xABC0, 0xABFF}, /* Meetei Mayek */ {0xAC00, 0xD7AF}, /* Hangul Syllables */ {0xD7B0, 0xD7FF}, /* Hangul Jamo Extended-B */ {0xD800, 0xDB7F}, /* High Surrogates */ {0xDB80, 0xDBFF}, /* High Private Use Surrogates */ {0xDC00, 0xDFFF}, /* Low Surrogates */ {0xE000, 0xF8FF}, /* Private Use Area */ {0xF900, 0xFAFF}, /* CJK Compatibility Ideographs */ {0xFB00, 0xFB4F}, /* Alphabetic Presentation Forms */ {0xFB50, 0xFDFF}, /* Arabic Presentation Forms-A */ {0xFE00, 0xFE0F}, /* Variation Selectors */ {0xFE10, 0xFE1F}, /* Vertical Forms */ {0xFE20, 0xFE2F}, /* Combining Half Marks */ {0xFE30, 0xFE4F}, /* CJK Compatibility Forms */ {0xFE50, 0xFE6F}, /* Small Form Variants */ {0xFE70, 0xFEFF}, /* Arabic Presentation Forms-B */ {0xFF00, 0xFFEF}, /* Halfwidth and Fullwidth Forms */ {0xFFF0, 0xFFFF}, /* Specials */ {0x10000, 0x1007F}, /* Linear B Syllabary */ {0x10080, 0x100FF}, /* Linear B Ideograms */ {0x10100, 0x1013F}, /* Aegean Numbers */ {0x10140, 0x1018F}, /* Ancient Greek Numbers */ {0x10190, 0x101CF}, /* Ancient Symbols */ {0x101D0, 0x101FF}, /* Phaistos Disc */ {0x10280, 0x1029F}, /* Lycian */ {0x102A0, 0x102DF}, /* Carian */ {0x102E0, 0x102FF}, /* Coptic Epact Numbers */ {0x10300, 0x1032F}, /* Old Italic */ {0x10330, 0x1034F}, /* Gothic */ {0x10350, 0x1037F}, /* Old Permic */ {0x10380, 0x1039F}, /* Ugaritic */ {0x103A0, 0x103DF}, /* Old Persian */ {0x10400, 0x1044F}, /* Deseret */ {0x10450, 0x1047F}, /* Shavian */ {0x10480, 0x104AF}, /* Osmanya */ {0x10500, 0x1052F}, /* Elbasan */ {0x10530, 0x1056F}, /* Caucasian Albanian */ {0x10600, 0x1077F}, /* Linear A */ {0x10800, 0x1083F}, /* Cypriot Syllabary */ {0x10840, 0x1085F}, /* Imperial Aramaic */ {0x10860, 0x1087F}, /* Palmyrene */ {0x10880, 0x108AF}, /* Nabataean */ {0x108E0, 0x108FF}, /* Hatran */ {0x10900, 0x1091F}, /* Phoenician */ {0x10920, 0x1093F}, /* Lydian */ {0x10980, 0x1099F}, /* Meroitic Hieroglyphs */ {0x109A0, 0x109FF}, /* Meroitic Cursive */ {0x10A00, 0x10A5F}, /* Kharoshthi */ {0x10A60, 0x10A7F}, /* Old South Arabian */ {0x10A80, 0x10A9F}, /* Old North Arabian */ {0x10AC0, 0x10AFF}, /* Manichaean */ {0x10B00, 0x10B3F}, /* Avestan */ {0x10B40, 0x10B5F}, /* Inscriptional Parthian */ {0x10B60, 0x10B7F}, /* Inscriptional Pahlavi */ {0x10B80, 0x10BAF}, /* Psalter Pahlavi */ {0x10C00, 0x10C4F}, /* Old Turkic */ {0x10C80, 0x10CFF}, /* Old Hungarian */ {0x10E60, 0x10E7F}, /* Rumi Numeral Symbols */ {0x11000, 0x1107F}, /* Brahmi */ {0x11080, 0x110CF}, /* Kaithi */ {0x110D0, 0x110FF}, /* Sora Sompeng */ {0x11100, 0x1114F}, /* Chakma */ {0x11150, 0x1117F}, /* Mahajani */ {0x11180, 0x111DF}, /* Sharada */ {0x111E0, 0x111FF}, /* Sinhala Archaic Numbers */ {0x11200, 0x1124F}, /* Khojki */ {0x11280, 0x112AF}, /* Multani */ {0x112B0, 0x112FF}, /* Khudawadi */ {0x11300, 0x1137F}, /* Grantha */ {0x11480, 0x114DF}, /* Tirhuta */ {0x11580, 0x115FF}, /* Siddham */ {0x11600, 0x1165F}, /* Modi */ {0x11680, 0x116CF}, /* Takri */ {0x11700, 0x1173F}, /* Ahom */ {0x118A0, 0x118FF}, /* Warang Citi */ {0x11AC0, 0x11AFF}, /* Pau Cin Hau */ {0x12000, 0x123FF}, /* Cuneiform */ {0x12400, 0x1247F}, /* Cuneiform Numbers and Punctuation */ {0x12480, 0x1254F}, /* Early Dynastic Cuneiform */ {0x13000, 0x1342F}, /* Egyptian Hieroglyphs */ {0x14400, 0x1467F}, /* Anatolian Hieroglyphs */ {0x16800, 0x16A3F}, /* Bamum Supplement */ {0x16A40, 0x16A6F}, /* Mro */ {0x16AD0, 0x16AFF}, /* Bassa Vah */ {0x16B00, 0x16B8F}, /* Pahawh Hmong */ {0x16F00, 0x16F9F}, /* Miao */ {0x1B000, 0x1B0FF}, /* Kana Supplement */ {0x1BC00, 0x1BC9F}, /* Duployan */ {0x1BCA0, 0x1BCAF}, /* Shorthand Format Controls */ {0x1D000, 0x1D0FF}, /* Byzantine Musical Symbols */ {0x1D100, 0x1D1FF}, /* Musical Symbols */ {0x1D200, 0x1D24F}, /* Ancient Greek Musical Notation */ {0x1D300, 0x1D35F}, /* Tai Xuan Jing Symbols */ {0x1D360, 0x1D37F}, /* Counting Rod Numerals */ {0x1D400, 0x1D7FF}, /* Mathematical Alphanumeric Symbols */ {0x1D800, 0x1DAAF}, /* Sutton SignWriting */ {0x1E800, 0x1E8DF}, /* Mende Kikakui */ {0x1EE00, 0x1EEFF}, /* Arabic Mathematical Alphabetic Symbols */ #if 0 {0x1F000, 0x1F02F}, /* Mahjong Tiles */ {0x1F030, 0x1F09F}, /* Domino Tiles */ {0x1F0A0, 0x1F0FF}, /* Playing Cards */ {0x1F100, 0x1F1FF}, /* Enclosed Alphanumeric Supplement */ {0x1F200, 0x1F2FF}, /* Enclosed Ideographic Supplement */ {0x1F300, 0x1F5FF}, /* Miscellaneous Symbols And Pictographs */ {0x1F600, 0x1F64F}, /* Emoticons */ {0x1F650, 0x1F67F}, /* Ornamental Dingbats */ {0x1F680, 0x1F6FF}, /* Transport And Map Symbols */ {0x1F700, 0x1F77F}, /* Alchemical Symbols */ {0x1F780, 0x1F7FF}, /* Geometric Shapes Extended */ {0x1F800, 0x1F8FF}, /* Supplemental Arrows-C */ {0x1F900, 0x1F9FF}, /* Supplemental Symbols and Pictographs */ #endif {0x20000, 0x2A6DF}, /* CJK Unified Ideographs Extension B */ {0x2A700, 0x2B73F}, /* CJK Unified Ideographs Extension C */ {0x2B740, 0x2B81F}, /* CJK Unified Ideographs Extension D */ {0x2B820, 0x2CEAF}, /* CJK Unified Ideographs Extension E */ {0x2F800, 0x2FA1F}, /* CJK Compatibility Ideographs Supplement */ }; /* --- static functions --- */ static char *get_user_rc_path(char *rcfile) { char *homedir; char *path; #ifdef _WIN32 if ((homedir = getenv("HOMEPATH")) && /* Enough for "%s/%s" */ (path = malloc(strlen(homedir) + 1 + strlen(rcfile) + 1))) { sprintf(path, "%s/%s", homedir, rcfile); return path; } #else if ((homedir = getenv("HOME")) && /* Enough for "%s/.config/%s" */ (path = malloc(strlen(homedir) + 9 + strlen(rcfile) + 1))) { struct stat st; char *p; sprintf(path, "%s/.config/%s", homedir, rcfile); p = strrchr(path, '/'); *p = '\0'; if (stat(path, &st) == 0) { *p = '/'; } else { sprintf(path, "%s/.%s", homedir, rcfile); } return path; } #endif return NULL; } static FcPattern *fc_pattern_create(const FcChar8* family) { FcPattern *pattern; if (!(pattern = FcPatternCreate())) { return NULL; } if (family) { FcPatternAddString(pattern, FC_FAMILY, family); } FcConfigSubstitute(NULL, pattern, FcMatchPattern); FcPatternRemove(pattern, FC_FAMILYLANG, 0); FcPatternRemove(pattern, FC_STYLELANG, 0); FcPatternRemove(pattern, FC_FULLNAMELANG, 0); #ifdef FC_NAMELANG FcPatternRemove(pattern, FC_NAMELANG, 0); #endif FcPatternRemove(pattern, FC_LANG, 0); return pattern; } static int is_same_family(FcPattern *pattern, const char *family) { int count; FcValue val; for (count = 0; FcPatternGet(pattern, FC_FAMILY, count, &val) == FcResultMatch; count++) { if (strcmp(family, val.u.s) == 0) { return 1; } } return 0; } static FcPattern *search_next_font(FcPattern *pattern) { FcPattern *match; FcValue val; FcResult result; while (1) { if (FcPatternGet(pattern, FC_FAMILY, 0, &val) != FcResultMatch) { return NULL; } if (!(match = FcFontMatch(NULL, pattern, &result))) { continue; } if (is_same_family(match, val.u.s)) { FcPatternRemove(pattern, FC_FAMILY, 0); return match; } FcPatternRemove(pattern, FC_FAMILY, 0); while (1) { if (FcPatternGet(pattern, FC_FAMILY, 0, &val) == FcResultMatch) { if (is_same_family(match, val.u.s)) { FcPatternRemove(pattern, FC_FAMILY, 0); return match; } FcPatternRemove(pattern, FC_FAMILY, 0); } else { return NULL; } } } } static void backup_config(const char *path) { FILE* fp; if ((fp = fopen(path, "r"))) { char buf[1024]; char *new_path; while (fgets(buf, sizeof(buf), fp)) { if (strcmp(buf, HEADER) == 0) { return; } } fclose(fp); if ((new_path = alloca(strlen(path) + 5))) { sprintf(new_path, "%s.bak", path); rename(path, new_path); } } } static int check_font_config(const char *default_family /* family name */ ) { const char *path; const char *default_path; FcPattern *pattern; FcPattern *matches[1024]; u_int num_matches = 0; int b_idx; struct { struct unicode_block *block; const char *family; const char *path; } outputs[MAX_AREAS]; u_int num_outputs = 0; FcValue val; u_int count; FILE* fp; if (!(pattern = fc_pattern_create(default_family))) { return 0; } #if 0 FcPatternPrint(pattern); #endif matches[num_matches++] = search_next_font(pattern); if (*default_family == '\0') { if (FcPatternGet(matches[0], FC_FAMILY, 0, &val) == FcResultMatch) { default_family = val.u.s; } } if (FcPatternGet(matches[0], FC_FILE, 0, &val) == FcResultMatch) { default_path = val.u.s; } else { default_path = NULL; } for (b_idx = 0; b_idx < sizeof(blocks) / sizeof(blocks[0]); b_idx++) { int m_idx; for (m_idx = 0;; m_idx++) { FcCharSet *charset; if (m_idx == num_matches) { if (num_matches == sizeof(matches) / sizeof(matches[0]) || matches[num_matches - 1] == NULL) { break; } if (!(matches[num_matches] = search_next_font(pattern))) { int count; FcPattern *pat = FcPatternCreate(); FcObjectSet *objset = FcObjectSetBuild(FC_FAMILY, FC_FILE, FC_CHARSET, NULL); FcFontSet *fontset = FcFontList(NULL, pat, objset); for (count = 0; count < fontset->nfont; count++) { matches[num_matches++] = fontset->fonts[count]; FcPatternGet(matches[num_matches - 1], FC_FAMILY, 0, &val); #if 0 fprintf(stderr, "Add Font List %s\n", val.u.s); #endif } matches[num_matches] = NULL; } num_matches++; } if (!matches[m_idx]) { break; } if (FcPatternGetCharSet(matches[m_idx], FC_CHARSET, 0, &charset) == FcResultMatch && (FcCharSetHasChar(charset, blocks[b_idx].beg) || FcCharSetHasChar(charset, blocks[b_idx].beg + 1))) { if (FcPatternGet(matches[m_idx], FC_FAMILY, 0, &val) == FcResultMatch && strcmp(val.u.s, default_family) != 0) { if (num_outputs > 0 && outputs[num_outputs - 1].block->end + 1 == blocks[b_idx].beg && strcmp(outputs[num_outputs - 1].family, val.u.s) == 0) { /* XXX Change blocks[b_idx - 1].end */ outputs[num_outputs - 1].block->end = blocks[b_idx].end; } else { outputs[num_outputs].block = blocks + b_idx; outputs[num_outputs].family = val.u.s; if (FcPatternGet(matches[m_idx], FC_FILE, 0, &val) == FcResultMatch) { outputs[num_outputs].path = val.u.s; } else { outputs[num_outputs].path = NULL; } num_outputs++; if (num_outputs == sizeof(outputs) / sizeof(outputs[0])) { break; } } } break; } } } if ((path = get_user_rc_path("mlterm/aafont"))) { backup_config(path); if (!(fp = fopen(path, "w"))) { return 0; } printf("Updating %s\n", path); fprintf(fp, HEADER); fprintf(fp, "ISO10646_UCS4_1=%s\n", default_family); for (count = 0; count < num_outputs; count++) { fprintf(fp, "U+%x-%x=%s\n", outputs[count].block->beg, outputs[count].block->end, outputs[count].family); } fclose(fp); } if (default_path && (path = get_user_rc_path("mlterm/font-fb"))) { backup_config(path); if (!(fp = fopen(path, "w"))) { return 0; } printf("Updating %s\n", path); fprintf(fp, HEADER); fprintf(fp, "ISO10646_UCS4_1=%s\n", default_path); for (count = 0; count < num_outputs; count++) { fprintf(fp, "U+%x-%x=%s\n", outputs[count].block->beg, outputs[count].block->end, outputs[count].path); } fclose(fp); } return 1; } /* --- global functions --- */ int main(int argc, char **argv) { if ((argc != 2 || *argv[1] == '-') && argc != 1) { fprintf(stderr, "Usage: mlfc \n"); return -1; } #ifdef _WIN32 if (!getenv("FONTCONFIG_PATH") && !getenv("FONTCONFIG_FILE")) { /* * See fontconfig-x.x.x/src/fccfg.c * (DllMain(), FcConfigFileExists(), FcConfigGetPath() and FcConfigFilename()) * * [commant in DllMain] * If the fontconfig DLL is in a "bin" or "lib" subfolder, assume it's a Unix-style * installation tree, and use "etc/fonts" in there as FONTCONFIG_PATH. * Otherwise use the folder where the DLL is as FONTCONFIG_PATH. * * [comment in FcConfigFileExists] * make sure there's a single separator * (=> If FONTCONFIG_PATH="", FONTCONFIG_FILE="/...") */ putenv("FONTCONFIG_PATH=."); } #endif if (!check_font_config(argc == 1 ? #ifdef _WIN32 "Courier" #else "" #endif : argv[1])) { fprintf(stderr, "Failed.\n"); return -1; } return 0; } mlterm-3.8.9/tool/accessories004075500017600000144000000000001356600660700147465ustar kenusersmlterm-3.8.9/tool/accessories/xconsole.sh010075500017600000144000000002451356600660700172140ustar kenusers#!/bin/sh if [ -e /tmp/.mlterm-* ]; then cmd="mlclient" else cmd="mlterm" fi ${cmd} --initstr 'printf "\\x1b[1m"\nprintf "\\x1b[2J"\ncat /dev/console||exit 0\n' mlterm-3.8.9/tool/accessories/README010064400017600000144000000016431356600660700157060ustar kenusersUtility scripts for mlterm. * google.sh Search specified keyword by google. (This script doesn't work with mlterm-3.1.7 or later + w3m remote img which consumes string of --inistr in checking OSC14t and OSC18t.) o Usage $ google.sh [keyword] * mlscp.sh Do secure copy over ssh connection. o Usage $ mlscp [src path] [dst path] = (remote:|local:)/dir/file * mlsearch.sh Move to characters matching a pattern. o Usage $ mlsearch.sh [keyword] $ mlsearch.sh prev [keyword] $ mlsearch.sh next [keyword] * mltracelog.sh Trace a log file mlterm --logseq outputs with trachet(http://pypi.python.org/pypi/trachet). o Usage $ mltracelog.sh [log file] * xconsole.sh Watch /dev/console like /usr/X11R6/bin/xconsole. o Usage $ xconsole.sh Exit by control+c. * mlsplit.sh Split screen and initialize encoding and input_method options. o Usage $ mlsplit.shmlterm-3.8.9/tool/accessories/gedit.sh010075500017600000144000000007161356600660700164610ustar kenusers#!/bin/bash # # for Linux # # Usage: ~/.mlterm/key # Button3 = gedit.sh # if [ -f $1 ];then echo "gedit.sh: Open $1 by gedit." >> ~/.mlterm/msg.log gedit $1 exit fi SH_PID=`ps --ppid $PPID --no-heading|grep pts/|awk '{ print $1 }'` for pid in $SH_PID ; do DIR=`readlink /proc/$pid/cwd` if [ -f $DIR/$1 ]; then echo "gedit.sh: Open $DIR/$1 by gedit." >> ~/.mlterm/msg.log gedit $DIR/$1 break fi done zenity --error --text=\\"Failed to open $1.\\" mlterm-3.8.9/tool/accessories/google.sh010075500017600000144000000003541356600660700166370ustar kenusers#!/bin/sh if [ ${#} -ne 1 ]; then echo "Usage: google.sh [keyword]" exit 1 fi if [ -e ~/.mlterm/socket ]; then cmd="mlclient" else cmd="mlterm" fi $cmd -T google --initstr " \n${1}\n \n" -e w3m http://www.google.com mlterm-3.8.9/tool/accessories/mlscp.sh010075500017600000144000000003271356600660700165010ustar kenusers#!/bin/sh if test ${#} != 2 ; then echo "Usage: mlscp.sh [src path] [dst path]" echo " = (remote:|local:)/dir/file" exit 0 else src=$1 dst=$2 fi printf "\x1b]5379;scp \"%s\" \"%s\"\x07" "$src" "$dst" mlterm-3.8.9/tool/accessories/mlsearch.sh010075500017600000144000000011371356600660700171610ustar kenusers#!/bin/sh reset_state() { printf "\x1b]5379;search_$1\x07" stty echo exit 0 } if test ${#} = 0 ; then echo "Reset searching position." printf "\x1b]5379;search_$1\x07" exit 0 elif test ${#} = 1 ; then pat=$1 dir="prev" elif test "$1" = "-h" -o ${#} != 2 ; then echo "Usage: mlsearch (prev|next) [pattern]" exit 0 else pat=$2 dir=$1 fi echo "Press Enter key to continue searching. Press ^C to exit." trap "reset_state $dir" 2 stty -echo printf "\x1b]5379;search_$dir %s\x07" "$pat" read input while true do printf "\x1b]5379;search_$dir %s\x07" "$pat" ; read input done reset_state $dir mlterm-3.8.9/tool/accessories/mlsplit.sh010075500017600000144000000024061356600660700170470ustar kenusers#!/bin/sh # for mlterm 3.8.2 or later get_challenge () { if [ "$challenge" = "" ]; then stty -echo /usr/bin/printf "\e]5380;challenge\a" read challenge challenge=`echo $challenge|sed 's/^#challenge=//'` stty echo fi } get_dev_list () { stty -echo /usr/bin/printf "\e]5380;%s;pty_list\a" $challenge read dev_list dev_list=`echo $dev_list|sed 's/^#pty_list=//'|tr ';' ' '` stty echo } get_dev_num () { get_challenge get_dev_list dev_num=0 for dev in $dev_list; do dev_num=`expr $dev_num + 1` done } set_config () { get_challenge get_dev_list count=0 for dev in $dev_list; do dev=`echo $dev|sed 's/\([^:]*\):.*/\1/'` if [ $count -eq $1 ]; then echo "$dev: $2" /usr/bin/printf "\e]5379;$dev:$2\a" fi count=`expr $count + 1`; done stty echo } get_dev_num # maximize window /usr/bin/printf "\x1b[9;1t" mlcc exec hsplit_screen 101 mlcc exec next_screen mlcc exec vsplit_screen 50% mlcc exec hsplit_screen 50% LC_CTYPE=en_US.UTF-8 set_config `expr $dev_num - 1` "input_method=none" set_config `expr $dev_num - 1` "col_size_of_width_a=1" set_config $dev_num "encoding=eucjp" set_config `expr $dev_num + 1` "encoding=eucjp" mlcc exec next_screen mlcc exec next_screen mlcc exec hsplit_screen 50% emacsclient -t #$HOME/.sayaka/sayaka.sh s & mlterm-3.8.9/tool/accessories/mltracelog.sh010075500017600000144000000016461356600660700175210ustar kenusers#!/bin/sh if [ ${#} -ne 1 ]; then echo "Usage: mltracelog.sh [log file]" exit 1 fi file="${1}" if [ ! -f "$file" ]; then echo "Not found $file" exit 1 fi _trachet=`which trachet` _printf=`which printf` if [ -z "$_trachet" -o "$_printf" != "/usr/bin/printf" ]; then echo "Not found trachet(http://pypi.python.org/pypi/trachet) or printf" exit 1 fi # /usr/bin/ is specified to avoid to use built-in printf. /usr/bin/printf "\e]5380;%s;pty_list\a" `cat $HOME/.mlterm/challenge` read oldlist mlclient -e cat /usr/bin/printf "\e]5380;%s;pty_list\a" `cat $HOME/.mlterm/challenge` read newlist for newdev in `echo $newlist | tr ';' ' ' | tr '=' ' '` ; do match=0 for olddev in `echo $oldlist | tr ';' ' ' | tr '=' ' '` ; do if [ $newdev = $olddev ]; then match=1 break fi done if [ $match = 0 ]; then newdev=`echo $newdev | tr ':1' ' ' | tr ':0' ' '` trachet -b -o $newdev "cat $file -" break fi done mlterm-3.8.9/tool/accessories/Makefile010064400017600000144000000003071356600660700164620ustar kenusersprefix=/usr/local bindir=$(prefix)/bin DESTDIR= BINDIR=$(DESTDIR)$(bindir) TARGETS=xconsole.sh google.sh mlsearch.sh mlscp.sh INSTALL=install -c install: $(INSTALL) -m 755 $(TARGETS) $(BINDIR)/ mlterm-3.8.9/tool/mlmenu004075500017600000144000000000001356600660700137405ustar kenusersmlterm-3.8.9/tool/mlmenu/Makefile.in010064400017600000144000000023431356600660700160630ustar kenuserstop_builddir = ../.. top_srcdir = @top_srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ libexecdir = @libexecdir@ bindir = @bindir@ sysconfdir = @sysconfdir@ VPATH = ${top_srcdir}/tool/mlmenu CC = @CC@ LIBTOOL = @LIBTOOL@ INSTALL = @INSTALL@ LIBEXECDIR = $(DESTDIR)$(libexecdir)/mlterm LIBEXECDIR_win32 = $(DESTDIR)$(bindir) SYSCONFDIR = $(DESTDIR)$(sysconfdir) CFLAGS = $(CFLAGS_LOCAL) @CFLAGS@ @CPPFLAGS@ @X_CFLAGS@ -DSYSCONFDIR=\"$(sysconfdir)\" LIBS = $(LIBS_LOCAL) @X_LIBS@ @X_EXTRA_LIBS@ #LIBS = $(LIBS_LOCAL) @X_LIBS@ @X_PRE_LIBS@ @X_EXTRA_LIBS@ LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) PACKAGE = @PACKAGE@ VERSION = @VERSION@ OBJS = main.o all: mlmenu mlmenu: $(OBJS) $(LIBTOOL_LINK) $(OBJS) $(CFLAGS) -o mlmenu $(LIBS) .c.o: $(CC) $(DEFS) $(CFLAGS) -c $< install: $(LIBEXECDIR@WIN32TAG@) $(LIBTOOL_INSTALL) -m 755 mlmenu $(LIBEXECDIR@WIN32TAG@) $(INSTALL) -m 644 ${top_srcdir}/tool/mlmenu/menu-simple $(SYSCONFDIR)/mlterm uninstall: rm -f $(LIBEXECDIR@WIN32TAG@)/mlmenu $(SYSCONFDIR)/mlterm/menu-simple $(LIBEXECDIR@WIN32TAG@): mkdir -p $(LIBEXECDIR@WIN32TAG@) clean: rm -rf $(OBJS) mlmenu mlmenu.exe *.core .libs distclean: clean rm -f Makefile mlterm-3.8.9/tool/mlmenu/main.c010064400017600000144000000173651356600660700151200ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include /* read */ #include /* malloc */ #include #include #include /* open */ #include #include #ifndef SYSCONFDIR #define SYSCONFDIR "/usr/local/etc" #endif #define MENU_FILE SYSCONFDIR "/mlterm/menu-simple" #define FONT_NAME "-*-fixed-*-*-*-*-12-*-*-*-*-*-iso8859-1" typedef struct entry { char *name; char *seq; } entry_t; /* --- static variables --- */ static Display *disp; static Window win; static GC gc1; static GC gc2; static XFontStruct *xfont; static entry_t entries[124]; static u_int n_ent; static int cur_ent = -1; /* --- static functions --- */ static char *get_value(char *dev, char *key) { int count; char ret[1024]; char c; if (dev) { printf("\x1b]5381;%s:%s\x07", dev, key); } else { printf("\x1b]5381;%s\x07", key); } fflush(stdout); for (count = 0; count < 1024; count++) { if (read(STDIN_FILENO, &c, 1) == 1) { if (c != '\n') { ret[count] = c; } else { ret[count] = '\0'; if (count < 2 + strlen(key) || strcmp(ret, "#error") == 0) { return NULL; } /* * #key=value */ return strdup(ret + 2 + strlen(key)); } } else { return NULL; } } return NULL; } static int open_menu_file(void) { char *menu_file; if (getenv("HOME") && (menu_file = malloc(strlen(getenv("HOME")) + 13 + 1))) { int fd; sprintf(menu_file, "%s/.mlterm/menu", getenv("HOME")); fd = open(menu_file, O_RDONLY, 0600); free(menu_file); if (fd >= 0) { return fd; } } return open(MENU_FILE, O_RDONLY, 0600); } static int init_entries(u_int *cols, u_int *rows) { int fd; struct stat st; char *buf; char *line; char *p; /* * XXX Use mmap instead of open/read/close. */ if ((fd = open_menu_file()) == -1) { return 0; } fstat(fd, &st); if ((buf = malloc(st.st_size + 1)) == NULL) { return 0; } read(fd, buf, st.st_size); buf[st.st_size] = '\0'; close(fd); *cols = 0; while (n_ent < 124 && buf) { char *name; char *seq; line = buf; if ((p = strchr(line, '\n'))) { *(p++) = '\0'; } buf = p; p = line; /* Ignore leading white space and tab. */ while (*p == ' ' || *p == '\t') { p++; } if (*p == '#') { continue; } name = p; /* * '\t' is the separator of name and seq. */ while (1) { if (*p == '\0') { seq = ""; goto end; } else if (*p != '\t' && *p != '\n') { p++; } else { *(p++) = '\0'; break; } } /* Ignore tab(separator) and trailing white space. */ while (*p == ' ' || *p == '\t') { p++; } seq = p; while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') { p++; } *p = '\0'; end: if (strcmp(name, "pty_list") == 0 && *seq == '\0') { char *pty_list; char *pty; int is_active; if ((pty_list = get_value(NULL, "pty_list")) == NULL) { return 1; } while (pty_list) { pty = pty_list; pty_list = strchr(pty_list, ':'); if (pty_list) { *pty_list = '\0'; } else { break; } if (*(pty_list + 1) == '1') { is_active = 1; } else { is_active = 0; } if ((pty_list = strchr(pty_list + 1, ';'))) { pty_list++; } if ((name = get_value(pty, "pty_name")) == NULL) { name = pty; } if (strncmp(name, "/dev/", 5) == 0) { name += 5; } seq = malloc(strlen(pty) + 12); sprintf(seq, "select_pty=%s", pty); entries[n_ent].name = name; entries[n_ent].seq = seq; if (*cols < strlen(entries[n_ent].name)) { *cols = strlen(entries[n_ent].name); } if (++n_ent >= 124) { break; } } } else { if (*name != '\0') { entries[n_ent].name = strdup(name); entries[n_ent].seq = strdup(seq); if (*cols < strlen(entries[n_ent].name)) { *cols = strlen(entries[n_ent].name); } if (++n_ent >= 124) { break; } } } } if (n_ent == 0) { return 0; } *rows = n_ent; return 1; } static int init(void) { int x; int y; u_int cols; u_int rows; u_int width; u_int height; if (!init_entries(&cols, &rows)) { return 0; } if ((disp = XOpenDisplay(NULL)) == NULL) { return 0; } if ((xfont = XLoadQueryFont(disp, FONT_NAME)) == NULL) { return 0; } width = xfont->max_bounds.width * cols; height = (xfont->ascent + xfont->descent) * rows; { Window root; Window child; int root_x; int root_y; u_int mask; XQueryPointer(disp, DefaultRootWindow(disp), &root, &child, &root_x, &root_y, &x, &y, &mask); } if (!(win = XCreateSimpleWindow(disp, DefaultRootWindow(disp), x, y, width, height, 1, BlackPixel(disp, DefaultScreen(disp)), WhitePixel(disp, DefaultScreen(disp))))) { return 0; } { XSetWindowAttributes attr; attr.override_redirect = True; XChangeWindowAttributes(disp, win, CWOverrideRedirect, &attr); } { XGCValues gc_value; gc_value.graphics_exposures = 0; gc1 = XCreateGC(disp, win, GCGraphicsExposures, &gc_value); gc2 = XCreateGC(disp, win, GCGraphicsExposures, &gc_value); } XSetForeground(disp, gc1, BlackPixel(disp, DefaultScreen(disp))); XSetBackground(disp, gc1, WhitePixel(disp, DefaultScreen(disp))); XSetFont(disp, gc1, xfont->fid); XSetForeground(disp, gc2, WhitePixel(disp, DefaultScreen(disp))); XSetBackground(disp, gc2, BlackPixel(disp, DefaultScreen(disp))); XSetFont(disp, gc2, xfont->fid); XSelectInput(disp, win, EnterWindowMask | LeaveWindowMask | PointerMotionMask | ButtonPressMask); if (XGrabPointer(disp, DefaultRootWindow(disp), True, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) != GrabSuccess) { return 0; } XMapWindow(disp, win); XClearWindow(disp, win); return 1; } static int update_screen(int n, int reverse) { int start; int end; int count; GC gc; if (n < 0) { /* n == -1 */ start = 0; end = n_ent - 1; } else if (n >= n_ent) { return 0; } else { start = n; end = n; } if (reverse) { gc = gc2; } else { gc = gc1; } for (count = start; count <= end; count++) { XDrawImageString(disp, win, gc, 0, count * (xfont->ascent + xfont->descent) + xfont->ascent, entries[count].name, strlen(entries[count].name)); } return 1; } static int mouse_motion(int y) { int entry; entry = y / (xfont->ascent + xfont->descent); if (entry != cur_ent) { if (cur_ent >= 0) { update_screen(cur_ent, 0); } update_screen(cur_ent = entry, 1); } return 1; } static int mouse_pressed(void) { printf("\x1b]5379;%s\x07", entries[cur_ent].seq); fflush(stdout); return 1; } static int event_loop(void) { XEvent ev; while (1) { XNextEvent(disp, &ev); if (ev.xany.window != win) { break; } if (ev.type == EnterNotify) { mouse_motion(ev.xcrossing.y - 1); } else if (ev.type == MotionNotify) { mouse_motion(ev.xcrossing.y - 1); } else if (ev.type == ButtonPress) { mouse_pressed(); break; } else if (ev.type == LeaveNotify) { update_screen(cur_ent, 0); cur_ent = -1; } } return 1; } /* --- global functions --- */ int main(int argc, char **argv) { if (!init() || !update_screen(-1, 0) || !event_loop()) { return 1; } return 0; } mlterm-3.8.9/tool/mlmenu/menu-simple010064400017600000144000000007161356600660700161760ustar kenusers# # Format: "/dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi func_show_eval '$RM "${nlist}I"' if test -n "$global_symbol_to_import"; then eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[];\ " if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ static void lt_syminit(void) { LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; for (; symbol->name; ++symbol) {" $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" echo >> "$output_objdir/$my_dlsyms" "\ } }" fi echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = { {\"$my_originator\", (void *) 0}," if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ {\"@INIT@\", (void *) <_syminit}," fi case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $debug_cmd win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then case $nm_interface in "MS dumpbin") if func_cygming_ms_implib_p "$1" || func_cygming_gnu_implib_p "$1" then win32_nmres=import else win32_nmres= fi ;; *) func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s|.*|import| p q } }'` ;; esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $debug_cmd sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $debug_cmd match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive that possess that section. Heuristic: eliminate # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $debug_cmd if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result= fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $debug_cmd f_ex_an_ar_dir=$1; shift f_ex_an_ar_oldlib=$1 if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $debug_cmd my_gentop=$1; shift my_oldlibs=${1+"$@"} my_oldobjs= my_xlib= my_xabs= my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` func_basename "$darwin_archive" darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches; do func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" cd "unfat-$$/$darwin_base_archive-$darwin_arch" func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result=$my_oldobjs } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* declarations of non-ANSI functions */ #if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ #if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC #elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined other platforms ... */ #endif #if defined PATH_MAX # define LT_PATHMAX PATH_MAX #elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free (stale); stale = 0; } \ } while (0) #if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; size_t tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined HAVE_DOS_BASED_FILE_SYSTEM if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined HAVE_DOS_BASED_FILE_SYSTEM } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = (size_t) (q - p); p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (STREQ (str, pat)) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else size_t len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { size_t orig_value_len = strlen (orig_value); size_t add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ size_t len = strlen (new_value); while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $debug_cmd case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_suncc_cstd_abi # !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! # Several compiler flags select an ABI that is incompatible with the # Cstd library. Avoid specifying it if any are in CXXFLAGS. func_suncc_cstd_abi () { $debug_cmd case " $compile_command " in *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) suncc_use_cstd_abi=no ;; *) suncc_use_cstd_abi=yes ;; esac } # func_mode_link arg... func_mode_link () { $debug_cmd case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=false prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test yes != "$build_libtool_libs" \ && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg=$1 shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir=$arg prev= continue ;; dlfiles|dlprefiles) $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=: } case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test no = "$dlself"; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test dlprefiles = "$prev"; then dlself=yes elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols=$arg test -f "$arg" \ || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex=$arg prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir=$arg prev= continue ;; mllvm) # Clang does not use LLVM to link, so we can simply discard any # '-mllvm $arg' options when doing the link step. prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object fi # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; os2dllname) os2dllname=$arg prev= continue ;; precious_regex) precious_files_regex=$arg prev= continue ;; release) release=-$arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds=$arg prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg=$arg case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between '-L' and '$1'" else func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of '$dir'" dir=$absdir ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test X-lc = "X$arg" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc due to us having libc/libc_r. test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test X-lc = "X$arg" && continue ;; esac elif test X-lc_r = "X$arg"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -mllvm) prev=mllvm continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module=$wl-multi_module continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "'-no-install' is ignored for $host" func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -os2dllname) prev=os2dllname continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -stdlib=* select c++ std lib with clang -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ -fopenacc|-fopenmp|-ftree-parallelize-loops=*|-fcilkplus|-fgnu-tm| \ -ffast-math|-funsafe-math-optimizations|-fvtable-verify*| \ -shared-libgcc|-static-libgcc|-static-libgfortran|-static-libstdc++) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; -Z*) if test os2 = "`expr $host : '.*\(os2\)'`"; then # OS/2 uses -Zxxx to specify OS/2-specific options compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case $arg in -Zlinker | -Zstack) prev=xcompiler ;; esac continue else # Otherwise treat like 'Some other compiler flag' below func_quote_for_eval "$arg" arg=$func_quote_for_eval_result fi ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result test none = "$pic_object" || { # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object } # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the '$prevarg' option requires an argument" if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname=$func_basename_result libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" # Definition is injected by LT_CONFIG during libtool generation. func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" func_dirname "$output" "/" "" output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs=$tmp_deplibs fi if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass"; then libs=$deplibs deplibs= fi if test prog = "$linkmode"; then case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs=$dlprefiles fi if test dlopen = "$pass"; then # Collect dlpreopened libraries save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test lib != "$linkmode" && test prog != "$linkmode"; then func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib=$searchdir/lib$name$search_ext if test -f "$lib"; then if test .la = "$search_ext"; then found=: else found=false fi break 2 fi done done if $found; then # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll=$l done if test "X$ll" = "X$old_library"; then # only static version available found=false func_dirname "$lib" "" "." ladir=$func_dirname_result lib=$ladir/$old_library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi else # deplib doesn't seem to be a libtool library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l *.ltframework) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=: fi ;; pass_all) valid_a_lib=: ;; esac if $valid_a_lib; then echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." fi ;; esac continue ;; prog) if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test conv = "$pass"; then deplibs="$deplib $deplibs" elif test prog = "$linkmode"; then if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=: continue ;; esac # case $deplib $found || test -f "$lib" \ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir=$func_dirname_result dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass" || { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test yes = "$prefer_static_libs" || test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib=$l done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. if test dlopen = "$pass"; then test -z "$libdir" \ && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || test yes != "$dlopen_support" || test no = "$build_libtool_libs" then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir=$ladir fi ;; esac func_basename "$lib" laname=$func_basename_result # Find the relevant object directory and library name. if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library '$lib' was moved." dir=$ladir absdir=$abs_ladir libdir=$abs_ladir else dir=$lt_sysroot$libdir absdir=$lt_sysroot$libdir fi test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir=$ladir absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else dir=$ladir/$objdir absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test dlpreopen = "$pass"; then if test -z "$libdir" && test prog = "$linkmode"; then func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=false if test no != "$link_all_deplibs" || test -z "$library_names" || test no = "$build_libtool_libs"; then linkalldeplibs=: fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && { { test no = "$prefer_static_libs" || test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if $alldeplibs && { test pass_all = "$deplibs_check_method" || { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule=$dlpremoduletest break fi done if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test lib = "$linkmode" && test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result versuffix=-$major ;; esac eval soname=\"$soname_spec\" else soname=$realname fi # Make a new name for the extract_expsyms_cmds to use soroot=$soname func_basename "$soroot" soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test no = "$hardcode_direct"; then add=$dir/$linklib case $host in *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add=$dir/$old_library fi elif test -n "$old_library"; then add=$dir/$old_library fi fi esac elif test no = "$hardcode_minus_L"; then case $host in *-*-sunos*) add_shlibpath=$dir ;; esac add_dir=-L$dir add=-l$name elif test no = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; relink) if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$dir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name elif test yes = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; *) lib_linked=no ;; esac if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test yes != "$hardcode_direct" && test yes != "$hardcode_minus_L" && test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$libdir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$libdir add=-l$name elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add=-l$name elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib"; then add=$inst_prefix_dir$libdir/$linklib else add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir=-L$libdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name fi if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test unsupported != "$hardcode_direct"; then test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test yes = "$build_libtool_libs"; then # Not a shared library if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test lib = "$linkmode"; then if test -n "$dependency_libs" && { test yes != "$hardcode_into_libs" || test yes = "$build_old_libs" || test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of '$dir'" absdir=$dir fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names"; then for tmp in $deplibrary_names; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl"; then depdepl=$absdir/$objdir/$depdepl darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) path=-L$absdir/$objdir ;; esac else eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "'$deplib' seems to be moved" path=-L$absdir fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test link = "$pass"; then if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs=$newdependency_libs if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test dlopen != "$pass"; then test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= } if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" else vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Add Sun CC postdeps if required: test CXX = "$tagname" && { case $host_os in linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; solaris*) func_cc_basename "$CC" case $func_cc_basename_result in CC* | sunCC*) func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; esac } # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i= ;; esac if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test prog = "$linkmode"; then dlfiles=$newdlfiles fi if test prog = "$linkmode" || test lib = "$linkmode"; then dlprefiles=$newdlprefiles fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs=$output func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test no = "$module" \ && func_fatal_help "libtool library '$output' must begin with 'lib'" if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test pass_all != "$deplibs_check_method"; then func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test no = "$dlself" \ || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test 1 -lt "$#" \ && func_warning "ignoring multiple '-rpath's for a libtool library" install_libdir=$1 oldlibs= if test -z "$rpath"; then if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift IFS=$save_ifs test -n "$7" && \ func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major=$1 number_minor=$2 number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|freebsd-elf|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_revision ;; freebsd-aout|qnx|sunos) current=$number_major revision=$number_minor age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_minor lt_irix_increment=no ;; esac ;; no) current=$1 revision=$2 age=$3 ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT '$current' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION '$revision' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE '$age' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE '$age' is greater than the current interface number '$current'" func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" # On Darwin other compilers case $CC in nagfor*) verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" ;; *) verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; esac ;; freebsd-aout) major=.$current versuffix=.$current.$revision ;; freebsd-elf) func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; irix | nonstopux) if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring_prefix$major.$iface:$verstring done # Before this point, $major must not contain '.'. major=.$major versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=.$current.$age.$revision verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring:$iface.0 done # Make executables depend on our current version. func_append verstring ":$current.0" ;; qnx) major=.$current versuffix=.$current ;; sco) major=.$current versuffix=.$current ;; sunos) major=.$current versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result versuffix=-$major ;; *) func_fatal_configuration "unknown library version type '$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring=0.0 ;; esac if test no = "$need_version"; then versuffix= else versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided if test yes,no = "$avoid_version,$need_version"; then major= versuffix= verstring= fi # Check to see if the archive will have undefined symbols. if test yes = "$allow_undefined"; then if test unsupported = "$allow_undefined_flag"; then if test yes = "$build_old_libs"; then func_warning "undefined symbols not allowed in $host shared libraries; building static only" build_libtool_libs=no else func_fatal_error "can't build $host shared library unless -no-undefined is specified" fi fi else # Don't allow undefined symbols. allow_undefined_flag=$no_undefined_flag fi fi func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" test " " = "$libobjs" && libobjs= if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release= versuffix= major= newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib= ;; esac fi if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test yes = "$allow_libtool_libs_with_static_runtimes"; then for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test yes = "$droppeddeps"; then if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test yes = "$build_libtool_libs"; then # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath=$finalize_rpath test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath=$finalize_shlibpath test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname=$realname fi if test -z "$dlname"; then dlname=$soname fi lib=$output_objdir/$realname linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS=$save_ifs if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi ${skipped_export-false} && { func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi } libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs=$IFS; IFS='~' for cmd in $cmds; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs # Restore the uninstalled library and exit if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. dlname=$soname fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ func_warning "'-version-info' is ignored for objects" test -n "$release" && \ func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj=$output ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # if reload_cmds runs $LD directly, get rid of -Wl from # whole_archive_flag_spec and hope we can get by with turning comma # into space. case $reload_cmds in *\$LD[\ \$]*) wl= ;; esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS } if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "'-version-info' is ignored for programs" test -n "$release" && \ func_warning "'-release' is ignored for programs" $preload \ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " $wl-bind_at_load" func_append finalize_command " $wl-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath=$rpath rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath=$rpath if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=false ;; *cygwin* | *mingw* ) test yes = "$build_libtool_libs" || wrappers_required=false ;; *) if test no = "$need_relink" || test yes != "$build_libtool_libs"; then wrappers_required=false fi ;; esac $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.$objext"; then func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test yes = "$no_install"; then # We don't need to create a wrapper script. link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi case $hardcode_action,$fast_install in relink,*) # Fast installation is not supported link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath func_warning "this platform does not like uninstalled shared libraries" func_warning "'$output' will be relinked during installation" ;; *,yes) link_command=$finalize_var$compile_command$finalize_rpath relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` ;; *,no) link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath ;; *,needless) link_command=$finalize_var$compile_command$finalize_rpath relink_command= ;; esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource=$output_path/$objdir/lt-$output_name.c cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do case $build_libtool_libs in convenience) oldobjs="$libobjs_save $symfileobj" addlibs=$convenience build_libtool_libs=no ;; module) oldobjs=$libobjs_save addlibs=$old_convenience build_libtool_libs=no ;; *) oldobjs="$old_deplibs $non_pic_objects" $preload && test -f "$symfileobj" \ && func_append oldobjs " $symfileobj" addlibs=$old_convenience ;; esac if test -n "$addlibs"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test yes = "$installed"; then if test -z "$install_libdir"; then break fi output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name=$func_basename_result func_resolve_sysroot "$deplib" eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } if test link = "$opt_mode" || test relink = "$opt_mode"; then func_mode_link ${1+"$@"} fi # func_mode_uninstall arg... func_mode_uninstall () { $debug_cmd RM=$nonopt files= rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic for arg do case $arg in -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir=$func_dirname_result if test . = "$dir"; then odir=$objdir else odir=$dir/$objdir fi func_basename "$file" name=$func_basename_result test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif $rmforce; then continue fi rmfiles=$file case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.$objext" if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name"; then func_append rmfiles " $odir/lt-$noexename.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then func_mode_uninstall ${1+"$@"} fi test -z "$opt_mode" && { help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: mlterm-3.8.9/encodefilter/src004075500017600000144000000000001356600661000147125ustar kenusersmlterm-3.8.9/encodefilter/src/table004075500017600000144000000000001356600661000160015ustar kenusersmlterm-3.8.9/encodefilter/src/table/ef_gb18030_2000_range.table010064400017600000144000000434621356600661000223520ustar kenusers/* * ef_gb18030_2000_range.table */ #ifndef __EF_GB18030_2000_RANGE_TABLE__ #define __EF_GB18030_2000_RANGE_TABLE__ /* ---> static variables <--- */ static gb18030_range_t gb18030_ranges[] = { { 0x0080 , 0x00a3 , { 0x81 , 0x30 , 0x81 , 0x30 } , { 0x81 , 0x30 , 0x84 , 0x35 } } , { 0x00a5 , 0x00a6 , { 0x81 , 0x30 , 0x84 , 0x36 } , { 0x81 , 0x30 , 0x84 , 0x37 } } , { 0x00a9 , 0x00af , { 0x81 , 0x30 , 0x84 , 0x38 } , { 0x81 , 0x30 , 0x85 , 0x34 } } , { 0x00b2 , 0x00b6 , { 0x81 , 0x30 , 0x85 , 0x35 } , { 0x81 , 0x30 , 0x85 , 0x39 } } , { 0x00b8 , 0x00d6 , { 0x81 , 0x30 , 0x86 , 0x30 } , { 0x81 , 0x30 , 0x89 , 0x30 } } , { 0x00d8 , 0x00df , { 0x81 , 0x30 , 0x89 , 0x31 } , { 0x81 , 0x30 , 0x89 , 0x38 } } , { 0x00e2 , 0x00e7 , { 0x81 , 0x30 , 0x89 , 0x39 } , { 0x81 , 0x30 , 0x8A , 0x34 } } , { 0x00eb , 0x00eb , { 0x81 , 0x30 , 0x8A , 0x35 } , { 0x81 , 0x30 , 0x8A , 0x35 } } , { 0x00ee , 0x00f1 , { 0x81 , 0x30 , 0x8A , 0x36 } , { 0x81 , 0x30 , 0x8A , 0x39 } } , { 0x00f4 , 0x00f6 , { 0x81 , 0x30 , 0x8B , 0x30 } , { 0x81 , 0x30 , 0x8B , 0x32 } } , { 0x00f8 , 0x00f8 , { 0x81 , 0x30 , 0x8B , 0x33 } , { 0x81 , 0x30 , 0x8B , 0x33 } } , { 0x00fb , 0x00fb , { 0x81 , 0x30 , 0x8B , 0x34 } , { 0x81 , 0x30 , 0x8B , 0x34 } } , { 0x00fd , 0x0100 , { 0x81 , 0x30 , 0x8B , 0x35 } , { 0x81 , 0x30 , 0x8B , 0x38 } } , { 0x0102 , 0x0112 , { 0x81 , 0x30 , 0x8B , 0x39 } , { 0x81 , 0x30 , 0x8D , 0x35 } } , { 0x0114 , 0x011a , { 0x81 , 0x30 , 0x8D , 0x36 } , { 0x81 , 0x30 , 0x8E , 0x32 } } , { 0x011c , 0x012a , { 0x81 , 0x30 , 0x8E , 0x33 } , { 0x81 , 0x30 , 0x8F , 0x37 } } , { 0x012c , 0x0143 , { 0x81 , 0x30 , 0x8F , 0x38 } , { 0x81 , 0x30 , 0x92 , 0x31 } } , { 0x0145 , 0x0147 , { 0x81 , 0x30 , 0x92 , 0x32 } , { 0x81 , 0x30 , 0x92 , 0x34 } } , { 0x0149 , 0x014c , { 0x81 , 0x30 , 0x92 , 0x35 } , { 0x81 , 0x30 , 0x92 , 0x38 } } , { 0x014e , 0x016a , { 0x81 , 0x30 , 0x92 , 0x39 } , { 0x81 , 0x30 , 0x95 , 0x37 } } , { 0x016c , 0x01cd , { 0x81 , 0x30 , 0x95 , 0x38 } , { 0x81 , 0x30 , 0x9F , 0x35 } } , { 0x01cf , 0x01cf , { 0x81 , 0x30 , 0x9F , 0x36 } , { 0x81 , 0x30 , 0x9F , 0x36 } } , { 0x01d1 , 0x01d1 , { 0x81 , 0x30 , 0x9F , 0x37 } , { 0x81 , 0x30 , 0x9F , 0x37 } } , { 0x01d3 , 0x01d3 , { 0x81 , 0x30 , 0x9F , 0x38 } , { 0x81 , 0x30 , 0x9F , 0x38 } } , { 0x01d5 , 0x01d5 , { 0x81 , 0x30 , 0x9F , 0x39 } , { 0x81 , 0x30 , 0x9F , 0x39 } } , { 0x01d7 , 0x01d7 , { 0x81 , 0x30 , 0xA0 , 0x30 } , { 0x81 , 0x30 , 0xA0 , 0x30 } } , { 0x01d9 , 0x01d9 , { 0x81 , 0x30 , 0xA0 , 0x31 } , { 0x81 , 0x30 , 0xA0 , 0x31 } } , { 0x01db , 0x01db , { 0x81 , 0x30 , 0xA0 , 0x32 } , { 0x81 , 0x30 , 0xA0 , 0x32 } } , { 0x01dd , 0x01f8 , { 0x81 , 0x30 , 0xA0 , 0x33 } , { 0x81 , 0x30 , 0xA3 , 0x30 } } , { 0x01fa , 0x0250 , { 0x81 , 0x30 , 0xA3 , 0x31 } , { 0x81 , 0x30 , 0xAB , 0x37 } } , { 0x0252 , 0x0260 , { 0x81 , 0x30 , 0xAB , 0x38 } , { 0x81 , 0x30 , 0xAD , 0x32 } } , { 0x0262 , 0x02c6 , { 0x81 , 0x30 , 0xAD , 0x33 } , { 0x81 , 0x30 , 0xB7 , 0x33 } } , { 0x02c8 , 0x02c8 , { 0x81 , 0x30 , 0xB7 , 0x34 } , { 0x81 , 0x30 , 0xB7 , 0x34 } } , { 0x02cc , 0x02d8 , { 0x81 , 0x30 , 0xB7 , 0x35 } , { 0x81 , 0x30 , 0xB8 , 0x37 } } , { 0x02da , 0x0390 , { 0x81 , 0x30 , 0xB8 , 0x38 } , { 0x81 , 0x30 , 0xCB , 0x30 } } , { 0x03a2 , 0x03a2 , { 0x81 , 0x30 , 0xCB , 0x31 } , { 0x81 , 0x30 , 0xCB , 0x31 } } , { 0x03aa , 0x03b0 , { 0x81 , 0x30 , 0xCB , 0x32 } , { 0x81 , 0x30 , 0xCB , 0x38 } } , { 0x03c2 , 0x03c2 , { 0x81 , 0x30 , 0xCB , 0x39 } , { 0x81 , 0x30 , 0xCB , 0x39 } } , { 0x03ca , 0x0400 , { 0x81 , 0x30 , 0xCC , 0x30 } , { 0x81 , 0x30 , 0xD1 , 0x34 } } , { 0x0402 , 0x040f , { 0x81 , 0x30 , 0xD1 , 0x35 } , { 0x81 , 0x30 , 0xD2 , 0x38 } } , { 0x0450 , 0x0450 , { 0x81 , 0x30 , 0xD2 , 0x39 } , { 0x81 , 0x30 , 0xD2 , 0x39 } } , { 0x2011 , 0x2012 , { 0x81 , 0x36 , 0xA5 , 0x32 } , { 0x81 , 0x36 , 0xA5 , 0x33 } } , { 0x2017 , 0x2017 , { 0x81 , 0x36 , 0xA5 , 0x34 } , { 0x81 , 0x36 , 0xA5 , 0x34 } } , { 0x201a , 0x201b , { 0x81 , 0x36 , 0xA5 , 0x35 } , { 0x81 , 0x36 , 0xA5 , 0x36 } } , { 0x201e , 0x2024 , { 0x81 , 0x36 , 0xA5 , 0x37 } , { 0x81 , 0x36 , 0xA6 , 0x33 } } , { 0x2027 , 0x202f , { 0x81 , 0x36 , 0xA6 , 0x34 } , { 0x81 , 0x36 , 0xA7 , 0x32 } } , { 0x2031 , 0x2031 , { 0x81 , 0x36 , 0xA7 , 0x33 } , { 0x81 , 0x36 , 0xA7 , 0x33 } } , { 0x2034 , 0x2034 , { 0x81 , 0x36 , 0xA7 , 0x34 } , { 0x81 , 0x36 , 0xA7 , 0x34 } } , { 0x2036 , 0x203a , { 0x81 , 0x36 , 0xA7 , 0x35 } , { 0x81 , 0x36 , 0xA7 , 0x39 } } , { 0x203c , 0x20ab , { 0x81 , 0x36 , 0xA8 , 0x30 } , { 0x81 , 0x36 , 0xB3 , 0x31 } } , { 0x20ad , 0x2102 , { 0x81 , 0x36 , 0xB3 , 0x32 } , { 0x81 , 0x36 , 0xBB , 0x37 } } , { 0x2104 , 0x2104 , { 0x81 , 0x36 , 0xBB , 0x38 } , { 0x81 , 0x36 , 0xBB , 0x38 } } , { 0x2106 , 0x2108 , { 0x81 , 0x36 , 0xBB , 0x39 } , { 0x81 , 0x36 , 0xBC , 0x31 } } , { 0x210a , 0x2115 , { 0x81 , 0x36 , 0xBC , 0x32 } , { 0x81 , 0x36 , 0xBD , 0x33 } } , { 0x2117 , 0x2120 , { 0x81 , 0x36 , 0xBD , 0x34 } , { 0x81 , 0x36 , 0xBE , 0x33 } } , { 0x2122 , 0x215f , { 0x81 , 0x36 , 0xBE , 0x34 } , { 0x81 , 0x36 , 0xC4 , 0x35 } } , { 0x216c , 0x216f , { 0x81 , 0x36 , 0xC4 , 0x36 } , { 0x81 , 0x36 , 0xC4 , 0x39 } } , { 0x217a , 0x218f , { 0x81 , 0x36 , 0xC5 , 0x30 } , { 0x81 , 0x36 , 0xC7 , 0x31 } } , { 0x2194 , 0x2195 , { 0x81 , 0x36 , 0xC7 , 0x32 } , { 0x81 , 0x36 , 0xC7 , 0x33 } } , { 0x219a , 0x2207 , { 0x81 , 0x36 , 0xC7 , 0x34 } , { 0x81 , 0x36 , 0xD2 , 0x33 } } , { 0x2209 , 0x220e , { 0x81 , 0x36 , 0xD2 , 0x34 } , { 0x81 , 0x36 , 0xD2 , 0x39 } } , { 0x2210 , 0x2210 , { 0x81 , 0x36 , 0xD3 , 0x30 } , { 0x81 , 0x36 , 0xD3 , 0x30 } } , { 0x2212 , 0x2214 , { 0x81 , 0x36 , 0xD3 , 0x31 } , { 0x81 , 0x36 , 0xD3 , 0x33 } } , { 0x2216 , 0x2219 , { 0x81 , 0x36 , 0xD3 , 0x34 } , { 0x81 , 0x36 , 0xD3 , 0x37 } } , { 0x221b , 0x221c , { 0x81 , 0x36 , 0xD3 , 0x38 } , { 0x81 , 0x36 , 0xD3 , 0x39 } } , { 0x2221 , 0x2222 , { 0x81 , 0x36 , 0xD4 , 0x30 } , { 0x81 , 0x36 , 0xD4 , 0x31 } } , { 0x2224 , 0x2224 , { 0x81 , 0x36 , 0xD4 , 0x32 } , { 0x81 , 0x36 , 0xD4 , 0x32 } } , { 0x2226 , 0x2226 , { 0x81 , 0x36 , 0xD4 , 0x33 } , { 0x81 , 0x36 , 0xD4 , 0x33 } } , { 0x222c , 0x222d , { 0x81 , 0x36 , 0xD4 , 0x34 } , { 0x81 , 0x36 , 0xD4 , 0x35 } } , { 0x222f , 0x2233 , { 0x81 , 0x36 , 0xD4 , 0x36 } , { 0x81 , 0x36 , 0xD5 , 0x30 } } , { 0x2238 , 0x223c , { 0x81 , 0x36 , 0xD5 , 0x31 } , { 0x81 , 0x36 , 0xD5 , 0x35 } } , { 0x223e , 0x2247 , { 0x81 , 0x36 , 0xD5 , 0x36 } , { 0x81 , 0x36 , 0xD6 , 0x35 } } , { 0x2249 , 0x224b , { 0x81 , 0x36 , 0xD6 , 0x36 } , { 0x81 , 0x36 , 0xD6 , 0x38 } } , { 0x224d , 0x2251 , { 0x81 , 0x36 , 0xD6 , 0x39 } , { 0x81 , 0x36 , 0xD7 , 0x33 } } , { 0x2253 , 0x225f , { 0x81 , 0x36 , 0xD7 , 0x34 } , { 0x81 , 0x36 , 0xD8 , 0x36 } } , { 0x2262 , 0x2263 , { 0x81 , 0x36 , 0xD8 , 0x37 } , { 0x81 , 0x36 , 0xD8 , 0x38 } } , { 0x2268 , 0x226d , { 0x81 , 0x36 , 0xD8 , 0x39 } , { 0x81 , 0x36 , 0xD9 , 0x34 } } , { 0x2270 , 0x2294 , { 0x81 , 0x36 , 0xD9 , 0x35 } , { 0x81 , 0x36 , 0xDD , 0x31 } } , { 0x2296 , 0x2298 , { 0x81 , 0x36 , 0xDD , 0x32 } , { 0x81 , 0x36 , 0xDD , 0x34 } } , { 0x229a , 0x22a4 , { 0x81 , 0x36 , 0xDD , 0x35 } , { 0x81 , 0x36 , 0xDE , 0x35 } } , { 0x22a6 , 0x22be , { 0x81 , 0x36 , 0xDE , 0x36 } , { 0x81 , 0x36 , 0xE1 , 0x30 } } , { 0x22c0 , 0x2311 , { 0x81 , 0x36 , 0xE1 , 0x31 } , { 0x81 , 0x36 , 0xE9 , 0x32 } } , { 0x2313 , 0x245f , { 0x81 , 0x36 , 0xE9 , 0x33 } , { 0x81 , 0x37 , 0x8C , 0x35 } } , { 0x246a , 0x2473 , { 0x81 , 0x37 , 0x8C , 0x36 } , { 0x81 , 0x37 , 0x8D , 0x35 } } , { 0x249c , 0x24ff , { 0x81 , 0x37 , 0x8D , 0x36 } , { 0x81 , 0x37 , 0x97 , 0x35 } } , { 0x254c , 0x254f , { 0x81 , 0x37 , 0x97 , 0x36 } , { 0x81 , 0x37 , 0x97 , 0x39 } } , { 0x2574 , 0x2580 , { 0x81 , 0x37 , 0x98 , 0x30 } , { 0x81 , 0x37 , 0x99 , 0x32 } } , { 0x2590 , 0x2592 , { 0x81 , 0x37 , 0x99 , 0x33 } , { 0x81 , 0x37 , 0x99 , 0x35 } } , { 0x2596 , 0x259f , { 0x81 , 0x37 , 0x99 , 0x36 } , { 0x81 , 0x37 , 0x9A , 0x35 } } , { 0x25a2 , 0x25b1 , { 0x81 , 0x37 , 0x9A , 0x36 } , { 0x81 , 0x37 , 0x9C , 0x31 } } , { 0x25b4 , 0x25bb , { 0x81 , 0x37 , 0x9C , 0x32 } , { 0x81 , 0x37 , 0x9C , 0x39 } } , { 0x25be , 0x25c5 , { 0x81 , 0x37 , 0x9D , 0x30 } , { 0x81 , 0x37 , 0x9D , 0x37 } } , { 0x25c8 , 0x25ca , { 0x81 , 0x37 , 0x9D , 0x38 } , { 0x81 , 0x37 , 0x9E , 0x30 } } , { 0x25cc , 0x25cd , { 0x81 , 0x37 , 0x9E , 0x31 } , { 0x81 , 0x37 , 0x9E , 0x32 } } , { 0x25d0 , 0x25e1 , { 0x81 , 0x37 , 0x9E , 0x33 } , { 0x81 , 0x37 , 0xA0 , 0x30 } } , { 0x25e6 , 0x2604 , { 0x81 , 0x37 , 0xA0 , 0x31 } , { 0x81 , 0x37 , 0xA3 , 0x31 } } , { 0x2607 , 0x2608 , { 0x81 , 0x37 , 0xA3 , 0x32 } , { 0x81 , 0x37 , 0xA3 , 0x33 } } , { 0x260a , 0x263f , { 0x81 , 0x37 , 0xA3 , 0x34 } , { 0x81 , 0x37 , 0xA8 , 0x37 } } , { 0x2641 , 0x2641 , { 0x81 , 0x37 , 0xA8 , 0x38 } , { 0x81 , 0x37 , 0xA8 , 0x38 } } , { 0x2e82 , 0x2e83 , { 0x81 , 0x38 , 0xFD , 0x39 } , { 0x81 , 0x38 , 0xFE , 0x30 } } , { 0x2e85 , 0x2e87 , { 0x81 , 0x38 , 0xFE , 0x31 } , { 0x81 , 0x38 , 0xFE , 0x33 } } , { 0x2e89 , 0x2e8a , { 0x81 , 0x38 , 0xFE , 0x34 } , { 0x81 , 0x38 , 0xFE , 0x35 } } , { 0x2e8d , 0x2e96 , { 0x81 , 0x38 , 0xFE , 0x36 } , { 0x81 , 0x39 , 0x81 , 0x35 } } , { 0x2e98 , 0x2ea6 , { 0x81 , 0x39 , 0x81 , 0x36 } , { 0x81 , 0x39 , 0x83 , 0x30 } } , { 0x2ea8 , 0x2ea9 , { 0x81 , 0x39 , 0x83 , 0x31 } , { 0x81 , 0x39 , 0x83 , 0x32 } } , { 0x2eab , 0x2ead , { 0x81 , 0x39 , 0x83 , 0x33 } , { 0x81 , 0x39 , 0x83 , 0x35 } } , { 0x2eaf , 0x2eb2 , { 0x81 , 0x39 , 0x83 , 0x36 } , { 0x81 , 0x39 , 0x83 , 0x39 } } , { 0x2eb4 , 0x2eb5 , { 0x81 , 0x39 , 0x84 , 0x30 } , { 0x81 , 0x39 , 0x84 , 0x31 } } , { 0x2eb8 , 0x2eba , { 0x81 , 0x39 , 0x84 , 0x32 } , { 0x81 , 0x39 , 0x84 , 0x34 } } , { 0x2ebc , 0x2ec9 , { 0x81 , 0x39 , 0x84 , 0x35 } , { 0x81 , 0x39 , 0x85 , 0x38 } } , { 0x2ecb , 0x2fef , { 0x81 , 0x39 , 0x85 , 0x39 } , { 0x81 , 0x39 , 0xA3 , 0x31 } } , { 0x2ffc , 0x2fff , { 0x81 , 0x39 , 0xA3 , 0x32 } , { 0x81 , 0x39 , 0xA3 , 0x35 } } , { 0x3004 , 0x3004 , { 0x81 , 0x39 , 0xA3 , 0x36 } , { 0x81 , 0x39 , 0xA3 , 0x36 } } , { 0x3018 , 0x301c , { 0x81 , 0x39 , 0xA3 , 0x37 } , { 0x81 , 0x39 , 0xA4 , 0x31 } } , { 0x301f , 0x3020 , { 0x81 , 0x39 , 0xA4 , 0x32 } , { 0x81 , 0x39 , 0xA4 , 0x33 } } , { 0x302a , 0x303d , { 0x81 , 0x39 , 0xA4 , 0x34 } , { 0x81 , 0x39 , 0xA6 , 0x33 } } , { 0x303f , 0x3040 , { 0x81 , 0x39 , 0xA6 , 0x34 } , { 0x81 , 0x39 , 0xA6 , 0x35 } } , { 0x3094 , 0x309a , { 0x81 , 0x39 , 0xA6 , 0x36 } , { 0x81 , 0x39 , 0xA7 , 0x32 } } , { 0x309f , 0x30a0 , { 0x81 , 0x39 , 0xA7 , 0x33 } , { 0x81 , 0x39 , 0xA7 , 0x34 } } , { 0x30f7 , 0x30fb , { 0x81 , 0x39 , 0xA7 , 0x35 } , { 0x81 , 0x39 , 0xA7 , 0x39 } } , { 0x30ff , 0x3104 , { 0x81 , 0x39 , 0xA8 , 0x30 } , { 0x81 , 0x39 , 0xA8 , 0x35 } } , { 0x312a , 0x321f , { 0x81 , 0x39 , 0xA8 , 0x36 } , { 0x81 , 0x39 , 0xC1 , 0x31 } } , { 0x322a , 0x3230 , { 0x81 , 0x39 , 0xC1 , 0x32 } , { 0x81 , 0x39 , 0xC1 , 0x38 } } , { 0x3232 , 0x32a2 , { 0x81 , 0x39 , 0xC1 , 0x39 } , { 0x81 , 0x39 , 0xCD , 0x31 } } , { 0x32a4 , 0x338d , { 0x81 , 0x39 , 0xCD , 0x32 } , { 0x81 , 0x39 , 0xE4 , 0x35 } } , { 0x3390 , 0x339b , { 0x81 , 0x39 , 0xE4 , 0x36 } , { 0x81 , 0x39 , 0xE5 , 0x37 } } , { 0x339f , 0x33a0 , { 0x81 , 0x39 , 0xE5 , 0x38 } , { 0x81 , 0x39 , 0xE5 , 0x39 } } , { 0x33a2 , 0x33c3 , { 0x81 , 0x39 , 0xE6 , 0x30 } , { 0x81 , 0x39 , 0xE9 , 0x33 } } , { 0x33c5 , 0x33cd , { 0x81 , 0x39 , 0xE9 , 0x34 } , { 0x81 , 0x39 , 0xEA , 0x32 } } , { 0x33cf , 0x33d0 , { 0x81 , 0x39 , 0xEA , 0x33 } , { 0x81 , 0x39 , 0xEA , 0x34 } } , { 0x33d3 , 0x33d4 , { 0x81 , 0x39 , 0xEA , 0x35 } , { 0x81 , 0x39 , 0xEA , 0x36 } } , { 0x33d6 , 0x3446 , { 0x81 , 0x39 , 0xEA , 0x37 } , { 0x81 , 0x39 , 0xF5 , 0x39 } } , { 0x3448 , 0x3472 , { 0x81 , 0x39 , 0xF6 , 0x30 } , { 0x81 , 0x39 , 0xFA , 0x32 } } , { 0x3474 , 0x359d , { 0x81 , 0x39 , 0xFA , 0x33 } , { 0x82 , 0x30 , 0x9A , 0x30 } } , { 0x359f , 0x360d , { 0x82 , 0x30 , 0x9A , 0x31 } , { 0x82 , 0x30 , 0xA5 , 0x31 } } , { 0x360f , 0x3619 , { 0x82 , 0x30 , 0xA5 , 0x32 } , { 0x82 , 0x30 , 0xA6 , 0x32 } } , { 0x3919 , 0x396d , { 0x82 , 0x30 , 0xF2 , 0x38 } , { 0x82 , 0x30 , 0xFB , 0x32 } } , { 0x396f , 0x39ce , { 0x82 , 0x30 , 0xFB , 0x33 } , { 0x82 , 0x31 , 0x86 , 0x38 } } , { 0x39d1 , 0x39de , { 0x82 , 0x31 , 0x86 , 0x39 } , { 0x82 , 0x31 , 0x88 , 0x32 } } , { 0x39e0 , 0x3a72 , { 0x82 , 0x31 , 0x88 , 0x33 } , { 0x82 , 0x31 , 0x96 , 0x39 } } , { 0x3a74 , 0x3b4d , { 0x82 , 0x31 , 0x97 , 0x30 } , { 0x82 , 0x31 , 0xAC , 0x37 } } , { 0x3b4f , 0x3c6d , { 0x82 , 0x31 , 0xAC , 0x38 } , { 0x82 , 0x31 , 0xC9 , 0x34 } } , { 0x3c6f , 0x3cdf , { 0x82 , 0x31 , 0xC9 , 0x35 } , { 0x82 , 0x31 , 0xD4 , 0x37 } } , { 0x4057 , 0x415e , { 0x82 , 0x32 , 0xAF , 0x33 } , { 0x82 , 0x32 , 0xC9 , 0x36 } } , { 0x4338 , 0x43ab , { 0x82 , 0x32 , 0xF8 , 0x38 } , { 0x82 , 0x33 , 0x86 , 0x33 } } , { 0x43ad , 0x43b0 , { 0x82 , 0x33 , 0x86 , 0x34 } , { 0x82 , 0x33 , 0x86 , 0x37 } } , { 0x43b2 , 0x43dc , { 0x82 , 0x33 , 0x86 , 0x38 } , { 0x82 , 0x33 , 0x8B , 0x30 } } , { 0x43de , 0x44d5 , { 0x82 , 0x33 , 0x8B , 0x31 } , { 0x82 , 0x33 , 0xA3 , 0x38 } } , { 0x464d , 0x4660 , { 0x82 , 0x33 , 0xC9 , 0x32 } , { 0x82 , 0x33 , 0xCB , 0x31 } } , { 0x4662 , 0x4722 , { 0x82 , 0x33 , 0xCB , 0x32 } , { 0x82 , 0x33 , 0xDE , 0x34 } } , { 0x4724 , 0x4728 , { 0x82 , 0x33 , 0xDE , 0x35 } , { 0x82 , 0x33 , 0xDE , 0x39 } } , { 0x472a , 0x477b , { 0x82 , 0x33 , 0xDF , 0x30 } , { 0x82 , 0x33 , 0xE7 , 0x31 } } , { 0x477d , 0x478c , { 0x82 , 0x33 , 0xE7 , 0x32 } , { 0x82 , 0x33 , 0xE8 , 0x37 } } , { 0x4948 , 0x4979 , { 0x82 , 0x34 , 0x96 , 0x39 } , { 0x82 , 0x34 , 0x9B , 0x38 } } , { 0x497b , 0x497c , { 0x82 , 0x34 , 0x9B , 0x39 } , { 0x82 , 0x34 , 0x9C , 0x30 } } , { 0x497e , 0x4981 , { 0x82 , 0x34 , 0x9C , 0x31 } , { 0x82 , 0x34 , 0x9C , 0x34 } } , { 0x4984 , 0x4984 , { 0x82 , 0x34 , 0x9C , 0x35 } , { 0x82 , 0x34 , 0x9C , 0x35 } } , { 0x4987 , 0x499a , { 0x82 , 0x34 , 0x9C , 0x36 } , { 0x82 , 0x34 , 0x9E , 0x35 } } , { 0x499c , 0x499e , { 0x82 , 0x34 , 0x9E , 0x36 } , { 0x82 , 0x34 , 0x9E , 0x38 } } , { 0x49a0 , 0x49b5 , { 0x82 , 0x34 , 0x9E , 0x39 } , { 0x82 , 0x34 , 0xA1 , 0x30 } } , { 0x4c78 , 0x4c9e , { 0x82 , 0x34 , 0xE7 , 0x34 } , { 0x82 , 0x34 , 0xEB , 0x32 } } , { 0x4ca4 , 0x4d12 , { 0x82 , 0x34 , 0xEB , 0x33 } , { 0x82 , 0x34 , 0xF6 , 0x33 } } , { 0x4d1a , 0x4dad , { 0x82 , 0x34 , 0xF6 , 0x34 } , { 0x82 , 0x35 , 0x87 , 0x31 } } , { 0x4daf , 0x4dff , { 0x82 , 0x35 , 0x87 , 0x32 } , { 0x82 , 0x35 , 0x8F , 0x32 } } , { 0xe76c , 0xe76c , { 0x83 , 0x36 , 0xC7 , 0x39 } , { 0x83 , 0x36 , 0xC7 , 0x39 } } , { 0xe7c8 , 0xe7c8 , { 0x83 , 0x36 , 0xC8 , 0x30 } , { 0x83 , 0x36 , 0xC8 , 0x30 } } , { 0xe7e7 , 0xe7f3 , { 0x83 , 0x36 , 0xC8 , 0x31 } , { 0x83 , 0x36 , 0xC9 , 0x33 } } , { 0xe815 , 0xe815 , { 0x83 , 0x36 , 0xC9 , 0x34 } , { 0x83 , 0x36 , 0xC9 , 0x34 } } , { 0xe819 , 0xe81d , { 0x83 , 0x36 , 0xC9 , 0x35 } , { 0x83 , 0x36 , 0xC9 , 0x39 } } , { 0xe81f , 0xe825 , { 0x83 , 0x36 , 0xCA , 0x30 } , { 0x83 , 0x36 , 0xCA , 0x36 } } , { 0xe827 , 0xe82a , { 0x83 , 0x36 , 0xCA , 0x37 } , { 0x83 , 0x36 , 0xCB , 0x30 } } , { 0xe82d , 0xe830 , { 0x83 , 0x36 , 0xCB , 0x31 } , { 0x83 , 0x36 , 0xCB , 0x34 } } , { 0xe833 , 0xe83a , { 0x83 , 0x36 , 0xCB , 0x35 } , { 0x83 , 0x36 , 0xCC , 0x32 } } , { 0xe83c , 0xe842 , { 0x83 , 0x36 , 0xCC , 0x33 } , { 0x83 , 0x36 , 0xCC , 0x39 } } , { 0xe844 , 0xe853 , { 0x83 , 0x36 , 0xCD , 0x30 } , { 0x83 , 0x36 , 0xCE , 0x35 } } , { 0xe856 , 0xe863 , { 0x83 , 0x36 , 0xCE , 0x36 } , { 0x83 , 0x36 , 0xCF , 0x39 } } , { 0xf92d , 0xf978 , { 0x84 , 0x30 , 0x85 , 0x35 } , { 0x84 , 0x30 , 0x8D , 0x30 } } , { 0xf97a , 0xf994 , { 0x84 , 0x30 , 0x8D , 0x31 } , { 0x84 , 0x30 , 0x8F , 0x37 } } , { 0xf996 , 0xf9e6 , { 0x84 , 0x30 , 0x8F , 0x38 } , { 0x84 , 0x30 , 0x97 , 0x38 } } , { 0xf9e8 , 0xf9f0 , { 0x84 , 0x30 , 0x97 , 0x39 } , { 0x84 , 0x30 , 0x98 , 0x37 } } , { 0xf9f2 , 0xfa0b , { 0x84 , 0x30 , 0x98 , 0x38 } , { 0x84 , 0x30 , 0x9B , 0x33 } } , { 0xfa10 , 0xfa10 , { 0x84 , 0x30 , 0x9B , 0x34 } , { 0x84 , 0x30 , 0x9B , 0x34 } } , { 0xfa12 , 0xfa12 , { 0x84 , 0x30 , 0x9B , 0x35 } , { 0x84 , 0x30 , 0x9B , 0x35 } } , { 0xfa15 , 0xfa17 , { 0x84 , 0x30 , 0x9B , 0x36 } , { 0x84 , 0x30 , 0x9B , 0x38 } } , { 0xfa19 , 0xfa1e , { 0x84 , 0x30 , 0x9B , 0x39 } , { 0x84 , 0x30 , 0x9C , 0x34 } } , { 0xfa22 , 0xfa22 , { 0x84 , 0x30 , 0x9C , 0x35 } , { 0x84 , 0x30 , 0x9C , 0x35 } } , { 0xfa25 , 0xfa26 , { 0x84 , 0x30 , 0x9C , 0x36 } , { 0x84 , 0x30 , 0x9C , 0x37 } } , { 0xfe32 , 0xfe32 , { 0x84 , 0x31 , 0x85 , 0x38 } , { 0x84 , 0x31 , 0x85 , 0x38 } } , { 0xfe45 , 0xfe48 , { 0x84 , 0x31 , 0x85 , 0x39 } , { 0x84 , 0x31 , 0x86 , 0x32 } } , { 0xfe53 , 0xfe53 , { 0x84 , 0x31 , 0x86 , 0x33 } , { 0x84 , 0x31 , 0x86 , 0x33 } } , { 0xfe58 , 0xfe58 , { 0x84 , 0x31 , 0x86 , 0x34 } , { 0x84 , 0x31 , 0x86 , 0x34 } } , { 0xfe67 , 0xfe67 , { 0x84 , 0x31 , 0x86 , 0x35 } , { 0x84 , 0x31 , 0x86 , 0x35 } } , { 0xfe6c , 0xff00 , { 0x84 , 0x31 , 0x86 , 0x36 } , { 0x84 , 0x31 , 0x95 , 0x34 } } , { 0xff5f , 0xffdf , { 0x84 , 0x31 , 0x95 , 0x35 } , { 0x84 , 0x31 , 0xA2 , 0x33 } } , { 0x0452 , 0x200f , { 0x81 , 0x30 , 0xD3 , 0x30 } , { 0x81 , 0x36 , 0xA5 , 0x31 } } , { 0x2643 , 0x2e80 , { 0x81 , 0x37 , 0xA8 , 0x39 } , { 0x81 , 0x38 , 0xFD , 0x38 } } , { 0x361b , 0x3917 , { 0x82 , 0x30 , 0xA6 , 0x33 } , { 0x82 , 0x30 , 0xF2 , 0x37 } } , { 0x3ce1 , 0x4055 , { 0x82 , 0x31 , 0xD4 , 0x38 } , { 0x82 , 0x32 , 0xAF , 0x32 } } , { 0x4160 , 0x4336 , { 0x82 , 0x32 , 0xC9 , 0x37 } , { 0x82 , 0x32 , 0xF8 , 0x37 } } , { 0x44d7 , 0x464b , { 0x82 , 0x33 , 0xA3 , 0x39 } , { 0x82 , 0x33 , 0xC9 , 0x31 } } , { 0x478e , 0x4946 , { 0x82 , 0x33 , 0xE8 , 0x38 } , { 0x82 , 0x34 , 0x96 , 0x38 } } , { 0x49b8 , 0x4c76 , { 0x82 , 0x34 , 0xA1 , 0x31 } , { 0x82 , 0x34 , 0xE7 , 0x33 } } , { 0x9fa6 , 0xd7ff , { 0x82 , 0x35 , 0x8F , 0x33 } , { 0x83 , 0x36 , 0xC7 , 0x38 } } , { 0xe865 , 0xf92b , { 0x83 , 0x36 , 0xD0 , 0x30 } , { 0x84 , 0x30 , 0x85 , 0x34 } } , { 0xfa2a , 0xfe2f , { 0x84 , 0x30 , 0x9C , 0x38 } , { 0x84 , 0x31 , 0x85 , 0x37 } } , { 0xffe6 , 0xffff , { 0x84 , 0x31 , 0xA2 , 0x34 } , { 0x84 , 0x31 , 0xA4 , 0x39 } } , { 0x10000 , 0x10ffff , { 0x90 , 0x30 , 0x81 , 0x30 } , { 0xE3 , 0x32 , 0x9A , 0x35 } } , } ; #endif mlterm-3.8.9/encodefilter/src/table/ef_ucs_property.table010064400017600000144000000622461356600661000223100ustar kenusers/* * ef_ucs_property.table */ #ifndef __EF_UCS_PROPERTY_TABLE__ #define __EF_UCS_PROPERTY_TABLE__ #include typedef struct ef_ucs_property { u_int32_t first ; u_int32_t last ; u_int8_t prop ; /* ef_property_t */ } ef_ucs_property_t ; static ef_ucs_property_t ucs_property_table[] = { { 0x00000000 , 0x00000000 , 0 } , { 0x000000a1 , 0x000000a1 , EF_AWIDTH } , { 0x000000a4 , 0x000000a4 , EF_AWIDTH } , { 0x000000a7 , 0x000000a8 , EF_AWIDTH } , { 0x000000aa , 0x000000aa , EF_AWIDTH } , { 0x000000ad , 0x000000ae , EF_AWIDTH } , { 0x000000b0 , 0x000000b4 , EF_AWIDTH } , { 0x000000b6 , 0x000000ba , EF_AWIDTH } , { 0x000000bc , 0x000000bf , EF_AWIDTH } , { 0x000000c6 , 0x000000c6 , EF_AWIDTH } , { 0x000000d0 , 0x000000d0 , EF_AWIDTH } , { 0x000000d7 , 0x000000d8 , EF_AWIDTH } , { 0x000000de , 0x000000e1 , EF_AWIDTH } , { 0x000000e6 , 0x000000e6 , EF_AWIDTH } , { 0x000000e8 , 0x000000ea , EF_AWIDTH } , { 0x000000ec , 0x000000ed , EF_AWIDTH } , { 0x000000f0 , 0x000000f0 , EF_AWIDTH } , { 0x000000f2 , 0x000000f3 , EF_AWIDTH } , { 0x000000f7 , 0x000000fa , EF_AWIDTH } , { 0x000000fc , 0x000000fc , EF_AWIDTH } , { 0x000000fe , 0x000000fe , EF_AWIDTH } , { 0x00000101 , 0x00000101 , EF_AWIDTH } , { 0x00000111 , 0x00000111 , EF_AWIDTH } , { 0x00000113 , 0x00000113 , EF_AWIDTH } , { 0x0000011b , 0x0000011b , EF_AWIDTH } , { 0x00000126 , 0x00000127 , EF_AWIDTH } , { 0x0000012b , 0x0000012b , EF_AWIDTH } , { 0x00000131 , 0x00000133 , EF_AWIDTH } , { 0x00000138 , 0x00000138 , EF_AWIDTH } , { 0x0000013f , 0x00000142 , EF_AWIDTH } , { 0x00000144 , 0x00000144 , EF_AWIDTH } , { 0x00000148 , 0x0000014b , EF_AWIDTH } , { 0x0000014d , 0x0000014d , EF_AWIDTH } , { 0x00000152 , 0x00000153 , EF_AWIDTH } , { 0x00000166 , 0x00000167 , EF_AWIDTH } , { 0x0000016b , 0x0000016b , EF_AWIDTH } , { 0x000001ce , 0x000001ce , EF_AWIDTH } , { 0x000001d0 , 0x000001d0 , EF_AWIDTH } , { 0x000001d2 , 0x000001d2 , EF_AWIDTH } , { 0x000001d4 , 0x000001d4 , EF_AWIDTH } , { 0x000001d6 , 0x000001d6 , EF_AWIDTH } , { 0x000001d8 , 0x000001d8 , EF_AWIDTH } , { 0x000001da , 0x000001da , EF_AWIDTH } , { 0x000001dc , 0x000001dc , EF_AWIDTH } , { 0x00000251 , 0x00000251 , EF_AWIDTH } , { 0x00000261 , 0x00000261 , EF_AWIDTH } , { 0x000002c4 , 0x000002c4 , EF_AWIDTH } , { 0x000002c7 , 0x000002c7 , EF_AWIDTH } , { 0x000002c9 , 0x000002cb , EF_AWIDTH } , { 0x000002cd , 0x000002cd , EF_AWIDTH } , { 0x000002d0 , 0x000002d0 , EF_AWIDTH } , { 0x000002d8 , 0x000002db , EF_AWIDTH } , { 0x000002dd , 0x000002dd , EF_AWIDTH } , { 0x000002df , 0x000002df , EF_AWIDTH } , { 0x00000300 , 0x0000036f , EF_COMBINING | EF_AWIDTH } , { 0x00000391 , 0x000003a1 , EF_AWIDTH } , { 0x000003a3 , 0x000003a9 , EF_AWIDTH } , { 0x000003b1 , 0x000003c1 , EF_AWIDTH } , { 0x000003c3 , 0x000003c9 , EF_AWIDTH } , { 0x00000401 , 0x00000401 , EF_AWIDTH } , { 0x00000410 , 0x0000044f , EF_AWIDTH } , { 0x00000451 , 0x00000451 , EF_AWIDTH } , { 0x00000483 , 0x00000489 , EF_COMBINING } , { 0x00000591 , 0x000005bd , EF_COMBINING } , { 0x000005bf , 0x000005bf , EF_COMBINING } , { 0x000005c1 , 0x000005c2 , EF_COMBINING } , { 0x000005c4 , 0x000005c5 , EF_COMBINING } , { 0x000005c7 , 0x000005c7 , EF_COMBINING } , { 0x00000610 , 0x0000061a , EF_COMBINING } , { 0x0000064b , 0x0000065f , EF_COMBINING } , { 0x00000670 , 0x00000670 , EF_COMBINING } , { 0x000006d6 , 0x000006dc , EF_COMBINING } , { 0x000006df , 0x000006e4 , EF_COMBINING } , { 0x000006e7 , 0x000006e8 , EF_COMBINING } , { 0x000006ea , 0x000006ed , EF_COMBINING } , { 0x00000711 , 0x00000711 , EF_COMBINING } , { 0x00000730 , 0x0000074a , EF_COMBINING } , { 0x000007a6 , 0x000007b0 , EF_COMBINING } , { 0x000007eb , 0x000007f3 , EF_COMBINING } , { 0x000007fd , 0x000007fd , EF_COMBINING } , { 0x00000816 , 0x00000819 , EF_COMBINING } , { 0x0000081b , 0x00000823 , EF_COMBINING } , { 0x00000825 , 0x00000827 , EF_COMBINING } , { 0x00000829 , 0x0000082d , EF_COMBINING } , { 0x00000859 , 0x0000085b , EF_COMBINING } , { 0x000008d3 , 0x000008e1 , EF_COMBINING } , { 0x000008e3 , 0x00000903 , EF_COMBINING } , { 0x0000093a , 0x0000093c , EF_COMBINING } , { 0x0000093e , 0x0000094f , EF_COMBINING } , { 0x00000951 , 0x00000957 , EF_COMBINING } , { 0x00000962 , 0x00000963 , EF_COMBINING } , { 0x00000981 , 0x00000983 , EF_COMBINING } , { 0x000009bc , 0x000009bc , EF_COMBINING } , { 0x000009be , 0x000009c4 , EF_COMBINING } , { 0x000009c7 , 0x000009c8 , EF_COMBINING } , { 0x000009cb , 0x000009cd , EF_COMBINING } , { 0x000009d7 , 0x000009d7 , EF_COMBINING } , { 0x000009e2 , 0x000009e3 , EF_COMBINING } , { 0x000009fe , 0x000009fe , EF_COMBINING } , { 0x00000a01 , 0x00000a03 , EF_COMBINING } , { 0x00000a3c , 0x00000a3c , EF_COMBINING } , { 0x00000a3e , 0x00000a42 , EF_COMBINING } , { 0x00000a47 , 0x00000a48 , EF_COMBINING } , { 0x00000a4b , 0x00000a4d , EF_COMBINING } , { 0x00000a51 , 0x00000a51 , EF_COMBINING } , { 0x00000a70 , 0x00000a71 , EF_COMBINING } , { 0x00000a75 , 0x00000a75 , EF_COMBINING } , { 0x00000a81 , 0x00000a83 , EF_COMBINING } , { 0x00000abc , 0x00000abc , EF_COMBINING } , { 0x00000abe , 0x00000ac5 , EF_COMBINING } , { 0x00000ac7 , 0x00000ac9 , EF_COMBINING } , { 0x00000acb , 0x00000acd , EF_COMBINING } , { 0x00000ae2 , 0x00000ae3 , EF_COMBINING } , { 0x00000afa , 0x00000aff , EF_COMBINING } , { 0x00000b01 , 0x00000b03 , EF_COMBINING } , { 0x00000b3c , 0x00000b3c , EF_COMBINING } , { 0x00000b3e , 0x00000b44 , EF_COMBINING } , { 0x00000b47 , 0x00000b48 , EF_COMBINING } , { 0x00000b4b , 0x00000b4d , EF_COMBINING } , { 0x00000b56 , 0x00000b57 , EF_COMBINING } , { 0x00000b62 , 0x00000b63 , EF_COMBINING } , { 0x00000b82 , 0x00000b82 , EF_COMBINING } , { 0x00000bbe , 0x00000bc2 , EF_COMBINING } , { 0x00000bc6 , 0x00000bc8 , EF_COMBINING } , { 0x00000bca , 0x00000bcd , EF_COMBINING } , { 0x00000bd7 , 0x00000bd7 , EF_COMBINING } , { 0x00000c00 , 0x00000c04 , EF_COMBINING } , { 0x00000c3e , 0x00000c44 , EF_COMBINING } , { 0x00000c46 , 0x00000c48 , EF_COMBINING } , { 0x00000c4a , 0x00000c4d , EF_COMBINING } , { 0x00000c55 , 0x00000c56 , EF_COMBINING } , { 0x00000c62 , 0x00000c63 , EF_COMBINING } , { 0x00000c81 , 0x00000c83 , EF_COMBINING } , { 0x00000cbc , 0x00000cbc , EF_COMBINING } , { 0x00000cbe , 0x00000cc4 , EF_COMBINING } , { 0x00000cc6 , 0x00000cc8 , EF_COMBINING } , { 0x00000cca , 0x00000ccd , EF_COMBINING } , { 0x00000cd5 , 0x00000cd6 , EF_COMBINING } , { 0x00000ce2 , 0x00000ce3 , EF_COMBINING } , { 0x00000d00 , 0x00000d03 , EF_COMBINING } , { 0x00000d3b , 0x00000d3c , EF_COMBINING } , { 0x00000d3e , 0x00000d44 , EF_COMBINING } , { 0x00000d46 , 0x00000d48 , EF_COMBINING } , { 0x00000d4a , 0x00000d4d , EF_COMBINING } , { 0x00000d57 , 0x00000d57 , EF_COMBINING } , { 0x00000d62 , 0x00000d63 , EF_COMBINING } , { 0x00000d82 , 0x00000d83 , EF_COMBINING } , { 0x00000dca , 0x00000dca , EF_COMBINING } , { 0x00000dcf , 0x00000dd4 , EF_COMBINING } , { 0x00000dd6 , 0x00000dd6 , EF_COMBINING } , { 0x00000dd8 , 0x00000ddf , EF_COMBINING } , { 0x00000df2 , 0x00000df3 , EF_COMBINING } , { 0x00000e31 , 0x00000e31 , EF_COMBINING } , { 0x00000e34 , 0x00000e3a , EF_COMBINING } , { 0x00000e47 , 0x00000e4e , EF_COMBINING } , { 0x00000eb1 , 0x00000eb1 , EF_COMBINING } , { 0x00000eb4 , 0x00000eb9 , EF_COMBINING } , { 0x00000ebb , 0x00000ebc , EF_COMBINING } , { 0x00000ec8 , 0x00000ecd , EF_COMBINING } , { 0x00000f18 , 0x00000f19 , EF_COMBINING } , { 0x00000f35 , 0x00000f35 , EF_COMBINING } , { 0x00000f37 , 0x00000f37 , EF_COMBINING } , { 0x00000f39 , 0x00000f39 , EF_COMBINING } , { 0x00000f3e , 0x00000f3f , EF_COMBINING } , { 0x00000f71 , 0x00000f84 , EF_COMBINING } , { 0x00000f86 , 0x00000f87 , EF_COMBINING } , { 0x00000f8d , 0x00000f97 , EF_COMBINING } , { 0x00000f99 , 0x00000fbc , EF_COMBINING } , { 0x00000fc6 , 0x00000fc6 , EF_COMBINING } , { 0x0000102b , 0x0000103e , EF_COMBINING } , { 0x00001056 , 0x00001059 , EF_COMBINING } , { 0x0000105e , 0x00001060 , EF_COMBINING } , { 0x00001062 , 0x00001064 , EF_COMBINING } , { 0x00001067 , 0x0000106d , EF_COMBINING } , { 0x00001071 , 0x00001074 , EF_COMBINING } , { 0x00001082 , 0x0000108d , EF_COMBINING } , { 0x0000108f , 0x0000108f , EF_COMBINING } , { 0x0000109a , 0x0000109d , EF_COMBINING } , { 0x00001100 , 0x0000115f , EF_FULLWIDTH } , { 0x00001160 , 0x000011ff , EF_COMBINING | EF_FULLWIDTH } , { 0x0000135d , 0x0000135f , EF_COMBINING } , { 0x00001712 , 0x00001714 , EF_COMBINING } , { 0x00001732 , 0x00001734 , EF_COMBINING } , { 0x00001752 , 0x00001753 , EF_COMBINING } , { 0x00001772 , 0x00001773 , EF_COMBINING } , { 0x000017b4 , 0x000017d3 , EF_COMBINING } , { 0x000017dd , 0x000017dd , EF_COMBINING } , { 0x0000180b , 0x0000180d , EF_COMBINING } , { 0x00001885 , 0x00001886 , EF_COMBINING } , { 0x000018a9 , 0x000018a9 , EF_COMBINING } , { 0x00001920 , 0x0000192b , EF_COMBINING } , { 0x00001930 , 0x0000193b , EF_COMBINING } , { 0x00001a17 , 0x00001a1b , EF_COMBINING } , { 0x00001a55 , 0x00001a5e , EF_COMBINING } , { 0x00001a60 , 0x00001a7c , EF_COMBINING } , { 0x00001a7f , 0x00001a7f , EF_COMBINING } , { 0x00001ab0 , 0x00001abe , EF_COMBINING } , { 0x00001b00 , 0x00001b04 , EF_COMBINING } , { 0x00001b34 , 0x00001b44 , EF_COMBINING } , { 0x00001b6b , 0x00001b73 , EF_COMBINING } , { 0x00001b80 , 0x00001b82 , EF_COMBINING } , { 0x00001ba1 , 0x00001bad , EF_COMBINING } , { 0x00001be6 , 0x00001bf3 , EF_COMBINING } , { 0x00001c24 , 0x00001c37 , EF_COMBINING } , { 0x00001cd0 , 0x00001cd2 , EF_COMBINING } , { 0x00001cd4 , 0x00001ce8 , EF_COMBINING } , { 0x00001ced , 0x00001ced , EF_COMBINING } , { 0x00001cf2 , 0x00001cf4 , EF_COMBINING } , { 0x00001cf7 , 0x00001cf9 , EF_COMBINING } , { 0x00001dc0 , 0x00001df9 , EF_COMBINING } , { 0x00001dfb , 0x00001dff , EF_COMBINING } , { 0x00002010 , 0x00002010 , EF_AWIDTH } , { 0x00002013 , 0x00002016 , EF_AWIDTH } , { 0x00002018 , 0x00002019 , EF_AWIDTH } , { 0x0000201c , 0x0000201d , EF_AWIDTH } , { 0x00002020 , 0x00002022 , EF_AWIDTH } , { 0x00002024 , 0x00002027 , EF_AWIDTH } , { 0x00002030 , 0x00002030 , EF_AWIDTH } , { 0x00002032 , 0x00002033 , EF_AWIDTH } , { 0x00002035 , 0x00002035 , EF_AWIDTH } , { 0x0000203b , 0x0000203b , EF_AWIDTH } , { 0x0000203e , 0x0000203e , EF_AWIDTH } , { 0x00002074 , 0x00002074 , EF_AWIDTH } , { 0x0000207f , 0x0000207f , EF_AWIDTH } , { 0x00002081 , 0x00002084 , EF_AWIDTH } , { 0x000020ac , 0x000020ac , EF_AWIDTH } , { 0x000020d0 , 0x000020f0 , EF_COMBINING } , { 0x00002103 , 0x00002103 , EF_AWIDTH } , { 0x00002105 , 0x00002105 , EF_AWIDTH } , { 0x00002109 , 0x00002109 , EF_AWIDTH } , { 0x00002113 , 0x00002113 , EF_AWIDTH } , { 0x00002116 , 0x00002116 , EF_AWIDTH } , { 0x00002121 , 0x00002122 , EF_AWIDTH } , { 0x00002126 , 0x00002126 , EF_AWIDTH } , { 0x0000212b , 0x0000212b , EF_AWIDTH } , { 0x00002153 , 0x00002154 , EF_AWIDTH } , { 0x0000215b , 0x0000215e , EF_AWIDTH } , { 0x00002160 , 0x0000216b , EF_AWIDTH } , { 0x00002170 , 0x00002179 , EF_AWIDTH } , { 0x00002189 , 0x00002189 , EF_AWIDTH } , { 0x00002190 , 0x00002199 , EF_AWIDTH } , { 0x000021b8 , 0x000021b9 , EF_AWIDTH } , { 0x000021d2 , 0x000021d2 , EF_AWIDTH } , { 0x000021d4 , 0x000021d4 , EF_AWIDTH } , { 0x000021e7 , 0x000021e7 , EF_AWIDTH } , { 0x00002200 , 0x00002200 , EF_AWIDTH } , { 0x00002202 , 0x00002203 , EF_AWIDTH } , { 0x00002207 , 0x00002208 , EF_AWIDTH } , { 0x0000220b , 0x0000220b , EF_AWIDTH } , { 0x0000220f , 0x0000220f , EF_AWIDTH } , { 0x00002211 , 0x00002211 , EF_AWIDTH } , { 0x00002215 , 0x00002215 , EF_AWIDTH } , { 0x0000221a , 0x0000221a , EF_AWIDTH } , { 0x0000221d , 0x00002220 , EF_AWIDTH } , { 0x00002223 , 0x00002223 , EF_AWIDTH } , { 0x00002225 , 0x00002225 , EF_AWIDTH } , { 0x00002227 , 0x0000222c , EF_AWIDTH } , { 0x0000222e , 0x0000222e , EF_AWIDTH } , { 0x00002234 , 0x00002237 , EF_AWIDTH } , { 0x0000223c , 0x0000223d , EF_AWIDTH } , { 0x00002248 , 0x00002248 , EF_AWIDTH } , { 0x0000224c , 0x0000224c , EF_AWIDTH } , { 0x00002252 , 0x00002252 , EF_AWIDTH } , { 0x00002260 , 0x00002261 , EF_AWIDTH } , { 0x00002264 , 0x00002267 , EF_AWIDTH } , { 0x0000226a , 0x0000226b , EF_AWIDTH } , { 0x0000226e , 0x0000226f , EF_AWIDTH } , { 0x00002282 , 0x00002283 , EF_AWIDTH } , { 0x00002286 , 0x00002287 , EF_AWIDTH } , { 0x00002295 , 0x00002295 , EF_AWIDTH } , { 0x00002299 , 0x00002299 , EF_AWIDTH } , { 0x000022a5 , 0x000022a5 , EF_AWIDTH } , { 0x000022bf , 0x000022bf , EF_AWIDTH } , { 0x00002312 , 0x00002312 , EF_AWIDTH } , { 0x0000231a , 0x0000231b , EF_FULLWIDTH } , { 0x00002329 , 0x0000232a , EF_FULLWIDTH } , { 0x000023e9 , 0x000023ec , EF_FULLWIDTH } , { 0x000023f0 , 0x000023f0 , EF_FULLWIDTH } , { 0x000023f3 , 0x000023f3 , EF_FULLWIDTH } , { 0x00002460 , 0x000024e9 , EF_AWIDTH } , { 0x000024eb , 0x0000254b , EF_AWIDTH } , { 0x00002550 , 0x00002573 , EF_AWIDTH } , { 0x00002580 , 0x0000258f , EF_AWIDTH } , { 0x00002592 , 0x00002595 , EF_AWIDTH } , { 0x000025a0 , 0x000025a1 , EF_AWIDTH } , { 0x000025a3 , 0x000025a9 , EF_AWIDTH } , { 0x000025b2 , 0x000025b3 , EF_AWIDTH } , { 0x000025b6 , 0x000025b7 , EF_AWIDTH } , { 0x000025bc , 0x000025bd , EF_AWIDTH } , { 0x000025c0 , 0x000025c1 , EF_AWIDTH } , { 0x000025c6 , 0x000025c8 , EF_AWIDTH } , { 0x000025cb , 0x000025cb , EF_AWIDTH } , { 0x000025ce , 0x000025d1 , EF_AWIDTH } , { 0x000025e2 , 0x000025e5 , EF_AWIDTH } , { 0x000025ef , 0x000025ef , EF_AWIDTH } , { 0x000025fd , 0x000025fe , EF_FULLWIDTH } , { 0x00002605 , 0x00002606 , EF_AWIDTH } , { 0x00002609 , 0x00002609 , EF_AWIDTH } , { 0x0000260e , 0x0000260f , EF_AWIDTH } , { 0x00002614 , 0x00002615 , EF_FULLWIDTH } , { 0x0000261c , 0x0000261c , EF_AWIDTH } , { 0x0000261e , 0x0000261e , EF_AWIDTH } , { 0x00002640 , 0x00002640 , EF_AWIDTH } , { 0x00002642 , 0x00002642 , EF_AWIDTH } , { 0x00002648 , 0x00002653 , EF_FULLWIDTH } , { 0x00002660 , 0x00002661 , EF_AWIDTH } , { 0x00002663 , 0x00002665 , EF_AWIDTH } , { 0x00002667 , 0x0000266a , EF_AWIDTH } , { 0x0000266c , 0x0000266d , EF_AWIDTH } , { 0x0000266f , 0x0000266f , EF_AWIDTH } , { 0x0000267f , 0x0000267f , EF_FULLWIDTH } , { 0x00002693 , 0x00002693 , EF_FULLWIDTH } , { 0x0000269e , 0x0000269f , EF_AWIDTH } , { 0x000026a1 , 0x000026a1 , EF_FULLWIDTH } , { 0x000026aa , 0x000026ab , EF_FULLWIDTH } , { 0x000026bd , 0x000026be , EF_FULLWIDTH } , { 0x000026bf , 0x000026bf , EF_AWIDTH } , { 0x000026c4 , 0x000026c5 , EF_FULLWIDTH } , { 0x000026c6 , 0x000026cd , EF_AWIDTH } , { 0x000026ce , 0x000026ce , EF_FULLWIDTH } , { 0x000026cf , 0x000026d3 , EF_AWIDTH } , { 0x000026d4 , 0x000026d4 , EF_FULLWIDTH } , { 0x000026d5 , 0x000026e1 , EF_AWIDTH } , { 0x000026e3 , 0x000026e3 , EF_AWIDTH } , { 0x000026e8 , 0x000026e9 , EF_AWIDTH } , { 0x000026ea , 0x000026ea , EF_FULLWIDTH } , { 0x000026eb , 0x000026f1 , EF_AWIDTH } , { 0x000026f2 , 0x000026f3 , EF_FULLWIDTH } , { 0x000026f4 , 0x000026f4 , EF_AWIDTH } , { 0x000026f5 , 0x000026f5 , EF_FULLWIDTH } , { 0x000026f6 , 0x000026f9 , EF_AWIDTH } , { 0x000026fa , 0x000026fa , EF_FULLWIDTH } , { 0x000026fb , 0x000026fc , EF_AWIDTH } , { 0x000026fd , 0x000026fd , EF_FULLWIDTH } , { 0x000026fe , 0x000026ff , EF_AWIDTH } , { 0x00002705 , 0x00002705 , EF_FULLWIDTH } , { 0x0000270a , 0x0000270b , EF_FULLWIDTH } , { 0x00002728 , 0x00002728 , EF_FULLWIDTH } , { 0x0000273d , 0x0000273d , EF_AWIDTH } , { 0x0000274c , 0x0000274c , EF_FULLWIDTH } , { 0x0000274e , 0x0000274e , EF_FULLWIDTH } , { 0x00002753 , 0x00002755 , EF_FULLWIDTH } , { 0x00002757 , 0x00002757 , EF_FULLWIDTH } , { 0x00002776 , 0x0000277f , EF_AWIDTH } , { 0x00002795 , 0x00002797 , EF_FULLWIDTH } , { 0x000027b0 , 0x000027b0 , EF_FULLWIDTH } , { 0x000027bf , 0x000027bf , EF_FULLWIDTH } , { 0x00002b1b , 0x00002b1c , EF_FULLWIDTH } , { 0x00002b50 , 0x00002b50 , EF_FULLWIDTH } , { 0x00002b55 , 0x00002b55 , EF_FULLWIDTH } , { 0x00002b56 , 0x00002b59 , EF_AWIDTH } , { 0x00002cef , 0x00002cf1 , EF_COMBINING } , { 0x00002d7f , 0x00002d7f , EF_COMBINING } , { 0x00002de0 , 0x00002dff , EF_COMBINING } , { 0x00002e80 , 0x00002e99 , EF_FULLWIDTH } , { 0x00002e9b , 0x00002ef3 , EF_FULLWIDTH } , { 0x00002f00 , 0x00002fd5 , EF_FULLWIDTH } , { 0x00002ff0 , 0x00002ffb , EF_FULLWIDTH } , { 0x00003000 , 0x00003029 , EF_FULLWIDTH } , { 0x0000302a , 0x0000302f , EF_COMBINING | EF_FULLWIDTH } , { 0x00003030 , 0x0000303e , EF_FULLWIDTH } , { 0x00003041 , 0x00003096 , EF_FULLWIDTH } , { 0x00003099 , 0x0000309a , EF_COMBINING | EF_FULLWIDTH } , { 0x0000309b , 0x000030ff , EF_FULLWIDTH } , { 0x00003105 , 0x0000312f , EF_FULLWIDTH } , { 0x00003131 , 0x0000318e , EF_FULLWIDTH } , { 0x00003190 , 0x000031ba , EF_FULLWIDTH } , { 0x000031c0 , 0x000031e3 , EF_FULLWIDTH } , { 0x000031f0 , 0x0000321e , EF_FULLWIDTH } , { 0x00003220 , 0x00003247 , EF_FULLWIDTH } , { 0x00003248 , 0x0000324f , EF_AWIDTH } , { 0x00003250 , 0x000032fe , EF_FULLWIDTH } , { 0x00003300 , 0x00004dbf , EF_FULLWIDTH } , { 0x00004e00 , 0x0000a48c , EF_FULLWIDTH } , { 0x0000a490 , 0x0000a4c6 , EF_FULLWIDTH } , { 0x0000a66f , 0x0000a672 , EF_COMBINING } , { 0x0000a674 , 0x0000a67d , EF_COMBINING } , { 0x0000a69e , 0x0000a69f , EF_COMBINING } , { 0x0000a6f0 , 0x0000a6f1 , EF_COMBINING } , { 0x0000a802 , 0x0000a802 , EF_COMBINING } , { 0x0000a806 , 0x0000a806 , EF_COMBINING } , { 0x0000a80b , 0x0000a80b , EF_COMBINING } , { 0x0000a823 , 0x0000a827 , EF_COMBINING } , { 0x0000a880 , 0x0000a881 , EF_COMBINING } , { 0x0000a8b4 , 0x0000a8c5 , EF_COMBINING } , { 0x0000a8e0 , 0x0000a8f1 , EF_COMBINING } , { 0x0000a8ff , 0x0000a8ff , EF_COMBINING } , { 0x0000a926 , 0x0000a92d , EF_COMBINING } , { 0x0000a947 , 0x0000a953 , EF_COMBINING } , { 0x0000a960 , 0x0000a97c , EF_FULLWIDTH } , { 0x0000a980 , 0x0000a983 , EF_COMBINING } , { 0x0000a9b3 , 0x0000a9c0 , EF_COMBINING } , { 0x0000a9e5 , 0x0000a9e5 , EF_COMBINING } , { 0x0000aa29 , 0x0000aa36 , EF_COMBINING } , { 0x0000aa43 , 0x0000aa43 , EF_COMBINING } , { 0x0000aa4c , 0x0000aa4d , EF_COMBINING } , { 0x0000aa7b , 0x0000aa7d , EF_COMBINING } , { 0x0000aab0 , 0x0000aab0 , EF_COMBINING } , { 0x0000aab2 , 0x0000aab4 , EF_COMBINING } , { 0x0000aab7 , 0x0000aab8 , EF_COMBINING } , { 0x0000aabe , 0x0000aabf , EF_COMBINING } , { 0x0000aac1 , 0x0000aac1 , EF_COMBINING } , { 0x0000aaeb , 0x0000aaef , EF_COMBINING } , { 0x0000aaf5 , 0x0000aaf6 , EF_COMBINING } , { 0x0000abe3 , 0x0000abea , EF_COMBINING } , { 0x0000abec , 0x0000abed , EF_COMBINING } , { 0x0000ac00 , 0x0000d7a3 , EF_FULLWIDTH } , { 0x0000e000 , 0x0000f8ff , EF_AWIDTH } , { 0x0000f900 , 0x0000faff , EF_FULLWIDTH } , { 0x0000fb1e , 0x0000fb1e , EF_COMBINING } , { 0x0000fe00 , 0x0000fe0f , EF_COMBINING | EF_AWIDTH } , { 0x0000fe10 , 0x0000fe19 , EF_FULLWIDTH } , { 0x0000fe20 , 0x0000fe2f , EF_COMBINING } , { 0x0000fe30 , 0x0000fe52 , EF_FULLWIDTH } , { 0x0000fe54 , 0x0000fe66 , EF_FULLWIDTH } , { 0x0000fe68 , 0x0000fe6b , EF_FULLWIDTH } , { 0x0000ff01 , 0x0000ff60 , EF_FULLWIDTH } , { 0x0000ffe0 , 0x0000ffe6 , EF_FULLWIDTH } , { 0x0000fffd , 0x0000fffd , EF_AWIDTH } , { 0x000101fd , 0x000101fd , EF_COMBINING } , { 0x000102e0 , 0x000102e0 , EF_COMBINING } , { 0x00010376 , 0x0001037a , EF_COMBINING } , { 0x00010a01 , 0x00010a03 , EF_COMBINING } , { 0x00010a05 , 0x00010a06 , EF_COMBINING } , { 0x00010a0c , 0x00010a0f , EF_COMBINING } , { 0x00010a38 , 0x00010a3a , EF_COMBINING } , { 0x00010a3f , 0x00010a3f , EF_COMBINING } , { 0x00010ae5 , 0x00010ae6 , EF_COMBINING } , { 0x00010d24 , 0x00010d27 , EF_COMBINING } , { 0x00010f46 , 0x00010f50 , EF_COMBINING } , { 0x00011000 , 0x00011002 , EF_COMBINING } , { 0x00011038 , 0x00011046 , EF_COMBINING } , { 0x0001107f , 0x00011082 , EF_COMBINING } , { 0x000110b0 , 0x000110ba , EF_COMBINING } , { 0x00011100 , 0x00011102 , EF_COMBINING } , { 0x00011127 , 0x00011134 , EF_COMBINING } , { 0x00011145 , 0x00011146 , EF_COMBINING } , { 0x00011173 , 0x00011173 , EF_COMBINING } , { 0x00011180 , 0x00011182 , EF_COMBINING } , { 0x000111b3 , 0x000111c0 , EF_COMBINING } , { 0x000111c9 , 0x000111cc , EF_COMBINING } , { 0x0001122c , 0x00011237 , EF_COMBINING } , { 0x0001123e , 0x0001123e , EF_COMBINING } , { 0x000112df , 0x000112ea , EF_COMBINING } , { 0x00011300 , 0x00011303 , EF_COMBINING } , { 0x0001133b , 0x0001133c , EF_COMBINING } , { 0x0001133e , 0x00011344 , EF_COMBINING } , { 0x00011347 , 0x00011348 , EF_COMBINING } , { 0x0001134b , 0x0001134d , EF_COMBINING } , { 0x00011357 , 0x00011357 , EF_COMBINING } , { 0x00011362 , 0x00011363 , EF_COMBINING } , { 0x00011366 , 0x0001136c , EF_COMBINING } , { 0x00011370 , 0x00011374 , EF_COMBINING } , { 0x00011435 , 0x00011446 , EF_COMBINING } , { 0x0001145e , 0x0001145e , EF_COMBINING } , { 0x000114b0 , 0x000114c3 , EF_COMBINING } , { 0x000115af , 0x000115b5 , EF_COMBINING } , { 0x000115b8 , 0x000115c0 , EF_COMBINING } , { 0x000115dc , 0x000115dd , EF_COMBINING } , { 0x00011630 , 0x00011640 , EF_COMBINING } , { 0x000116ab , 0x000116b7 , EF_COMBINING } , { 0x0001171d , 0x0001172b , EF_COMBINING } , { 0x0001182c , 0x0001183a , EF_COMBINING } , { 0x00011a01 , 0x00011a0a , EF_COMBINING } , { 0x00011a33 , 0x00011a39 , EF_COMBINING } , { 0x00011a3b , 0x00011a3e , EF_COMBINING } , { 0x00011a47 , 0x00011a47 , EF_COMBINING } , { 0x00011a51 , 0x00011a5b , EF_COMBINING } , { 0x00011a8a , 0x00011a99 , EF_COMBINING } , { 0x00011c2f , 0x00011c36 , EF_COMBINING } , { 0x00011c38 , 0x00011c3f , EF_COMBINING } , { 0x00011c92 , 0x00011ca7 , EF_COMBINING } , { 0x00011ca9 , 0x00011cb6 , EF_COMBINING } , { 0x00011d31 , 0x00011d36 , EF_COMBINING } , { 0x00011d3a , 0x00011d3a , EF_COMBINING } , { 0x00011d3c , 0x00011d3d , EF_COMBINING } , { 0x00011d3f , 0x00011d45 , EF_COMBINING } , { 0x00011d47 , 0x00011d47 , EF_COMBINING } , { 0x00011d8a , 0x00011d8e , EF_COMBINING } , { 0x00011d90 , 0x00011d91 , EF_COMBINING } , { 0x00011d93 , 0x00011d97 , EF_COMBINING } , { 0x00011ef3 , 0x00011ef6 , EF_COMBINING } , { 0x00016af0 , 0x00016af4 , EF_COMBINING } , { 0x00016b30 , 0x00016b36 , EF_COMBINING } , { 0x00016f51 , 0x00016f7e , EF_COMBINING } , { 0x00016f8f , 0x00016f92 , EF_COMBINING } , { 0x00016fe0 , 0x00016fe1 , EF_FULLWIDTH } , { 0x00017000 , 0x000187f1 , EF_FULLWIDTH } , { 0x00018800 , 0x00018af2 , EF_FULLWIDTH } , { 0x0001b000 , 0x0001b11e , EF_FULLWIDTH } , { 0x0001b170 , 0x0001b2fb , EF_FULLWIDTH } , { 0x0001bc9d , 0x0001bc9e , EF_COMBINING } , { 0x0001d165 , 0x0001d169 , EF_COMBINING } , { 0x0001d16d , 0x0001d172 , EF_COMBINING } , { 0x0001d17b , 0x0001d182 , EF_COMBINING } , { 0x0001d185 , 0x0001d18b , EF_COMBINING } , { 0x0001d1aa , 0x0001d1ad , EF_COMBINING } , { 0x0001d242 , 0x0001d244 , EF_COMBINING } , { 0x0001da00 , 0x0001da36 , EF_COMBINING } , { 0x0001da3b , 0x0001da6c , EF_COMBINING } , { 0x0001da75 , 0x0001da75 , EF_COMBINING } , { 0x0001da84 , 0x0001da84 , EF_COMBINING } , { 0x0001da9b , 0x0001da9f , EF_COMBINING } , { 0x0001daa1 , 0x0001daaf , EF_COMBINING } , { 0x0001e000 , 0x0001e006 , EF_COMBINING } , { 0x0001e008 , 0x0001e018 , EF_COMBINING } , { 0x0001e01b , 0x0001e021 , EF_COMBINING } , { 0x0001e023 , 0x0001e024 , EF_COMBINING } , { 0x0001e026 , 0x0001e02a , EF_COMBINING } , { 0x0001e8d0 , 0x0001e8d6 , EF_COMBINING } , { 0x0001e944 , 0x0001e94a , EF_COMBINING } , { 0x0001f004 , 0x0001f004 , EF_FULLWIDTH } , { 0x0001f0cf , 0x0001f0cf , EF_FULLWIDTH } , { 0x0001f100 , 0x0001f10a , EF_AWIDTH } , { 0x0001f110 , 0x0001f12d , EF_AWIDTH } , { 0x0001f130 , 0x0001f169 , EF_AWIDTH } , { 0x0001f170 , 0x0001f18d , EF_AWIDTH } , { 0x0001f18e , 0x0001f18e , EF_FULLWIDTH } , { 0x0001f18f , 0x0001f190 , EF_AWIDTH } , { 0x0001f191 , 0x0001f19a , EF_FULLWIDTH } , { 0x0001f19b , 0x0001f1ac , EF_AWIDTH } , { 0x0001f200 , 0x0001f202 , EF_FULLWIDTH } , { 0x0001f210 , 0x0001f23b , EF_FULLWIDTH } , { 0x0001f240 , 0x0001f248 , EF_FULLWIDTH } , { 0x0001f250 , 0x0001f251 , EF_FULLWIDTH } , { 0x0001f260 , 0x0001f265 , EF_FULLWIDTH } , { 0x0001f300 , 0x0001f320 , EF_FULLWIDTH } , { 0x0001f32d , 0x0001f335 , EF_FULLWIDTH } , { 0x0001f337 , 0x0001f37c , EF_FULLWIDTH } , { 0x0001f37e , 0x0001f393 , EF_FULLWIDTH } , { 0x0001f3a0 , 0x0001f3ca , EF_FULLWIDTH } , { 0x0001f3cf , 0x0001f3d3 , EF_FULLWIDTH } , { 0x0001f3e0 , 0x0001f3f0 , EF_FULLWIDTH } , { 0x0001f3f4 , 0x0001f3f4 , EF_FULLWIDTH } , { 0x0001f3f8 , 0x0001f43e , EF_FULLWIDTH } , { 0x0001f440 , 0x0001f440 , EF_FULLWIDTH } , { 0x0001f442 , 0x0001f4fc , EF_FULLWIDTH } , { 0x0001f4ff , 0x0001f53d , EF_FULLWIDTH } , { 0x0001f54b , 0x0001f54e , EF_FULLWIDTH } , { 0x0001f550 , 0x0001f567 , EF_FULLWIDTH } , { 0x0001f57a , 0x0001f57a , EF_FULLWIDTH } , { 0x0001f595 , 0x0001f596 , EF_FULLWIDTH } , { 0x0001f5a4 , 0x0001f5a4 , EF_FULLWIDTH } , { 0x0001f5fb , 0x0001f64f , EF_FULLWIDTH } , { 0x0001f680 , 0x0001f6c5 , EF_FULLWIDTH } , { 0x0001f6cc , 0x0001f6cc , EF_FULLWIDTH } , { 0x0001f6d0 , 0x0001f6d2 , EF_FULLWIDTH } , { 0x0001f6eb , 0x0001f6ec , EF_FULLWIDTH } , { 0x0001f6f4 , 0x0001f6f9 , EF_FULLWIDTH } , { 0x0001f910 , 0x0001f93e , EF_FULLWIDTH } , { 0x0001f940 , 0x0001f970 , EF_FULLWIDTH } , { 0x0001f973 , 0x0001f976 , EF_FULLWIDTH } , { 0x0001f97a , 0x0001f97a , EF_FULLWIDTH } , { 0x0001f97c , 0x0001f9a2 , EF_FULLWIDTH } , { 0x0001f9b0 , 0x0001f9b9 , EF_FULLWIDTH } , { 0x0001f9c0 , 0x0001f9c2 , EF_FULLWIDTH } , { 0x0001f9d0 , 0x0001f9ff , EF_FULLWIDTH } , { 0x00020000 , 0x0002fffd , EF_FULLWIDTH } , { 0x00030000 , 0x0003fffd , EF_FULLWIDTH } , { 0x000e0100 , 0x000e01ef , EF_COMBINING | EF_AWIDTH } , { 0x000f0000 , 0x000ffffd , EF_AWIDTH } , { 0x00100000 , 0x0010fffd , EF_AWIDTH } , { 0xffffffff , 0xffffffff , 0 } , } ; #endif mlterm-3.8.9/encodefilter/src/dexport.map010064400017600000144000000006551356600661000171600ustar kenusersmef { global: ef_parser_* ; __ef_parser_* ; ef_*_parser_new ; ef_*_conv_new ; ef_iso2022_illegal_char ; ef_map_ucs4_to_cs ; ef_map_ucs4_to_with_funcs ; ef_map_ucs4_to ; ef_map_ucs4_to_iso2022cs ; ef_map_to_ucs4 ; ef_map_via_ucs ; ef_map_locale_ucs4_to ; ef_get_ucs_property ; ef_map_johab_to_uhc ; ef_map_uhc_to_ksc5601_1987 ; ef_map_ucs4_to_iscii ; ef_bytes_to_int ; ef_int_to_bytes ; local: * ; } ; mlterm-3.8.9/encodefilter/src/ef_8bit_conv.c010064400017600000144000000253531356600661000175070ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_8bit_conv.h" #include #include #include "ef_ru_map.h" #include "ef_ucs4_map.h" #if 0 #define __DEBUG #endif typedef struct ef_iscii_conv { ef_conv_t conv; ef_charset_t cs; } ef_iscii_conv_t; /* --- static functions --- */ static int map_direct(ef_char_t *dst, ef_char_t *src, ef_charset_t to_cs) { if (src->cs == KOI8_U && to_cs == KOI8_R) { return ef_map_koi8_u_to_koi8_r(dst, src); } else if (src->cs == KOI8_R && to_cs == KOI8_U) { return ef_map_koi8_r_to_koi8_u(dst, src); } else if (src->cs == ISO10646_UCS4_1 && src->ch[0] == 0 && src->ch[1] == 0 && src->ch[2] == 0 && src->ch[3] <= 0x7f) { dst->cs = US_ASCII; dst->size = 1; dst->property = 0; dst->ch[0] = src->ch[3]; return 1; } return 0; } static void remap_unsupported_charset(ef_char_t *ch, ef_charset_t to_cs) { ef_char_t c; if (ch->cs == to_cs) { /* do nothing */ } else if (map_direct(&c, ch, to_cs)) { *ch = c; } else if (ef_map_via_ucs(&c, ch, to_cs)) { *ch = c; } if (to_cs == VISCII && ch->cs == US_ASCII) { if (ch->ch[0] == 0x02 || ch->ch[0] == 0x05 || ch->ch[0] == 0x06 || ch->ch[0] == 0x14 || ch->ch[0] == 0x19 || ch->ch[0] == 0x1e) { ch->cs = VISCII; } } } static size_t convert_to_intern(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser, ef_charset_t to_cs) { size_t filled_size; ef_char_t ch; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { remap_unsupported_charset(&ch, to_cs); if (to_cs == ch.cs || ch.cs == US_ASCII) { if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ch.ch[0]; filled_size++; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } return filled_size; } static size_t convert_to_koi8_r(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, KOI8_R); } static size_t convert_to_koi8_u(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, KOI8_U); } static size_t convert_to_koi8_t(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, KOI8_T); } static size_t convert_to_georgian_ps(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, GEORGIAN_PS); } static size_t convert_to_cp1250(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, CP1250); } static size_t convert_to_cp1251(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, CP1251); } static size_t convert_to_cp1252(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, CP1252); } static size_t convert_to_cp1253(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, CP1253); } static size_t convert_to_cp1254(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, CP1254); } static size_t convert_to_cp1255(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, CP1255); } static size_t convert_to_cp1256(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, CP1256); } static size_t convert_to_cp1257(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, CP1257); } static size_t convert_to_cp1258(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, CP1258); } static size_t convert_to_cp874(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, CP874); } static size_t convert_to_viscii(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, VISCII); } static size_t convert_to_iscii(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_intern(conv, dst, dst_size, parser, ((ef_iscii_conv_t*)conv)->cs); } static void conv_init(ef_conv_t *conv) {} static void conv_destroy(ef_conv_t *conv) { free(conv); } static ef_conv_t *iscii_conv_new(ef_charset_t cs) { ef_iscii_conv_t *iscii_conv; if ((iscii_conv = malloc(sizeof(ef_iscii_conv_t))) == NULL) { return NULL; } iscii_conv->conv.convert = convert_to_iscii; iscii_conv->conv.init = conv_init; iscii_conv->conv.destroy = conv_destroy; iscii_conv->conv.illegal_char = NULL; iscii_conv->cs = cs; return &iscii_conv->conv; } /* --- global functions --- */ ef_conv_t *ef_koi8_r_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_koi8_r; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_koi8_u_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_koi8_u; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_koi8_t_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_koi8_t; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_georgian_ps_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_georgian_ps; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_cp1250_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_cp1250; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_cp1251_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_cp1251; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_cp1252_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_cp1252; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_cp1253_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_cp1253; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_cp1254_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_cp1254; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_cp1255_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_cp1255; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_cp1256_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_cp1256; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_cp1257_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_cp1257; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_cp1258_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_cp1258; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_cp874_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_cp874; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_viscii_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_viscii; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_iscii_assamese_conv_new(void) { return iscii_conv_new(ISCII_ASSAMESE); } ef_conv_t *ef_iscii_bengali_conv_new(void) { return iscii_conv_new(ISCII_BENGALI); } ef_conv_t *ef_iscii_gujarati_conv_new(void) { return iscii_conv_new(ISCII_GUJARATI); } ef_conv_t *ef_iscii_hindi_conv_new(void) { return iscii_conv_new(ISCII_HINDI); } ef_conv_t *ef_iscii_kannada_conv_new(void) { return iscii_conv_new(ISCII_KANNADA); } ef_conv_t *ef_iscii_malayalam_conv_new(void) { return iscii_conv_new(ISCII_MALAYALAM); } ef_conv_t *ef_iscii_oriya_conv_new(void) { return iscii_conv_new(ISCII_ORIYA); } ef_conv_t *ef_iscii_punjabi_conv_new(void) { return iscii_conv_new(ISCII_PUNJABI); } ef_conv_t *ef_iscii_tamil_conv_new(void) { return iscii_conv_new(ISCII_TAMIL); } ef_conv_t *ef_iscii_telugu_conv_new(void) { return iscii_conv_new(ISCII_TELUGU); } mlterm-3.8.9/encodefilter/src/ef_8bit_conv.h010064400017600000144000000022241356600661000175040ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_8BIT_CONV_H__ #define __EF_8BIT_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_koi8_r_conv_new(void); ef_conv_t *ef_koi8_u_conv_new(void); ef_conv_t *ef_koi8_t_conv_new(void); ef_conv_t *ef_georgian_ps_conv_new(void); ef_conv_t *ef_cp1250_conv_new(void); ef_conv_t *ef_cp1251_conv_new(void); ef_conv_t *ef_cp1252_conv_new(void); ef_conv_t *ef_cp1253_conv_new(void); ef_conv_t *ef_cp1254_conv_new(void); ef_conv_t *ef_cp1255_conv_new(void); ef_conv_t *ef_cp1256_conv_new(void); ef_conv_t *ef_cp1257_conv_new(void); ef_conv_t *ef_cp1258_conv_new(void); ef_conv_t *ef_cp874_conv_new(void); ef_conv_t *ef_viscii_conv_new(void); ef_conv_t *ef_iscii_assamese_conv_new(void); ef_conv_t *ef_iscii_bengali_conv_new(void); ef_conv_t *ef_iscii_gujarati_conv_new(void); ef_conv_t *ef_iscii_hindi_conv_new(void); ef_conv_t *ef_iscii_kannada_conv_new(void); ef_conv_t *ef_iscii_malayalam_conv_new(void); ef_conv_t *ef_iscii_oriya_conv_new(void); ef_conv_t *ef_iscii_punjabi_conv_new(void); ef_conv_t *ef_iscii_tamil_conv_new(void); ef_conv_t *ef_iscii_telugu_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_8bit_parser.c010064400017600000144000000233341356600661000200330ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_8bit_parser.h" #include #include typedef struct ef_iscii_parser { ef_parser_t parser; ef_charset_t cs; } ef_iscii_parser_t; /* --- static functions --- */ static int parser_next_char_intern(ef_parser_t *parser, ef_char_t *ch, ef_charset_t cs) { u_char c; if (parser->is_eos) { return 0; } ef_parser_mark(parser); ch->ch[0] = c = *parser->str; ch->size = 1; ch->property = 0; if (/* 0x0 <= c && */ c <= 0x7f && (cs != VISCII || (c != 0x02 && c != 0x05 && c != 0x06 && c != 0x14 && c != 0x19 && c != 0x1e))) { ch->cs = US_ASCII; } else { if (cs == CP874 && (c == 0xd1 || (0xd4 <= c && c <= 0xda) || (0xe7 <= c && c <= 0xee))) { ch->property = EF_COMBINING; } ch->cs = cs; } ef_parser_increment(parser); return 1; } static int koi8_r_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, KOI8_R); } static int koi8_u_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, KOI8_U); } static int koi8_t_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, KOI8_T); } static int georgian_ps_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, GEORGIAN_PS); } static int cp1250_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, CP1250); } static int cp1251_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, CP1251); } static int cp1252_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, CP1252); } static int cp1253_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, CP1253); } static int cp1254_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, CP1254); } static int cp1255_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, CP1255); } static int cp1256_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, CP1256); } static int cp1257_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, CP1257); } static int cp1258_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, CP1258); } static int cp874_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, CP874); } static int viscii_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, VISCII); } static int iscii_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return parser_next_char_intern(parser, ch, ((ef_iscii_parser_t*)parser)->cs); } static void parser_set_str(ef_parser_t *parser, u_char *str, size_t size) { parser->str = str; parser->left = size; parser->marked_left = 0; parser->is_eos = 0; } static void parser_destroy(ef_parser_t *s) { free(s); } static ef_parser_t *iscii_parser_new(ef_charset_t cs) { ef_iscii_parser_t *iscii_parser; if ((iscii_parser = malloc(sizeof(ef_iscii_parser_t))) == NULL) { return NULL; } ef_parser_init(&iscii_parser->parser); iscii_parser->parser.init = ef_parser_init; iscii_parser->parser.next_char = iscii_parser_next_char; iscii_parser->parser.set_str = parser_set_str; iscii_parser->parser.destroy = parser_destroy; iscii_parser->cs = cs; return &iscii_parser->parser; } /* --- global functions --- */ ef_parser_t *ef_koi8_r_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = koi8_r_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_koi8_u_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = koi8_u_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_koi8_t_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = koi8_t_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_georgian_ps_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = georgian_ps_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_cp1250_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = cp1250_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_cp1251_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = cp1251_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_cp1252_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = cp1252_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_cp1253_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = cp1253_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_cp1254_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = cp1254_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_cp1255_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = cp1255_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_cp1256_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = cp1256_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_cp1257_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = cp1257_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_cp1258_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = cp1258_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_cp874_parser_new(void) { ef_parser_t *parser; if ((parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(parser); parser->init = ef_parser_init; parser->next_char = cp874_parser_next_char; parser->set_str = parser_set_str; parser->destroy = parser_destroy; return parser; } ef_parser_t *ef_viscii_parser_new(void) { ef_parser_t *viscii_parser; if ((viscii_parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(viscii_parser); viscii_parser->init = ef_parser_init; viscii_parser->next_char = viscii_parser_next_char; viscii_parser->set_str = parser_set_str; viscii_parser->destroy = parser_destroy; return viscii_parser; } ef_parser_t *ef_iscii_assamese_parser_new(void) { return iscii_parser_new(ISCII_ASSAMESE); } ef_parser_t *ef_iscii_bengali_parser_new(void) { return iscii_parser_new(ISCII_BENGALI); } ef_parser_t *ef_iscii_gujarati_parser_new(void) { return iscii_parser_new(ISCII_GUJARATI); } ef_parser_t *ef_iscii_hindi_parser_new(void) { return iscii_parser_new(ISCII_HINDI); } ef_parser_t *ef_iscii_kannada_parser_new(void) { return iscii_parser_new(ISCII_KANNADA); } ef_parser_t *ef_iscii_malayalam_parser_new(void) { return iscii_parser_new(ISCII_MALAYALAM); } ef_parser_t *ef_iscii_oriya_parser_new(void) { return iscii_parser_new(ISCII_ORIYA); } ef_parser_t *ef_iscii_punjabi_parser_new(void) { return iscii_parser_new(ISCII_PUNJABI); } ef_parser_t *ef_iscii_tamil_parser_new(void) { return iscii_parser_new(ISCII_TAMIL); } ef_parser_t *ef_iscii_telugu_parser_new(void) { return iscii_parser_new(ISCII_TELUGU); } mlterm-3.8.9/encodefilter/src/ef_8bit_parser.h010064400017600000144000000023761356600661000200430ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_8BIT_PARSER_H__ #define __EF_8BIT_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_koi8_r_parser_new(void); ef_parser_t *ef_koi8_u_parser_new(void); ef_parser_t *ef_koi8_t_parser_new(void); ef_parser_t *ef_georgian_ps_parser_new(void); ef_parser_t *ef_cp1250_parser_new(void); ef_parser_t *ef_cp1251_parser_new(void); ef_parser_t *ef_cp1252_parser_new(void); ef_parser_t *ef_cp1253_parser_new(void); ef_parser_t *ef_cp1254_parser_new(void); ef_parser_t *ef_cp1255_parser_new(void); ef_parser_t *ef_cp1256_parser_new(void); ef_parser_t *ef_cp1257_parser_new(void); ef_parser_t *ef_cp1258_parser_new(void); ef_parser_t *ef_cp874_parser_new(void); ef_parser_t *ef_viscii_parser_new(void); ef_parser_t *ef_iscii_assamese_parser_new(void); ef_parser_t *ef_iscii_bengali_parser_new(void); ef_parser_t *ef_iscii_gujarati_parser_new(void); ef_parser_t *ef_iscii_hindi_parser_new(void); ef_parser_t *ef_iscii_kannada_parser_new(void); ef_parser_t *ef_iscii_malayalam_parser_new(void); ef_parser_t *ef_iscii_oriya_parser_new(void); ef_parser_t *ef_iscii_punjabi_parser_new(void); ef_parser_t *ef_iscii_tamil_parser_new(void); ef_parser_t *ef_iscii_telugu_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_big5_conv.c010064400017600000144000000050741356600661000174650ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_big5_conv.h" #include /* strncmp */ #include #include #include #include "ef_zh_tw_map.h" #include "ef_zh_hk_map.h" /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { char *locale; locale = bl_get_locale(); if (strncmp(locale, "zh_HK", 5) == 0) { if (!ef_map_ucs4_to_zh_hk(&c, ch)) { return; } } else { if (!ef_map_ucs4_to_zh_tw(&c, ch)) { return; } } *ch = c; } if (ch->cs == CNS11643_1992_1) { if (ef_map_cns11643_1992_1_to_big5(&c, ch)) { *ch = c; } } else if (ch->cs == CNS11643_1992_2) { if (ef_map_cns11643_1992_2_to_big5(&c, ch)) { *ch = c; } } } static size_t convert_to_big5(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { size_t filled_size; ef_char_t ch; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { remap_unsupported_charset(&ch); if (ch.cs == BIG5 || ch.cs == HKSCS) { if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ch.ch[0]; *(dst++) = ch.ch[1]; filled_size += 2; } else if (ch.cs == US_ASCII) { if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ch.ch[0]; filled_size++; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } return filled_size; } static void conv_init(ef_conv_t *conv) {} static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_big5_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_big5; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_big5hkscs_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_big5; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } mlterm-3.8.9/encodefilter/src/ef_big5_conv.h010064400017600000144000000003461356600661000174670ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_BIG5_CONV_H___ #define __EF_BIG5_CONV_H___ #include "ef_conv.h" ef_conv_t *ef_big5_conv_new(void); ef_conv_t *ef_big5hkscs_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_big5_parser.c010064400017600000144000000055741356600661000200210ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_big5_parser.h" #include #include /* * the same macro is defined in ef_ucs4_big5.c */ #define IS_HKSCS(code) \ ((0x8140 <= (code) && (code) <= 0xa0fe) || (0xc6a1 <= (code) && (code) <= 0xc8fe) || \ (0xf9d6 <= (code) && (code) <= 0xfefe)) /* --- static functions --- */ static int big5_parser_next_char_intern(ef_parser_t *big5_parser, ef_char_t *ch, int use_hkscs) { if (big5_parser->is_eos) { return 0; } ef_parser_mark(big5_parser); if (/* 0x0 <= *big5_parser->str && */ *big5_parser->str <= 0x7f) { ch->ch[0] = *big5_parser->str; ch->size = 1; ch->cs = US_ASCII; } /* * 8140-a0fe is user defined area. */ else if (0x81 <= *big5_parser->str && *big5_parser->str <= 0xfe) { u_int16_t code; ch->ch[0] = *big5_parser->str; if (ef_parser_increment(big5_parser) == 0) { goto shortage; } if ((0x40 <= *big5_parser->str && *big5_parser->str <= 0x7e) || (0xa1 <= *big5_parser->str && *big5_parser->str <= 0xfe)) { ch->ch[1] = *big5_parser->str; } else { goto error; } code = ef_bytes_to_int(ch->ch, 2); if (use_hkscs && IS_HKSCS(code)) { ch->cs = HKSCS; } else { ch->cs = BIG5; } ch->size = 2; } else { goto error; } ch->property = 0; ef_parser_increment(big5_parser); return 1; error: shortage: ef_parser_reset(big5_parser); return 0; } static int big5_parser_next_char(ef_parser_t *big5_parser, ef_char_t *ch) { return big5_parser_next_char_intern(big5_parser, ch, 0); } static int big5hkscs_parser_next_char(ef_parser_t *big5_parser, ef_char_t *ch) { return big5_parser_next_char_intern(big5_parser, ch, 1); } static void big5_parser_set_str(ef_parser_t *big5_parser, u_char *str, size_t size) { big5_parser->str = str; big5_parser->left = size; big5_parser->marked_left = 0; big5_parser->is_eos = 0; } static void big5_parser_destroy(ef_parser_t *s) { free(s); } /* --- global functions --- */ ef_parser_t *ef_big5_parser_new(void) { ef_parser_t *big5_parser; if ((big5_parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(big5_parser); big5_parser->init = ef_parser_init; big5_parser->next_char = big5_parser_next_char; big5_parser->set_str = big5_parser_set_str; big5_parser->destroy = big5_parser_destroy; return big5_parser; } ef_parser_t *ef_big5hkscs_parser_new(void) { ef_parser_t *big5_parser; if ((big5_parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(big5_parser); big5_parser->init = ef_parser_init; big5_parser->next_char = big5hkscs_parser_next_char; big5_parser->set_str = big5_parser_set_str; big5_parser->destroy = big5_parser_destroy; return big5_parser; } mlterm-3.8.9/encodefilter/src/ef_big5_parser.h010064400017600000144000000003621356600661000200140ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_BIG5_PARSER_H__ #define __EF_BIG5_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_big5_parser_new(void); ef_parser_t *ef_big5hkscs_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_char.c010064400017600000144000000015361356600661000165260ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_char.h" #include /* NULL */ #include /* BE*DEC */ /* --- global functions --- */ u_char *ef_int_to_bytes(u_char *bytes, size_t len, u_int32_t int_ch) { if (len == 1) { bytes[0] = int_ch & 0xff; } else if (len == 2) { bytes[0] = (int_ch >> 8) & 0xff; bytes[1] = int_ch & 0xff; } else if (len == 4) { bytes[0] = (int_ch >> 24) & 0xff; bytes[1] = (int_ch >> 16) & 0xff; bytes[2] = (int_ch >> 8) & 0xff; bytes[3] = int_ch & 0xff; } else { return NULL; } return bytes; } u_int32_t ef_bytes_to_int(const u_char *bytes, size_t len) { switch (len) { case 1: return bytes[0]; case 2: return BE16DEC(bytes); case 4: return BE32DEC(bytes); default: return 0; } } mlterm-3.8.9/encodefilter/src/ef_char.h010064400017600000144000000015411356600661000165270ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_CHAR_H__ #define __EF_CHAR_H__ #include /* u_xxx */ #include "ef_property.h" #include "ef_charset.h" /* * use UNMAP_FROM_GR or MAP_TO_GR to operate gr byte. * these are for 8bit cs(ISO8859-R...). */ #define SET_MSB(ch) ((ch) |= 0x80) #define UNSET_MSB(ch) ((ch) &= 0x7f) /* UCS-4 is the max. */ #define MAX_CS_BYTELEN 4 /* * this should be kept as small as possible. */ typedef struct ef_char { u_char ch[MAX_CS_BYTELEN]; /* Big Endian */ u_int8_t size; u_int8_t property; /* ef_property_t */ int16_t cs; /* ef_charset_t */ } ef_char_t; u_char *ef_int_to_bytes(u_char *bytes, size_t len, u_int32_t int_ch); u_int32_t ef_bytes_to_int(const u_char *bytes, size_t len); #define ef_char_to_int(c) ef_bytes_to_int((c)->ch, (c)->size) #endif mlterm-3.8.9/encodefilter/src/ef_charset.h010064400017600000144000000152371356600661000172520ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_CHARSET_H__ #define __EF_CHARSET_H__ #include /* u_xxx */ /* * ISO2022 Ft should be within 0x40('@') and 0x7e('~') except * DEC_SPECIAL(Ft='0'). */ /* 0x00 - 0x4e (Ft is within 0x30 and 0x7e) (0x30-0x3f is for DRCS) */ #define CS94SB_ID(c) ((u_char)(c) - 0x30) /* 0x50 - 0x9e (Ft is within 0x30 and 0x7e) (0x30-0x3f is for DRCS) */ #define CS96SB_ID(c) ((u_char)(c) + 0x20) /* 0xa0 - 0xbf (XXX Ft is within 0x40 and 0x5f) */ #define CS94MB_ID(c) ((u_char)(c) + 0x60) /* No 96^n cs exists. */ #define CS96MB_ID(c) UNKNOWN_CS /* 0xc0 - 0xcf (Ft is within 0x40 and 0x4f) */ #define NON_ISO2022_1_ID(c) ((u_char)(c) + 0x80) /* 0xd0 - 0xdf (Ft is within 0x40 and 0x4f) */ #define NON_ISO2022_2_ID(c) ((u_char)(c) + 0x90) /* 0x100 - 0x1bf (= 0x100 | CS9XXB_ID) */ #define CS_REVISION_1(cs) ((cs) + 0x100) /* 0x200 - 0x2bf (= 0x200 | CS9XXB_ID) */ #define CS_REVISION_2(cs) ((cs) + 0x200) /* * 'and 0xff' should be done because 0x100 - region is used for 'or cs_revision' */ #define CS94SB_FT(cs) (((cs)&0xff) + 0x30) #define CS96SB_FT(cs) (((cs)&0xff) - 0x20) #define CS94MB_FT(cs) (((cs)&0xff) - 0x60) #define CS96MB_FT(cs) ' ' /* dummy */ #define IS_CS94SB(cs) ((unsigned int)((cs)&0xff) <= 0x4e) /* same as 0x00 <= .. <= 0x4e */ #define IS_CS96SB(cs) (0x50 <= ((cs)&0xff) && ((cs)&0xff) <= 0x9e) #define IS_CS94MB(cs) (0xa0 <= ((cs)&0xff) && ((cs)&0xff) <= 0xbf) #define IS_CS96MB(cs) (0) /* always false */ #define IS_CS_BASED_ON_ISO2022(cs) (0x0 <= ((cs)&0xff) && ((cs)&0xff) <= 0xbf) /* without "(cs) != UNKNOWN_CS &&", 0xa0 <= (UNKNOWN_CS & 0xff) returns true. */ #define IS_NON_ISO2022(cs) ((cs) != UNKNOWN_CS && 0xc0 <= ((cs)&0xff)) #define IS_ISCII(cs) (0xf0 <= (cs) && (cs) <= 0xfa) #define IS_FULLWIDTH_CS(cs) (IS_CS94MB(cs) || IS_CS96MB(cs) || (0x1e0 <= (cs) && (cs) <= 0x1ff)) #define CS_SIZE(cs) \ ((cs) == ISO10646_UCS4_1 ? 4 : ((IS_FULLWIDTH_CS(cs) || (cs) == ISO10646_UCS2_1) ? 2 : 1)) #define IS_ISO10646_UCS4(cs) (((cs) & ~CS_REVISION_1(0)) == ISO10646_UCS4_1) /* * These enumeration numbers are based on iso2022 Ft(0x30-0x7e). * Total range is -1 <-> 0x2ff(int16). */ typedef enum ef_charset { UNKNOWN_CS = -1, /* 94 sb cs */ DEC_SPECIAL = CS94SB_ID('0'), ISO646_IRV = CS94SB_ID('@'), ISO646_EN = CS94SB_ID('A'), US_ASCII = CS94SB_ID('B'), NATS_PRIMARY_FOR_FIN_SWEDEN = CS94SB_ID('C'), NATS_PRIMARY_FOR_DEN_NOR = CS94SB_ID('E'), ISO646_SWEDEN = CS94SB_ID('G'), ISO646_SWEDEN_NAME = CS94SB_ID('H'), JISX0201_KATA = CS94SB_ID('I'), JISX0201_ROMAN = CS94SB_ID('J'), /* 96 sb cs */ ISO8859_1_R = CS96SB_ID('A'), ISO8859_2_R = CS96SB_ID('B'), ISO8859_3_R = CS96SB_ID('C'), ISO8859_4_R = CS96SB_ID('D'), ISO8859_7_R = CS96SB_ID('F'), ISO8859_6_R = CS96SB_ID('G'), ISO8859_8_R = CS96SB_ID('H'), ISO8859_5_R = CS96SB_ID('L'), ISO8859_9_R = CS96SB_ID('M'), ISO8859_10_R = CS96SB_ID('V'), TIS620_2533 = CS96SB_ID('T'), ISO8859_13_R = CS96SB_ID('Y'), /* Ft = 5/9 */ ISO8859_14_R = CS96SB_ID('_'), /* Ft = 5/15 */ ISO8859_15_R = CS96SB_ID('b'), /* Ft = 6/2 */ ISO8859_16_R = CS96SB_ID('f'), /* Ft = 6/6 */ TCVN5712_3_1993 = CS96SB_ID('Z'), /* 94 mb cs */ JISC6226_1978 = CS94MB_ID('@'), GB2312_80 = CS94MB_ID('A'), JISX0208_1983 = CS94MB_ID('B'), KSC5601_1987 = CS94MB_ID('C'), JISX0212_1990 = CS94MB_ID('D'), CNS11643_1992_1 = CS94MB_ID('G'), CNS11643_1992_2 = CS94MB_ID('H'), CNS11643_1992_3 = CS94MB_ID('I'), CNS11643_1992_4 = CS94MB_ID('J'), CNS11643_1992_5 = CS94MB_ID('K'), CNS11643_1992_6 = CS94MB_ID('L'), CNS11643_1992_7 = CS94MB_ID('M'), JISX0213_2000_1 = CS94MB_ID('O'), JISX0213_2000_2 = CS94MB_ID('P'), /* 96 mb cs */ /* Nothing */ /* NOT ISO2022 class 1 (ESC 2/5 Ft) */ UTF1 = NON_ISO2022_1_ID('B'), UTF8 = NON_ISO2022_1_ID('G'), /* NOT ISO2022 class 2 (ESC 2/5 2/15 Ft) */ XCT_NON_ISO2022_CS_1 = NON_ISO2022_2_ID('1'), /* CTEXT */ XCT_NON_ISO2022_CS_2 = NON_ISO2022_2_ID('2'), /* CTEXT */ ISO10646_UCS2_1 = NON_ISO2022_2_ID('@'), /* Including US_ASCII(0x0-0x7f) */ ISO10646_UCS4_1 = NON_ISO2022_2_ID('A'), /* Including US_ASCII(0x0-0x7f) */ /* Followings are mef original classifications */ /* * Those who are not ISO2022 registed characterset or do not confirm to * ISO2022. * 0xe0 - 0xfa */ VISCII = 0xe0, /* Excluding US_ASCII(0x0-0x7f) */ TCVN5712_1_1993 = 0xe1, /* ISO2022 compat */ KOI8_R = 0xe2, /* Excluding US_ASCII(0x0-0x7f) */ KOI8_U = 0xe3, /* Excluding US_ASCII(0x0-0x7f) */ KOI8_T = 0xe4, /* Excluding US_ASCII(0x0-0x7f) */ GEORGIAN_PS = 0xe5, /* Excluding US_ASCII(0x0-0x7f) */ CP1250 = 0xe6, /* Excluding US_ASCII(0x0-0x7f) */ CP1251 = 0xe7, /* Excluding US_ASCII(0x0-0x7f) */ CP1252 = 0xe8, /* Excluding US_ASCII(0x0-0x7f) */ CP1253 = 0xe9, /* Excluding US_ASCII(0x0-0x7f) */ CP1254 = 0xea, /* Excluding US_ASCII(0x0-0x7f) */ CP1255 = 0xeb, /* Excluding US_ASCII(0x0-0x7f) */ CP1256 = 0xec, /* Excluding US_ASCII(0x0-0x7f) */ CP1257 = 0xed, /* Excluding US_ASCII(0x0-0x7f) */ CP1258 = 0xee, /* Excluding US_ASCII(0x0-0x7f) */ CP874 = 0xef, /* Excluding US_ASCII(0x0-0x7f) */ ISCII_ASSAMESE = 0xf0, /* Excluding US_ASCII(0x0-0x7f) */ ISCII_BENGALI = 0xf1, /* Excluding US_ASCII(0x0-0x7f) */ ISCII_GUJARATI = 0xf2, /* Excluding US_ASCII(0x0-0x7f) */ ISCII_HINDI = 0xf3, /* Excluding US_ASCII(0x0-0x7f) */ ISCII_KANNADA = 0xf4, /* Excluding US_ASCII(0x0-0x7f) */ ISCII_MALAYALAM = 0xf5, /* Excluding US_ASCII(0x0-0x7f) */ ISCII_ORIYA = 0xf6, /* Excluding US_ASCII(0x0-0x7f) */ ISCII_PUNJABI = 0xf7, /* Excluding US_ASCII(0x0-0x7f) */ ISCII_TAMIL = 0xf8, /* Excluding US_ASCII(0x0-0x7f) */ ISCII_TELUGU = 0xf9, /* Excluding US_ASCII(0x0-0x7f) */ #if 0 ISCII_ROMAN = 0xfa, /* Excluding US_ASCII(0x0-0x7f) */ #endif /* Followings are ISO2022 based charsets with revisions. */ /* Revision 1 */ JISX0208_1990 = CS_REVISION_1(JISX0208_1983), ISO10646_UCS4_1_V = CS_REVISION_1(ISO10646_UCS4_1), /* mef original */ /* Followings are mef original classifications */ /* * Those who are not ISO2022 registed characterset but confirm to ISO2022. * (Bi-width) * 0x1e0 - 0xf5 */ JISC6226_1978_NEC_EXT = 0x1e0, JISC6226_1978_NECIBM_EXT = 0x1e1, JISX0208_1983_MAC_EXT = 0x1e2, /* * Those who are not ISO2022 registed characterset or do not confirm to * ISO2022. * (Bi-width) * 0x1e3 - 0x1e9 */ SJIS_IBM_EXT = 0x1e3, UHC = 0x1e4, BIG5 = 0x1e5, CNS11643_1992_EUCTW_G2 = 0x1e6, GBK = 0x1e7, JOHAB = 0x1e8, HKSCS = 0x1e9, MAX_CHARSET = 0x2ff } ef_charset_t; #endif mlterm-3.8.9/encodefilter/src/ef_codepoint_parser.c010064400017600000144000000042521356600661000211470ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_codepoint_parser.h" #include #include typedef struct cp_parser { ef_parser_t parser; ef_charset_t cs; size_t cp_size; } cp_parser_t; /* --- static functions --- */ static void cp_parser_init(ef_parser_t *parser) { cp_parser_t *cp_parser; cp_parser = (cp_parser_t*)parser; ef_parser_init(parser); cp_parser->cs = UNKNOWN_CS; cp_parser->cp_size = 1; } static void cp_parser_set_str(ef_parser_t *parser, u_char *str, size_t size /* size(max 16bit) | cs << 16 */ ) { ef_charset_t cs; cp_parser_t *cp_parser; cp_parser = (cp_parser_t*)parser; cs = (ef_charset_t)((size >> 16) & 0xffff); cp_parser->parser.str = str; cp_parser->parser.left = size & 0xffff; cp_parser->parser.marked_left = 0; cp_parser->parser.is_eos = 0; cp_parser->cs = cs; if (cs == ISO10646_UCS4_1) { cp_parser->cp_size = 4; } else if (IS_FULLWIDTH_CS(cs) || cs == ISO10646_UCS2_1) { cp_parser->cp_size = 2; } else { cp_parser->cp_size = 1; } } static void cp_parser_destroy(ef_parser_t *parser) { free(parser); } static int cp_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { cp_parser_t *cp_parser; size_t count; cp_parser = (cp_parser_t*)parser; if (cp_parser->parser.is_eos) { return 0; } if (cp_parser->parser.left < cp_parser->cp_size) { cp_parser->parser.is_eos = 1; return 0; } for (count = 0; count < cp_parser->cp_size; count++) { ch->ch[count] = cp_parser->parser.str[count]; } ef_parser_n_increment(cp_parser, count); ch->size = count; ch->cs = cp_parser->cs; ch->property = 0; return 1; } /* --- global functions --- */ ef_parser_t *ef_codepoint_parser_new(void) { cp_parser_t *cp_parser; if ((cp_parser = malloc(sizeof(cp_parser_t))) == NULL) { return NULL; } cp_parser_init(&cp_parser->parser); cp_parser->parser.init = cp_parser_init; cp_parser->parser.set_str = cp_parser_set_str; cp_parser->parser.destroy = cp_parser_destroy; cp_parser->parser.next_char = cp_parser_next_char; return &cp_parser->parser; } mlterm-3.8.9/encodefilter/src/ef_codepoint_parser.h010064400017600000144000000003241356600661000211500ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_CODEPOINT_PARSER_H__ #define __EF_CODEPOINT_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_codepoint_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_conv.h010064400017600000144000000007011356600661000165540ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_CONV_H__ #define __EF_CONV_H__ #include /* size_t */ #include "ef_parser.h" typedef struct ef_conv { void (*init)(struct ef_conv *); void (*destroy)(struct ef_conv *); size_t (*convert)(struct ef_conv *, u_char *, size_t, ef_parser_t *); size_t (*illegal_char)(struct ef_conv *, u_char *, size_t, int *, ef_char_t *); } ef_conv_t; #endif mlterm-3.8.9/encodefilter/src/ef_euccn_conv.c010064400017600000144000000113561356600661000177340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_euccn_conv.h" #include #include #include "ef_iso2022_conv.h" #include "ef_iso2022_intern.h" #include "ef_ucs4_map.h" #include "ef_zh_cn_map.h" #include "ef_gb18030_2000_intern.h" typedef enum euccn_encoding { EUCCN_NORMAL, EUCCN_GBK, EUCCN_GB18030_2000 } enccn_encoding_t; /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch, enccn_encoding_t encoding) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { if (ef_map_ucs4_to_zh_cn(&c, ch)) { *ch = c; } } if (encoding == EUCCN_NORMAL) { ef_iso2022_remap_unsupported_charset(ch); } else { if (ch->cs == ISO10646_UCS4_1) { return; } if (ch->cs == GB2312_80) { if (ef_map_gb2312_80_to_gbk(&c, ch)) { *ch = c; } } } } static size_t convert_to_euccn_intern(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser, enccn_encoding_t encoding) { size_t filled_size; ef_char_t ch; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { remap_unsupported_charset(&ch, encoding); if (ch.cs == US_ASCII) { if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = *ch.ch; filled_size++; } else if (encoding == EUCCN_NORMAL && ch.cs == GB2312_80) { if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = MAP_TO_GR(ch.ch[0]); *(dst++) = MAP_TO_GR(ch.ch[1]); filled_size += 2; } else if ((encoding == EUCCN_GBK || encoding == EUCCN_GB18030_2000) && ch.cs == GBK) { if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ch.ch[0]; *(dst++) = ch.ch[1]; filled_size += 2; } else if (encoding == EUCCN_GB18030_2000 && ch.cs == ISO10646_UCS4_1) { u_char gb18030[4]; if (filled_size + 3 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } if (ef_encode_ucs4_to_gb18030_2000(gb18030, ch.ch) == 0) { continue; } *(dst++) = gb18030[0]; *(dst++) = gb18030[1]; *(dst++) = gb18030[2]; *(dst++) = gb18030[3]; filled_size += 4; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } return filled_size; } static size_t convert_to_euccn(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_euccn_intern(conv, dst, dst_size, parser, EUCCN_NORMAL); } static size_t convert_to_gbk(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_euccn_intern(conv, dst, dst_size, parser, EUCCN_GBK); } static size_t convert_to_gb18030_2000(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_euccn_intern(conv, dst, dst_size, parser, EUCCN_GB18030_2000); } static void euccn_conv_init(ef_conv_t *conv) { ef_iso2022_conv_t *iso2022_conv; iso2022_conv = (ef_iso2022_conv_t*)conv; iso2022_conv->gl = &iso2022_conv->g0; iso2022_conv->gr = &iso2022_conv->g1; iso2022_conv->g0 = US_ASCII; iso2022_conv->g1 = GB2312_80; iso2022_conv->g2 = UNKNOWN_CS; iso2022_conv->g3 = UNKNOWN_CS; } static void conv_init(ef_conv_t *conv) {} static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_euccn_conv_new(void) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } euccn_conv_init((ef_conv_t*)iso2022_conv); iso2022_conv->conv.convert = convert_to_euccn; iso2022_conv->conv.init = euccn_conv_init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t*)iso2022_conv; } ef_conv_t *ef_gbk_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_gbk; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_gb18030_2000_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_gb18030_2000; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } mlterm-3.8.9/encodefilter/src/ef_euccn_conv.h010064400017600000144000000004151356600661000177330ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_EUCCN_CONV_H__ #define __EF_EUCCN_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_euccn_conv_new(void); ef_conv_t *ef_gbk_conv_new(void); ef_conv_t *ef_gb18030_2000_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_euccn_parser.c010064400017600000144000000116561356600661000202660ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_euccn_parser.h" #include /* NULL */ #include #include #include "ef_iso2022_parser.h" #include "ef_gb18030_2000_intern.h" #include "ef_ucs_property.h" #if 0 #define __DEBUG #endif /* --- static functions --- */ static int gbk_parser_next_char_intern(ef_parser_t *parser, ef_char_t *ch, int is_gb18030) { if (parser->is_eos) { return 0; } ef_parser_mark(parser); if (/* 0x00 <= *parser->str && */ *parser->str <= 0x80) { ch->ch[0] = *parser->str; ch->cs = US_ASCII; ch->size = 1; ch->property = 0; ef_parser_increment(parser); return 1; } else { u_char bytes[4]; u_char ucs4[4]; if (is_gb18030) { if (0x81 <= *parser->str && *parser->str <= 0xa0) { bytes[0] = *parser->str; if (ef_parser_increment(parser) == 0) { goto shortage; } if (0x30 <= *parser->str && *parser->str <= 0x39) { goto is_4_bytes; } } else if (0xa1 <= *parser->str && *parser->str <= 0xfe) { bytes[0] = *parser->str; if (ef_parser_increment(parser) == 0) { goto shortage; } if (0x30 <= *parser->str && *parser->str <= 0x39) { goto is_4_bytes; } } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " illegal GBK format. [%x ...]\n", *parser->str); #endif goto error; } } else { bytes[0] = *parser->str; if (ef_parser_increment(parser) == 0) { goto shortage; } } ch->ch[0] = bytes[0]; if (*parser->str < 0x40) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " illegal GBK format. [%.2x%.2x ...]\n", bytes[0], *parser->str); #endif goto error; } ch->ch[1] = *parser->str; ch->size = 2; ch->cs = GBK; ch->property = 0; ef_parser_increment(parser); return 1; is_4_bytes: bytes[1] = *parser->str; if (ef_parser_increment(parser) == 0) { goto shortage; } if (*parser->str < 0x81 || 0xfe < *parser->str) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " illegal GBK format. [%.2x%.2x%.2x ...]\n", bytes[0], bytes[1], *parser->str); #endif goto error; } bytes[2] = *parser->str; if (ef_parser_increment(parser) == 0) { goto shortage; } if (*parser->str < 0x30 || 0x39 < *parser->str) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " illegal GBK format. [%.2x%.2x%.2x%.2x]\n", bytes[0], bytes[1], bytes[2], *parser->str); #endif goto error; } bytes[3] = *parser->str; ef_parser_increment(parser); if (ef_decode_gb18030_2000_to_ucs4(ucs4, bytes) == 0) { goto error; } memcpy(ch->ch, ucs4, 4); ch->size = 4; ch->cs = ISO10646_UCS4_1; ch->property = 0; return 1; } error: shortage: ef_parser_reset(parser); return 0; } static int gbk_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return gbk_parser_next_char_intern(parser, ch, 0); } static int gb18030_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { return gbk_parser_next_char_intern(parser, ch, 1); } static void euccn_parser_init_intern(ef_parser_t *parser, ef_charset_t g1_cs) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t *)parser; iso2022_parser->g0 = US_ASCII; iso2022_parser->g1 = g1_cs; iso2022_parser->g2 = UNKNOWN_CS; iso2022_parser->g3 = UNKNOWN_CS; iso2022_parser->gl = &iso2022_parser->g0; iso2022_parser->gr = &iso2022_parser->g1; iso2022_parser->non_iso2022_cs = UNKNOWN_CS; iso2022_parser->is_single_shifted = 0; } static void euccn_parser_init(ef_parser_t *parser) { euccn_parser_init_intern(parser, GB2312_80); } /* * shared by gbk and gbk18030_2000 */ static void gbk_parser_init(ef_parser_t *parser) { euccn_parser_init_intern(parser, GBK); } static ef_parser_t *gbk_parser_new(void (*init)(struct ef_parser *), int (*next_char)(struct ef_parser *, ef_char_t *)) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } (*init)((ef_parser_t *)iso2022_parser); /* override */ iso2022_parser->parser.init = init; iso2022_parser->parser.next_char = next_char; return (ef_parser_t *)iso2022_parser; } /* --- global functions --- */ ef_parser_t *ef_euccn_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } euccn_parser_init((ef_parser_t *)iso2022_parser); /* override */ iso2022_parser->parser.init = euccn_parser_init; return (ef_parser_t *)iso2022_parser; } ef_parser_t *ef_gbk_parser_new(void) { return gbk_parser_new(gbk_parser_init, gbk_parser_next_char); } ef_parser_t *ef_gb18030_2000_parser_new(void) { return gbk_parser_new(gbk_parser_init, gb18030_parser_next_char); } mlterm-3.8.9/encodefilter/src/ef_parser.c010064400017600000144000000037011356600661000171010ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_parser.h" #include /* NULL */ #include /* --- global functions --- */ void ef_parser_init(ef_parser_t *parser) { parser->str = NULL; parser->marked_left = 0; parser->left = 0; parser->is_eos = 0; } size_t __ef_parser_increment(ef_parser_t *parser) { if (parser->left <= 1) { parser->str += parser->left; parser->left = 0; parser->is_eos = 1; } else { parser->str++; parser->left--; } return parser->left; } size_t __ef_parser_n_increment(ef_parser_t *parser, size_t n) { if (parser->left <= n) { parser->str += parser->left; parser->left = 0; parser->is_eos = 1; } else { parser->str += n; parser->left -= n; } return parser->left; } void __ef_parser_mark(ef_parser_t *parser) { parser->marked_left = parser->left; } void __ef_parser_reset(ef_parser_t *parser) { parser->str -= (parser->marked_left - parser->left); parser->left = parser->marked_left; } void __ef_parser_full_reset(ef_parser_t *parser) { if (parser->is_eos && parser->marked_left > parser->left) { parser->is_eos = 0; } __ef_parser_reset(parser); } /* * short cut function. (ignoring error) */ int ef_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { while (1) { #if 0 /* * just to be sure... * ef_parser_mark() should be called inside [encoding]_next_char() * function. */ ef_parser_mark(parser); #endif if ((*parser->next_char)(parser, ch)) { return 1; } else if (parser->is_eos || /* parser->next_char() returns error and skip to next char */ ef_parser_increment(parser) == 0) { #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " parser reached the end of string.\n"); #endif return 0; } #ifdef DEBUG else { bl_warn_printf(BL_DEBUG_TAG " parser->next_char() returns error , continuing...\n"); } #endif } } mlterm-3.8.9/encodefilter/src/ef_euccn_parser.h010064400017600000144000000004371356600661000202660ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_EUCCN_PARSER_H__ #define __EF_EUCCN_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_euccn_parser_new(void); ef_parser_t *ef_gbk_parser_new(void); ef_parser_t *ef_gb18030_2000_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_eucjp_conv.c010064400017600000144000000132311356600661000177370ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_eucjp_conv.h" #include #include #include "ef_iso2022_conv.h" #include "ef_iso2022_intern.h" #include "ef_ucs4_map.h" #include "ef_ja_jp_map.h" /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch, ef_charset_t g1, ef_charset_t g3) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { if (ef_map_ucs4_to_ja_jp(&c, ch)) { *ch = c; } } ef_iso2022_remap_unsupported_charset(ch); /* * various gaiji chars => jis */ if (ch->cs == JISC6226_1978_NEC_EXT) { if (!ef_map_jisx0208_nec_ext_to_jisx0208_1983(&c, ch) && !ef_map_jisx0208_nec_ext_to_jisx0212_1990(&c, ch)) { return; } *ch = c; } else if (ch->cs == JISC6226_1978_NECIBM_EXT) { if (!ef_map_jisx0208_necibm_ext_to_jisx0208_1983(&c, ch) && !ef_map_jisx0208_necibm_ext_to_jisx0212_1990(&c, ch)) { return; } *ch = c; } else if (ch->cs == SJIS_IBM_EXT) { if (!ef_map_sjis_ibm_ext_to_jisx0208_1983(&c, ch) && !ef_map_sjis_ibm_ext_to_jisx0212_1990(&c, ch)) { return; } *ch = c; } else if (ch->cs == JISX0208_1983_MAC_EXT) { if (!ef_map_jisx0208_mac_ext_to_jisx0208_1983(&c, ch) && !ef_map_jisx0208_mac_ext_to_jisx0212_1990(&c, ch)) { return; } *ch = c; } /* * conversion between JIS charsets. */ if (ch->cs == JISC6226_1978) { /* * we ef_eucjp_parser don't support JISC6226_1978. * If you want to use JISC6226_1978 , use iso2022(jp). * * XXX * 22 characters are swapped between 1978 and 1983. * so , we should reswap these here , but for the time being , * we do nothing. */ ch->cs = JISX0208_1983; } else if (g1 == JISX0208_1983 && ch->cs == JISX0213_2000_1) { if (ef_map_jisx0213_2000_1_to_jisx0208_1983(&c, ch)) { *ch = c; } } else if (g1 == JISX0213_2000_1 && ch->cs == JISX0208_1983) { if (ef_map_jisx0208_1983_to_jisx0213_2000_1(&c, ch)) { *ch = c; } } else if (g3 == JISX0212_1990 && ch->cs == JISX0213_2000_2) { if (ef_map_jisx0213_2000_2_to_jisx0212_1990(&c, ch)) { *ch = c; } } else if (g3 == JISX0213_2000_2 && ch->cs == JISX0212_1990) { if (ef_map_jisx0212_1990_to_jisx0213_2000_2(&c, ch)) { *ch = c; } } } static size_t convert_to_eucjp(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { size_t filled_size; ef_char_t ch; ef_iso2022_conv_t *iso2022_conv; iso2022_conv = (ef_iso2022_conv_t*)conv; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { remap_unsupported_charset(&ch, iso2022_conv->g1, iso2022_conv->g3); if (ch.cs == US_ASCII || ch.cs == JISX0201_ROMAN) { if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = *ch.ch; filled_size++; } else if (ch.cs == iso2022_conv->g1) { if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = MAP_TO_GR(ch.ch[0]); *(dst++) = MAP_TO_GR(ch.ch[1]); filled_size += 2; } else if (ch.cs == JISX0201_KATA) { if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = SS2; *(dst++) = SET_MSB(*ch.ch); filled_size += 2; } else if (ch.cs == iso2022_conv->g3) { if (filled_size + 2 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = SS3; *(dst++) = MAP_TO_GR(ch.ch[0]); *(dst++) = MAP_TO_GR(ch.ch[1]); filled_size += 3; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } return filled_size; } static void eucjp_conv_init(ef_conv_t *conv) { ef_iso2022_conv_t *iso2022_conv; iso2022_conv = (ef_iso2022_conv_t*)conv; iso2022_conv->gl = &iso2022_conv->g0; iso2022_conv->gr = &iso2022_conv->g1; iso2022_conv->g0 = US_ASCII; iso2022_conv->g1 = JISX0208_1983; iso2022_conv->g2 = JISX0201_KATA; iso2022_conv->g3 = JISX0212_1990; } static void eucjisx0213_conv_init(ef_conv_t *conv) { ef_iso2022_conv_t *iso2022_conv; iso2022_conv = (ef_iso2022_conv_t*)conv; iso2022_conv->gl = &iso2022_conv->g0; iso2022_conv->gr = &iso2022_conv->g1; iso2022_conv->g0 = US_ASCII; iso2022_conv->g1 = JISX0213_2000_1; iso2022_conv->g2 = JISX0201_KATA; iso2022_conv->g3 = JISX0213_2000_2; } static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_eucjp_conv_new(void) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } eucjp_conv_init((ef_conv_t*)iso2022_conv); iso2022_conv->conv.convert = convert_to_eucjp; iso2022_conv->conv.init = eucjp_conv_init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t*)iso2022_conv; } ef_conv_t *ef_eucjisx0213_conv_new(void) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } eucjisx0213_conv_init((ef_conv_t*)iso2022_conv); iso2022_conv->conv.convert = convert_to_eucjp; iso2022_conv->conv.init = eucjisx0213_conv_init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t*)iso2022_conv; } mlterm-3.8.9/encodefilter/src/ef_eucjp_conv.h010064400017600000144000000003511356600661000177430ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_EUCJP_CONV_H__ #define __EF_EUCJP_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_eucjp_conv_new(void); ef_conv_t *ef_eucjisx0213_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_eucjp_parser.c010064400017600000144000000035341356600661000202730ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_eucjp_parser.h" #include /* NULL */ #include "ef_iso2022_parser.h" #if 0 #define __DEBUG #endif /* --- static functions --- */ static void eucjp_parser_init(ef_parser_t *parser) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t*)parser; iso2022_parser->g0 = US_ASCII; iso2022_parser->g1 = JISX0208_1983; iso2022_parser->g2 = JISX0201_KATA; iso2022_parser->g3 = JISX0212_1990; iso2022_parser->gl = &iso2022_parser->g0; iso2022_parser->gr = &iso2022_parser->g1; iso2022_parser->non_iso2022_cs = UNKNOWN_CS; iso2022_parser->is_single_shifted = 0; } static void eucjisx0213_parser_init(ef_parser_t *parser) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t*)parser; iso2022_parser->g0 = US_ASCII; iso2022_parser->g1 = JISX0213_2000_1; iso2022_parser->g2 = JISX0201_KATA; iso2022_parser->g3 = JISX0213_2000_2; iso2022_parser->gl = &iso2022_parser->g0; iso2022_parser->gr = &iso2022_parser->g1; iso2022_parser->is_single_shifted = 0; } /* --- global functions --- */ ef_parser_t *ef_eucjp_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } /* override */ iso2022_parser->parser.init = eucjp_parser_init; eucjp_parser_init((ef_parser_t*)iso2022_parser); return (ef_parser_t*)iso2022_parser; } ef_parser_t *ef_eucjisx0213_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } eucjisx0213_parser_init((ef_parser_t*)iso2022_parser); /* overwrite */ iso2022_parser->parser.init = eucjisx0213_parser_init; return (ef_parser_t*)iso2022_parser; } mlterm-3.8.9/encodefilter/src/ef_eucjp_parser.h010064400017600000144000000003671356600661000203010ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_EUCJP_PARSER_H__ #define __EF_EUCJP_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_eucjp_parser_new(void); ef_parser_t *ef_eucjisx0213_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_euckr_conv.c010064400017600000144000000071531356600661000177500ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_euckr_conv.h" #include #include #include "ef_iso2022_conv.h" #include "ef_iso2022_intern.h" #include "ef_ucs4_map.h" #include "ef_ko_kr_map.h" /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch, int is_uhc) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { if (ef_map_ucs4_to_ko_kr(&c, ch)) { *ch = c; } } if (is_uhc) { if (ch->cs == ISO10646_UCS4_1) { return; } if (ch->cs == JOHAB) { if (!ef_map_johab_to_uhc(&c, ch)) { return; } *ch = c; } if (ef_map_ksc5601_1987_to_uhc(&c, ch)) { *ch = c; } } else { ef_iso2022_remap_unsupported_charset(ch); } } static size_t convert_to_euckr_intern(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser, int is_uhc) { size_t filled_size; ef_char_t ch; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { remap_unsupported_charset(&ch, is_uhc); if (ch.cs == US_ASCII) { if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = *ch.ch; filled_size++; } else if ((!is_uhc) && ch.cs == KSC5601_1987) { if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = MAP_TO_GR(ch.ch[0]); *(dst++) = MAP_TO_GR(ch.ch[1]); filled_size += 2; } else if (is_uhc && ch.cs == UHC) { if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ch.ch[0]; *(dst++) = ch.ch[1]; filled_size += 2; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } return filled_size; } static size_t convert_to_euckr(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_euckr_intern(conv, dst, dst_size, parser, 0); } static size_t convert_to_uhc(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_euckr_intern(conv, dst, dst_size, parser, 1); } static void euckr_conv_init(ef_conv_t *conv) { ef_iso2022_conv_t *iso2022_conv; iso2022_conv = (ef_iso2022_conv_t*)conv; iso2022_conv->gl = &iso2022_conv->g0; iso2022_conv->gr = &iso2022_conv->g1; iso2022_conv->g0 = US_ASCII; iso2022_conv->g1 = KSC5601_1987; iso2022_conv->g2 = UNKNOWN_CS; iso2022_conv->g3 = UNKNOWN_CS; } static void uhc_conv_init(ef_conv_t *conv) {} static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_euckr_conv_new(void) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } euckr_conv_init((ef_conv_t*)iso2022_conv); iso2022_conv->conv.convert = convert_to_euckr; iso2022_conv->conv.init = euckr_conv_init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t*)iso2022_conv; } ef_conv_t *ef_uhc_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_uhc; conv->init = uhc_conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } mlterm-3.8.9/encodefilter/src/ef_euckr_conv.h010064400017600000144000000003411356600661000177450ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_EUCKR_CONV_H__ #define __EF_EUCKR_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_euckr_conv_new(void); ef_conv_t *ef_uhc_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_euckr_parser.c010064400017600000144000000043071356600661000202750ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_euckr_parser.h" #include /* NULL */ #include #include "ef_iso2022_parser.h" #if 0 #define __DEBUG #endif /* --- static functions --- */ static int uhc_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { if (parser->is_eos) { return 0; } ef_parser_mark(parser); if (/* 0x00 <= *parser->str && */ *parser->str <= 0x80) { ch->ch[0] = *parser->str; ch->cs = US_ASCII; ch->size = 1; } else { ch->ch[0] = *parser->str; if (ef_parser_increment(parser) == 0) { ef_parser_reset(parser); return 0; } ch->ch[1] = *parser->str; ch->size = 2; ch->cs = UHC; } ch->property = 0; ef_parser_increment(parser); return 1; } static void euckr_parser_init_intern(ef_parser_t *parser, ef_charset_t g1_cs) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t*)parser; iso2022_parser->g0 = US_ASCII; iso2022_parser->g1 = g1_cs; iso2022_parser->g2 = UNKNOWN_CS; iso2022_parser->g3 = UNKNOWN_CS; iso2022_parser->gl = &iso2022_parser->g0; iso2022_parser->gr = &iso2022_parser->g1; iso2022_parser->non_iso2022_cs = UNKNOWN_CS; iso2022_parser->is_single_shifted = 0; } static void euckr_parser_init(ef_parser_t *parser) { euckr_parser_init_intern(parser, KSC5601_1987); } static void uhc_parser_init(ef_parser_t *parser) { euckr_parser_init_intern(parser, UHC); } /* --- global functions --- */ ef_parser_t *ef_euckr_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } euckr_parser_init((ef_parser_t*)iso2022_parser); /* override */ iso2022_parser->parser.init = euckr_parser_init; return (ef_parser_t*)iso2022_parser; } ef_parser_t *ef_uhc_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } uhc_parser_init((ef_parser_t*)iso2022_parser); /* override */ iso2022_parser->parser.init = uhc_parser_init; iso2022_parser->parser.next_char = uhc_parser_next_char; return (ef_parser_t*)iso2022_parser; } mlterm-3.8.9/encodefilter/src/ef_euckr_parser.h010064400017600000144000000003571356600661000203030ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_EUCKR_PARSER_H__ #define __EF_EUCKR_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_euckr_parser_new(void); ef_parser_t *ef_uhc_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_euctw_conv.c010064400017600000144000000076151356600661000177710ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_euctw_conv.h" #include #include #include "ef_iso2022_conv.h" #include "ef_iso2022_intern.h" #include "ef_ucs4_map.h" #include "ef_zh_tw_map.h" /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { if (ef_map_ucs4_to_zh_tw(&c, ch)) { *ch = c; } } ef_iso2022_remap_unsupported_charset(ch); } static size_t convert_to_euctw(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { size_t filled_size; ef_char_t ch; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { remap_unsupported_charset(&ch); if (ch.cs == CNS11643_1992_1) { if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = MAP_TO_GR(ch.ch[0]); *(dst++) = MAP_TO_GR(ch.ch[1]); filled_size += 2; } else if (ch.cs == CNS11643_1992_2) { if (filled_size + 2 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = 0xa2; *(dst++) = MAP_TO_GR(ch.ch[0]); *(dst++) = MAP_TO_GR(ch.ch[1]); } else if (ch.cs == CNS11643_1992_3) { if (filled_size + 2 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = 0xa3; *(dst++) = MAP_TO_GR(ch.ch[0]); *(dst++) = MAP_TO_GR(ch.ch[1]); } else if (ch.cs == CNS11643_1992_4) { if (filled_size + 2 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = 0xa4; *(dst++) = MAP_TO_GR(ch.ch[0]); *(dst++) = MAP_TO_GR(ch.ch[1]); } else if (ch.cs == CNS11643_1992_5) { if (filled_size + 2 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = 0xa5; *(dst++) = MAP_TO_GR(ch.ch[0]); *(dst++) = MAP_TO_GR(ch.ch[1]); } else if (ch.cs == CNS11643_1992_6) { if (filled_size + 2 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = 0xa6; *(dst++) = MAP_TO_GR(ch.ch[0]); *(dst++) = MAP_TO_GR(ch.ch[1]); } else if (ch.cs == CNS11643_1992_7) { if (filled_size + 2 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = 0xa7; *(dst++) = MAP_TO_GR(ch.ch[0]); *(dst++) = MAP_TO_GR(ch.ch[1]); } else if (ch.cs == US_ASCII) { if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = *ch.ch; filled_size++; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } return filled_size; } static void conv_init(ef_conv_t *conv) { ef_iso2022_conv_t *iso2022_conv; iso2022_conv = (ef_iso2022_conv_t*)conv; iso2022_conv->gl = &iso2022_conv->g0; iso2022_conv->gr = &iso2022_conv->g1; iso2022_conv->g0 = US_ASCII; iso2022_conv->g1 = CNS11643_1992_EUCTW_G2; iso2022_conv->g2 = UNKNOWN_CS; iso2022_conv->g3 = UNKNOWN_CS; } static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_euctw_conv_new(void) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } conv_init((ef_conv_t*)iso2022_conv); iso2022_conv->conv.convert = convert_to_euctw; iso2022_conv->conv.init = conv_init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t*)iso2022_conv; } mlterm-3.8.9/encodefilter/src/ef_euctw_conv.h010064400017600000144000000002761356600661000177720ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_EUCTW_CONV_H__ #define __EF_EUCTW_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_euctw_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_euctw_parser.c010064400017600000144000000037751356600661000203230ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_euctw_parser.h" #include /* NULL */ #include #include "ef_iso2022_parser.h" #if 0 #define __DEBUG #endif /* --- static functions --- */ static int euctw_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { if (ef_iso2022_parser_next_char(parser, ch) == 0) { return 0; } if (ch->cs == CNS11643_1992_EUCTW_G2) { if (ch->ch[0] == 0xa2) { ch->cs = CNS11643_1992_2; } else if (ch->ch[0] == 0xa3) { ch->cs = CNS11643_1992_3; } else if (ch->ch[0] == 0xa4) { ch->cs = CNS11643_1992_4; } else if (ch->ch[0] == 0xa5) { ch->cs = CNS11643_1992_5; } else if (ch->ch[0] == 0xa6) { ch->cs = CNS11643_1992_6; } else if (ch->ch[0] == 0xa7) { ch->cs = CNS11643_1992_7; } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " %x is illegal euctw G2 tag.\n", ch->ch[0]); #endif ef_parser_reset(parser); return 0; } ch->ch[0] = ch->ch[1]; ch->ch[1] = ch->ch[2]; ch->size = 2; ch->property = 0; } return 1; } static void euctw_parser_init(ef_parser_t *parser) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t*)parser; iso2022_parser->g0 = US_ASCII; iso2022_parser->g1 = CNS11643_1992_1; iso2022_parser->g2 = CNS11643_1992_EUCTW_G2; iso2022_parser->g3 = UNKNOWN_CS; iso2022_parser->gl = &iso2022_parser->g0; iso2022_parser->gr = &iso2022_parser->g1; iso2022_parser->non_iso2022_cs = UNKNOWN_CS; iso2022_parser->is_single_shifted = 0; } /* --- global functions --- */ ef_parser_t *ef_euctw_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } euctw_parser_init((ef_parser_t*)iso2022_parser); /* override */ iso2022_parser->parser.init = euctw_parser_init; iso2022_parser->parser.next_char = euctw_parser_next_char; return (ef_parser_t*)iso2022_parser; } mlterm-3.8.9/encodefilter/src/ef_euctw_parser.h010064400017600000144000000003101356600661000203060ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_EUCTW_PARSER_H__ #define __EF_EUCTW_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_euctw_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_gb18030_2000_intern.c010064400017600000144000000046541356600661000206210ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_gb18030_2000_intern.h" typedef struct gb18030_range { u_int32_t u_first; u_int32_t u_last; u_char b_first[4]; u_char b_last[4]; } gb18030_range_t; #include "table/ef_gb18030_2000_range.table" /* --- static functions --- */ static u_int32_t bytes_to_linear(u_char *bytes /* should be 4 bytes. */ ) { return ((bytes[0] * 10 + bytes[1]) * 126 + bytes[2]) * 10 + bytes[3]; } static void linear_to_bytes(u_char *bytes, /* should be 4 bytes. */ u_int32_t linear) { linear -= bytes_to_linear((u_char *)"\x81\x30\x81\x30"); bytes[3] = 0x30 + linear % 10; linear /= 10; bytes[2] = 0x81 + linear % 126; linear /= 126; bytes[1] = 0x30 + linear % 10; linear /= 10; bytes[0] = 0x81 + linear; } /* --- global functions --- */ int ef_decode_gb18030_2000_to_ucs4(u_char *ucs4, /* should be 4 bytes. */ u_char *gb18030 /* should be 4 bytes. */ ) { int count; u_int32_t linear; u_int32_t ucs4_code; linear = bytes_to_linear(gb18030); for (count = 0; count < sizeof(gb18030_ranges) / sizeof(gb18030_ranges[0]); count++) { if (bytes_to_linear(gb18030_ranges[count].b_first) <= linear && linear <= bytes_to_linear(gb18030_ranges[count].b_last)) { ucs4_code = gb18030_ranges[count].u_first + (linear - bytes_to_linear(gb18030_ranges[count].b_first)); ucs4[0] = (ucs4_code >> 24) & 0xff; ucs4[1] = (ucs4_code >> 16) & 0xff; ucs4[2] = (ucs4_code >> 8) & 0xff; ucs4[3] = ucs4_code & 0xff; return 1; } } return 0; } int ef_encode_ucs4_to_gb18030_2000(u_char *gb18030, /* should be 4 bytes */ u_char *ucs4 /* should be 4 bytes */ ) { int count; u_int32_t ucs4_code; ucs4_code = ((ucs4[0] << 24) & 0xff000000) + ((ucs4[1] << 16) & 0xff0000) + ((ucs4[2] << 8) & 0xff00) + ucs4[3]; for (count = 0; count < sizeof(gb18030_ranges) / sizeof(gb18030_ranges[0]); count++) { if (gb18030_ranges[count].u_first <= ucs4_code && ucs4_code <= gb18030_ranges[count].u_last) { linear_to_bytes(gb18030, bytes_to_linear(gb18030_ranges[count].b_first) + (ucs4_code - gb18030_ranges[count].u_first)); return 1; } } return 0; } mlterm-3.8.9/encodefilter/src/ef_gb18030_2000_intern.h010064400017600000144000000005061356600661000206160ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_GB18030_2000_INTERN_H__ #define __EF_GB18030_2000_INTERN_H__ #include /* u_char */ int ef_decode_gb18030_2000_to_ucs4(u_char *ucs4, u_char *gb18030); int ef_encode_ucs4_to_gb18030_2000(u_char *gb18030, u_char *ucs4); #endif mlterm-3.8.9/encodefilter/src/ef_hz_conv.c010064400017600000144000000054071356600661000172600ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_hz_conv.h" #include /* NULL */ #include #include #include "ef_zh_cn_map.h" typedef struct ef_hz_conv { ef_conv_t conv; ef_charset_t cur_cs; } ef_hz_conv_t; /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { if (!ef_map_ucs4_to_zh_cn(&c, ch)) { return; } *ch = c; } if (ch->cs == GBK) { if (ef_map_gbk_to_gb2312_80(&c, ch)) { *ch = c; } } } static size_t convert_to_hz(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { ef_hz_conv_t *hz_conv; size_t filled_size; ef_char_t ch; int count; hz_conv = (ef_hz_conv_t *)conv; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { remap_unsupported_charset(&ch); if (ch.ch[0] == '~' && ch.cs == US_ASCII) { ch.ch[1] = '~'; ch.size = 2; } if (ch.cs == hz_conv->cur_cs) { if (filled_size + ch.size - 1 > dst_size) { ef_parser_full_reset(parser); return filled_size; } } else { hz_conv->cur_cs = ch.cs; if (ch.cs == GB2312_80) { if (filled_size + ch.size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = '~'; *(dst++) = '{'; filled_size += 2; } else if (ch.cs == US_ASCII) { if (filled_size + ch.size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = '~'; *(dst++) = '}'; filled_size += 2; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; continue; } else { continue; } } for (count = 0; count < ch.size; count++) { *(dst++) = ch.ch[count]; } filled_size += ch.size; } return filled_size; } static void conv_init(ef_conv_t *conv) { ef_hz_conv_t *hz_conv; hz_conv = (ef_hz_conv_t *)conv; hz_conv->cur_cs = US_ASCII; } static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_hz_conv_new(void) { ef_hz_conv_t *hz_conv; if ((hz_conv = malloc(sizeof(ef_hz_conv_t))) == NULL) { return NULL; } hz_conv->conv.convert = convert_to_hz; hz_conv->conv.init = conv_init; hz_conv->conv.destroy = conv_destroy; hz_conv->conv.illegal_char = NULL; hz_conv->cur_cs = US_ASCII; return (ef_conv_t *)hz_conv; } mlterm-3.8.9/encodefilter/src/ef_hz_conv.h010064400017600000144000000002651356600661000172620ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_HZ_CONV_H__ #define __EF_HZ_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_hz_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_hz_parser.c010064400017600000144000000060301356600661000176000ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_hz_parser.h" #include #include typedef struct ef_hz_parser { ef_parser_t parser; ef_charset_t cur_cs; } ef_hz_parser_t; /* --- static functions --- */ static void hz_parser_init(ef_parser_t *parser) { ef_hz_parser_t *hz_parser; ef_parser_init(parser); hz_parser = (ef_hz_parser_t*)parser; hz_parser->cur_cs = US_ASCII; } static void hz_parser_set_str(ef_parser_t *parser, u_char *str, size_t size) { parser->str = str; parser->left = size; parser->marked_left = 0; parser->is_eos = 0; } static void hz_parser_destroy(ef_parser_t *parser) { free(parser); } static int hz_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { ef_hz_parser_t *hz_parser; hz_parser = (ef_hz_parser_t*)parser; if (parser->is_eos) { return 0; } while (1) { ef_parser_mark(parser); if (*parser->str != '~') { /* is not tilda */ break; } else { if (ef_parser_increment(parser) == 0) { goto shortage; } } /* is tilda */ if (*parser->str == '~') { /* double tilda */ ch->ch[0] = *parser->str; ch->size = 1; ch->cs = US_ASCII; ch->property = 0; ef_parser_increment(parser); return 1; } else if (*parser->str == '{') { /* ~{ */ hz_parser->cur_cs = GB2312_80; } else if (*parser->str == '}') { /* ~} */ hz_parser->cur_cs = US_ASCII; } else if (*parser->str == '\n') { /* line continuation */ } else { /* * XXX * this is an illegal format(see rfc-1843) , but for the time being * the char of parser->str[-1](=='~') is output. */ ch->ch[0] = '~'; ch->size = 1; ch->cs = US_ASCII; ch->property = 0; /* already incremented. */ return 1; } if (ef_parser_increment(parser) == 0) { /* * a set of hz sequence was completely parsed , * so ef_parser_reset() is not executed here. */ return 0; } } if (/* 0x0 <= *parser->str && */ *parser->str <= 0x1f || hz_parser->cur_cs == US_ASCII) { /* control char */ ch->ch[0] = *parser->str; ch->size = 1; ch->cs = US_ASCII; } else /* if( hz_parser->cur_cs == GB2312_80) */ { ch->ch[0] = *parser->str; if (ef_parser_increment(parser) == 0) { goto shortage; } ch->ch[1] = *parser->str; ch->size = 2; ch->cs = GB2312_80; } ch->property = 0; ef_parser_increment(parser); return 1; shortage: ef_parser_reset(parser); return 0; } /* --- global functions --- */ ef_parser_t *ef_hz_parser_new(void) { ef_hz_parser_t *hz_parser; if ((hz_parser = malloc(sizeof(ef_hz_parser_t))) == NULL) { return NULL; } hz_parser_init((ef_parser_t*)hz_parser); hz_parser->parser.init = hz_parser_init; hz_parser->parser.set_str = hz_parser_set_str; hz_parser->parser.destroy = hz_parser_destroy; hz_parser->parser.next_char = hz_parser_next_char; return (ef_parser_t*)hz_parser; } mlterm-3.8.9/encodefilter/src/ef_hz_parser.h010064400017600000144000000002771356600661000176140ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_HZ_PARSER_H__ #define __EF_HZ_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_hz_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_iso2022_conv.c010064400017600000144000000107331356600661000177350ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_iso2022_conv.h" #include "ef_iso2022_intern.h" #include "ef_zh_cn_map.h" #include "ef_zh_tw_map.h" #include "ef_ko_kr_map.h" #include "ef_viet_map.h" #include "ef_ru_map.h" #include "ef_uk_map.h" #include "ef_tg_map.h" #include "ef_ucs4_map.h" /* --- static functions --- */ static size_t designate_to_g0(u_char *dst, size_t dst_size, int *is_full, ef_charset_t cs) { *is_full = 0; if (IS_CS94SB(cs)) { if (3 > dst_size) { *is_full = 1; return 0; } *(dst++) = '\x1b'; *(dst++) = '('; *(dst++) = CS94SB_FT(cs); return 3; } else if (IS_CS94MB(cs)) { if (4 > dst_size) { *is_full = 1; return 0; } *(dst++) = '\x1b'; *(dst++) = '$'; *(dst++) = '('; *(dst++) = CS94MB_FT(cs); return 4; } else if (IS_CS96SB(cs)) { if (3 > dst_size) { *is_full = 1; return 0; } *(dst++) = '\x1b'; *(dst++) = '-'; *(dst++) = CS96SB_FT(cs); return 3; } else if (IS_CS96MB(cs)) { if (4 > dst_size) { *is_full = 1; return 0; } *(dst++) = '\x1b'; *(dst++) = '$'; *(dst++) = '-'; *(dst++) = CS96MB_FT(cs); return 4; } /* error */ return 0; } /* --- global functions --- */ size_t ef_iso2022_illegal_char(ef_conv_t *conv, u_char *dst, size_t dst_size, int *is_full, ef_char_t *ch) { ef_iso2022_conv_t *iso2022_conv; size_t filled_size; size_t size; int count; iso2022_conv = (ef_iso2022_conv_t*)conv; *is_full = 0; if (!IS_CS_BASED_ON_ISO2022(ch->cs)) { /* error */ return 0; } filled_size = 0; /* * locking shift G0 to GL */ if (iso2022_conv->gl != &iso2022_conv->g0) { if (filled_size + 1 > dst_size) { *is_full = 1; return 0; } *(dst++) = LS0; filled_size++; } /* * designating ch->cs to G0. */ if ((size = designate_to_g0(dst, dst_size - filled_size, is_full, ch->cs)) == 0) { return 0; } dst += size; filled_size += size; /* * appending character bytes. */ if (filled_size + ch->size > dst_size) { *is_full = 1; return 0; } if (IS_CS94SB(ch->cs) || IS_CS94MB(ch->cs)) { for (count = 0; count < ch->size; count++) { *(dst++) = ch->ch[count]; } } else if (IS_CS96SB(ch->cs) || IS_CS96MB(ch->cs)) { for (count = 0; count < ch->size; count++) { *(dst++) = MAP_TO_GR(ch->ch[count]); } } else { /* error */ return 0; } filled_size += ch->size; /* * restoring GL */ if (iso2022_conv->gl == &iso2022_conv->g1) { if (filled_size + 1 > dst_size) { *is_full = 1; return 0; } *(dst++) = LS1; filled_size++; } else if (iso2022_conv->gl == &iso2022_conv->g2) { if (filled_size + 2 > dst_size) { *is_full = 1; return 0; } *(dst++) = ESC; *(dst++) = LS2; filled_size += 2; } else if (iso2022_conv->gl == &iso2022_conv->g3) { if (filled_size + 2 > dst_size) { *is_full = 1; return 0; } *(dst++) = ESC; *(dst++) = LS3; filled_size += 2; } /* * restoring G0 */ if ((size = designate_to_g0(dst, dst_size - filled_size, is_full, iso2022_conv->g0)) == 0) { return 0; } return filled_size + size; } void ef_iso2022_remap_unsupported_charset(ef_char_t *ch) { ef_char_t c; if (IS_CS_BASED_ON_ISO2022(ch->cs)) { /* do nothing */ } else if (ch->cs == ISO10646_UCS4_1) { if (ef_map_ucs4_to_iso2022cs(&c, ch)) { *ch = c; } } else if (ch->cs == VISCII) { if (ef_map_viscii_to_tcvn5712_3_1993(&c, ch)) { *ch = c; } } else if (ch->cs == KOI8_R) { if (ef_map_koi8_r_to_iso8859_5_r(&c, ch)) { *ch = c; } } else if (ch->cs == KOI8_U) { if (ef_map_koi8_u_to_iso8859_5_r(&c, ch)) { *ch = c; } } else if (ch->cs == KOI8_T) { if (ef_map_koi8_t_to_iso8859_5_r(&c, ch)) { *ch = c; } } else if (ch->cs == GBK) { if (ef_map_gbk_to_gb2312_80(&c, ch)) { *ch = c; } } else { if (ch->cs == JOHAB) { if (!ef_map_johab_to_uhc(&c, ch)) { return; } *ch = c; } if (ch->cs == UHC) { if (ef_map_uhc_to_ksc5601_1987(&c, ch)) { *ch = c; } return; } /* HKSCS includes BIG5 */ if (ch->cs == HKSCS) { ch->cs = BIG5; } if (ch->cs == BIG5) { if (ef_map_big5_to_cns11643_1992(&c, ch)) { *ch = c; } return; } } } mlterm-3.8.9/encodefilter/src/ef_iso2022_conv.h010064400017600000144000000011161356600661000177350ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ISO2022_CONV_H__ #define __EF_ISO2022_CONV_H__ #include /* size_t */ #include "ef_conv.h" typedef struct ef_iso2022_conv { ef_conv_t conv; ef_charset_t *gl; ef_charset_t *gr; ef_charset_t g0; ef_charset_t g1; ef_charset_t g2; ef_charset_t g3; } ef_iso2022_conv_t; size_t ef_iso2022_illegal_char(ef_conv_t *conv, u_char *dst, size_t dst_size, int *is_full, ef_char_t *ch); void ef_iso2022_remap_unsupported_charset(ef_char_t *ch); #endif mlterm-3.8.9/encodefilter/src/ef_iso2022_intern.h010064400017600000144000000021401356600661000202650ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ISO2022_INTERN_H__ #define __EF_ISO2022_INTERN_H__ #define ESC 0x1b #define SS2 0x8e #define SS3 0x8f /* these should be preceded by ESC */ #define SS2_7 0x4e #define SS3_7 0x4f #define LS0 0x0f #define LS1 0x0e /* these should be preceded by ESC */ #define LS2 0x6e #define LS3 0x6f #define LS1R 0x7e #define LS2R 0x7d #define LS3R 0x7c /* this should be preceded by ESC */ #define MB_CS '$' /* these should be preceded by ESC(+MB_CS) */ #define CS94_TO_G0 '(' #define CS94_TO_G1 ')' #define CS94_TO_G2 '*' #define CS94_TO_G3 '+' #define CS96_TO_G1 '-' #define CS96_TO_G2 '.' #define CS96_TO_G3 '/' /* this should be preceded by ESC */ #define CS_REV '&' /* this should be preceded by ESC+CS_REV */ #define REV_NUM(c) ((u_char)(c) - '@' + 1) /* these should be preceded by ESC */ #define NON_ISO2022_CS '%' /* these should be preceded by ESC + NON_ISO2022_CS */ #define NON_ISO2022_CS_2 '/' /* MSB (most significant bit) on/off */ #define MAP_TO_GR(c) (((u_char)c) | 0x80) #define UNMAP_FROM_GR(c) (((u_char)c) & 0x7f) #endif mlterm-3.8.9/encodefilter/src/ef_iso2022_parser.c010064400017600000144000000356741356600661000202770ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_iso2022_parser.h" #include /* strncmp/memset */ #include #include #include "ef_iso2022_intern.h" #include "ef_jis_property.h" #define IS_C0(c) ((u_char)c <= 0x1f) #define IS_C1(c) (0x80 <= (u_char)c && (u_char)c <= 0x9f) #define IS_GL(c) (0x20 <= (u_char)c && (u_char)c <= 0x7f) /* msb is 0 */ #define IS_GR(c) (0xa0 <= (u_char)c && (u_char)c <= 0xff) /* msb is 1 */ #define IS_INTERMEDIATE(c) (0x20 <= (u_char)c && (u_char)c <= 0x2f) #define IS_FT(c) ((0x30 <= ((u_char)c) && ((u_char)c) <= 0x7e)) #define IS_ESCAPE(c) ((((u_char)c) & 0x7e) == 0x0e || ((u_char)c) == 0x1b) /* --- static functions --- */ inline static size_t get_cs_bytelen(ef_charset_t cs) { if (IS_CS94SB(cs) || IS_CS96SB(cs)) { return 1; } else if (IS_CS94MB(cs) || IS_CS96MB(cs)) { if (cs == CNS11643_1992_EUCTW_G2) { return 3; } else { /* * XXX * there may be more exceptions ... */ return 2; } } else if (cs == ISO10646_UCS2_1) { return 2; } else if (cs == ISO10646_UCS4_1) { return 4; } /* * for XCTEXT extensions. */ else if (cs == BIG5 || cs == GBK) { return 2; } else if (IS_ISCII(cs) || cs == KOI8_R || cs == KOI8_U || cs == VISCII) { return 1; } return 0; } inline static ef_charset_t get_charset(u_char ft, /* 0x30 - 0x7f */ int is_mb, int glyph_size, /* 94 or 96 */ int rev) { ef_charset_t cs; if (glyph_size == 94) { if (is_mb) { cs = CS94MB_ID(ft); } else { cs = CS94SB_ID(ft); } } else if (glyph_size == 96) { if (is_mb) { cs = CS96MB_ID(ft); } else { cs = CS96SB_ID(ft); } } else { return UNKNOWN_CS; } if (rev == 0) { return cs; } else if (rev == 1) { return CS_REVISION_1(cs); } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " unsupported charset revision.\n"); #endif return UNKNOWN_CS; } } static int parse_escape(ef_iso2022_parser_t *iso2022_parser, ef_char_t *ch /* if single shifted ch->cs is set , otherwise this is not touched. */ ) { ef_parser_mark(iso2022_parser); if (*iso2022_parser->parser.str == SS2) { ch->cs = iso2022_parser->g2; iso2022_parser->is_single_shifted = 1; } else if (*iso2022_parser->parser.str == SS3) { ch->cs = iso2022_parser->g3; iso2022_parser->is_single_shifted = 1; } else if (*iso2022_parser->parser.str == LS0) { iso2022_parser->gl = &iso2022_parser->g0; } else if (*iso2022_parser->parser.str == LS1) { #ifdef DECSP_HACK static ef_charset_t decsp = DEC_SPECIAL; if (iso2022_parser->g1_is_decsp) { iso2022_parser->gl = &decsp; } else #endif { iso2022_parser->gl = &iso2022_parser->g1; } } else if (*iso2022_parser->parser.str == ESC) { if (ef_parser_increment(iso2022_parser) == 0) { /* we reach eos */ goto reset; } if (*iso2022_parser->parser.str == SS2_7) { ch->cs = iso2022_parser->g2; iso2022_parser->is_single_shifted = 1; } else if (*iso2022_parser->parser.str == SS3_7) { ch->cs = iso2022_parser->g3; iso2022_parser->is_single_shifted = 1; } else { if (*iso2022_parser->parser.str == LS2) { iso2022_parser->gl = &iso2022_parser->g2; } else if (*iso2022_parser->parser.str == LS3) { iso2022_parser->gl = &iso2022_parser->g3; } else if (*iso2022_parser->parser.str == LS1R) { iso2022_parser->gr = &iso2022_parser->g1; } else if (*iso2022_parser->parser.str == LS2R) { iso2022_parser->gr = &iso2022_parser->g2; } else if (*iso2022_parser->parser.str == LS3R) { iso2022_parser->gr = &iso2022_parser->g3; } else if (*iso2022_parser->parser.str == NON_ISO2022_CS) { int is_class_2; ef_charset_t cs; if (ef_parser_increment(iso2022_parser) == 0) { /* we reach eos */ goto reset; } if (*iso2022_parser->parser.str == NON_ISO2022_CS_2) { if (ef_parser_increment(iso2022_parser) == 0) { /* we reach eos. */ goto reset; } is_class_2 = 1; } else { is_class_2 = 0; } if (!IS_FT(*iso2022_parser->parser.str)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " illegal ft (ESC - % - I - %x)\n", *iso2022_parser->parser.str); #endif ef_parser_increment(iso2022_parser); return 0; } if (is_class_2) { cs = NON_ISO2022_2_ID(*iso2022_parser->parser.str); } else { cs = NON_ISO2022_1_ID(*iso2022_parser->parser.str); } if (ef_parser_increment(iso2022_parser) == 0) { /* we reach eos */ goto reset; } if (iso2022_parser->non_iso2022_is_started) { iso2022_parser->non_iso2022_cs = cs; return (*iso2022_parser->non_iso2022_is_started)(iso2022_parser); } else { /* ignored */ } } else if (IS_INTERMEDIATE(*iso2022_parser->parser.str)) { int is_mb; int rev; u_char to_GN; u_char ft; if (*iso2022_parser->parser.str == CS_REV) { /* ESC - 2/6 - Ft ESC - I - Ft */ if (ef_parser_increment(iso2022_parser) == 0) { /* we reach eos */ goto reset; } if (REV_NUM(*iso2022_parser->parser.str) == 1) { rev = 1; } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " charset revisions except 1 is not supported.\n"); #endif ef_parser_increment(iso2022_parser); return 0; } if (ef_parser_increment(iso2022_parser) == 0) { /* we reach eos. */ goto reset; } if (*iso2022_parser->parser.str != ESC) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " ESC & Ft should follow ESC I Ft.\n"); #endif ef_parser_increment(iso2022_parser); return 0; } if (ef_parser_increment(iso2022_parser) == 0) { /* we reach eos. */ goto reset; } } else { rev = 0; } if (*iso2022_parser->parser.str == MB_CS) { is_mb = 1; if (ef_parser_increment(iso2022_parser) == 0) { /* we reach eos */ goto reset; } } else { is_mb = 0; } if (is_mb && IS_FT(*iso2022_parser->parser.str)) { /* backward compatibility */ to_GN = CS94_TO_G0; ft = *iso2022_parser->parser.str; } else { to_GN = *iso2022_parser->parser.str; if (ef_parser_increment(iso2022_parser) == 0) { /* we reach eos. */ goto reset; } if (*iso2022_parser->parser.str == ' ') { /* is DRCS */ if (ef_parser_increment(iso2022_parser) == 0) { /* we reach eos */ goto reset; } } if (!IS_FT(*iso2022_parser->parser.str)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " illegal ft(ESC - I - %x %x)\n", to_GN, *iso2022_parser->parser.str); #endif ef_parser_increment(iso2022_parser); return 0; } ft = *iso2022_parser->parser.str; } if (to_GN == CS94_TO_G0) { iso2022_parser->g0 = get_charset(ft, is_mb, 94, rev); } else if (to_GN == CS94_TO_G1) { #ifdef DECSP_HACK if (ft == '0' && !is_mb) { iso2022_parser->g1_is_decsp = 1; } else #endif { #ifdef DECSP_HACK iso2022_parser->g1_is_decsp = 0; #endif iso2022_parser->g1 = get_charset(ft, is_mb, 94, rev); } } else if (to_GN == CS94_TO_G2) { iso2022_parser->g2 = get_charset(ft, is_mb, 94, rev); } else if (to_GN == CS94_TO_G3) { iso2022_parser->g3 = get_charset(ft, is_mb, 94, rev); } else if (to_GN == CS96_TO_G1) { #ifdef DECSP_HACK iso2022_parser->g1_is_decsp = 0; #endif iso2022_parser->g1 = get_charset(ft, is_mb, 96, rev); } else if (to_GN == CS96_TO_G2) { iso2022_parser->g2 = get_charset(ft, is_mb, 96, rev); } else if (to_GN == CS96_TO_G3) { iso2022_parser->g3 = get_charset(ft, is_mb, 96, rev); } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " illegal ISO2022 designation char %c\n", to_GN); #endif /* No increment in case VT100 sequence like "ESC # 8" */ #if 0 ef_parser_increment(iso2022_parser); #else ef_parser_reset(iso2022_parser); #endif return 0; } } else { /* not ISO2022 intermediate char */ goto reset; } } } else { /* error. this is not escape sequence. */ goto reset; } ef_parser_increment(iso2022_parser); return 1; reset: ef_parser_reset(iso2022_parser); return 0; } static int next_byte(ef_iso2022_parser_t *iso2022_parser, ef_char_t *ch) { if (iso2022_parser->parser.is_eos) { ef_parser_reset(iso2022_parser); ch->size = 0; return 0; } else if (IS_NON_ISO2022(iso2022_parser->non_iso2022_cs)) { if (iso2022_parser->next_non_iso2022_byte && (*iso2022_parser->next_non_iso2022_byte)(iso2022_parser, ch)) { return 1; } else { iso2022_parser->non_iso2022_cs = UNKNOWN_CS; return next_byte(iso2022_parser, ch); } } else if (IS_ESCAPE(*iso2022_parser->parser.str)) { if (!parse_escape(iso2022_parser, ch)) { return 0; } return next_byte(iso2022_parser, ch); } else if (iso2022_parser->is_single_shifted) { ch->ch[ch->size++] = UNMAP_FROM_GR(*iso2022_parser->parser.str); } else { if (IS_C0(*iso2022_parser->parser.str) || IS_C1(*iso2022_parser->parser.str)) { ch->ch[ch->size++] = *iso2022_parser->parser.str; ch->cs = US_ASCII; } else if (IS_GL(*(iso2022_parser->parser.str))) { if (!iso2022_parser->gl) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " gl is not set.\n"); #endif ef_parser_increment(iso2022_parser); return next_byte(iso2022_parser, ch); } ch->ch[ch->size++] = *iso2022_parser->parser.str; if ((IS_CS94SB(*iso2022_parser->gl) || IS_CS94MB(*iso2022_parser->gl)) && (*iso2022_parser->parser.str == 0x20 || *iso2022_parser->parser.str == 0x7f)) { ch->cs = US_ASCII; } else { ch->cs = *iso2022_parser->gl; } } else { if (!iso2022_parser->gr) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " gr is not set.\n"); #endif ef_parser_increment(iso2022_parser); return next_byte(iso2022_parser, ch); } if ((IS_CS94SB(*iso2022_parser->gr) || IS_CS94MB(*iso2022_parser->gr)) && (*iso2022_parser->parser.str == 0xa0 || *iso2022_parser->parser.str == 0xff)) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " 0xa0/0xff appears in 94CS. skipping...\n"); #endif ef_parser_increment(iso2022_parser); return next_byte(iso2022_parser, ch); } else { ch->ch[ch->size++] = UNMAP_FROM_GR(*iso2022_parser->parser.str); ch->cs = *iso2022_parser->gr; } } } ef_parser_increment(iso2022_parser); return 1; } static int sub_next_char(ef_iso2022_parser_t *iso2022_parser, ef_char_t *ch) { size_t bytelen; ef_charset_t cs; iso2022_parser->is_single_shifted = 0; while (1) { /* initialize */ memset(ch, 0, sizeof(ef_char_t)); ef_parser_mark(iso2022_parser); if (!next_byte(iso2022_parser, ch)) { return 0; } cs = ch->cs; if ((bytelen = get_cs_bytelen(cs)) > 0) { break; } } while (1) { if (ch->size > bytelen) { #ifdef DEBUG bl_debug_printf(BL_DEBUG_TAG " Char size(%d) and char byte len(%d) of cs(%x) is illegal. This" " may cause unexpected error. Parsing the sequence stopped.\n", ch->size, bytelen, cs); #endif return 0; } else if (ch->size == bytelen) { #if 0 if (ch->cs == JISX0208_1983 || ch->cs == JISC6226_1978) { /* * XXX * we should check gaiji here and replace JISX0208 or JISC6226_1978 * by it. */ } #endif return 1; } if (!next_byte(iso2022_parser, ch)) { return 0; } if (cs != ch->cs) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " prev byte cs(%x) and cur byte cs(%x) are not the same , strange !" " ignoring this char.\n", cs, ch->cs); #endif return sub_next_char(iso2022_parser, ch); } } } static void iso2022_parser_init(ef_parser_t *parser) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t *)parser; iso2022_parser->g0 = UNKNOWN_CS; iso2022_parser->g1 = UNKNOWN_CS; iso2022_parser->g2 = UNKNOWN_CS; iso2022_parser->g3 = UNKNOWN_CS; iso2022_parser->gl = NULL; iso2022_parser->gr = NULL; iso2022_parser->non_iso2022_cs = UNKNOWN_CS; iso2022_parser->is_single_shifted = 0; #ifdef DECSP_HACK iso2022_parser->g1_is_decsp = 0; #endif } /* --- global functions --- */ ef_iso2022_parser_t *ef_iso2022_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = malloc(sizeof(ef_iso2022_parser_t))) == NULL) { return NULL; } ef_iso2022_parser_init_func(iso2022_parser); iso2022_parser_init((ef_parser_t *)iso2022_parser); return iso2022_parser; } void ef_iso2022_parser_init_func(ef_iso2022_parser_t *iso2022_parser) { iso2022_parser->non_iso2022_is_started = NULL; iso2022_parser->next_non_iso2022_byte = NULL; iso2022_parser->parser.init = iso2022_parser_init; iso2022_parser->parser.set_str = ef_iso2022_parser_set_str; iso2022_parser->parser.destroy = ef_iso2022_parser_destroy; iso2022_parser->parser.next_char = ef_iso2022_parser_next_char; } void ef_iso2022_parser_set_str(ef_parser_t *parser, u_char *str, size_t size) { parser->str = str; parser->left = size; parser->marked_left = 0; parser->is_eos = 0; } void ef_iso2022_parser_destroy(ef_parser_t *parser) { free(parser); } int ef_iso2022_parser_next_char(ef_parser_t *parser, ef_char_t *ch) { if (sub_next_char((ef_iso2022_parser_t *)parser, ch) == 0) { return 0; } if (ch->cs == JISX0208_1983) { ch->property = ef_get_jisx0208_1983_property(ch->ch); } else if (ch->cs == JISX0213_2000_1) { ch->property = ef_get_jisx0213_2000_1_property(ch->ch); } else if (ch->cs == TCVN5712_1_1993) { if (0x30 <= ch->ch[0] && ch->ch[0] <= 0x34) { ch->property = EF_COMBINING; } } else if (ch->cs == TIS620_2533) { if (ch->ch[0] == 0x51 || (0x54 <= ch->ch[0] && ch->ch[0] <= 0x5a) || (0x67 <= ch->ch[0] && ch->ch[0] <= 0x6e)) { ch->property = EF_COMBINING; } } else { ch->property = 0; } return 1; } mlterm-3.8.9/encodefilter/src/ef_iso2022_parser.h010064400017600000144000000023731356600661000202720ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ISO2022_PARSER_H__ #define __EF_ISO2022_PARSER_H__ #include /* size_t */ #include "ef_parser.h" /* * If enacs=\E(B\E)0,smacs=^N,rmacs=^O, G1 of current encoding is unexpectedly * changed * by enacs. DECSP_HACK is a hack to avoid this problem. (If * enacs=,smacs=\E(0,rmacs=\E(B, * no problem.) * (enacs:initialize, smacs: start decsp, rmacs: end decsp) */ #if 1 #define DECSP_HACK #endif typedef struct ef_iso2022_parser { ef_parser_t parser; ef_charset_t *gl; ef_charset_t *gr; ef_charset_t g0; ef_charset_t g1; ef_charset_t g2; ef_charset_t g3; ef_charset_t non_iso2022_cs; #ifdef DECSP_HACK int8_t g1_is_decsp; #endif int8_t is_single_shifted; int (*non_iso2022_is_started)(struct ef_iso2022_parser *); int (*next_non_iso2022_byte)(struct ef_iso2022_parser *, ef_char_t *); } ef_iso2022_parser_t; ef_iso2022_parser_t *ef_iso2022_parser_new(void); void ef_iso2022_parser_init_func(ef_iso2022_parser_t *iso2022_parser); void ef_iso2022_parser_set_str(ef_parser_t *parser, u_char *str, size_t size); void ef_iso2022_parser_destroy(ef_parser_t *parser); int ef_iso2022_parser_next_char(ef_parser_t *parser, ef_char_t *ch); #endif mlterm-3.8.9/encodefilter/src/ef_iso2022cn_conv.c010064400017600000144000000105011356600661000202470ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_iso2022cn_conv.h" #include #include #include "ef_iso2022_intern.h" #include "ef_iso2022_conv.h" #include "ef_ucs4_map.h" #include "ef_zh_cn_map.h" #include "ef_zh_tw_map.h" /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { if (ef_map_ucs4_to_zh_cn(&c, ch)) { *ch = c; } else if (ef_map_ucs4_to_zh_tw(&c, ch)) { *ch = c; } } ef_iso2022_remap_unsupported_charset(ch); } static size_t convert_to_iso2022cn(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { ef_iso2022_conv_t *iso2022_conv; size_t filled_size; ef_char_t ch; int count; iso2022_conv = (ef_iso2022_conv_t*)conv; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { remap_unsupported_charset(&ch); if (ch.cs == *iso2022_conv->gl) { if (filled_size + ch.size > dst_size) { ef_parser_full_reset(parser); return filled_size; } if (ch.cs == US_ASCII && ch.ch[0] == '\n') { /* reset */ iso2022_conv->g1 = UNKNOWN_CS; iso2022_conv->g2 = UNKNOWN_CS; } } else if (ch.cs == CNS11643_1992_2) { /* single shifted */ if (iso2022_conv->g2 != CNS11643_1992_2) { if (filled_size + ch.size + 6 > dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ESC; *(dst++) = MB_CS; *(dst++) = CS94_TO_G2; *(dst++) = CS94MB_FT(CNS11643_1992_2); *(dst++) = ESC; *(dst++) = SS2_7; filled_size += 6; iso2022_conv->g2 = CNS11643_1992_2; } else { if (filled_size + ch.size + 2 > dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ESC; *(dst++) = SS2_7; filled_size += 2; } } else if (ch.cs == CNS11643_1992_1 || ch.cs == GB2312_80) { if (iso2022_conv->g1 != ch.cs) { if (filled_size + ch.size + 5 > dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ESC; *(dst++) = MB_CS; *(dst++) = CS94_TO_G1; *(dst++) = CS94MB_FT(ch.cs); *(dst++) = LS1; filled_size += 5; iso2022_conv->g1 = ch.cs; } else { if (filled_size + ch.size + 1 > dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = LS1; filled_size++; } iso2022_conv->gl = &iso2022_conv->g1; } else if (ch.cs == US_ASCII) { if (filled_size + ch.size + 1 > dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = LS0; filled_size++; if (ch.ch[0] == '\n') { /* reset */ iso2022_conv->g1 = UNKNOWN_CS; iso2022_conv->g2 = UNKNOWN_CS; } iso2022_conv->gl = &iso2022_conv->g0; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; continue; } else { continue; } for (count = 0; count < ch.size; count++) { *(dst++) = ch.ch[count]; } filled_size += ch.size; } return filled_size; } static void conv_init(ef_conv_t *conv) { ef_iso2022_conv_t *iso2022_conv; iso2022_conv = (ef_iso2022_conv_t*)conv; iso2022_conv->gl = &iso2022_conv->g0; iso2022_conv->gr = NULL; iso2022_conv->g0 = US_ASCII; iso2022_conv->g1 = UNKNOWN_CS; iso2022_conv->g2 = UNKNOWN_CS; } static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_iso2022cn_conv_new(void) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } conv_init((ef_conv_t*)iso2022_conv); iso2022_conv->conv.convert = convert_to_iso2022cn; iso2022_conv->conv.init = conv_init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t*)iso2022_conv; } mlterm-3.8.9/encodefilter/src/ef_iso2022cn_conv.h010064400017600000144000000003121356600661000202530ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ISO2022CN_CONV_H__ #define __EF_ISO2022CN_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_iso2022cn_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_iso2022cn_parser.c010064400017600000144000000021001356600661000205720ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_iso2022cn_parser.h" #include /* NULL */ #include "ef_iso2022_parser.h" /* --- static functions --- */ static void iso2022cn_parser_init(ef_parser_t *parser) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t*)parser; iso2022_parser->g0 = US_ASCII; iso2022_parser->g1 = UNKNOWN_CS; /* CNS11643_1 or GB2312 */ iso2022_parser->g2 = UNKNOWN_CS; /* CNS11643_2 */ iso2022_parser->g3 = UNKNOWN_CS; iso2022_parser->gl = &iso2022_parser->g0; iso2022_parser->gr = NULL; iso2022_parser->non_iso2022_cs = UNKNOWN_CS; iso2022_parser->is_single_shifted = 0; } /* --- global functions --- */ ef_parser_t *ef_iso2022cn_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } iso2022cn_parser_init((ef_parser_t*)iso2022_parser); /* override */ iso2022_parser->parser.init = iso2022cn_parser_init; return (ef_parser_t*)iso2022_parser; } mlterm-3.8.9/encodefilter/src/ef_iso2022cn_parser.h010064400017600000144000000003241356600661000206050ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ISO2022CN_PARSER_H__ #define __EF_ISO2022CN_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_iso2022cn_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_iso2022jp_conv.c010064400017600000144000000211571356600661000202710ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_iso2022jp_conv.h" #include /* NULL */ #include #include #include "ef_iso2022_conv.h" #include "ef_iso2022_intern.h" #include "ef_ucs4_map.h" #include "ef_ja_jp_map.h" /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch, int version) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { if (ef_map_ucs4_to_ja_jp(&c, ch)) { *ch = c; } } ef_iso2022_remap_unsupported_charset(ch); /* * various gaiji chars => jis */ if (ch->cs == SJIS_IBM_EXT) { /* * IBM extension characters cannot be regarded as * jisc6226_1978/jisx0208_1983 * gaiji (which is based on iso2022 94n charset) , so we managed to remap * here. */ if (!ef_map_sjis_ibm_ext_to_jisx0208_1983(&c, ch) && !ef_map_sjis_ibm_ext_to_jisx0212_1990(&c, ch)) { return; } *ch = c; } /* * NEC special characters and NEC selected IBM characters are exactly in gaiji * area * of jisc6226_1978 , and MAC extension charcters are also in gaiji area of * jisx0208_1983 , so we do not remap these. */ else if (ch->cs == JISC6226_1978_NEC_EXT || ch->cs == JISC6226_1978_NECIBM_EXT) { ch->cs = JISC6226_1978; } else if (ch->cs == JISX0208_1983_MAC_EXT) { ch->cs = JISX0208_1983; } /* * conversion between JIS charsets. */ if (version == 3) { if (ch->cs == JISX0208_1983) { if (ef_map_jisx0208_1983_to_jisx0213_2000_1(&c, ch)) { *ch = c; } } } else { if (ch->cs == JISX0213_2000_1) { if (ef_map_jisx0213_2000_1_to_jisx0208_1983(&c, ch)) { *ch = c; } } } } static size_t convert_to_iso2022jp(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser, int is_7, int version) { ef_iso2022_conv_t *iso2022_conv; size_t filled_size; ef_char_t ch; iso2022_conv = (ef_iso2022_conv_t*)conv; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { remap_unsupported_charset(&ch, version); if ((!is_7) && ch.cs == JISX0201_KATA) { if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = MAP_TO_GR(*ch.ch); filled_size++; } else { int count; if (ch.cs == iso2022_conv->g0) { if (filled_size + ch.size > dst_size) { ef_parser_full_reset(parser); return filled_size; } } else { if (ch.cs == JISX0208_1983 || (version <= 2 && ch.cs == JISC6226_1978) || /* GB2312_80 for ISO2022JP-2(rfc1154) */ (version == 2 && ch.cs == GB2312_80)) { #if 1 /* based on old iso2022 */ if (filled_size + ch.size + 2 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ESC; *(dst++) = MB_CS; *(dst++) = CS94MB_FT(ch.cs); filled_size += 3; #else /* based on new iso2022 */ if (filled_size + ch.size + 3 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ESC; *(dst++) = MB_CS; *(dst++) = CS94_TO_G0; *(dst++) = CS94MB_FT(ch.cs); filled_size += 4; #endif } else if (ch.cs == JISX0212_1990 || /* KSC5601_1987 for ISO2022JP-2(rfc1154) */ (version == 2 && ch.cs == KSC5601_1987) || (version >= 3 && (ch.cs == JISX0213_2000_1 || ch.cs == JISX0213_2000_2))) { if (filled_size + ch.size + 3 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ESC; *(dst++) = MB_CS; *(dst++) = CS94_TO_G0; *(dst++) = CS94MB_FT(ch.cs); filled_size += 4; } else if (ch.cs == US_ASCII || (version <= 2 && (ch.cs == JISX0201_ROMAN || ch.cs == JISX0201_KATA))) { if (filled_size + ch.size + 2 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ESC; *(dst++) = CS94_TO_G0; *(dst++) = CS94SB_FT(ch.cs); filled_size += 3; } else if (version >= 2 && (ch.cs == ISO8859_1_R || ch.cs == ISO8859_7_R)) { /* for ISO2022JP-2(rfc1154) */ if (filled_size + ch.size + 2 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ESC; *(dst++) = CS96_TO_G2; *(dst++) = CS96SB_FT(ch.cs); filled_size += 3; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; continue; } else { continue; } iso2022_conv->g0 = ch.cs; } for (count = 0; count < ch.size; count++) { *(dst++) = ch.ch[count]; } filled_size += ch.size; } } return filled_size; } static size_t convert_to_iso2022jp_8(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_iso2022jp(conv, dst, dst_size, parser, 0, 1); } static size_t convert_to_iso2022jp_7(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_iso2022jp(conv, dst, dst_size, parser, 1, 1); } static size_t convert_to_iso2022jp2(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_iso2022jp(conv, dst, dst_size, parser, 1, 2); } static size_t convert_to_iso2022jp3(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_iso2022jp(conv, dst, dst_size, parser, 1, 3); } static void iso2022jp_7_conv_init(ef_conv_t *conv) { ef_iso2022_conv_t *iso2022_conv; iso2022_conv = (ef_iso2022_conv_t*)conv; iso2022_conv->gl = &iso2022_conv->g0; iso2022_conv->gr = NULL; iso2022_conv->g0 = US_ASCII; iso2022_conv->g1 = UNKNOWN_CS; iso2022_conv->g2 = UNKNOWN_CS; iso2022_conv->g3 = UNKNOWN_CS; } static void iso2022jp_8_conv_init(ef_conv_t *conv) { ef_iso2022_conv_t *iso2022_conv; iso2022_conv = (ef_iso2022_conv_t*)conv; iso2022_conv->gl = &iso2022_conv->g0; iso2022_conv->gr = &iso2022_conv->g1; iso2022_conv->g0 = US_ASCII; iso2022_conv->g1 = JISX0201_KATA; iso2022_conv->g2 = UNKNOWN_CS; iso2022_conv->g3 = UNKNOWN_CS; } static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_iso2022jp_8_conv_new(void) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } iso2022jp_8_conv_init((ef_conv_t*)iso2022_conv); iso2022_conv->conv.convert = convert_to_iso2022jp_8; iso2022_conv->conv.init = iso2022jp_8_conv_init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t*)iso2022_conv; } ef_conv_t *ef_iso2022jp_7_conv_new(void) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } iso2022jp_7_conv_init((ef_conv_t*)iso2022_conv); iso2022_conv->conv.convert = convert_to_iso2022jp_7; iso2022_conv->conv.init = iso2022jp_7_conv_init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t*)iso2022_conv; } ef_conv_t *ef_iso2022jp2_conv_new(void) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } iso2022jp_7_conv_init((ef_conv_t*)iso2022_conv); iso2022_conv->conv.convert = convert_to_iso2022jp2; iso2022_conv->conv.init = iso2022jp_7_conv_init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t*)iso2022_conv; } ef_conv_t *ef_iso2022jp3_conv_new(void) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } iso2022jp_7_conv_init((ef_conv_t*)iso2022_conv); iso2022_conv->conv.convert = convert_to_iso2022jp3; iso2022_conv->conv.init = iso2022jp_7_conv_init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t*)iso2022_conv; } mlterm-3.8.9/encodefilter/src/ef_iso2022jp_conv.h010064400017600000144000000005131356600661000202670ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ISO2022JP_CONV_H__ #define __EF_ISO2022JP_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_iso2022jp_7_conv_new(void); ef_conv_t *ef_iso2022jp_8_conv_new(void); ef_conv_t *ef_iso2022jp2_conv_new(void); ef_conv_t *ef_iso2022jp3_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_iso2022jp_parser.c010064400017600000144000000064511356600661000206200ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_iso2022jp_parser.h" #include /* NULL */ #include #include "ef_iso2022_parser.h" /* --- static functions --- */ static void iso2022jp_8_parser_init(ef_parser_t *parser) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t*)parser; iso2022_parser->g0 = US_ASCII; iso2022_parser->g1 = JISX0201_KATA; iso2022_parser->g2 = UNKNOWN_CS; iso2022_parser->g3 = UNKNOWN_CS; iso2022_parser->gl = &iso2022_parser->g0; iso2022_parser->gr = &iso2022_parser->g1; iso2022_parser->non_iso2022_cs = UNKNOWN_CS; iso2022_parser->is_single_shifted = 0; } static void iso2022jp_7_parser_init(ef_parser_t *parser) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t*)parser; iso2022_parser->g0 = US_ASCII; iso2022_parser->g1 = JISX0201_KATA; iso2022_parser->g2 = UNKNOWN_CS; iso2022_parser->g3 = UNKNOWN_CS; iso2022_parser->gl = &iso2022_parser->g0; iso2022_parser->is_single_shifted = 0; } static void iso2022jp2_parser_init(ef_parser_t *parser) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t*)parser; iso2022_parser->g0 = US_ASCII; iso2022_parser->g1 = UNKNOWN_CS; iso2022_parser->g2 = UNKNOWN_CS; iso2022_parser->g3 = UNKNOWN_CS; iso2022_parser->gl = &iso2022_parser->g0; iso2022_parser->gr = NULL; iso2022_parser->is_single_shifted = 0; } static void iso2022jp3_parser_init(ef_parser_t *parser) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t*)parser; iso2022_parser->g0 = US_ASCII; iso2022_parser->g1 = UNKNOWN_CS; iso2022_parser->g2 = UNKNOWN_CS; iso2022_parser->g3 = UNKNOWN_CS; iso2022_parser->gl = &iso2022_parser->g0; iso2022_parser->is_single_shifted = 0; } /* --- global functions --- */ ef_parser_t *ef_iso2022jp_8_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } iso2022jp_8_parser_init((ef_parser_t*)iso2022_parser); /* overwrite */ iso2022_parser->parser.init = iso2022jp_8_parser_init; return (ef_parser_t*)iso2022_parser; } ef_parser_t *ef_iso2022jp_7_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } iso2022jp_7_parser_init((ef_parser_t*)iso2022_parser); /* overwrite */ iso2022_parser->parser.init = iso2022jp_7_parser_init; return (ef_parser_t*)iso2022_parser; } ef_parser_t *ef_iso2022jp2_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } iso2022jp2_parser_init((ef_parser_t*)iso2022_parser); /* overwrite */ iso2022_parser->parser.init = iso2022jp2_parser_init; return (ef_parser_t*)iso2022_parser; } ef_parser_t *ef_iso2022jp3_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } iso2022jp3_parser_init((ef_parser_t*)iso2022_parser); /* overwrite */ iso2022_parser->parser.init = iso2022jp3_parser_init; return (ef_parser_t*)iso2022_parser; } mlterm-3.8.9/encodefilter/src/ef_iso2022jp_parser.h010064400017600000144000000005411356600661000206170ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ISO2022JP_PARSER_H__ #define __EF_ISO2022JP_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_iso2022jp_7_parser_new(void); ef_parser_t *ef_iso2022jp_8_parser_new(void); ef_parser_t *ef_iso2022jp2_parser_new(void); ef_parser_t *ef_iso2022jp3_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_iso2022kr_conv.c010064400017600000144000000071611356600661000202730ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_iso2022kr_conv.h" #include #include #include "ef_iso2022_conv.h" #include "ef_iso2022_intern.h" #include "ef_ucs4_map.h" #include "ef_ko_kr_map.h" typedef struct ef_iso2022kr_conv { ef_iso2022_conv_t iso2022_conv; int is_designated; } ef_iso2022kr_conv_t; /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { if (ef_map_ucs4_to_ko_kr(&c, ch)) { *ch = c; } } ef_iso2022_remap_unsupported_charset(ch); } static size_t convert_to_iso2022kr(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { ef_iso2022kr_conv_t *iso2022kr_conv; size_t filled_size; ef_char_t ch; iso2022kr_conv = (ef_iso2022kr_conv_t*)conv; filled_size = 0; if (!iso2022kr_conv->is_designated) { if (dst_size < 4) { return 0; } *(dst++) = ESC; *(dst++) = MB_CS; *(dst++) = CS94_TO_G1; *(dst++) = CS94MB_FT(KSC5601_1987); filled_size += 4; iso2022kr_conv->is_designated = 1; iso2022kr_conv->iso2022_conv.g1 = KSC5601_1987; } while (ef_parser_next_char(parser, &ch)) { int count; remap_unsupported_charset(&ch); if (ch.cs == *iso2022kr_conv->iso2022_conv.gl) { if (filled_size + ch.size > dst_size) { ef_parser_full_reset(parser); return filled_size; } } else { if (ch.cs == KSC5601_1987) { if (filled_size + ch.size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = LS1; filled_size++; iso2022kr_conv->iso2022_conv.gl = &iso2022kr_conv->iso2022_conv.g1; } else if (ch.cs == US_ASCII) { if (filled_size + ch.size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = LS0; filled_size++; iso2022kr_conv->iso2022_conv.gl = &iso2022kr_conv->iso2022_conv.g0; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; continue; } else { continue; } } for (count = 0; count < ch.size; count++) { *(dst++) = ch.ch[count]; } filled_size += ch.size; } return filled_size; } static void conv_init(ef_conv_t *conv) { ef_iso2022kr_conv_t *iso2022kr_conv; iso2022kr_conv = (ef_iso2022kr_conv_t*)conv; iso2022kr_conv->iso2022_conv.gl = &iso2022kr_conv->iso2022_conv.g0; iso2022kr_conv->iso2022_conv.gr = NULL; iso2022kr_conv->iso2022_conv.g0 = US_ASCII; iso2022kr_conv->iso2022_conv.g1 = UNKNOWN_CS; iso2022kr_conv->iso2022_conv.g2 = UNKNOWN_CS; iso2022kr_conv->iso2022_conv.g3 = UNKNOWN_CS; iso2022kr_conv->is_designated = 0; } static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_iso2022kr_conv_new(void) { ef_iso2022kr_conv_t *iso2022kr_conv; if ((iso2022kr_conv = malloc(sizeof(ef_iso2022kr_conv_t))) == NULL) { return NULL; } conv_init((ef_conv_t*)iso2022kr_conv); iso2022kr_conv->iso2022_conv.conv.convert = convert_to_iso2022kr; iso2022kr_conv->iso2022_conv.conv.init = conv_init; iso2022kr_conv->iso2022_conv.conv.destroy = conv_destroy; iso2022kr_conv->iso2022_conv.conv.illegal_char = NULL; return (ef_conv_t*)iso2022kr_conv; } mlterm-3.8.9/encodefilter/src/ef_iso2022kr_conv.h010064400017600000144000000003121356600661000202670ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ISO2022KR_CONV_H__ #define __EF_ISO2022KR_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_iso2022kr_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_iso2022kr_parser.c010064400017600000144000000021471356600661000206210ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_iso2022kr_parser.h" #include /* NULL */ #include #include "ef_iso2022_parser.h" /* --- static functions --- */ static void iso2022kr_parser_init(ef_parser_t *parser) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t*)parser; iso2022_parser->g0 = US_ASCII; #if 0 iso2022_parser->g1 = KSC5601_1987; #else iso2022_parser->g1 = UNKNOWN_CS; #endif iso2022_parser->g2 = UNKNOWN_CS; iso2022_parser->g3 = UNKNOWN_CS; iso2022_parser->gl = &iso2022_parser->g0; iso2022_parser->gr = NULL; iso2022_parser->non_iso2022_cs = UNKNOWN_CS; iso2022_parser->is_single_shifted = 0; } /* --- global functions --- */ ef_parser_t *ef_iso2022kr_parser_new(void) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } iso2022kr_parser_init((ef_parser_t*)iso2022_parser); /* override */ iso2022_parser->parser.init = iso2022kr_parser_init; return (ef_parser_t*)iso2022_parser; } mlterm-3.8.9/encodefilter/src/ef_iso2022kr_parser.h010064400017600000144000000003241356600661000206210ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ISO2022KR_PARSER_H__ #define __EF_ISO2022KR_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_iso2022kr_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_iso8859_conv.c010064400017600000144000000127141356600661000177660ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_iso8859_conv.h" #include /* NULL */ #include #include #include "ef_iso2022_conv.h" #include "ef_iso2022_intern.h" #include "ef_viet_map.h" #include "ef_ru_map.h" #include "ef_ucs4_iso8859.h" #include "ef_ucs4_map.h" /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch, ef_charset_t gr_cs) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { if (ef_map_ucs4_to_cs(&c, ch, gr_cs)) { *ch = c; return; } } ef_iso2022_remap_unsupported_charset(ch); } static size_t convert_to_iso8859(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { ef_iso2022_conv_t *iso2022_conv; size_t filled_size; ef_char_t ch; iso2022_conv = (ef_iso2022_conv_t *)conv; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { remap_unsupported_charset(&ch, iso2022_conv->g1); if (ch.cs == US_ASCII) { if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ch.ch[0]; filled_size++; } else if (ch.cs == iso2022_conv->g1) { if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = SET_MSB(ch.ch[0]); filled_size++; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } return filled_size; } static void conv_init_intern(ef_conv_t *conv, ef_charset_t g1) { ef_iso2022_conv_t *iso2022_conv; iso2022_conv = (ef_iso2022_conv_t *)conv; iso2022_conv->gl = &iso2022_conv->g0; iso2022_conv->gr = &iso2022_conv->g1; iso2022_conv->g0 = US_ASCII; iso2022_conv->g1 = g1; iso2022_conv->g2 = UNKNOWN_CS; iso2022_conv->g3 = UNKNOWN_CS; } static void conv_init_iso8859_1(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_1_R); } static void conv_init_iso8859_2(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_2_R); } static void conv_init_iso8859_3(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_3_R); } static void conv_init_iso8859_4(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_4_R); } static void conv_init_iso8859_5(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_5_R); } static void conv_init_iso8859_6(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_6_R); } static void conv_init_iso8859_7(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_7_R); } static void conv_init_iso8859_8(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_8_R); } static void conv_init_iso8859_9(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_9_R); } static void conv_init_iso8859_10(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_10_R); } static void conv_init_tis620_2533(ef_conv_t *conv) { conv_init_intern(conv, TIS620_2533); } static void conv_init_iso8859_13(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_13_R); } static void conv_init_iso8859_14(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_14_R); } static void conv_init_iso8859_15(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_15_R); } static void conv_init_iso8859_16(ef_conv_t *conv) { conv_init_intern(conv, ISO8859_16_R); } static void conv_init_tcvn5712_3_1993(ef_conv_t *conv) { conv_init_intern(conv, TCVN5712_3_1993); } static void conv_destroy(ef_conv_t *conv) { free(conv); } static ef_conv_t *iso8859_conv_new(void (*init)(ef_conv_t *)) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } (*init)((ef_conv_t *)iso2022_conv); iso2022_conv->conv.convert = convert_to_iso8859; iso2022_conv->conv.init = init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t *)iso2022_conv; } /* --- global functions --- */ ef_conv_t *ef_iso8859_1_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_1); } ef_conv_t *ef_iso8859_2_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_2); } ef_conv_t *ef_iso8859_3_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_3); } ef_conv_t *ef_iso8859_4_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_4); } ef_conv_t *ef_iso8859_5_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_5); } ef_conv_t *ef_iso8859_6_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_6); } ef_conv_t *ef_iso8859_7_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_7); } ef_conv_t *ef_iso8859_8_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_8); } ef_conv_t *ef_iso8859_9_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_9); } ef_conv_t *ef_iso8859_10_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_10); } ef_conv_t *ef_tis620_2533_conv_new(void) { return iso8859_conv_new(conv_init_tis620_2533); } ef_conv_t *ef_iso8859_13_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_13); } ef_conv_t *ef_iso8859_14_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_14); } ef_conv_t *ef_iso8859_15_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_15); } ef_conv_t *ef_iso8859_16_conv_new(void) { return iso8859_conv_new(conv_init_iso8859_16); } ef_conv_t *ef_tcvn5712_3_1993_conv_new(void) { return iso8859_conv_new(conv_init_tcvn5712_3_1993); } mlterm-3.8.9/encodefilter/src/ef_iso8859_conv.h010064400017600000144000000015211356600661000177650ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ISO8859_CONV_H__ #define __EF_ISO8859_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_iso8859_1_conv_new(void); ef_conv_t *ef_iso8859_2_conv_new(void); ef_conv_t *ef_iso8859_3_conv_new(void); ef_conv_t *ef_iso8859_4_conv_new(void); ef_conv_t *ef_iso8859_5_conv_new(void); ef_conv_t *ef_iso8859_6_conv_new(void); ef_conv_t *ef_iso8859_7_conv_new(void); ef_conv_t *ef_iso8859_8_conv_new(void); ef_conv_t *ef_iso8859_9_conv_new(void); ef_conv_t *ef_iso8859_10_conv_new(void); /* a.k.a ISO8859-11 */ ef_conv_t *ef_tis620_2533_conv_new(void); ef_conv_t *ef_iso8859_13_conv_new(void); ef_conv_t *ef_iso8859_14_conv_new(void); ef_conv_t *ef_iso8859_15_conv_new(void); ef_conv_t *ef_iso8859_16_conv_new(void); ef_conv_t *ef_tcvn5712_3_1993_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_iso8859_parser.c010064400017600000144000000104401356600661000203070ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_iso8859_parser.h" #include /* NULL */ #include #include "ef_iso2022_parser.h" /* --- static functions --- */ static void iso8859_parser_init(ef_parser_t *parser, ef_charset_t gr_cs) { ef_iso2022_parser_t *iso2022_parser; ef_parser_init(parser); iso2022_parser = (ef_iso2022_parser_t *)parser; iso2022_parser->g0 = US_ASCII; iso2022_parser->g1 = gr_cs; iso2022_parser->g2 = UNKNOWN_CS; iso2022_parser->g3 = UNKNOWN_CS; iso2022_parser->gl = &iso2022_parser->g0; iso2022_parser->gr = &iso2022_parser->g1; iso2022_parser->non_iso2022_cs = UNKNOWN_CS; iso2022_parser->is_single_shifted = 0; } static void iso8859_1_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_1_R); } static void iso8859_2_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_2_R); } static void iso8859_3_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_3_R); } static void iso8859_4_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_4_R); } static void iso8859_5_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_5_R); } static void iso8859_6_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_6_R); } static void iso8859_7_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_7_R); } static void iso8859_8_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_8_R); } static void iso8859_9_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_9_R); } static void iso8859_10_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_10_R); } static void tis620_2533_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, TIS620_2533); } static void iso8859_13_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_13_R); } static void iso8859_14_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_14_R); } static void iso8859_15_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_15_R); } static void iso8859_16_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, ISO8859_16_R); } static void tcvn5712_3_1993_parser_init(ef_parser_t *parser) { iso8859_parser_init(parser, TCVN5712_3_1993); } static ef_parser_t *iso8859_parser_new(void (*init)(struct ef_parser *)) { ef_iso2022_parser_t *iso2022_parser; if ((iso2022_parser = ef_iso2022_parser_new()) == NULL) { return NULL; } (*init)((ef_parser_t *)iso2022_parser); /* overwrite */ iso2022_parser->parser.init = init; return (ef_parser_t *)iso2022_parser; } /* --- global functions --- */ ef_parser_t *ef_iso8859_1_parser_new(void) { return iso8859_parser_new(iso8859_1_parser_init); } ef_parser_t *ef_iso8859_2_parser_new(void) { return iso8859_parser_new(iso8859_2_parser_init); } ef_parser_t *ef_iso8859_3_parser_new(void) { return iso8859_parser_new(iso8859_3_parser_init); } ef_parser_t *ef_iso8859_4_parser_new(void) { return iso8859_parser_new(iso8859_4_parser_init); } ef_parser_t *ef_iso8859_5_parser_new(void) { return iso8859_parser_new(iso8859_5_parser_init); } ef_parser_t *ef_iso8859_6_parser_new(void) { return iso8859_parser_new(iso8859_6_parser_init); } ef_parser_t *ef_iso8859_7_parser_new(void) { return iso8859_parser_new(iso8859_7_parser_init); } ef_parser_t *ef_iso8859_8_parser_new(void) { return iso8859_parser_new(iso8859_8_parser_init); } ef_parser_t *ef_iso8859_9_parser_new(void) { return iso8859_parser_new(iso8859_9_parser_init); } ef_parser_t *ef_iso8859_10_parser_new(void) { return iso8859_parser_new(iso8859_10_parser_init); } ef_parser_t *ef_tis620_2533_parser_new(void) { return iso8859_parser_new(tis620_2533_parser_init); } ef_parser_t *ef_iso8859_13_parser_new(void) { return iso8859_parser_new(iso8859_13_parser_init); } ef_parser_t *ef_iso8859_14_parser_new(void) { return iso8859_parser_new(iso8859_14_parser_init); } ef_parser_t *ef_iso8859_15_parser_new(void) { return iso8859_parser_new(iso8859_15_parser_init); } ef_parser_t *ef_iso8859_16_parser_new(void) { return iso8859_parser_new(iso8859_16_parser_init); } ef_parser_t *ef_tcvn5712_3_1993_parser_new(void) { return iso8859_parser_new(tcvn5712_3_1993_parser_init); } mlterm-3.8.9/encodefilter/src/ef_iso8859_parser.h010064400017600000144000000016271356600661000203230ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ISO8859_PARSER_H__ #define __EF_ISO8859_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_iso8859_1_parser_new(void); ef_parser_t *ef_iso8859_2_parser_new(void); ef_parser_t *ef_iso8859_3_parser_new(void); ef_parser_t *ef_iso8859_4_parser_new(void); ef_parser_t *ef_iso8859_5_parser_new(void); ef_parser_t *ef_iso8859_6_parser_new(void); ef_parser_t *ef_iso8859_7_parser_new(void); ef_parser_t *ef_iso8859_8_parser_new(void); ef_parser_t *ef_iso8859_9_parser_new(void); ef_parser_t *ef_iso8859_10_parser_new(void); /* a.k.a ISO8859-11 */ ef_parser_t *ef_tis620_2533_parser_new(void); ef_parser_t *ef_iso8859_13_parser_new(void); ef_parser_t *ef_iso8859_14_parser_new(void); ef_parser_t *ef_iso8859_15_parser_new(void); ef_parser_t *ef_iso8859_16_parser_new(void); ef_parser_t *ef_tcvn5712_3_1993_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_ja_jp_map.c010064400017600000144000000121531356600661000175260ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include /* memcpy */ #include "ef_ja_jp_map.h" #include "ef_ucs4_map.h" #include "ef_ucs4_jisx0201.h" #include "ef_ucs4_jisx0208.h" #include "ef_ucs4_jisx0212.h" #include "ef_ucs4_jisx0213.h" /* --- static variables --- */ static ef_map_ucs4_to_func_t map_ucs4_to_funcs[] = { ef_map_ucs4_to_jisx0201_roman, ef_map_ucs4_to_jisx0201_kata, ef_map_ucs4_to_jisx0208_1983, ef_map_ucs4_to_jisx0212_1990, ef_map_ucs4_to_jisx0213_2000_1, ef_map_ucs4_to_jisx0213_2000_2, }; /* --- global functions --- */ int ef_map_ucs4_to_ja_jp(ef_char_t *jajp, ef_char_t *ucs4) { return ef_map_ucs4_to_with_funcs(jajp, ucs4, map_ucs4_to_funcs, sizeof(map_ucs4_to_funcs) / sizeof(map_ucs4_to_funcs[0])); } int ef_map_jisx0213_2000_1_to_jisx0208_1983(ef_char_t *jis2k, ef_char_t *jis83) { memcpy(jis2k->ch, jis83->ch, 2); jis2k->size = 2; jis2k->cs = JISX0213_2000_1; jis2k->property = jis83->property; return 1; } int ef_map_jisx0208_1983_to_jisx0213_2000_1(ef_char_t *jis83, ef_char_t *jis2k) { /* * XXX * since JISX0213-1 is upper compatible with JISX0208 , some chars of * JISX0213-1 * must not be mapped to JISX0208. */ memcpy(jis83->ch, jis2k->ch, 2); jis83->size = 2; jis83->cs = JISX0213_2000_1; jis83->property = jis2k->property; return 1; } int ef_map_jisx0213_2000_2_to_jisx0212_1990(ef_char_t *jis90, ef_char_t *jis2k) { return ef_map_via_ucs(jis2k, jis90, JISX0213_2000_2); } int ef_map_jisx0212_1990_to_jisx0213_2000_2(ef_char_t *jis2k, ef_char_t *jis90) { return ef_map_via_ucs(jis90, jis2k, JISX0212_1990); } /* * Gaiji characters */ /* SJIS_IBM_EXT */ int ef_map_sjis_ibm_ext_to_jisx0208_1983(ef_char_t *jis, ef_char_t *ibm) { return ef_map_via_ucs(jis, ibm, JISX0208_1983); } int ef_map_sjis_ibm_ext_to_jisx0212_1990(ef_char_t *jis, ef_char_t *ibm) { return ef_map_via_ucs(jis, ibm, JISX0212_1990); } int ef_map_sjis_ibm_ext_to_jisx0213_2000(ef_char_t *jis, ef_char_t *ibm) { ef_char_t ucs4; if (!ef_map_to_ucs4(&ucs4, ibm)) { return 0; } if (!ef_map_ucs4_to_cs(jis, &ucs4, JISX0213_2000_2) && !ef_map_ucs4_to_cs(jis, &ucs4, JISX0213_2000_1)) { return 0; } return 1; } int ef_map_jisx0212_1990_to_sjis_ibm_ext(ef_char_t *ibm, ef_char_t *jis) { return ef_map_via_ucs(ibm, jis, SJIS_IBM_EXT); } int ef_map_jisx0213_2000_2_to_sjis_ibm_ext(ef_char_t *ibm, ef_char_t *jis) { return ef_map_via_ucs(ibm, jis, SJIS_IBM_EXT); } /* NEC EXT */ int ef_map_jisx0208_nec_ext_to_jisx0208_1983(ef_char_t *jis, ef_char_t *nec_ext) { return ef_map_via_ucs(jis, nec_ext, JISX0208_1983); } int ef_map_jisx0208_nec_ext_to_jisx0212_1990(ef_char_t *jis, ef_char_t *nec_ext) { return ef_map_via_ucs(jis, nec_ext, JISX0212_1990); } int ef_map_jisx0208_nec_ext_to_jisx0213_2000(ef_char_t *jis, ef_char_t *nec_ext) { ef_char_t ucs4; if (!ef_map_to_ucs4(&ucs4, nec_ext)) { return 0; } if (!ef_map_ucs4_to_cs(jis, &ucs4, JISX0213_2000_2) && !ef_map_ucs4_to_cs(jis, &ucs4, JISX0213_2000_1)) { return 0; } return 1; } int ef_map_jisx0212_1990_to_jisx0208_nec_ext(ef_char_t *nec_ext, ef_char_t *jis) { return ef_map_via_ucs(nec_ext, jis, JISC6226_1978_NEC_EXT); } int ef_map_jisx0213_2000_2_to_jisx0208_nec_ext(ef_char_t *nec_ext, ef_char_t *jis) { return ef_map_via_ucs(nec_ext, jis, JISC6226_1978_NEC_EXT); } /* NEC IBM EXT */ int ef_map_jisx0208_necibm_ext_to_jisx0208_1983(ef_char_t *jis, ef_char_t *necibm) { return ef_map_via_ucs(jis, necibm, JISX0208_1983); } int ef_map_jisx0208_necibm_ext_to_jisx0212_1990(ef_char_t *jis, ef_char_t *necibm) { return ef_map_via_ucs(jis, necibm, JISX0212_1990); } int ef_map_jisx0208_necibm_ext_to_jisx0213_2000(ef_char_t *jis, ef_char_t *necibm) { ef_char_t ucs4; if (!ef_map_to_ucs4(&ucs4, necibm)) { return 0; } if (!ef_map_ucs4_to_cs(jis, &ucs4, JISX0213_2000_2) && !ef_map_ucs4_to_cs(jis, &ucs4, JISX0213_2000_1)) { return 0; } return 1; } int ef_map_jisx0212_1990_to_jisx0208_necibm_ext(ef_char_t *necibm, ef_char_t *jis) { return ef_map_via_ucs(necibm, jis, JISC6226_1978_NECIBM_EXT); } int ef_map_jisx0213_2000_2_to_jisx0208_necibm_ext(ef_char_t *necibm, ef_char_t *jis) { return ef_map_via_ucs(necibm, jis, JISC6226_1978_NECIBM_EXT); } /* MAC EXT */ int ef_map_jisx0208_mac_ext_to_jisx0208_1983(ef_char_t *jis, ef_char_t *mac) { return ef_map_via_ucs(jis, mac, JISX0208_1983); } int ef_map_jisx0208_mac_ext_to_jisx0212_1990(ef_char_t *jis, ef_char_t *mac) { return ef_map_via_ucs(jis, mac, JISX0212_1990); } int ef_map_jisx0208_mac_ext_to_jisx0213_2000(ef_char_t *jis, ef_char_t *mac) { ef_char_t ucs4; if (!ef_map_to_ucs4(&ucs4, mac)) { return 0; } if (!ef_map_ucs4_to_cs(jis, &ucs4, JISX0213_2000_2) && !ef_map_ucs4_to_cs(jis, &ucs4, JISX0213_2000_1)) { return 0; } return 1; } int ef_map_jisx0212_1990_to_jisx0208_mac_ext(ef_char_t *mac, ef_char_t *jis) { return ef_map_via_ucs(mac, jis, JISX0208_1983_MAC_EXT); } int ef_map_jisx0213_2000_2_to_jisx0208_mac_ext(ef_char_t *mac, ef_char_t *jis) { return ef_map_via_ucs(mac, jis, JISX0208_1983_MAC_EXT); } mlterm-3.8.9/encodefilter/src/ef_ja_jp_map.h010064400017600000144000000041561356600661000175370ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_JA_JP_MAP_H__ #define __EF_JA_JP_MAP_H__ #include "ef_char.h" int ef_map_ucs4_to_ja_jp(ef_char_t *jajp, ef_char_t *ucs4); int ef_map_jisx0213_2000_1_to_jisx0208_1983(ef_char_t *jis2k, ef_char_t *jis83); int ef_map_jisx0208_1983_to_jisx0213_2000_1(ef_char_t *jis83, ef_char_t *jis2k); int ef_map_jisx0213_2000_2_to_jisx0212_1990(ef_char_t *jis2k, ef_char_t *jis90); int ef_map_jisx0212_1990_to_jisx0213_2000_2(ef_char_t *jis90, ef_char_t *jis2k); int ef_map_sjis_ibm_ext_to_jisx0208_1983(ef_char_t *jis, ef_char_t *ibm); int ef_map_sjis_ibm_ext_to_jisx0212_1990(ef_char_t *jis, ef_char_t *ibm); int ef_map_sjis_ibm_ext_to_jisx0213_2000(ef_char_t *jis, ef_char_t *ibm); int ef_map_jisx0212_1990_to_sjis_ibm_ext(ef_char_t *ibm, ef_char_t *jis); int ef_map_jisx0213_2000_2_to_sjis_ibm_ext(ef_char_t *ibm, ef_char_t *jis); int ef_map_jisx0208_nec_ext_to_jisx0208_1983(ef_char_t *jis, ef_char_t *nec_ext); int ef_map_jisx0208_nec_ext_to_jisx0212_1990(ef_char_t *jis, ef_char_t *nec_ext); int ef_map_jisx0208_nec_ext_to_jisx0213_2000(ef_char_t *jis, ef_char_t *nec_ext); int ef_map_jisx0212_1990_to_jisx0208_nec_ext(ef_char_t *nec_ext, ef_char_t *jis); int ef_map_jisx0213_2000_2_to_jisx0208_nec_ext(ef_char_t *nec_ext, ef_char_t *jis); int ef_map_jisx0208_necibm_ext_to_jisx0208_1983(ef_char_t *jis, ef_char_t *necibm); int ef_map_jisx0208_necibm_ext_to_jisx0212_1990(ef_char_t *jis, ef_char_t *necibm); int ef_map_jisx0208_necibm_ext_to_jisx0213_2000(ef_char_t *jis, ef_char_t *necibm); int ef_map_jisx0212_1990_to_jisx0208_necibm_ext(ef_char_t *necibm, ef_char_t *jis); int ef_map_jisx0213_2000_2_to_jisx0208_necibm_ext(ef_char_t *necibm, ef_char_t *jis); int ef_map_jisx0208_mac_ext_to_jisx0208_1983(ef_char_t *jis, ef_char_t *mac); int ef_map_jisx0208_mac_ext_to_jisx0212_1990(ef_char_t *jis, ef_char_t *mac); int ef_map_jisx0208_mac_ext_to_jisx0213_2000(ef_char_t *jis, ef_char_t *mac); int ef_map_jisx0212_1990_to_jisx0208_mac_ext(ef_char_t *mac, ef_char_t *jis); int ef_map_jisx0213_2000_2_to_jisx0208_mac_ext(ef_char_t *mac, ef_char_t *jis); #endif mlterm-3.8.9/encodefilter/src/ef_jis_property.c010064400017600000144000000052661356600661000203460ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_jis_property.h" /* * COMBINING_ENCLOSING_CIRCLE is regarded as LARGE_CIRCLE in JISX0208_1997. */ #if 0 #define JISX0208_COMBINING_ENCLOSING_CIRCLE #endif /* --- static variables --- */ static u_int8_t jisx0213_2000_1_property_table[] = { /* 0x2b52 */ EF_COMBINING, /* COMBINING DOUBLE INVERTED BREVE */ 0, 0, 0, 0, EF_COMBINING, /* COMBINING BREVE */ 0, EF_COMBINING, /* COMBINING DOUBLE ACUTE ACCENT */ EF_COMBINING, /* COMBINING ACUTE ACCENT */ EF_COMBINING, /* COMBINING MACRON */ EF_COMBINING, /* COMBINING GRAVE ACCENT */ EF_COMBINING, /* COMBINING DOUBLE GRAVE ACCENT */ EF_COMBINING, /* COMBINING CARON */ EF_COMBINING, /* COMBINING CIRCUMFLEX ACCENT */ /* 0x2b60 */ 0, 0, 0, 0, 0, 0, 0, EF_COMBINING, /* COMBINING RING BELOW */ EF_COMBINING, /* COMBINING CARON BELOW */ EF_COMBINING, /* COMBINING RIGHT HALF RING BELOW */ EF_COMBINING, /* COMBINING LEFT HALF RING BELOW */ EF_COMBINING, /* COMBINING PLUS SIGN BELOW */ EF_COMBINING, /* COMBINING MINUS SIGN BELOW */ EF_COMBINING, /* COMBINING DIAERESIS */ EF_COMBINING, /* COMBINING X ABOVE */ EF_COMBINING, /* COMBINING VERTICAL LINE BELOW */ /* 0x2b70 */ EF_COMBINING, /* COMBINING INVERTED BREVE BELOW */ 0, EF_COMBINING, /* COMBINING DIAERESIS BELOW */ EF_COMBINING, /* COMBINING TILDE BELOW */ EF_COMBINING, /* COMBINING SEAGULL BELOW */ EF_COMBINING, /* COMBINING TILDE OVERLAY */ EF_COMBINING, /* COMBINING UP TACK BELOW */ EF_COMBINING, /* COMBINING DOWN TACK BELOW */ EF_COMBINING, /* COMBINING LEFT TACK BELOW */ EF_COMBINING, /* COMBINING RIGHT TACK BELOW */ EF_COMBINING, /* COMBINING BRIDGE BELOW */ EF_COMBINING, /* COMBINING INVERTED BRIDGE BELOW */ EF_COMBINING, /* COMBINING SQUARE BELOW */ EF_COMBINING, /* COMBINING TILDE */ EF_COMBINING, /* COMBINING LEFT ANGLE ABOVE */ }; /* --- global functions --- */ ef_property_t ef_get_jisx0208_1983_property(u_char *ch /* 2 bytes */) { #ifdef JISX0208_COMBINING_ENCLOSING_CIRCLE if (memcmp(ch, "\x22\x7e", 2) == 0) { return EF_COMBINING; } #endif return 0; } ef_property_t ef_get_jisx0213_2000_1_property(u_char *ch /* 2 bytes */) { if (ch[0] == 0x2b) { if (0x52 <= ch[1] && ch[1] <= 0x7e) { return jisx0213_2000_1_property_table[ch[1] - 0x52]; } } return 0; } mlterm-3.8.9/encodefilter/src/ef_jis_property.h010064400017600000144000000005001356600661000203350ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_JIS_PROPERTY_H__ #define __EF_JIS_PROPERTY_H__ #include /* u_char */ #include "ef_property.h" ef_property_t ef_get_jisx0208_1983_property(u_char *ch); ef_property_t ef_get_jisx0213_2000_1_property(u_char *ch); #endif mlterm-3.8.9/encodefilter/src/ef_johab_conv.c010064400017600000144000000100171356600661000177130ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_johab_conv.h" #include #include #include "ef_ko_kr_map.h" #if 0 #define __DEBUG #endif /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { if (!ef_map_ucs4_to_ko_kr(&c, ch)) { return; } *ch = c; } /* * once all korean characters are converted to UHC. */ if (ch->cs == KSC5601_1987) { if (ef_map_ksc5601_1987_to_uhc(&c, ch)) { *ch = c; } } if (ch->cs == UHC) { /* * converting hangul to johab. */ if (ef_map_uhc_to_johab(&c, ch)) { *ch = c; } /* * the rest may be chinese characters or so , and they all are converted * to ksc5601. */ if (ef_map_uhc_to_ksc5601_1987(&c, ch)) { *ch = c; } } } static size_t convert_to_johab(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { size_t filled_size; ef_char_t ch; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { remap_unsupported_charset(&ch); if (ch.cs == JOHAB) { /* Hangul */ if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ch.ch[0]; *(dst++) = ch.ch[1]; filled_size += 2; } else if (ch.cs == KSC5601_1987) { /* * not Hangul * KSC5601_1987 Hangul chars are remapped to JOHAB in * remap_unsupported_charset() */ u_char byte1; u_char byte2; if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } #ifdef __DEBUG bl_debug_printf("0x%.2x%.2x -> ", ch.ch[0], ch.ch[1]); #endif if (ch.ch[0] <= 0x2c) { if (ch.ch[0] % 2 == 1) { byte1 = (ch.ch[0] - 0x20 + 0x1b1) / 2; goto pattern_1; } else { byte1 = (ch.ch[0] - 0x20 + 0x1b0) / 2; goto pattern_2; } } else if (ch.ch[0] == 0x49) { byte1 = 0xd8; goto pattern_1; } else if (ch.ch[0] == 0x7e) { byte1 = 0xd8; goto pattern_2; } else if (0x4a <= ch.ch[0] && ch.ch[0] <= 0x7d) { if (ch.ch[0] % 2 == 0) { byte1 = (ch.ch[0] - 0x20 + 0x196) / 2; goto pattern_1; } else { byte1 = (ch.ch[0] - 0x20 + 0x195) / 2; goto pattern_2; } } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " illegal johab format. cs(%x)/char(%x) is discarded.\n", ch.cs, ef_char_to_int(&ch)); #endif bl_msg_printf("conversion failed.\n"); continue; } pattern_1: if (ch.ch[1] <= 0x6e) { byte2 = ch.ch[1] - 0x20 + 0x30; } else { byte2 = ch.ch[1] - 0x20 + 0x42; } goto encoded; pattern_2: byte2 = ch.ch[1] - 0x20 + 0xa0; encoded: #ifdef __DEBUG bl_debug_printf("0x%.2x%.2x\n", byte1, byte2); #endif *(dst++) = byte1; *(dst++) = byte2; filled_size += 2; } else if (ch.cs == US_ASCII) { if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ch.ch[0]; filled_size++; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } return filled_size; } static void conv_init(ef_conv_t *conv) {} static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_johab_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_johab; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } mlterm-3.8.9/encodefilter/src/ef_johab_conv.h010064400017600000144000000002761356600661000177260ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_JOHAB_CONV_H__ #define __EF_JOHAB_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_johab_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_johab_parser.c010064400017600000144000000054431356600661000202510ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_johab_parser.h" #include #include /* --- static functions --- */ static int johab_parser_next_char(ef_parser_t *johab_parser, ef_char_t *ch) { if (johab_parser->is_eos) { return 0; } ef_parser_mark(johab_parser); if (/* 0x0 <= *johab_parser->str && */ *johab_parser->str <= 0x7f) { ch->ch[0] = *johab_parser->str; ch->size = 1; ch->cs = US_ASCII; } else if ((0xd8 <= *johab_parser->str && *johab_parser->str <= 0xde) || (0xe0 <= *johab_parser->str && *johab_parser->str <= 0xf9)) { /* KSX1001 except Hangul */ u_char byte1; u_char byte2; byte1 = *johab_parser->str; if (ef_parser_increment(johab_parser) == 0) { goto shortage; } byte2 = *johab_parser->str; #ifdef __DEBUG bl_debug_printf("0x%.2x%.2x -> ", byte1, byte2); #endif if (byte2 <= 0xa0) { if (byte1 == 0xd8) { ch->ch[0] = 0x29 + 0x20; } else { if (byte1 <= 0xde) { ch->ch[0] = byte1 * 2 - 0x1b1 + 0x20; } else /* if( 0xe0 <= byte1) */ { ch->ch[0] = byte1 * 2 - 0x196 + 0x20; } } if (byte2 <= 0x7e) { ch->ch[1] = byte2 - 0x30 + 0x20; } else { ch->ch[1] = byte2 - 0x42 + 0x20; } } else { if (byte1 == 0xd8) { ch->ch[0] = 0x5e + 0x20; } else { if (byte1 <= 0xde) { ch->ch[0] = byte1 * 2 - 0x1b0 + 0x20; } else /* if( 0xe0 <= byte1) */ { ch->ch[0] = byte1 * 2 - 0x195 + 0x20; } } ch->ch[1] = byte2 - 0xa0 + 0x20; } #ifdef __DEBUG bl_debug_printf("0x%.2x%.2x\n", ch->ch[0], ch->ch[1]); #endif ch->size = 2; ch->cs = KSC5601_1987; } else { ch->ch[0] = *johab_parser->str; if (ef_parser_increment(johab_parser) == 0) { goto shortage; } ch->ch[1] = *johab_parser->str; ch->size = 2; ch->cs = JOHAB; } ch->property = 0; ef_parser_increment(johab_parser); return 1; shortage: ef_parser_reset(johab_parser); return 0; } static void johab_parser_set_str(ef_parser_t *johab_parser, u_char *str, size_t size) { johab_parser->str = str; johab_parser->left = size; johab_parser->marked_left = 0; johab_parser->is_eos = 0; } static void johab_parser_destroy(ef_parser_t *s) { free(s); } /* --- global functions --- */ ef_parser_t *ef_johab_parser_new(void) { ef_parser_t *johab_parser; if ((johab_parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(johab_parser); johab_parser->init = ef_parser_init; johab_parser->next_char = johab_parser_next_char; johab_parser->set_str = johab_parser_set_str; johab_parser->destroy = johab_parser_destroy; return johab_parser; } mlterm-3.8.9/encodefilter/src/ef_johab_parser.h010064400017600000144000000003101356600661000202420ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_JOHAB_PARSER_H__ #define __EF_JOHAB_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_johab_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_ko_kr_map.c010064400017600000144000000027111356600661000175470ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ko_kr_map.h" #include "ef_iso2022_intern.h" #include "ef_ucs4_map.h" #include "ef_ucs4_ksc5601.h" #include "ef_ucs4_uhc.h" #include "ef_ucs4_johab.h" #include "ef_tblfunc_loader.h" /* * johab <=> ucs4 conversion is so simple without conversion table that * ucs4 -> johab conversion is done first of all. */ static ef_map_ucs4_to_func_t map_ucs4_to_funcs[] = { ef_map_ucs4_to_johab, ef_map_ucs4_to_ksc5601_1987, ef_map_ucs4_to_uhc, }; /* --- global functions --- */ int ef_map_ucs4_to_ko_kr(ef_char_t *kokr, ef_char_t *ucs4) { return ef_map_ucs4_to_with_funcs(kokr, ucs4, map_ucs4_to_funcs, sizeof(map_ucs4_to_funcs) / sizeof(map_ucs4_to_funcs[0])); } int ef_map_uhc_to_ksc5601_1987(ef_char_t *ksc, ef_char_t *uhc) { if (0xa1 <= uhc->ch[0] && uhc->ch[0] <= 0xfe && 0xa1 <= uhc->ch[1] && uhc->ch[1] <= 0xfe) { ksc->ch[0] = UNMAP_FROM_GR(uhc->ch[0]); ksc->ch[1] = UNMAP_FROM_GR(uhc->ch[1]); ksc->size = 2; ksc->cs = KSC5601_1987; return 1; } else { return 0; } } int ef_map_ksc5601_1987_to_uhc(ef_char_t *uhc, ef_char_t *ksc) { uhc->ch[0] = MAP_TO_GR(ksc->ch[0]); uhc->ch[1] = MAP_TO_GR(ksc->ch[1]); uhc->size = 2; uhc->cs = UHC; return 1; } #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_uhc_johab.c" #else ef_map_func2(kokr, ef_map_johab_to_uhc) ef_map_func2(kokr, ef_map_uhc_to_johab) #endif mlterm-3.8.9/encodefilter/src/ef_ko_kr_map.h010064400017600000144000000007161356600661000175570ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_KO_KR_MAP_H__ #define __EF_KO_KR_MAP_H__ #include "ef_char.h" int ef_map_ucs4_to_ko_kr(ef_char_t *kokr, ef_char_t *ucs4); int ef_map_uhc_to_ksc5601_1987(ef_char_t *ksc, ef_char_t *uhc); int ef_map_ksc5601_1987_to_uhc(ef_char_t *uhc, ef_char_t *ksc); int ef_map_johab_to_uhc(ef_char_t *uhc, ef_char_t *johab); int ef_map_uhc_to_johab(ef_char_t *johab, ef_char_t *uhc); #endif mlterm-3.8.9/encodefilter/src/ef_locale_ucs4_map.c010064400017600000144000000043201356600661000206350ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_locale_ucs4_map.h" #include /* strncmp */ #include #include "ef_ucs4_map.h" #include "ef_ja_jp_map.h" #include "ef_ko_kr_map.h" #include "ef_ru_map.h" #include "ef_tg_map.h" #include "ef_uk_map.h" #include "ef_viet_map.h" #include "ef_zh_cn_map.h" #include "ef_zh_hk_map.h" #include "ef_zh_tw_map.h" typedef int (*map_func_t)(ef_char_t *, ef_char_t *); typedef struct map_ucs4_to_func_table { char *lang; char *country; map_func_t func; } map_ucs4_to_func_table_t; /* --- static variables --- */ /* * XXX * in the future , ef_map_ucs4_to_[locale]_iso2022cs() should be prepared. * * XXX * other languages(especially ISO8859 variants) are not supported yet. */ static map_ucs4_to_func_table_t map_ucs4_to_func_table[] = { {"ja", NULL, ef_map_ucs4_to_ja_jp}, {"ko", NULL, ef_map_ucs4_to_ko_kr}, {"ru", NULL, ef_map_ucs4_to_ru}, {"tg", NULL, ef_map_ucs4_to_tg}, {"uk", NULL, ef_map_ucs4_to_uk}, {"vi", NULL, ef_map_ucs4_to_viet}, {"zh", "CN", ef_map_ucs4_to_zh_cn}, {"zh", "HK", ef_map_ucs4_to_zh_hk}, {"zh", "TW", ef_map_ucs4_to_zh_tw}, {"zh", NULL, ef_map_ucs4_to_zh_tw}, }; /* --- static functions --- */ static map_func_t get_map_ucs4_to_func_for_current_locale(void) { size_t count; char *lang; char *country; map_ucs4_to_func_table_t *tablep; static map_func_t cached_func; static int cached; /* Once cached, never changed. NULL is also cached. */ if (cached) { return cached_func; } cached = 1; lang = bl_get_lang(); country = bl_get_country(); for (count = 0; count < sizeof(map_ucs4_to_func_table) / sizeof(map_ucs4_to_func_table[0]); count++) { tablep = map_ucs4_to_func_table + count; if (!strcmp(tablep->lang, lang) && (!tablep->country || !strcmp(tablep->country, country))) { return (cached_func = tablep->func); } } return NULL; } /* --- global functions --- */ int ef_map_locale_ucs4_to(ef_char_t *non_ucs4, ef_char_t *ucs4) { map_func_t func; if ((func = get_map_ucs4_to_func_for_current_locale()) == NULL || !(*func)(non_ucs4, ucs4)) { return ef_map_ucs4_to(non_ucs4, ucs4); } return 1; } mlterm-3.8.9/encodefilter/src/ef_locale_ucs4_map.h010064400017600000144000000003451356600661000206450ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_LOCALE_UCS4_MAP_H__ #define __EF_LOCALE_UCS4_MAP_H__ #include "ef_char.h" int ef_map_locale_ucs4_to(ef_char_t *non_ucs4, ef_char_t *ucs4); #endif mlterm-3.8.9/encodefilter/src/ef_parser.h010064400017600000144000000024301356600661000171040ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_PARSER_H__ #define __EF_PARSER_H__ #include /* size_t */ #include "ef_char.h" typedef struct ef_parser { /* private */ u_char *str; size_t marked_left; size_t left; /* public */ int is_eos; /* public */ void (*init)(struct ef_parser *); void (*set_str)(struct ef_parser *, u_char *str, size_t size); void (*destroy)(struct ef_parser *); int (*next_char)(struct ef_parser *, ef_char_t *); } ef_parser_t; #define ef_parser_increment(parser) __ef_parser_increment((ef_parser_t *)parser) #define ef_parser_n_increment(parser, n) __ef_parser_n_increment((ef_parser_t *)parser, n) #define ef_parser_reset(parser) __ef_parser_reset((ef_parser_t *)parser) #define ef_parser_full_reset(parser) __ef_parser_full_reset((ef_parser_t *)parser) #define ef_parser_mark(parser) __ef_parser_mark((ef_parser_t *)parser) void ef_parser_init(ef_parser_t *parser); size_t __ef_parser_increment(ef_parser_t *parser); size_t __ef_parser_n_increment(ef_parser_t *parser, size_t n); void __ef_parser_mark(ef_parser_t *parser); void __ef_parser_reset(ef_parser_t *parser); void __ef_parser_full_reset(ef_parser_t *parser); int ef_parser_next_char(ef_parser_t *parser, ef_char_t *ch); #endif mlterm-3.8.9/encodefilter/src/ef_property.h010064400017600000144000000004041356600661000174730ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_PROPERTY_H__ #define __EF_PROPERTY_H__ typedef enum ef_property { EF_COMBINING = 0x1u, /* only for UCS */ EF_FULLWIDTH = 0x2u, EF_AWIDTH = 0x4u } ef_property_t; #endif mlterm-3.8.9/encodefilter/src/ef_ru_map.c010064400017600000144000000025221356600661000170700ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ru_map.h" #include #include "ef_ucs4_map.h" #include "ef_ucs4_iso8859.h" #include "ef_ucs4_koi8.h" /* * about KOI8-R <-> KOI8-U uncompatibility , see rfc2319. */ #define IS_NOT_COMPAT_AREA_OF_KOI8_R_U(ch) \ (ch == 0xa4 || ch == 0xa6 || ch == 0xa7 || ch == 0xad || ch == 0xb4 || ch == 0xb6 || \ ch == 0xb7 || ch == 0xbd) static ef_map_ucs4_to_func_t map_ucs4_to_funcs[] = { ef_map_ucs4_to_koi8_r, ef_map_ucs4_to_iso8859_5_r, }; /* --- global functions --- */ int ef_map_ucs4_to_ru(ef_char_t *ru, ef_char_t *ucs4) { return ef_map_ucs4_to_with_funcs(ru, ucs4, map_ucs4_to_funcs, sizeof(map_ucs4_to_funcs) / sizeof(map_ucs4_to_funcs[0])); } int ef_map_koi8_r_to_iso8859_5_r(ef_char_t *iso8859, ef_char_t *ru) { return ef_map_via_ucs(iso8859, ru, ISO8859_5_R); } int ef_map_koi8_r_to_koi8_u(ef_char_t *koi8_u, ef_char_t *koi8_r) { if (IS_NOT_COMPAT_AREA_OF_KOI8_R_U(koi8_r->ch[0])) { return 0; } *koi8_u = *koi8_r; koi8_u->cs = KOI8_U; return 1; } int ef_map_koi8_u_to_koi8_r(ef_char_t *koi8_r, ef_char_t *koi8_u) { if (IS_NOT_COMPAT_AREA_OF_KOI8_R_U(koi8_u->ch[0])) { return 0; } *koi8_r = *koi8_u; koi8_r->cs = KOI8_R; return 1; } mlterm-3.8.9/encodefilter/src/ef_ru_map.h010064400017600000144000000006271356600661000171010ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_RU_MAP_H__ #define __EF_RU_MAP_H__ #include "ef_char.h" int ef_map_ucs4_to_ru(ef_char_t *ru, ef_char_t *ucs4); int ef_map_koi8_r_to_iso8859_5_r(ef_char_t *iso8859, ef_char_t *ru); int ef_map_koi8_r_to_koi8_u(ef_char_t *koi8_u, ef_char_t *koi8_r); int ef_map_koi8_u_to_koi8_r(ef_char_t *koi8_r, ef_char_t *koi8_u); #endif mlterm-3.8.9/encodefilter/src/ef_sjis_conv.c010064400017600000144000000201731356600661000176040ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_sjis_conv.h" #include #include #include "ef_iso2022_intern.h" #include "ef_ja_jp_map.h" #include "ef_sjis_env.h" /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch, int is_sjisx0213) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { if (!ef_map_ucs4_to_ja_jp(&c, ch)) { return; } *ch = c; } if (ch->cs == JISC6226_1978) { /* * we ef_sjis_parser don't support JISC6226_1978. * If you want to use JISC6226_1978 , use iso2022(jp). * * XXX * 22 characters are swapped between 1978 and 1983. * so , we should reswap these here , but for the time being , * we do nothing. */ ch->cs = JISX0208_1983; } else if (ch->cs == JISX0212_1990) { if (is_sjisx0213) { if (ef_map_jisx0212_1990_to_jisx0213_2000_2(&c, ch)) { *ch = c; } } else { if (ef_get_sjis_input_type() == MICROSOFT_CS) { if (ef_map_jisx0212_1990_to_jisx0208_nec_ext(&c, ch) || ef_map_jisx0212_1990_to_jisx0208_necibm_ext(&c, ch) || ef_map_jisx0212_1990_to_sjis_ibm_ext(&c, ch)) { *ch = c; } } else if (ef_get_sjis_input_type() == APPLE_CS) { if (ef_map_jisx0212_1990_to_jisx0208_mac_ext(&c, ch)) { *ch = c; } } } } else if (is_sjisx0213 && ch->cs == JISC6226_1978_NEC_EXT) { if (ef_map_jisx0208_nec_ext_to_jisx0213_2000(&c, ch)) { *ch = c; } } else if (is_sjisx0213 && ch->cs == JISC6226_1978_NECIBM_EXT) { if (ef_map_jisx0208_necibm_ext_to_jisx0213_2000(&c, ch)) { *ch = c; } } else if (is_sjisx0213 && ch->cs == SJIS_IBM_EXT) { if (ef_map_sjis_ibm_ext_to_jisx0213_2000(&c, ch)) { *ch = c; } } else if (is_sjisx0213 && ch->cs == JISX0208_1983_MAC_EXT) { if (ef_map_jisx0208_mac_ext_to_jisx0213_2000(&c, ch)) { *ch = c; } } else if (is_sjisx0213 && ch->cs == JISX0208_1983) { if (ef_map_jisx0208_1983_to_jisx0213_2000_1(&c, ch)) { *ch = c; } } else if (!is_sjisx0213 && ch->cs == JISX0213_2000_1) { if (ef_map_jisx0213_2000_1_to_jisx0208_1983(&c, ch)) { *ch = c; } } else if (!is_sjisx0213 && ch->cs == JISX0213_2000_2) { if (ef_get_sjis_input_type() == MICROSOFT_CS) { if (ef_map_jisx0213_2000_2_to_jisx0208_nec_ext(&c, ch) || ef_map_jisx0213_2000_2_to_jisx0208_necibm_ext(&c, ch) || ef_map_jisx0213_2000_2_to_sjis_ibm_ext(&c, ch)) { *ch = c; } } else if (ef_get_sjis_input_type() == APPLE_CS) { if (ef_map_jisx0213_2000_2_to_jisx0208_mac_ext(&c, ch)) { *ch = c; } } } } static int map_jisx0208_1983_to_sjis(u_char *dst, /* 2bytes */ u_char *src /* 2bytes */ ) { int high; int low; high = *src; low = *(src + 1); if ((high & 0x01) == 1) { low += 0x1f; } else { low += 0x7d; } if (low >= 0x7f) { low++; } high = (high - 0x21) / 2 + 0x81; if (high > 0x9f) { high += 0x40; } *dst = high; *(dst + 1) = low; return 1; } static int map_jisx0213_2000_to_sjis(u_char *dst, /* 2bytes */ u_char *src, /* 2bytes */ int map /* map of jisx0213(1 or 2) */ ) { int high; int low; high = *src; low = *(src + 1); if (high % 2 == 1) { if (low <= 0x5f) { low += 0x1f; } else if (/* 0x60 <= low && */ low <= 0x7e) { low += 0x20; } } else { low += 0x7e; } if (map == 1) { if (high <= 0x5e) { high = (high + 0xe1) / 2; } else if (/* 0x5f <= high && */ high <= 0x7e) { high = (high + 0x161) / 2; } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " 0x%.2x is illegal upper byte of jisx0213.\n", high); #endif return 0; } } else if (map == 2) { if (high == 0x21 || high == 0x23 || high == 0x24 || high == 0x25 || high == 0x28 || high == 0x2c || high == 0x2d || high == 0x2e || high == 0x2f) { high = (high + 0x1bf) / 2 - ((high - 0x20) / 8) * 3; } else if (0x6e <= high && high <= 0x7e) { high = (high + 0x17b) / 2; } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " 0x%.2x is illegal higher byte of jisx0213.\n", high); #endif return 0; } } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " %d is illegal map of jisx0213.\n", map); #endif return 0; } *dst = high; *(dst + 1) = low; return 1; } static size_t convert_to_sjis_intern(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser, int is_sjisx0213) { size_t filled_size; ef_char_t ch; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { remap_unsupported_charset(&ch, is_sjisx0213); /* * encoding the following characterset to shift-jis. */ if (is_sjisx0213 == 1 && ch.cs == JISX0213_2000_1) { if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } if (map_jisx0213_2000_to_sjis(dst, ch.ch, 1) == 0) { /* ignoring these two bytes. */ continue; } dst += 2; filled_size += 2; } else if (is_sjisx0213 == 1 && ch.cs == JISX0213_2000_2) { if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } if (map_jisx0213_2000_to_sjis(dst, ch.ch, 2) == 0) { /* ignoring these two bytes. */ continue; } dst += 2; filled_size += 2; } else if (is_sjisx0213 == 0 && (ch.cs == JISX0208_1983 || ch.cs == JISC6226_1978_NEC_EXT || ch.cs == JISC6226_1978_NECIBM_EXT || ch.cs == JISX0208_1983_MAC_EXT)) { if (filled_size + 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } if (map_jisx0208_1983_to_sjis(dst, ch.ch) == 0) { /* ignoring these two bytes. */ continue; } dst += 2; filled_size += 2; } else if (is_sjisx0213 == 0 && ch.cs == SJIS_IBM_EXT) { if (filled_size + 2 > dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ch.ch[0]; *(dst++) = ch.ch[1]; } else if (ch.cs == US_ASCII || ch.cs == JISX0201_ROMAN) { if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = *ch.ch; filled_size++; } else if (ch.cs == JISX0201_KATA) { if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = MAP_TO_GR(*ch.ch); filled_size++; } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } return filled_size; } static size_t convert_to_sjis(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_sjis_intern(conv, dst, dst_size, parser, 0); } static size_t convert_to_sjisx0213(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_sjis_intern(conv, dst, dst_size, parser, 1); } static void conv_init(ef_conv_t *conv) {} static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_sjis_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_sjis; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } ef_conv_t *ef_sjisx0213_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_sjisx0213; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } mlterm-3.8.9/encodefilter/src/ef_sjis_conv.h010064400017600000144000000003441356600661000176070ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_SJIS_CONV_H__ #define __EF_SJIS_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_sjis_conv_new(void); ef_conv_t *ef_sjisx0213_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_sjis_env.c010064400017600000144000000010371356600661000174250ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_sjis_env.h" /* --- static variables --- */ static ef_sjis_type_t input_type = MICROSOFT_CS; static ef_sjis_type_t output_type = MICROSOFT_CS; /* --- global functions --- */ void ef_set_sjis_input_type(ef_sjis_type_t type) { input_type = type; } void ef_set_sjis_output_type(ef_sjis_type_t type) { output_type = type; } ef_sjis_type_t ef_get_sjis_input_type(void) { return input_type; } ef_sjis_type_t ef_get_sjis_output_type(void) { return output_type; } mlterm-3.8.9/encodefilter/src/ef_sjis_env.h010064400017600000144000000007421356600661000174340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_SJIS_ENV_H__ #define __EF_SJIS_ENV_H__ typedef enum ef_sjis_type_t { APPLE_CS, MICROSOFT_CS, MS_CS_WITH_NECDOS_9_12 /* chars(9 - 12 section) not included in MS charset. */ } ef_sjis_type_t; void ef_set_sjis_input_type(ef_sjis_type_t type); void ef_set_sjis_output_type(ef_sjis_type_t type); ef_sjis_type_t ef_get_sjis_input_type(void); ef_sjis_type_t ef_get_sjis_output_type(void); #endif mlterm-3.8.9/encodefilter/src/ef_sjis_parser.c010064400017600000144000000141521356600661000201330ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_sjis_parser.h" #include /* memset */ #include #include #include "ef_iso2022_parser.h" #include "ef_sjis_env.h" #include "ef_jis_property.h" /* --- static functions --- */ static int sjis_parser_next_char_intern(ef_parser_t *sjis_parser, ef_char_t *ch, int is_sjisx0213) { u_char c1; if (sjis_parser->is_eos) { return 0; } /* initialize */ ef_parser_mark(sjis_parser); memset(ch, 0, sizeof(ef_char_t)); c1 = *sjis_parser->str; if (c1 <= 0x7E) { ch->cs = US_ASCII; *ch->ch = c1; ch->size = 1; ch->property = 0; } else if (0xa1 <= c1 && c1 <= 0xdf) { ch->cs = JISX0201_KATA; *ch->ch = UNSET_MSB(c1); ch->size = 1; ch->property = 0; } else { u_char c2; u_int16_t sjis_ch; u_char high; u_char low; ef_charset_t cs; if (ef_parser_increment(sjis_parser) == 0) { goto shortage; } c2 = *sjis_parser->str; /* * specifying character set type. */ sjis_ch = ((c1 << 8) & 0xff00) + (c2 & 0xff); if (is_sjisx0213) { if (c1 >= 0xf0) { cs = JISX0213_2000_2; } else { cs = JISX0213_2000_1; } } else { if (ef_get_sjis_output_type() == APPLE_CS) { /* * XXX * this check is not exact , but not a problem for practical use. */ if (0x00fd <= sjis_ch && sjis_ch <= 0x00ff) { cs = JISX0208_1983_MAC_EXT; } else if (0x8540 <= sjis_ch && sjis_ch <= 0x886d) { cs = JISX0208_1983_MAC_EXT; } else if (0xeb41 <= sjis_ch && sjis_ch <= 0xed96) { cs = JISX0208_1983_MAC_EXT; } else { cs = JISX0208_1983; } } else /* if( ef_get_sjis_output_type() == MICROSOFT_CS) */ { /* * XXX * this check is not exact , but not a problem for practical use. */ if (0x8740 <= sjis_ch && sjis_ch <= 0x879c) { cs = JISC6226_1978_NEC_EXT; } else if (0xed40 <= sjis_ch && sjis_ch <= 0xeefc) { cs = JISC6226_1978_NECIBM_EXT; } else if (0xfa40 <= sjis_ch && sjis_ch <= 0xfc4b) { cs = SJIS_IBM_EXT; } else { cs = JISX0208_1983; } } } /* * converting SJIS -> JIS process. */ if (cs == SJIS_IBM_EXT) { /* * SJIS_IBM_EXT * * IBM extension characters are placed in the empty space of Shift-JIS *encoding , * then these characters cannot be mapped to jisx0208 which uses only *0x20-0x7f * because the decoded byte of them can be 0x93,0x94,0x95,0x96... * So , we keep them sjis encoded bytes in ef_char_t as * JIS6226_1978_IBM_EXT charset. */ ch->cs = SJIS_IBM_EXT; ch->ch[0] = c1; ch->ch[1] = c2; ch->size = 2; } else if (cs == JISX0213_2000_2) { u_char sjis_upper_to_jisx02132_map_1[] = { /* 0xf0 - 0xfc(sjis) */ 0x21, 0x23, 0x25, 0x2d, 0x2f, 0x6f, 0x71, 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d, }; u_char sjis_upper_to_jisx02132_map_2[] = { /* 0xf0 - 0xfc(sjis) */ 0x28, 0x24, 0x2c, 0x2e, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, }; if (0xf0 <= c1 && c1 <= 0xfc) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " 0x%.2x is illegal upper byte of jisx0213_2.\n", c1); #endif goto error; } if (c2 <= 0x9e) { high = sjis_upper_to_jisx02132_map_1[c1 - 0xf0]; if (c2 > 0x7e) { low = c2 - 0x20; } else { low = c2 - 0x1f; } } else { high = sjis_upper_to_jisx02132_map_2[c1 - 0xf0]; c2 -= 0x7e; } } else { /* * JISX0213 2000 2 */ if (0x81 <= c1 && c1 <= 0x9f) { high = c1 - 0x71; } else if (0xe0 <= c1 && c1 <= 0xfc) { high = c1 - 0xb1; } else { /* XXX what's this ? */ goto error; } high = high * 2 + 1; if (0x80 <= c2) { low = c2 - 1; } else { low = c2; } if (0x9e <= low && low <= 0xfb) { low -= 0x7d; high++; } else if (0x40 <= low && low <= 0x9d) { low -= 0x1f; } else { /* XXX what's this ? */ goto error; } ch->ch[0] = high; ch->ch[1] = low; ch->size = 2; ch->cs = cs; } if (cs == JISX0208_1983) { ch->property = ef_get_jisx0208_1983_property(ch->ch); } else if (cs == JISX0213_2000_1) { ch->property = ef_get_jisx0213_2000_1_property(ch->ch); } else { ch->property = 0; } } ef_parser_increment(sjis_parser); return 1; error: shortage: ef_parser_reset(sjis_parser); return 0; } static int sjis_parser_next_char(ef_parser_t *sjis_parser, ef_char_t *ch) { return sjis_parser_next_char_intern(sjis_parser, ch, 0); } static int sjisx0213_parser_next_char(ef_parser_t *sjis_parser, ef_char_t *ch) { return sjis_parser_next_char_intern(sjis_parser, ch, 1); } static void sjis_parser_set_str(ef_parser_t *sjis_parser, u_char *str, size_t size) { sjis_parser->str = str; sjis_parser->left = size; sjis_parser->marked_left = 0; sjis_parser->is_eos = 0; } static void sjis_parser_destroy(ef_parser_t *s) { free(s); } /* --- global functions --- */ ef_parser_t *ef_sjis_parser_new(void) { ef_parser_t *sjis_parser; if ((sjis_parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(sjis_parser); sjis_parser->init = ef_parser_init; sjis_parser->set_str = sjis_parser_set_str; sjis_parser->destroy = sjis_parser_destroy; sjis_parser->next_char = sjis_parser_next_char; return sjis_parser; } ef_parser_t *ef_sjisx0213_parser_new(void) { ef_parser_t *sjis_parser; if ((sjis_parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(sjis_parser); sjis_parser->init = ef_parser_init; sjis_parser->set_str = sjis_parser_set_str; sjis_parser->destroy = sjis_parser_destroy; sjis_parser->next_char = sjisx0213_parser_next_char; return sjis_parser; } mlterm-3.8.9/encodefilter/src/ef_sjis_parser.h010064400017600000144000000003621356600661000201360ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_SJIS_PARSER_H__ #define __EF_SJIS_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_sjis_parser_new(void); ef_parser_t *ef_sjisx0213_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_tblfunc_loader.c010064400017600000144000000034651356600661000205770ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_tblfunc_loader.h" #ifndef NO_DYNAMIC_LOAD_TABLE #include /* NULL */ /* --- global functions --- */ void *ef_load_8bits_func(const char *symname) { static bl_dl_handle_t handle; static int is_tried; if (!is_tried) { is_tried = 1; if (!(handle = bl_dl_open(MEFLIB_DIR, "mef_8bits")) && !(handle = bl_dl_open("", "mef_8bits"))) { return NULL; } bl_dl_close_at_exit(handle); } if (handle) { return bl_dl_func_symbol(handle, symname); } else { return NULL; } } void *ef_load_jajp_func(const char *symname) { static bl_dl_handle_t handle; static int is_tried; if (!is_tried) { is_tried = 1; if (!(handle = bl_dl_open(MEFLIB_DIR, "mef_jajp")) && !(handle = bl_dl_open("", "mef_jajp"))) { return NULL; } bl_dl_close_at_exit(handle); } if (handle) { return bl_dl_func_symbol(handle, symname); } else { return NULL; } } void *ef_load_kokr_func(const char *symname) { static bl_dl_handle_t handle; static int is_tried; if (!is_tried) { is_tried = 1; if (!(handle = bl_dl_open(MEFLIB_DIR, "mef_kokr")) && !(handle = bl_dl_open("", "mef_kokr"))) { return NULL; } bl_dl_close_at_exit(handle); } if (handle) { return bl_dl_func_symbol(handle, symname); } else { return NULL; } } void *ef_load_zh_func(const char *symname) { static bl_dl_handle_t handle; static int is_tried; if (!is_tried) { is_tried = 1; if (!(handle = bl_dl_open(MEFLIB_DIR, "mef_zh")) && !(handle = bl_dl_open("", "mef_zh"))) { return NULL; } bl_dl_close_at_exit(handle); } if (handle) { return bl_dl_func_symbol(handle, symname); } else { return NULL; } } #endif /* NO_DYNAMIC_LOAD_TABLE */ mlterm-3.8.9/encodefilter/src/ef_tblfunc_loader.h010064400017600000144000000034451356600661000206020ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_TBLFUNC_LOADER_H__ #define __EF_TBLFUNC_LOADER_H__ #include #include #include "ef_char.h" #ifndef LIBDIR #define MEFLIB_DIR "/usr/local/lib/mef/" #else #define MEFLIB_DIR LIBDIR "/mef/" #endif #ifdef DLFCN_NONE #ifndef NO_DYNAMIC_LOAD_TABLE #define NO_DYNAMIC_LOAD_TABLE #endif #endif #ifndef NO_DYNAMIC_LOAD_TABLE #define ef_map_func(libname, funcname, bits) \ int funcname(ef_char_t *ch, u_int##bits##_t ucscode) { \ static int (*_##funcname)(ef_char_t *, u_int##bits##_t); \ if (!_##funcname && !(_##funcname = ef_load_##libname##_func(#funcname))) { \ return 0; \ } \ return (*_##funcname)(ch, ucscode); \ } #define ef_map_func2(libname, funcname) \ int funcname(ef_char_t *dst_ch, ef_char_t *src_ch) { \ static int (*_##funcname)(ef_char_t *, ef_char_t *); \ if (!_##funcname && !(_##funcname = ef_load_##libname##_func(#funcname))) { \ return 0; \ } \ return (*_##funcname)(dst_ch, src_ch); \ } void *ef_load_8bits_func(const char *symname); void *ef_load_jajp_func(const char *symname); void *ef_load_kokr_func(const char *symname); void *ef_load_zh_func(const char *symname); #endif /* NO_DYNAMIC_LOAD_TABLE */ #endif mlterm-3.8.9/encodefilter/src/ef_tg_map.c010064400017600000144000000012551356600661000170560ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_tg_map.h" #include #include "ef_ucs4_map.h" #include "ef_ucs4_iso8859.h" #include "ef_ucs4_koi8.h" static ef_map_ucs4_to_func_t map_ucs4_to_funcs[] = { ef_map_ucs4_to_koi8_t, ef_map_ucs4_to_iso8859_5_r, }; /* --- global functions --- */ int ef_map_ucs4_to_tg(ef_char_t *tg, ef_char_t *ucs4) { return ef_map_ucs4_to_with_funcs(tg, ucs4, map_ucs4_to_funcs, sizeof(map_ucs4_to_funcs) / sizeof(map_ucs4_to_funcs[0])); } int ef_map_koi8_t_to_iso8859_5_r(ef_char_t *iso8859, ef_char_t *tg) { return ef_map_via_ucs(iso8859, tg, ISO8859_5_R); } mlterm-3.8.9/encodefilter/src/ef_tg_map.h010064400017600000144000000004171356600661000170620ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_TG_MAP_H__ #define __EF_TG_MAP_H__ #include "ef_char.h" int ef_map_ucs4_to_tg(ef_char_t *tg, ef_char_t *ucs4); int ef_map_koi8_t_to_iso8859_5_r(ef_char_t *iso8859, ef_char_t *tg); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_big5.c010064400017600000144000000006271356600661000173750ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_big5.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_big5.c" #else ef_map_func(zh, ef_map_big5_to_ucs4, 16) ef_map_func(zh, ef_map_hkscs_to_ucs4, 16) ef_map_func(zh, ef_map_ucs4_to_big5, 32) ef_map_func(zh, ef_map_ucs4_to_hkscs, 32) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_big5.h010064400017600000144000000006751356600661000174050ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_BIG5_H__ #define __EF_UCS4_BIG5_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_big5_to_ucs4(ef_char_t *ucs4, u_int16_t big5); int ef_map_hkscs_to_ucs4(ef_char_t *ucs4, u_int16_t big5); int ef_map_ucs4_to_big5(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_hkscs(ef_char_t *non_ucs, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_cns11643.c010064400017600000144000000010611356600661000177220ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_cns11643.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_cns11643.c" #else ef_map_func(zh, ef_map_cns11643_1992_1_to_ucs4, 16) ef_map_func(zh, ef_map_cns11643_1992_2_to_ucs4, 16) ef_map_func(zh, ef_map_cns11643_1992_3_to_ucs4, 16) ef_map_func(zh, ef_map_ucs4_to_cns11643_1992_1, 32) ef_map_func(zh, ef_map_ucs4_to_cns11643_1992_2, 32) ef_map_func(zh, ef_map_ucs4_to_cns11643_1992_3, 32) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_cns11643.h010064400017600000144000000011641356600661000177330ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_CNS11643_H__ #define __EF_UCS4_CNS11643_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_cns11643_1992_1_to_ucs4(ef_char_t *ucs4, u_int16_t cns); int ef_map_cns11643_1992_2_to_ucs4(ef_char_t *ucs4, u_int16_t cns); int ef_map_cns11643_1992_3_to_ucs4(ef_char_t *ucs4, u_int16_t cns); int ef_map_ucs4_to_cns11643_1992_1(ef_char_t *cns, u_int32_t ucs4_code); int ef_map_ucs4_to_cns11643_1992_2(ef_char_t *cns, u_int32_t ucs4_code); int ef_map_ucs4_to_cns11643_1992_3(ef_char_t *cns, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_cp125x.c010064400017600000144000000046431356600661000175730ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_cp125x.h" #include "ef_tblfunc_loader.h" #include "ef_ucs4_iso8859.h" /* --- static variables --- */ static struct { u_int8_t cp874; u_int8_t ucs4; /* 0x20NN */ } cp874_table[] = { {0x80, 0xac}, {0x85, 0x26}, {0x91, 0x18}, {0x92, 0x19}, {0x93, 0x1c}, {0x94, 0x1d}, {0x95, 0x22}, {0x96, 0x13}, {0x97, 0x14}, }; /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_cp125x.c" #else ef_map_func(8bits, ef_map_cp1250_to_ucs4, 16) ef_map_func(8bits, ef_map_cp1251_to_ucs4, 16) ef_map_func(8bits, ef_map_cp1252_to_ucs4, 16) ef_map_func(8bits, ef_map_cp1253_to_ucs4, 16) ef_map_func(8bits, ef_map_cp1254_to_ucs4, 16) ef_map_func(8bits, ef_map_cp1255_to_ucs4, 16) ef_map_func(8bits, ef_map_cp1256_to_ucs4, 16) ef_map_func(8bits, ef_map_cp1257_to_ucs4, 16) ef_map_func(8bits, ef_map_cp1258_to_ucs4, 16) ef_map_func(8bits, ef_map_ucs4_to_cp1250, 32) ef_map_func(8bits, ef_map_ucs4_to_cp1251, 32) ef_map_func(8bits, ef_map_ucs4_to_cp1252, 32) ef_map_func(8bits, ef_map_ucs4_to_cp1253, 32) ef_map_func(8bits, ef_map_ucs4_to_cp1254, 32) ef_map_func(8bits, ef_map_ucs4_to_cp1255, 32) ef_map_func(8bits, ef_map_ucs4_to_cp1256, 32) ef_map_func(8bits, ef_map_ucs4_to_cp1257, 32) ef_map_func(8bits, ef_map_ucs4_to_cp1258, 32) #endif int ef_map_cp874_to_ucs4(ef_char_t *ucs4, u_int16_t cp874_code) { size_t count; if (ef_map_tis620_2533_to_ucs4(ucs4, cp874_code & 0x7f)) { return 1; } for (count = 0; count < sizeof(cp874_table) / sizeof(cp874_table[0]); count++) { if (cp874_table[count].cp874 == cp874_code) { ucs4->ch[0] = 0x0; ucs4->ch[1] = 0x0; ucs4->ch[2] = 0x20; ucs4->ch[3] = cp874_table[count].ucs4; ucs4->size = 4; ucs4->cs = ISO10646_UCS4_1; ucs4->property = 0; return 1; } } return 0; } int ef_map_ucs4_to_cp874(ef_char_t *non_ucs, u_int32_t ucs4_code) { size_t count; if (ef_map_ucs4_to_tis620_2533(non_ucs, ucs4_code)) { non_ucs->ch[0] |= 0x80; non_ucs->cs = CP874; return 1; } for (count = 0; count < sizeof(cp874_table) / sizeof(cp874_table[0]); count++) { if (((u_int32_t)cp874_table[count].ucs4) + 0x2000 == ucs4_code) { non_ucs->ch[0] = cp874_table[count].cp874; non_ucs->size = 1; non_ucs->cs = CP874; non_ucs->property = 0; return 1; } } return 0; } mlterm-3.8.9/encodefilter/src/ef_ucs4_cp125x.h010064400017600000144000000027631356600661000176010ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_CP125X_H__ #define __EF_UCS4_CP125X_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_cp1250_to_ucs4(ef_char_t *ucs4, u_int16_t cp_code); int ef_map_cp1251_to_ucs4(ef_char_t *ucs4, u_int16_t cp_code); int ef_map_cp1252_to_ucs4(ef_char_t *ucs4, u_int16_t cp_code); int ef_map_cp1253_to_ucs4(ef_char_t *ucs4, u_int16_t cp_code); int ef_map_cp1254_to_ucs4(ef_char_t *ucs4, u_int16_t cp_code); int ef_map_cp1255_to_ucs4(ef_char_t *ucs4, u_int16_t cp_code); int ef_map_cp1256_to_ucs4(ef_char_t *ucs4, u_int16_t cp_code); int ef_map_cp1257_to_ucs4(ef_char_t *ucs4, u_int16_t cp_code); int ef_map_cp1258_to_ucs4(ef_char_t *ucs4, u_int16_t cp_code); int ef_map_cp874_to_ucs4(ef_char_t *ucs4, u_int16_t cp_code); int ef_map_ucs4_to_cp1250(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_cp1251(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_cp1252(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_cp1253(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_cp1254(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_cp1255(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_cp1256(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_cp1257(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_cp1258(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_cp874(ef_char_t *non_ucs, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_gb2312.c010064400017600000144000000012031356600661000174360ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_gb2312.h" #include "ef_ucs4_gbk.h" /* --- global functions --- */ int ef_map_gb2312_80_to_ucs4(ef_char_t *ucs4, u_int16_t gb) { /* converting to GBK */ gb |= 0x8080; if (ef_map_gbk_to_ucs4(ucs4, gb)) { return 1; } return 0; } int ef_map_ucs4_to_gb2312_80(ef_char_t *gb, u_int32_t ucs4_code) { if (ef_map_ucs4_to_gbk(gb, ucs4_code)) { if (gb->ch[0] >= 0xa1 && gb->ch[1] >= 0xa1) { /* converting to GB2312 */ gb->ch[0] &= 0x7f; gb->ch[1] &= 0x7f; gb->cs = GB2312_80; return 1; } } return 0; } mlterm-3.8.9/encodefilter/src/ef_ucs4_gb2312.h010064400017600000144000000005111356600661000174440ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_GB2312_H__ #define __EF_UCS4_GB2312_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_gb2312_80_to_ucs4(ef_char_t *ucs4, u_int16_t gb); int ef_map_ucs4_to_gb2312_80(ef_char_t *non_ucs, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_gbk.c010064400017600000144000000004771356600661000173150ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_gbk.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_gbk.c" #else ef_map_func(zh, ef_map_gbk_to_ucs4, 16) ef_map_func(zh, ef_map_ucs4_to_gbk, 32) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_gbk.h010064400017600000144000000004671356600661000173210ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_GBK_H__ #define __EF_UCS4_GBK_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_gbk_to_ucs4(ef_char_t *ucs4, u_int16_t gb); int ef_map_ucs4_to_gbk(ef_char_t *non_ucs, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_georgian_ps.c010064400017600000144000000005451356600661000210430ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_georgian_ps.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_georgian_ps.c" #else ef_map_func(8bits, ef_map_georgian_ps_to_ucs4, 16) ef_map_func(8bits, ef_map_ucs4_to_georgian_ps, 32) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_georgian_ps.h010064400017600000144000000005341356600661000210460ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_GEORGIAN_PS_H__ #define __EF_UCS4_GEORGIAN_PS_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_georgian_ps_to_ucs4(ef_char_t *ucs4, u_int16_t gp_code); int ef_map_ucs4_to_georgian_ps(ef_char_t *non_ucs, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_intern.h010064400017600000144000000007121356600661000200460ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_INTERN_H__ #define __EF_UCS4_INTERN_H__ #define IS_ALPHABET(ucs4) (/* 0 <= (ucs4) && */ (ucs4) <= 0x33ff) #define IS_EXTENSION_A(ucs4) (0x3400 <= (ucs4) && (ucs4) <= 0x4dff) #define IS_CJK(ucs4) (0x4e00 <= (ucs4) && (ucs4) <= 0x9fff) #define IS_HANGUL(ucs4) (0xac00 <= (ucs4) && (ucs4) <= 0xd7ff) #define IS_COMPAT(ucs4) (0xf900 <= (ucs4) && (ucs4) <= 0xfffd) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_iscii.c010064400017600000144000000014571356600661000176510ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_iscii.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_iscii.c" #else ef_map_func(8bits, ef_map_ucs4_to_iscii, 32) ef_map_func(8bits, ef_map_iscii_assamese_to_ucs4, 16) ef_map_func(8bits, ef_map_iscii_bengali_to_ucs4, 16) ef_map_func(8bits, ef_map_iscii_gujarati_to_ucs4, 16) ef_map_func(8bits, ef_map_iscii_hindi_to_ucs4, 16) ef_map_func(8bits, ef_map_iscii_kannada_to_ucs4, 16) ef_map_func(8bits, ef_map_iscii_malayalam_to_ucs4, 16) ef_map_func(8bits, ef_map_iscii_oriya_to_ucs4, 16) ef_map_func(8bits, ef_map_iscii_punjabi_to_ucs4, 16) ef_map_func(8bits, ef_map_iscii_tamil_to_ucs4, 16) ef_map_func(8bits, ef_map_iscii_telugu_to_ucs4, 16) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_iscii.h010064400017600000144000000017461356600661000176570ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_ISCII_H__ #define __EF_UCS4_ISCII_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_iscii_assamese_to_ucs4(ef_char_t *ucs4, u_int16_t iscii_code); int ef_map_iscii_bengali_to_ucs4(ef_char_t *ucs4, u_int16_t iscii_code); int ef_map_iscii_gujarati_to_ucs4(ef_char_t *ucs4, u_int16_t iscii_code); int ef_map_iscii_hindi_to_ucs4(ef_char_t *ucs4, u_int16_t iscii_code); int ef_map_iscii_kannada_to_ucs4(ef_char_t *ucs4, u_int16_t iscii_code); int ef_map_iscii_malayalam_to_ucs4(ef_char_t *ucs4, u_int16_t iscii_code); int ef_map_iscii_oriya_to_ucs4(ef_char_t *ucs4, u_int16_t iscii_code); int ef_map_iscii_punjabi_to_ucs4(ef_char_t *ucs4, u_int16_t iscii_code); int ef_map_iscii_tamil_to_ucs4(ef_char_t *ucs4, u_int16_t iscii_code); int ef_map_iscii_telugu_to_ucs4(ef_char_t *ucs4, u_int16_t iscii_code); int ef_map_ucs4_to_iscii(ef_char_t *non_ucs, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_iso8859.c010064400017600000144000000035511356600661000176760ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_iso8859.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_iso8859.c" #else ef_map_func(8bits, ef_map_ucs4_to_iso8859_1_r, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_2_r, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_3_r, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_4_r, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_5_r, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_6_r, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_7_r, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_8_r, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_9_r, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_10_r, 32) ef_map_func(8bits, ef_map_ucs4_to_tis620_2533, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_13_r, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_14_r, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_15_r, 32) ef_map_func(8bits, ef_map_ucs4_to_iso8859_16_r, 32) ef_map_func(8bits, ef_map_ucs4_to_tcvn5712_3_1993, 32) ef_map_func(8bits, ef_map_iso8859_1_r_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_2_r_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_3_r_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_4_r_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_5_r_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_6_r_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_7_r_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_8_r_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_9_r_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_10_r_to_ucs4, 16) ef_map_func(8bits, ef_map_tis620_2533_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_13_r_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_14_r_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_15_r_to_ucs4, 16) ef_map_func(8bits, ef_map_iso8859_16_r_to_ucs4, 16) ef_map_func(8bits, ef_map_tcvn5712_3_1993_to_ucs4, 16) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_iso8859.h010064400017600000144000000050231356600661000176770ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_ISO8859_H__ #define __EF_UCS4_ISO8859_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_ucs4_to_iso8859_1_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_2_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_3_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_4_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_5_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_6_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_7_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_8_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_9_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_10_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_tis620_2533(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_13_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_14_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_15_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_iso8859_16_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_tcvn5712_3_1993(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_iso8859_1_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_iso8859_2_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_iso8859_3_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_iso8859_4_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_iso8859_5_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_iso8859_6_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_iso8859_7_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_iso8859_8_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_iso8859_9_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_iso8859_10_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_tis620_2533_to_ucs4(ef_char_t *ucs4, u_int16_t tis620_code); int ef_map_iso8859_13_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_iso8859_14_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_iso8859_15_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_iso8859_16_r_to_ucs4(ef_char_t *ucs4, u_int16_t iso8859_code); int ef_map_tcvn5712_3_1993_to_ucs4(ef_char_t *ucs4, u_int16_t tcvn_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_jisx0201.c010064400017600000144000000034441356600661000200270ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include "ef_ucs4_jisx0201.h" /* * XXX * jisx0201_kata msb bit is 0 in mef and is 94 sb charset(excluding space 0x20 * and delete 0x7f). */ /* --- global functions --- */ int ef_map_jisx0201_kata_to_ucs4(ef_char_t *ucs4, u_int16_t jis) { if (!(0x21 <= jis && jis <= 0x5f)) { return 0; } ucs4->ch[0] = '\x00'; ucs4->ch[1] = '\x00'; ucs4->ch[2] = '\xff'; ucs4->ch[3] = jis + 0x40; ucs4->size = 4; ucs4->cs = ISO10646_UCS4_1; ucs4->property = 0; return 1; } int ef_map_jisx0201_roman_to_ucs4(ef_char_t *ucs4, u_int16_t jis) { if (!(0x21 <= jis && jis <= 0x7e)) { return 0; } if (jis == 0x5c) { memcpy(ucs4->ch, "\x00\x00\x00\xa5", 4); ucs4->size = 4; ucs4->cs = ISO10646_UCS4_1; ucs4->property = 0; } else if (jis == 0x7e) { memcpy(ucs4->ch, "\x00\x00\x20\x3e", 4); ucs4->size = 4; ucs4->cs = ISO10646_UCS4_1; ucs4->property = 0; } else { ucs4->ch[0] = jis; ucs4->size = 1; ucs4->cs = US_ASCII; ucs4->property = 0; } return 1; } int ef_map_ucs4_to_jisx0201_kata(ef_char_t *non_ucs, u_int32_t ucs4_code) { if (0xff61 <= ucs4_code && ucs4_code <= 0xff9f) { non_ucs->ch[0] = ucs4_code - 0xff40; non_ucs->size = 1; non_ucs->cs = JISX0201_KATA; non_ucs->property = 0; return 1; } else { return 0; } } int ef_map_ucs4_to_jisx0201_roman(ef_char_t *non_ucs, u_int32_t ucs4_code) { if (!(0x21 <= ucs4_code && ucs4_code <= 0x7e)) { return 0; } if (ucs4_code == 0x00a5) { non_ucs->ch[0] = 0x5c; } else if (ucs4_code == 0x203E) { non_ucs->ch[0] = 0x7e; } else { non_ucs->ch[0] = ucs4_code; } non_ucs->size = 1; non_ucs->cs = JISX0201_ROMAN; non_ucs->property = 0; return 1; } mlterm-3.8.9/encodefilter/src/ef_ucs4_jisx0201.h010064400017600000144000000007471356600661000200370ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_JISX0201_H__ #define __EF_UCS4_JISX0201_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_jisx0201_kata_to_ucs4(ef_char_t *ucs4, u_int16_t jis); int ef_map_jisx0201_roman_to_ucs4(ef_char_t *ucs4, u_int16_t jis); int ef_map_ucs4_to_jisx0201_kata(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_jisx0201_roman(ef_char_t *non_ucs, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_jisx0208.c010064400017600000144000000012511356600661000200300ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_jisx0208.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_jisx0208.c" #else ef_map_func(jajp, ef_map_jisx0208_1983_to_ucs4, 16) ef_map_func(jajp, ef_map_jisx0208_nec_ext_to_ucs4, 16) ef_map_func(jajp, ef_map_jisx0208_necibm_ext_to_ucs4, 16) ef_map_func(jajp, ef_map_sjis_ibm_ext_to_ucs4, 16) ef_map_func(jajp, ef_map_ucs4_to_jisx0208_1983, 32) ef_map_func(jajp, ef_map_ucs4_to_jisx0208_nec_ext, 32) ef_map_func(jajp, ef_map_ucs4_to_jisx0208_necibm_ext, 32) ef_map_func(jajp, ef_map_ucs4_to_sjis_ibm_ext, 32) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_jisx0208.h010064400017600000144000000014421356600661000200370ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_JISX0208_H__ #define __EF_UCS4_JISX0208_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_jisx0208_1983_to_ucs4(ef_char_t *ucs4, u_int16_t jis); int ef_map_jisx0208_nec_ext_to_ucs4(ef_char_t *ucs4, u_int16_t nec_ext); int ef_map_jisx0208_necibm_ext_to_ucs4(ef_char_t *ucs4, u_int16_t necibm_ext); int ef_map_sjis_ibm_ext_to_ucs4(ef_char_t *ucs4, u_int16_t ibm_ext); int ef_map_ucs4_to_jisx0208_1983(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_jisx0208_nec_ext(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_jisx0208_necibm_ext(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_sjis_ibm_ext(ef_char_t *non_ucs, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_jisx0212.c010064400017600000144000000005411356600661000200240ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_jisx0212.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_jisx0212.c" #else ef_map_func(jajp, ef_map_jisx0212_1990_to_ucs4, 16) ef_map_func(jajp, ef_map_ucs4_to_jisx0212_1990, 32) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_jisx0212.h010064400017600000144000000005221356600661000200300ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_JISX0212_H__ #define __EF_UCS4_JISX0212_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_jisx0212_1990_to_ucs4(ef_char_t *ucs4, u_int16_t jis); int ef_map_ucs4_to_jisx0212_1990(ef_char_t *jis, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_jisx0213.c010064400017600000144000000007211356600661000200250ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_jisx0213.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_jisx0213.c" #else ef_map_func(jajp, ef_map_jisx0213_2000_1_to_ucs4, 16) ef_map_func(jajp, ef_map_jisx0213_2000_2_to_ucs4, 16) ef_map_func(jajp, ef_map_ucs4_to_jisx0213_2000_1, 32) ef_map_func(jajp, ef_map_ucs4_to_jisx0213_2000_2, 32) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_jisx0213.h010064400017600000144000000007451356600661000200400ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_JISX0213_H__ #define __EF_UCS4_JISX0213_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_jisx0213_2000_1_to_ucs4(ef_char_t *ucs4, u_int16_t jis); int ef_map_jisx0213_2000_2_to_ucs4(ef_char_t *ucs4, u_int16_t jis); int ef_map_ucs4_to_jisx0213_2000_1(ef_char_t *jis, u_int32_t ucs4_code); int ef_map_ucs4_to_jisx0213_2000_2(ef_char_t *jis, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_johab.c010064400017600000144000000056111356600661000176300ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_johab.h" /* --- static functions --- */ /* 32 = 2^5 */ static int8_t johab_first_to_linear[32] = {0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static int8_t johab_middle_to_linear[32] = {0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 6, 7, 8, 9, 10, 11, 0, 0, 12, 13, 14, 15, 16, 17, 0, 0, 18, 19, 20, 21, 0, 0}; static int8_t johab_last_to_linear[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 0, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 0, 0}; static int8_t linear_to_johab_first[32] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static int8_t linear_to_johab_middle[32] = {3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21, 22, 23, 26, 27, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static int8_t linear_to_johab_last[32] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 0, 0, 0}; /* --- global functions --- */ int ef_map_johab_to_ucs4(ef_char_t *ucs4, u_int16_t johab) { int first_linear; int middle_linear; int last_linear; u_int16_t johab_linear; first_linear = johab_first_to_linear[(johab >> 10) & 0x1f]; middle_linear = johab_middle_to_linear[(johab >> 5) & 0x1f]; last_linear = johab_last_to_linear[johab & 0x1f]; if (first_linear == 0 || middle_linear == 0 || last_linear == 0) { /* illegal johab format */ return 0; } johab_linear = ((first_linear - 1) * 21 + (middle_linear - 1)) * 28 + (last_linear - 1); ef_int_to_bytes(ucs4->ch, 4, johab_linear + 0xac00); ucs4->size = 4; ucs4->cs = ISO10646_UCS4_1; ucs4->property = 0; return 1; } int ef_map_ucs4_to_johab(ef_char_t *johab, u_int32_t ucs4_code) { int first; int middle; int last; u_int32_t linear; u_int16_t johab_code; if (ucs4_code < 0xac00 || 0xd7a3 < ucs4_code) { /* not hangul */ return 0; } linear = ucs4_code - 0xac00; first = linear_to_johab_first[(linear / 28) / 21]; middle = linear_to_johab_middle[(linear / 28) % 21]; last = linear_to_johab_last[linear % 28]; johab_code = 0x8000 + (first << 10) + (middle << 5) + last; ef_int_to_bytes(johab->ch, 2, johab_code); johab->size = 2; johab->cs = JOHAB; johab->property = 0; return 1; } mlterm-3.8.9/encodefilter/src/ef_ucs4_johab.h010064400017600000144000000005001356600661000176250ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_JOHAB_H__ #define __EF_UCS4_JOHAB_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_johab_to_ucs4(ef_char_t *ucs4, u_int16_t johab); int ef_map_ucs4_to_johab(ef_char_t *johab, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_uk_map.c010064400017600000144000000012551356600661000170630ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_uk_map.h" #include #include "ef_ucs4_map.h" #include "ef_ucs4_iso8859.h" #include "ef_ucs4_koi8.h" static ef_map_ucs4_to_func_t map_ucs4_to_funcs[] = { ef_map_ucs4_to_koi8_u, ef_map_ucs4_to_iso8859_5_r, }; /* --- global functions --- */ int ef_map_ucs4_to_uk(ef_char_t *uk, ef_char_t *ucs4) { return ef_map_ucs4_to_with_funcs(uk, ucs4, map_ucs4_to_funcs, sizeof(map_ucs4_to_funcs) / sizeof(map_ucs4_to_funcs[0])); } int ef_map_koi8_u_to_iso8859_5_r(ef_char_t *iso8859, ef_char_t *uk) { return ef_map_via_ucs(iso8859, uk, ISO8859_5_R); } mlterm-3.8.9/encodefilter/src/ef_ucs4_koi8.c010064400017600000144000000010051356600661000174100ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_koi8.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_koi8.c" #else ef_map_func(8bits, ef_map_koi8_r_to_ucs4, 16) ef_map_func(8bits, ef_map_koi8_u_to_ucs4, 16) ef_map_func(8bits, ef_map_koi8_t_to_ucs4, 16) ef_map_func(8bits, ef_map_ucs4_to_koi8_r, 32) ef_map_func(8bits, ef_map_ucs4_to_koi8_u, 32) ef_map_func(8bits, ef_map_ucs4_to_koi8_t, 32) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_koi8.h010064400017600000144000000011241356600661000174170ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_KOI8_H__ #define __EF_UCS4_KOI8_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_koi8_r_to_ucs4(ef_char_t *ucs4, u_int16_t koi8_code); int ef_map_koi8_u_to_ucs4(ef_char_t *ucs4, u_int16_t koi8_code); int ef_map_koi8_t_to_ucs4(ef_char_t *ucs4, u_int16_t koi8_code); int ef_map_ucs4_to_koi8_r(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_koi8_u(ef_char_t *non_ucs, u_int32_t ucs4_code); int ef_map_ucs4_to_koi8_t(ef_char_t *non_ucs, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_ksc5601.c010064400017600000144000000012231356600661000176340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_ksc5601.h" #include "ef_ucs4_uhc.h" /* --- global functions --- */ int ef_map_ksc5601_1987_to_ucs4(ef_char_t *ucs4, u_int16_t ks) { /* converting to UHC */ ks |= 0x8080; if (ef_map_uhc_to_ucs4(ucs4, ks)) { return 1; } return 0; } int ef_map_ucs4_to_ksc5601_1987(ef_char_t *ks, u_int32_t ucs4_code) { if (ef_map_ucs4_to_uhc(ks, ucs4_code)) { if (ks->ch[0] >= 0xa1 && ks->ch[1] >= 0xa1) { /* converting to KSC5601_1987 */ ks->ch[0] &= 0x7f; ks->ch[1] &= 0x7f; ks->cs = KSC5601_1987; return 1; } } return 0; } mlterm-3.8.9/encodefilter/src/ef_ucs4_ksc5601.h010064400017600000144000000005141356600661000176430ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_KSC5601_H__ #define __EF_UCS4_KSC5601_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_ucs4_to_ksc5601_1987(ef_char_t *ks, u_int32_t ucs4_code); int ef_map_ksc5601_1987_to_ucs4(ef_char_t *ucs4, u_int16_t ks); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_map.c010064400017600000144000000237611356600661000173300ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_map.h" #include #include #include "ef_ucs4_iso8859.h" #include "ef_ucs4_viscii.h" #include "ef_ucs4_koi8.h" #include "ef_ucs4_iscii.h" #include "ef_ucs4_georgian_ps.h" #include "ef_ucs4_cp125x.h" #include "ef_ucs4_jisx0201.h" #include "ef_ucs4_jisx0208.h" #include "ef_ucs4_jisx0212.h" #include "ef_ucs4_jisx0213.h" #include "ef_ucs4_ksc5601.h" #include "ef_ucs4_uhc.h" #include "ef_ucs4_johab.h" #include "ef_ucs4_gb2312.h" #include "ef_ucs4_gbk.h" #include "ef_ucs4_big5.h" #include "ef_ucs4_cns11643.h" typedef struct map { ef_charset_t cs; int (*map_ucs4_to)(ef_char_t*, u_int32_t); int (*map_to_ucs4)(ef_char_t*, u_int16_t); } map_t; /* --- static variables --- */ static map_t map_table[] = { {ISO8859_1_R, ef_map_ucs4_to_iso8859_1_r, ef_map_iso8859_1_r_to_ucs4}, {ISO8859_2_R, ef_map_ucs4_to_iso8859_2_r, ef_map_iso8859_2_r_to_ucs4}, {ISO8859_3_R, ef_map_ucs4_to_iso8859_3_r, ef_map_iso8859_3_r_to_ucs4}, {ISO8859_4_R, ef_map_ucs4_to_iso8859_4_r, ef_map_iso8859_4_r_to_ucs4}, {ISO8859_5_R, ef_map_ucs4_to_iso8859_5_r, ef_map_iso8859_5_r_to_ucs4}, {ISO8859_6_R, ef_map_ucs4_to_iso8859_6_r, ef_map_iso8859_6_r_to_ucs4}, {ISO8859_7_R, ef_map_ucs4_to_iso8859_7_r, ef_map_iso8859_7_r_to_ucs4}, {ISO8859_8_R, ef_map_ucs4_to_iso8859_8_r, ef_map_iso8859_8_r_to_ucs4}, {ISO8859_9_R, ef_map_ucs4_to_iso8859_9_r, ef_map_iso8859_9_r_to_ucs4}, {ISO8859_10_R, ef_map_ucs4_to_iso8859_10_r, ef_map_iso8859_10_r_to_ucs4}, {TIS620_2533, ef_map_ucs4_to_tis620_2533, ef_map_tis620_2533_to_ucs4}, {ISO8859_13_R, ef_map_ucs4_to_iso8859_13_r, ef_map_iso8859_13_r_to_ucs4}, {ISO8859_14_R, ef_map_ucs4_to_iso8859_14_r, ef_map_iso8859_14_r_to_ucs4}, {ISO8859_15_R, ef_map_ucs4_to_iso8859_15_r, ef_map_iso8859_15_r_to_ucs4}, {ISO8859_16_R, ef_map_ucs4_to_iso8859_16_r, ef_map_iso8859_16_r_to_ucs4}, {TCVN5712_3_1993, ef_map_ucs4_to_tcvn5712_3_1993, ef_map_tcvn5712_3_1993_to_ucs4}, {VISCII, ef_map_ucs4_to_viscii, ef_map_viscii_to_ucs4}, {KOI8_R, ef_map_ucs4_to_koi8_r, ef_map_koi8_r_to_ucs4}, {KOI8_U, ef_map_ucs4_to_koi8_u, ef_map_koi8_u_to_ucs4}, {ISCII_ASSAMESE, ef_map_ucs4_to_iscii, ef_map_iscii_assamese_to_ucs4}, {ISCII_BENGALI, ef_map_ucs4_to_iscii, ef_map_iscii_bengali_to_ucs4}, {ISCII_GUJARATI, ef_map_ucs4_to_iscii, ef_map_iscii_gujarati_to_ucs4}, {ISCII_HINDI, ef_map_ucs4_to_iscii, ef_map_iscii_hindi_to_ucs4}, {ISCII_KANNADA, ef_map_ucs4_to_iscii, ef_map_iscii_kannada_to_ucs4}, {ISCII_MALAYALAM, ef_map_ucs4_to_iscii, ef_map_iscii_malayalam_to_ucs4}, {ISCII_ORIYA, ef_map_ucs4_to_iscii, ef_map_iscii_oriya_to_ucs4}, {ISCII_PUNJABI, ef_map_ucs4_to_iscii, ef_map_iscii_punjabi_to_ucs4}, {ISCII_TAMIL, ef_map_ucs4_to_iscii, ef_map_iscii_tamil_to_ucs4}, {ISCII_TELUGU, ef_map_ucs4_to_iscii, ef_map_iscii_telugu_to_ucs4}, {KOI8_T, ef_map_ucs4_to_koi8_t, ef_map_koi8_t_to_ucs4}, {GEORGIAN_PS, ef_map_ucs4_to_georgian_ps, ef_map_georgian_ps_to_ucs4}, {CP1250, ef_map_ucs4_to_cp1250, ef_map_cp1250_to_ucs4}, {CP1251, ef_map_ucs4_to_cp1251, ef_map_cp1251_to_ucs4}, {CP1252, ef_map_ucs4_to_cp1252, ef_map_cp1252_to_ucs4}, {CP1253, ef_map_ucs4_to_cp1253, ef_map_cp1253_to_ucs4}, {CP1254, ef_map_ucs4_to_cp1254, ef_map_cp1254_to_ucs4}, {CP1255, ef_map_ucs4_to_cp1255, ef_map_cp1255_to_ucs4}, {CP1256, ef_map_ucs4_to_cp1256, ef_map_cp1256_to_ucs4}, {CP1257, ef_map_ucs4_to_cp1257, ef_map_cp1257_to_ucs4}, {CP1258, ef_map_ucs4_to_cp1258, ef_map_cp1258_to_ucs4}, {CP874, ef_map_ucs4_to_cp874, ef_map_cp874_to_ucs4}, {JISX0201_ROMAN, ef_map_ucs4_to_jisx0201_roman, ef_map_jisx0201_roman_to_ucs4}, {JISX0201_KATA, ef_map_ucs4_to_jisx0201_kata, ef_map_jisx0201_kata_to_ucs4}, {JISX0208_1983, ef_map_ucs4_to_jisx0208_1983, ef_map_jisx0208_1983_to_ucs4}, {JISX0212_1990, ef_map_ucs4_to_jisx0212_1990, ef_map_jisx0212_1990_to_ucs4}, {JISX0213_2000_1, ef_map_ucs4_to_jisx0213_2000_1, ef_map_jisx0213_2000_1_to_ucs4}, {JISX0213_2000_2, ef_map_ucs4_to_jisx0213_2000_2, ef_map_jisx0213_2000_2_to_ucs4}, {JISC6226_1978_NEC_EXT, ef_map_ucs4_to_jisx0208_nec_ext, ef_map_jisx0208_nec_ext_to_ucs4}, {JISC6226_1978_NECIBM_EXT, ef_map_ucs4_to_jisx0208_necibm_ext, ef_map_jisx0208_necibm_ext_to_ucs4}, {SJIS_IBM_EXT, ef_map_ucs4_to_sjis_ibm_ext, ef_map_sjis_ibm_ext_to_ucs4}, {GB2312_80, ef_map_ucs4_to_gb2312_80, ef_map_gb2312_80_to_ucs4}, {GBK, ef_map_ucs4_to_gbk, ef_map_gbk_to_ucs4}, {CNS11643_1992_1, ef_map_ucs4_to_cns11643_1992_1, ef_map_cns11643_1992_1_to_ucs4}, {CNS11643_1992_2, ef_map_ucs4_to_cns11643_1992_2, ef_map_cns11643_1992_2_to_ucs4}, {CNS11643_1992_3, ef_map_ucs4_to_cns11643_1992_3, ef_map_cns11643_1992_3_to_ucs4}, {BIG5, ef_map_ucs4_to_big5, ef_map_big5_to_ucs4}, {HKSCS, ef_map_ucs4_to_hkscs, ef_map_hkscs_to_ucs4}, {KSC5601_1987, ef_map_ucs4_to_ksc5601_1987, ef_map_ksc5601_1987_to_ucs4}, {UHC, ef_map_ucs4_to_uhc, ef_map_uhc_to_ucs4}, {JOHAB, ef_map_ucs4_to_johab, ef_map_johab_to_ucs4}, }; /* --- global functions --- */ int ef_map_ucs4_to_cs(ef_char_t *non_ucs, ef_char_t *ucs4, ef_charset_t cs) { u_int32_t ucs4_code; map_t *map; static map_t *cached_map; #ifdef DEBUG if (ucs4->cs != ISO10646_UCS4_1) { bl_debug_printf(BL_DEBUG_TAG " ucs4 is not ucs4.\n"); return 0; } #endif ucs4_code = ef_char_to_int(ucs4); if (!(map = cached_map) || map->cs != cs) { size_t count; for (count = 0; count < sizeof(map_table) / sizeof(map_t); count++) { if (map_table[count].cs == cs) { cached_map = map = &map_table[count]; goto found; } } #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " %x cs is not supported to map to ucs4.\n", cs); #endif return 0; } found: if ((*map->map_ucs4_to)(non_ucs, ucs4_code)) { return 1; } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " UCS4 char(0x%.2x%.2x%.2x%.2x) is not supported to %x cs.\n", ucs4->ch[0], ucs4->ch[1], ucs4->ch[2], ucs4->ch[3], cs); #endif return 0; } } int ef_map_ucs4_to_with_funcs(ef_char_t *non_ucs, ef_char_t *ucs4, ef_map_ucs4_to_func_t *map_ucs4_to_funcs, size_t list_size) { size_t count; u_int32_t ucs4_code; #ifdef DEBUG if (ucs4->cs != ISO10646_UCS4_1) { bl_debug_printf(BL_DEBUG_TAG " ucs4 is not ucs4.\n"); return 0; } #endif ucs4_code = ef_char_to_int(ucs4); for (count = 0; count < list_size; count++) { if ((*map_ucs4_to_funcs[count])(non_ucs, ucs4_code)) { return 1; } } #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " UCS4 char(0x%.2x%.2x%.2x%.2x) is not supported.\n", ucs4->ch[0], ucs4->ch[1], ucs4->ch[2], ucs4->ch[3]); #endif return 0; } /* * using the default order of the mapping table. */ int ef_map_ucs4_to(ef_char_t *non_ucs, ef_char_t *ucs4) { size_t count; u_int32_t ucs4_code; map_t *map; static map_t *cached_map; #ifdef DEBUG if (ucs4->cs != ISO10646_UCS4_1) { bl_debug_printf(BL_DEBUG_TAG " ucs4 is not ucs4.\n"); return 0; } #endif ucs4_code = ef_char_to_int(ucs4); if ((map = cached_map) && (*map->map_ucs4_to)(non_ucs, ucs4_code)) { return 1; } for (count = 0; count < sizeof(map_table) / sizeof(map_table[0]); count++) { if ((*map_table[count].map_ucs4_to)(non_ucs, ucs4_code)) { ef_charset_t cs; cs = map_table[count].cs; /* * Don't cache the map functions of JISX0213_2000_1 and * non ISO2022 cs (GBK etc), in order not to map the * following chars automatically to JISX0213_2000_1, * GBK etc if a ucs4 character is mapped to the one of * JISX0213_2000_1, GBK etc which doesn't exist in * JISX0208, GB2312 etc. */ if (!IS_NON_ISO2022(cs) && cs != JISX0213_2000_1) { cached_map = &map_table[count]; } return 1; } } #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " UCS4 char(0x%.2x%.2x%.2x%.2x) is not supported.\n", ucs4->ch[0], ucs4->ch[1], ucs4->ch[2], ucs4->ch[3]); #endif return 0; } /* * using the default order of the mapping table. */ int ef_map_ucs4_to_iso2022cs(ef_char_t *non_ucs, ef_char_t *ucs4) { size_t count; u_int32_t ucs4_code; map_t *map; static map_t *cached_map; #ifdef DEBUG if (ucs4->cs != ISO10646_UCS4_1) { bl_debug_printf(BL_DEBUG_TAG " ucs4 is not ucs4.\n"); return 0; } #endif ucs4_code = ef_char_to_int(ucs4); if ((map = cached_map) && (*map->map_ucs4_to)(non_ucs, ucs4_code)) { return 1; } for (count = 0; count < sizeof(map_table) / sizeof(map_table[0]); count++) { if (IS_CS_BASED_ON_ISO2022(map_table[count].cs)) { if ((*map_table[count].map_ucs4_to)(non_ucs, ucs4_code)) { cached_map = &map_table[count]; return 1; } } } #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " UCS4 char(0x%.2x%.2x%.2x%.2x) is not supported.\n", ucs4->ch[0], ucs4->ch[1], ucs4->ch[2], ucs4->ch[3]); #endif return 0; } int ef_map_to_ucs4(ef_char_t *ucs4, ef_char_t *non_ucs) { u_int32_t code; map_t *map; static map_t *cached_map; if (non_ucs->cs == ISO10646_UCS4_1) { *ucs4 = *non_ucs; return 1; } code = ef_char_to_int(non_ucs); if (!(map = cached_map) || map->cs != non_ucs->cs) { size_t count; for (count = 0; count < sizeof(map_table) / sizeof(map_t); count++) { if (map_table[count].cs == non_ucs->cs) { cached_map = map = &map_table[count]; goto found; } } #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " %x cs is not supported to map to ucs4.\n", non_ucs->cs); #endif return 0; } found: if ((*map->map_to_ucs4)(ucs4, code)) { return 1; } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " this cs(%x) (code %x) cannot be mapped to UCS4.\n", non_ucs->cs, code); #endif return 0; } } int ef_map_via_ucs(ef_char_t *dst, ef_char_t *src, ef_charset_t cs) { ef_char_t ucs4; if (!ef_map_to_ucs4(&ucs4, src) || !ef_map_ucs4_to_cs(dst, &ucs4, cs)) { return 0; } return 1; } mlterm-3.8.9/encodefilter/src/ef_ucs4_map.h010064400017600000144000000020621356600661000173240ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_MAP_H__ #define __EF_UCS4_MAP_H__ #include /* u_xxx */ #include "ef_char.h" #define UCSBMP_IS_ALPHABET(ucs) (0 <= (ucs) && (ucs) <= 33ff) #define UCSBMP_IS_CJK(ucs) (0x3400 <= (ucs) && (ucs) <= 0x9fff) #define UCSBMP_IS_HANGUL(ucs) (0xac00 <= (ucs) && (ucs) <= 0xd7ff) #define UCSBMP_IS_SURROGATE(ucs) (0xd800 <= (ucs) && (ucs) <= 0xdfff) #define UCSBMP_IS_COMPAT(ucs) (0xf900 <= (ucs) && (ucs) <= 0xfffd) typedef int (*ef_map_ucs4_to_func_t)(ef_char_t*, u_int32_t); int ef_map_ucs4_to_cs(ef_char_t *non_ucs, ef_char_t *ucs4, ef_charset_t cs); int ef_map_ucs4_to_with_funcs(ef_char_t *non_ucs, ef_char_t *ucs4, ef_map_ucs4_to_func_t *map_ucs4_to_funcs, size_t list_size); int ef_map_ucs4_to(ef_char_t *non_ucs, ef_char_t *ucs4); int ef_map_ucs4_to_iso2022cs(ef_char_t *non_ucs, ef_char_t *ucs4); int ef_map_to_ucs4(ef_char_t *ucs4, ef_char_t *non_ucs); int ef_map_via_ucs(ef_char_t *dst, ef_char_t *src, ef_charset_t cs); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_tcvn5712_1.c010064400017600000144000000006661356600661000202630ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_tcvn5712_1.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_tcvn5712_1.c" #else /* * not compatible with ISO2022. * at the present time , not used. */ ef_map_func(8bits, ef_map_ucs4_to_tcvn5712_1_1993, 32) ef_map_func(8bits, ef_map_tcvn5712_1_1992_to_ucs4, 16) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_tcvn5712_1.h010064400017600000144000000005441356600661000202630ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_TCVN5712_1_H__ #define __EF_UCS4_TCVN5712_1_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_tcvn5712_1_1993_to_ucs4(ef_char_t *ucs4, u_int16_t tcvn_code); int ef_map_ucs4_to_tcvn5712_1_1993(ef_char_t *non_ucs, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_uhc.c010064400017600000144000000005031356600661000173170ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_uhc.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_uhc.c" #else ef_map_func(kokr, ef_map_uhc_to_ucs4, 16) ef_map_func(kokr, ef_map_ucs4_to_uhc, 32) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_uhc.h010064400017600000144000000004621356600661000173300ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_UHC_H__ #define __EF_UCS4_UHC_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_uhc_to_ucs4(ef_char_t *ucs4, u_int16_t ks); int ef_map_ucs4_to_uhc(ef_char_t *ks, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_viscii.c010064400017600000144000000005211356600661000200260ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs4_viscii.h" #include "ef_tblfunc_loader.h" /* --- global functions --- */ #ifdef NO_DYNAMIC_LOAD_TABLE #include "../module/ef_ucs4_viscii.c" #else ef_map_func(8bits, ef_map_viscii_to_ucs4, 16) ef_map_func(8bits, ef_map_ucs4_to_viscii, 32) #endif mlterm-3.8.9/encodefilter/src/ef_ucs4_viscii.h010064400017600000144000000005141356600661000200350ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS4_VISCII_H__ #define __EF_UCS4_VISCII_H__ #include /* u_xxx */ #include "ef_char.h" int ef_map_viscii_to_ucs4(ef_char_t *ucs4, u_int16_t viscii_code); int ef_map_ucs4_to_viscii(ef_char_t *non_ucs, u_int32_t ucs4_code); #endif mlterm-3.8.9/encodefilter/src/ef_ucs_property.c010064400017600000144000000037701356600661000203510ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_ucs_property.h" #ifndef REMOVE_PROPERTY_TABLE #include "table/ef_ucs_property.table" #endif /* '(i) | 0x2' is done in order for the result of BIT_SHIFT_32() to be over 0. */ #define BIT_SHIFT_32(i) ((((i) | 0x2) >> 1) & 0x7fffffff) #define DEFAULT_INTERVAL BIT_SHIFT_32(sizeof(ucs_property_table) / sizeof(ucs_property_table[0])) #if 0 #define SELF_TEST #endif #ifdef SELF_TEST static int debug_count; #endif /* --- global functions --- */ ef_property_t ef_get_ucs_property(u_int32_t ucs) { #ifndef REMOVE_PROPERTY_TABLE u_int32_t idx; u_int32_t interval; interval = DEFAULT_INTERVAL; idx = interval; #ifdef SELF_TEST debug_count = 0; #endif while (1) { #ifdef SELF_TEST debug_count++; #endif if (ucs < ucs_property_table[idx].first) { /* * If idx == 0, 'ucs < ucs_property_table[idx].first' * is always false because ucs_property_table[0].first * is 0. So following 'idx - 1' is never minus value. */ if (ucs_property_table[idx - 1].last < ucs) { return 0; } else { interval = BIT_SHIFT_32(interval); } idx -= interval; } else if (ucs_property_table[idx].last < ucs) { /* * If idx == max value * ( sizeof(ucs_property_table)/sizeof(ucs_property_table[0]) ), * 'ucs_property_table[idx].last < ucs' is always false because * ucs_property_table[max].last is 0xffffffff. * So following 'idx + 1' is never over max value. */ if (ucs < ucs_property_table[idx + 1].first) { return 0; } else { interval = BIT_SHIFT_32(interval); } idx += interval; } else { return ucs_property_table[idx].prop; } } #else return 0; #endif } #ifdef SELF_TEST int main(void) { u_int32_t ucs; for (ucs = 0; ucs <= 0x10ffff; ucs++) { ef_property_t prop = ef_get_ucs_property(ucs); printf("UCS %x => PROP %x (Loop %d)\n", ucs, prop, debug_count); } } #endif mlterm-3.8.9/encodefilter/src/ef_ucs_property.h010064400017600000144000000004001356600661000203410ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UCS_PROPERTY_H__ #define __EF_UCS_PROPERTY_H__ #include /* u_int32_t */ #include "ef_property.h" ef_property_t ef_get_ucs_property(u_int32_t ucs); #endif mlterm-3.8.9/encodefilter/src/ef_uk_map.h010064400017600000144000000004171356600661000170670ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UK_MAP_H__ #define __EF_UK_MAP_H__ #include "ef_char.h" int ef_map_ucs4_to_uk(ef_char_t *uk, ef_char_t *ucs4); int ef_map_koi8_u_to_iso8859_5_r(ef_char_t *iso8859, ef_char_t *uk); #endif mlterm-3.8.9/encodefilter/src/ef_utf16_conv.c010064400017600000144000000107611356600661000176030ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_utf16_conv.h" #include #include #include "ef_ucs4_map.h" typedef struct ef_utf16_conv { ef_conv_t conv; int is_bof; /* beginning of file */ int use_bom; } ef_utf16_conv_t; /* --- static functions --- */ static size_t convert_to_utf16(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { ef_utf16_conv_t *utf16_conv; size_t filled_size; ef_char_t ch; utf16_conv = (ef_utf16_conv_t*)conv; filled_size = 0; if (utf16_conv->use_bom && utf16_conv->is_bof) { if (dst_size < 2) { return 0; } /* * mark big endian */ *(dst++) = 0xfe; *(dst++) = 0xff; filled_size += 2; utf16_conv->is_bof = 0; } while (1) { if (!ef_parser_next_char(parser, &ch)) { return filled_size; } #if 0 if (ch.cs == ISO10646_UCS2_1) { if (filled_size + 2 > dst_size) { ef_parser_full_reset(parser); return filled_size; } (*dst++) = ch.ch[0]; (*dst++) = ch.ch[1]; filled_size += 2; } else #endif if (ch.cs == US_ASCII) { if (filled_size + 2 > dst_size) { ef_parser_full_reset(parser); return filled_size; } (*dst++) = '\0'; (*dst++) = ch.ch[0]; filled_size += 2; } else { if (ch.cs != ISO10646_UCS4_1) { ef_char_t ucs4_ch; if (ef_map_to_ucs4(&ucs4_ch, &ch)) { ch = ucs4_ch; } } if (ch.cs != ISO10646_UCS4_1 || ch.ch[0] > 0x0 || ch.ch[1] > 0x10) { if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } else if (ch.ch[1] == 0x0) { /* BMP */ if (filled_size + 2 > dst_size) { ef_parser_full_reset(parser); return filled_size; } (*dst++) = ch.ch[2]; (*dst++) = ch.ch[3]; filled_size += 2; } else /* if( 0x1 <= ch.ch[1] && ch.ch[1] <= 0x10) */ { /* surrogate pair */ u_int32_t linear; u_char c; if (filled_size + 4 > dst_size) { ef_parser_full_reset(parser); return filled_size; } linear = ef_bytes_to_int(ch.ch, 4) - 0x10000; c = (u_char)(linear / (0x100 * 0x400)); linear -= (c * 0x100 * 0x400); (*dst++) = c + 0xd8; c = (u_char)(linear / 0x400); linear -= (c * 0x400); (*dst++) = c; c = (u_char)(linear / 0x100); linear -= (c * 0x100); (*dst++) = c + 0xdc; (*dst++) = (u_char)linear; filled_size += 4; } } } } static size_t convert_to_utf16le(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { size_t size; int count; if ((size = convert_to_utf16(conv, dst, dst_size, parser)) == 0) { return 0; } for (count = 0; count < size - 1; count += 2) { u_char c; c = dst[count]; dst[count] = dst[count + 1]; dst[count + 1] = c; } return size; } static void conv_init(ef_conv_t *conv) { ef_utf16_conv_t *utf16_conv; utf16_conv = (ef_utf16_conv_t*)conv; utf16_conv->is_bof = 1; } static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_utf16_conv_new(void) { ef_utf16_conv_t *utf16_conv; if ((utf16_conv = malloc(sizeof(ef_utf16_conv_t))) == NULL) { return NULL; } utf16_conv->conv.convert = convert_to_utf16; utf16_conv->conv.init = conv_init; utf16_conv->conv.destroy = conv_destroy; utf16_conv->conv.illegal_char = NULL; utf16_conv->is_bof = 1; utf16_conv->use_bom = 0; return (ef_conv_t*)utf16_conv; } ef_conv_t *ef_utf16le_conv_new(void) { ef_utf16_conv_t *utf16_conv; if ((utf16_conv = malloc(sizeof(ef_utf16_conv_t))) == NULL) { return NULL; } utf16_conv->conv.convert = convert_to_utf16le; utf16_conv->conv.init = conv_init; utf16_conv->conv.destroy = conv_destroy; utf16_conv->conv.illegal_char = NULL; utf16_conv->is_bof = 1; utf16_conv->use_bom = 0; return (ef_conv_t*)utf16_conv; } void ef_utf16_conv_use_bom(ef_conv_t *conv) { ef_utf16_conv_t *utf16_conv; utf16_conv = (ef_utf16_conv_t*)conv; utf16_conv->use_bom = 1; } mlterm-3.8.9/encodefilter/src/ef_utf16_conv.h010064400017600000144000000004231356600661000176020ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UTF16_CONV_H__ #define __EF_UTF16_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_utf16_conv_new(void); ef_conv_t *ef_utf16le_conv_new(void); void ef_utf16_conv_use_bom(ef_conv_t *conv); #endif mlterm-3.8.9/encodefilter/src/ef_utf16_parser.c010064400017600000144000000102071356600661000201250ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_utf16_parser.h" #include #include #include #include "ef_ucs_property.h" typedef struct ef_utf16_parser { ef_parser_t parser; int is_big_endian; } ef_utf16_parser_t; /* --- static functions --- */ static void utf16_parser_init(ef_parser_t *parser) { ef_parser_init(parser); ((ef_utf16_parser_t*)parser)->is_big_endian = 1; } static void utf16le_parser_init(ef_parser_t *parser) { ef_parser_init(parser); ((ef_utf16_parser_t*)parser)->is_big_endian = 0; } static void utf16_parser_set_str(ef_parser_t *parser, u_char *str, size_t size) { parser->str = str; parser->left = size; parser->marked_left = 0; parser->is_eos = 0; } static void utf16_parser_destroy(ef_parser_t *parser) { free(parser); } static int utf16_parser_next_char(ef_parser_t *parser, ef_char_t *ucs4_ch) { ef_utf16_parser_t *utf16_parser; if (parser->is_eos) { return 0; } ef_parser_mark(parser); if (parser->left < 2) { parser->is_eos = 1; return 0; } utf16_parser = (ef_utf16_parser_t*)parser; if (memcmp(parser->str, "\xfe\xff", 2) == 0) { utf16_parser->is_big_endian = 1; ef_parser_n_increment(parser, 2); return utf16_parser_next_char(parser, ucs4_ch); } else if (memcmp(parser->str, "\xff\xfe", 2) == 0) { utf16_parser->is_big_endian = 0; ef_parser_n_increment(parser, 2); return utf16_parser_next_char(parser, ucs4_ch); } else { u_char ch[2]; u_int32_t ucs4; if (utf16_parser->is_big_endian) { ch[0] = parser->str[0]; ch[1] = parser->str[1]; } else { ch[0] = parser->str[1]; ch[1] = parser->str[0]; } if (0xd8 <= ch[0] && ch[0] <= 0xdb) { /* surrogate pair */ u_char ch2[2]; if (parser->left < 4) { parser->is_eos = 1; return 0; } if (utf16_parser->is_big_endian) { ch2[0] = parser->str[2]; ch2[1] = parser->str[3]; } else { ch2[0] = parser->str[3]; ch2[1] = parser->str[2]; } if (ch2[0] < 0xdc || 0xdf < ch2[0]) { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " illegal UTF-16 surrogate-pair format.\n"); #endif goto error; } ucs4 = ((ch[0] - 0xd8) * 0x100 * 0x400 + ch[1] * 0x400 + (ch2[0] - 0xdc) * 0x100 + ch2[1]) + 0x10000; #ifdef DEBUG if (ucs4 < 0x10000 || 0x10ffff < ucs4) { bl_warn_printf(BL_DEBUG_TAG " illegal UTF-16 surrogate-pair format.\n"); goto error; } #endif ef_int_to_bytes(ucs4_ch->ch, 4, ucs4); ef_parser_n_increment(parser, 4); } else { ef_parser_n_increment(parser, 2); if ((ucs4 = ef_bytes_to_int(ch, 2)) <= 0x7f) { ucs4_ch->ch[0] = ucs4; ucs4_ch->cs = US_ASCII; ucs4_ch->size = 1; ucs4_ch->property = 0; return 1; } ucs4_ch->ch[0] = 0x0; ucs4_ch->ch[1] = 0x0; ucs4_ch->ch[2] = ch[0]; ucs4_ch->ch[3] = ch[1]; } ucs4_ch->cs = ISO10646_UCS4_1; ucs4_ch->size = 4; ucs4_ch->property = ef_get_ucs_property(ucs4); return 1; } error: ef_parser_reset(parser); return 0; } /* --- global functions --- */ ef_parser_t *ef_utf16_parser_new(void) { ef_utf16_parser_t *utf16_parser; if ((utf16_parser = malloc(sizeof(ef_utf16_parser_t))) == NULL) { return NULL; } utf16_parser_init((ef_parser_t*)utf16_parser); utf16_parser->parser.init = utf16_parser_init; utf16_parser->parser.set_str = utf16_parser_set_str; utf16_parser->parser.destroy = utf16_parser_destroy; utf16_parser->parser.next_char = utf16_parser_next_char; return (ef_parser_t*)utf16_parser; } ef_parser_t *ef_utf16le_parser_new(void) { ef_utf16_parser_t *utf16_parser; if ((utf16_parser = malloc(sizeof(ef_utf16_parser_t))) == NULL) { return NULL; } utf16le_parser_init((ef_parser_t*)utf16_parser); utf16_parser->parser.init = utf16le_parser_init; utf16_parser->parser.set_str = utf16_parser_set_str; utf16_parser->parser.destroy = utf16_parser_destroy; utf16_parser->parser.next_char = utf16_parser_next_char; return (ef_parser_t*)utf16_parser; } mlterm-3.8.9/encodefilter/src/ef_utf16_parser.h010064400017600000144000000003631356600661000201340ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UTF16_PARSER_H__ #define __EF_UTF16_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_utf16_parser_new(void); ef_parser_t *ef_utf16le_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_utf32_conv.c010064400017600000144000000071121356600661000175750ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_utf32_conv.h" #include #include #include #include "ef_ucs4_map.h" typedef struct ef_utf32_conv { ef_conv_t conv; int is_bof; /* beginning of file */ int use_bom; } ef_utf32_conv_t; /* --- static functions --- */ static size_t convert_to_utf32(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { ef_utf32_conv_t *utf32_conv; size_t filled_size; ef_char_t ch; utf32_conv = (ef_utf32_conv_t*)conv; filled_size = 0; if (utf32_conv->use_bom && utf32_conv->is_bof) { if (dst_size < 4) { return 0; } /* * mark big endian */ *(dst++) = 0x0; *(dst++) = 0x0; *(dst++) = 0xfe; *(dst++) = 0xff; filled_size += 4; utf32_conv->is_bof = 0; } while (filled_size + 4 <= dst_size) { if (!ef_parser_next_char(parser, &ch)) { return filled_size; } if (ch.cs == US_ASCII) { dst[0] = 0x0; dst[1] = 0x0; dst[2] = 0x0; dst[3] = ch.ch[0]; } #if 0 else if (ch.cs == ISO10646_UCS2_1) { dst[0] = 0x0; dst[1] = 0x0; dst[2] = ch.ch[0]; dst[3] = ch.ch[1]; } #endif else if (ch.cs == ISO10646_UCS4_1) { dst[0] = ch.ch[0]; dst[1] = ch.ch[1]; dst[2] = ch.ch[2]; dst[3] = ch.ch[3]; } else { ef_char_t ucs4_ch; if (ef_map_to_ucs4(&ucs4_ch, &ch)) { memcpy(dst, ucs4_ch.ch, 4); } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } dst += 4; filled_size += 4; } return filled_size; } static size_t convert_to_utf32le(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { size_t size; int count; if ((size = convert_to_utf32(conv, dst, dst_size, parser)) == 0) { return 0; } for (count = 0; count < size - 3; count += 4) { u_char c; c = dst[count]; dst[count] = dst[count + 3]; dst[count + 3] = c; c = dst[count + 1]; dst[count + 1] = dst[count + 2]; dst[count + 2] = c; } return size; } static void conv_init(ef_conv_t *conv) { ef_utf32_conv_t *utf32_conv; utf32_conv = (ef_utf32_conv_t*)conv; utf32_conv->is_bof = 1; } static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_utf32_conv_new(void) { ef_utf32_conv_t *utf32_conv; if ((utf32_conv = malloc(sizeof(ef_utf32_conv_t))) == NULL) { return NULL; } utf32_conv->conv.convert = convert_to_utf32; utf32_conv->conv.init = conv_init; utf32_conv->conv.destroy = conv_destroy; utf32_conv->conv.illegal_char = NULL; utf32_conv->is_bof = 1; utf32_conv->use_bom = 0; return (ef_conv_t*)utf32_conv; } ef_conv_t *ef_utf32le_conv_new(void) { ef_utf32_conv_t *utf32_conv; if ((utf32_conv = malloc(sizeof(ef_utf32_conv_t))) == NULL) { return NULL; } utf32_conv->conv.convert = convert_to_utf32le; utf32_conv->conv.init = conv_init; utf32_conv->conv.destroy = conv_destroy; utf32_conv->conv.illegal_char = NULL; utf32_conv->is_bof = 1; utf32_conv->use_bom = 0; return (ef_conv_t*)utf32_conv; } void ef_utf32_conv_use_bom(ef_conv_t *conv) { ef_utf32_conv_t *utf32_conv; utf32_conv = (ef_utf32_conv_t*)conv; utf32_conv->use_bom = 1; } mlterm-3.8.9/encodefilter/src/ef_utf32_conv.h010064400017600000144000000004231356600661000176000ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UTF32_CONV_H__ #define __EF_UTF32_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_utf32_conv_new(void); ef_conv_t *ef_utf32le_conv_new(void); void ef_utf32_conv_use_bom(ef_conv_t *conv); #endif mlterm-3.8.9/encodefilter/src/ef_utf32_parser.c010064400017600000144000000061541356600661000201310ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_utf32_parser.h" #include #include #include #include "ef_ucs_property.h" typedef struct ef_utf32_parser { ef_parser_t parser; int is_big_endian; } ef_utf32_parser_t; /* --- static functions --- */ static void utf32_parser_init(ef_parser_t *parser) { ef_parser_init(parser); ((ef_utf32_parser_t*)parser)->is_big_endian = 1; } static void utf32le_parser_init(ef_parser_t *parser) { ef_parser_init(parser); ((ef_utf32_parser_t*)parser)->is_big_endian = 0; } static void utf32_parser_set_str(ef_parser_t *parser, u_char *str, size_t size) { parser->str = str; parser->left = size; parser->marked_left = 0; parser->is_eos = 0; } static void utf32_parser_destroy(ef_parser_t *parser) { free(parser); } static int utf32_parser_next_char(ef_parser_t *parser, ef_char_t *ucs4_ch) { ef_utf32_parser_t *utf32_parser; if (parser->is_eos) { return 0; } ef_parser_mark(parser); utf32_parser = (ef_utf32_parser_t*)parser; if (parser->left < 4) { parser->is_eos = 1; return 0; } if (memcmp(parser->str, "\x00\x00\xfe\xff", 4) == 0) { utf32_parser->is_big_endian = 1; ef_parser_n_increment(parser, 4); return utf32_parser_next_char(parser, ucs4_ch); } else if (memcmp(parser->str, "\xff\xfe\x00\x00", 4) == 0) { utf32_parser->is_big_endian = 0; ef_parser_n_increment(parser, 4); return utf32_parser_next_char(parser, ucs4_ch); } else { u_int32_t ucs4; if (utf32_parser->is_big_endian) { memcpy(ucs4_ch->ch, parser->str, 4); } else { ucs4_ch->ch[0] = parser->str[3]; ucs4_ch->ch[1] = parser->str[2]; ucs4_ch->ch[2] = parser->str[1]; ucs4_ch->ch[3] = parser->str[0]; } if ((ucs4 = ef_bytes_to_int(ucs4_ch->ch, 4)) <= 0x7f) { ucs4_ch->ch[0] = ucs4; ucs4_ch->cs = US_ASCII; ucs4_ch->size = 1; ucs4_ch->property = 0; } else { ucs4_ch->cs = ISO10646_UCS4_1; ucs4_ch->size = 4; ucs4_ch->property = ef_get_ucs_property(ucs4); } ef_parser_n_increment(parser, 4); return 1; } } /* --- global functions --- */ ef_parser_t *ef_utf32_parser_new(void) { ef_utf32_parser_t *utf32_parser; if ((utf32_parser = malloc(sizeof(ef_utf32_parser_t))) == NULL) { return NULL; } utf32_parser_init((ef_parser_t*)utf32_parser); utf32_parser->parser.init = utf32_parser_init; utf32_parser->parser.set_str = utf32_parser_set_str; utf32_parser->parser.destroy = utf32_parser_destroy; utf32_parser->parser.next_char = utf32_parser_next_char; return (ef_parser_t*)utf32_parser; } ef_parser_t *ef_utf32le_parser_new(void) { ef_utf32_parser_t *utf32_parser; if ((utf32_parser = malloc(sizeof(ef_utf32_parser_t))) == NULL) { return NULL; } utf32_parser_init((ef_parser_t*)utf32_parser); utf32_parser->parser.init = utf32le_parser_init; utf32_parser->parser.set_str = utf32_parser_set_str; utf32_parser->parser.destroy = utf32_parser_destroy; utf32_parser->parser.next_char = utf32_parser_next_char; return (ef_parser_t*)utf32_parser; } mlterm-3.8.9/encodefilter/src/ef_utf32_parser.h010064400017600000144000000003631356600661000201320ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UTF32_PARSER_H__ #define __EF_UTF32_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_utf32_parser_new(void); ef_parser_t *ef_utf32le_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_utf8_conv.c010064400017600000144000000100271356600661000175170ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_utf8_conv.h" #include #include #include "ef_ucs4_map.h" /* --- static functions --- */ static int remap_unsupported_charset(ef_char_t *ch) { ef_char_t c; if (ch->cs != US_ASCII && ch->cs != ISO10646_UCS4_1 /* && ch->cs != ISO10646_UCS2_1 */) { if (ef_map_to_ucs4(&c, ch)) { *ch = c; } else { return 0; } } return 1; } static size_t convert_to_utf8(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { size_t filled_size; ef_char_t ch; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { /* * utf8 encoding */ if (remap_unsupported_charset(&ch)) { u_int32_t ucs_ch; ucs_ch = ef_char_to_int(&ch); /* ucs_ch is unsigned */ if (/* 0x00 <= ucs_ch && */ ucs_ch <= 0x7f) { /* encoded to 8 bit */ if (filled_size + 1 > dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ucs_ch; filled_size++; } else if (ucs_ch <= 0x07ff) { /* encoded to 16bit */ if (filled_size + 2 > dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ((ucs_ch >> 6) & 0xff) | 0xc0; *(dst++) = (ucs_ch & 0x3f) | 0x80; filled_size += 2; } else if (ucs_ch <= 0xffff) { if (filled_size + 3 > dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ((ucs_ch >> 12) & 0x0f) | 0xe0; *(dst++) = ((ucs_ch >> 6) & 0x3f) | 0x80; *(dst++) = (ucs_ch & 0x3f) | 0x80; filled_size += 3; } else if (ucs_ch <= 0x1fffff) { if (filled_size + 4 > dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ((ucs_ch >> 18) & 0x07) | 0xf0; *(dst++) = ((ucs_ch >> 12) & 0x3f) | 0x80; *(dst++) = ((ucs_ch >> 6) & 0x3f) | 0x80; *(dst++) = (ucs_ch & 0x3f) | 0x80; filled_size += 4; } else if (ucs_ch <= 0x03ffffff) { if (filled_size + 5 > dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ((ucs_ch >> 24) & 0x03) | 0xf8; *(dst++) = ((ucs_ch >> 18) & 0x3f) | 0x80; *(dst++) = ((ucs_ch >> 12) & 0x3f) | 0x80; *(dst++) = ((ucs_ch >> 6) & 0x3f) | 0x80; *(dst++) = (ucs_ch & 0x3f) | 0x80; filled_size += 5; } else if (ucs_ch <= 0x7fffffff) { if (filled_size + 6 > dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ((ucs_ch >> 30) & 0x01) | 0xfc; *(dst++) = ((ucs_ch >> 24) & 0x3f) | 0x80; *(dst++) = ((ucs_ch >> 18) & 0x3f) | 0x80; *(dst++) = ((ucs_ch >> 12) & 0x3f) | 0x80; *(dst++) = ((ucs_ch >> 6) & 0x3f) | 0x80; *(dst++) = (ucs_ch & 0x3f) | 0x80; filled_size += 6; } else { #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " strange ucs4 character %x\n", ucs_ch); #endif if (filled_size >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = ' '; filled_size++; } } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } return filled_size; } static void conv_init(ef_conv_t *conv) {} static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_utf8_conv_new(void) { ef_conv_t *conv; if ((conv = malloc(sizeof(ef_conv_t))) == NULL) { return NULL; } conv->convert = convert_to_utf8; conv->init = conv_init; conv->destroy = conv_destroy; conv->illegal_char = NULL; return conv; } mlterm-3.8.9/encodefilter/src/ef_utf8_conv.h010064400017600000144000000002731356600661000175260ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UTF8_CONV_H__ #define __EF_UTF8_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_utf8_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_utf8_parser.c010064400017600000144000000104021356600661000200430ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_utf8_parser.h" #include #include #include "ef_ucs_property.h" /* --- static functions --- */ static int utf8_parser_next_char(ef_parser_t *utf8_parser, ef_char_t *ucs4_ch) { u_char *utf8_ch; u_int32_t ucs4_int; size_t bytes; if (utf8_parser->is_eos) { return 0; } ef_parser_mark(utf8_parser); utf8_ch = utf8_parser->str; if ((utf8_ch[0] & 0xc0) == 0x80) { goto utf8_err; } else if ((utf8_ch[0] & 0x80) == 0) { /* 0x00 - 0x7f */ ucs4_ch->ch[0] = utf8_ch[0]; ef_parser_n_increment(utf8_parser, 1); ucs4_ch->size = 1; ucs4_ch->cs = US_ASCII; ucs4_ch->property = 0; return 1; } else if ((utf8_ch[0] & 0xe0) == 0xc0) { bytes = 2; if (utf8_parser->left < bytes) { utf8_parser->is_eos = 1; return 0; } if (utf8_ch[1] < 0x80) { goto utf8_err; } ucs4_int = (((utf8_ch[0] & 0x1f) << 6) & 0xffffffc0) | (utf8_ch[1] & 0x3f); if (ucs4_int < 0x80) { goto utf8_err; } } else if ((utf8_ch[0] & 0xf0) == 0xe0) { bytes = 3; if (utf8_parser->left < bytes) { utf8_parser->is_eos = 1; return 0; } if (utf8_ch[1] < 0x80 || utf8_ch[2] < 0x80) { goto utf8_err; } ucs4_int = (((utf8_ch[0] & 0x0f) << 12) & 0xffff000) | (((utf8_ch[1] & 0x3f) << 6) & 0xffffffc0) | (utf8_ch[2] & 0x3f); if (ucs4_int < 0x800) { goto utf8_err; } } else if ((utf8_ch[0] & 0xf8) == 0xf0) { bytes = 4; if (utf8_parser->left < bytes) { utf8_parser->is_eos = 1; return 0; } if (utf8_ch[1] < 0x80 || utf8_ch[2] < 0x80 || utf8_ch[3] < 0x80) { goto utf8_err; } ucs4_int = (((utf8_ch[0] & 0x07) << 18) & 0xfffc0000) | (((utf8_ch[1] & 0x3f) << 12) & 0xffff000) | (((utf8_ch[2] & 0x3f) << 6) & 0xffffffc0) | (utf8_ch[3] & 0x3f); if (ucs4_int < 0x10000) { goto utf8_err; } } else if ((utf8_ch[0] & 0xfc) == 0xf8) { bytes = 5; if (utf8_parser->left < bytes) { utf8_parser->is_eos = 1; return 0; } if (utf8_ch[1] < 0x80 || utf8_ch[2] < 0x80 || utf8_ch[3] < 0x80 || utf8_ch[4] < 0x80) { goto utf8_err; } ucs4_int = (((utf8_ch[0] & 0x03) << 24) & 0xff000000) | (((utf8_ch[1] & 0x3f) << 18) & 0xfffc0000) | (((utf8_ch[2] & 0x3f) << 12) & 0xffff000) | (((utf8_ch[3] & 0x3f) << 6) & 0xffffffc0) | (utf8_ch[4] & 0x3f); if (ucs4_int < 0x200000) { goto utf8_err; } } else if ((utf8_ch[0] & 0xfe) == 0xfc) { bytes = 6; if (utf8_parser->left < bytes) { utf8_parser->is_eos = 1; return 0; } if (utf8_ch[1] < 0x80 || utf8_ch[2] < 0x80 || utf8_ch[3] < 0x80 || utf8_ch[4] < 0x80 || utf8_ch[5] < 0x80) { goto utf8_err; } ucs4_int = (((utf8_ch[0] & 0x01 << 30) & 0xc0000000)) | (((utf8_ch[1] & 0x3f) << 24) & 0xff000000) | (((utf8_ch[2] & 0x3f) << 18) & 0xfffc0000) | (((utf8_ch[3] & 0x3f) << 12) & 0xffff000) | (((utf8_ch[4] & 0x3f) << 6) & 0xffffffc0) | (utf8_ch[4] & 0x3f); if (ucs4_int < 0x4000000) { goto utf8_err; } } else { goto utf8_err; } ef_int_to_bytes(ucs4_ch->ch, 4, ucs4_int); ef_parser_n_increment(utf8_parser, bytes); ucs4_ch->size = 4; ucs4_ch->cs = ISO10646_UCS4_1; ucs4_ch->property = ef_get_ucs_property(ucs4_int); return 1; utf8_err: #ifdef DEBUG bl_warn_printf(BL_DEBUG_TAG " illegal utf8 sequence [0x%.2x ...].\n", utf8_ch[0]); #endif ef_parser_reset(utf8_parser); return 0; } static void utf8_parser_set_str(ef_parser_t *utf8_parser, u_char *str, size_t size) { utf8_parser->str = str; utf8_parser->left = size; utf8_parser->marked_left = 0; utf8_parser->is_eos = 0; } static void utf8_parser_destroy(ef_parser_t *s) { free(s); } /* --- global functions --- */ ef_parser_t *ef_utf8_parser_new(void) { ef_parser_t *utf8_parser; if ((utf8_parser = malloc(sizeof(ef_parser_t))) == NULL) { return NULL; } ef_parser_init(utf8_parser); utf8_parser->init = ef_parser_init; utf8_parser->set_str = utf8_parser_set_str; utf8_parser->destroy = utf8_parser_destroy; utf8_parser->next_char = utf8_parser_next_char; return utf8_parser; } mlterm-3.8.9/encodefilter/src/ef_utf8_parser.h010064400017600000144000000003051356600661000200510ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_UTF8_PARSER_H__ #define __EF_UTF8_PARSER_H__ #include "ef_parser.h" ef_parser_t *ef_utf8_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_viet_map.c010064400017600000144000000013461356600661000174140ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_viet_map.h" #include #include "ef_ucs4_map.h" #include "ef_ucs4_viscii.h" #include "ef_ucs4_iso8859.h" /* --- static variables --- */ static ef_map_ucs4_to_func_t map_ucs4_to_funcs[] = { ef_map_ucs4_to_tcvn5712_3_1993, ef_map_ucs4_to_viscii, }; /* --- global functions --- */ int ef_map_ucs4_to_viet(ef_char_t *viet, ef_char_t *ucs4) { return ef_map_ucs4_to_with_funcs(viet, ucs4, map_ucs4_to_funcs, sizeof(map_ucs4_to_funcs) / sizeof(map_ucs4_to_funcs[0])); } int ef_map_viscii_to_tcvn5712_3_1993(ef_char_t *tcvn, ef_char_t *viscii) { return ef_map_via_ucs(tcvn, viscii, TCVN5712_3_1993); } mlterm-3.8.9/encodefilter/src/ef_viet_map.h010064400017600000144000000004341356600661000174160ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_VIET_MAP_H__ #define __EF_VIET_MAP_H__ #include "ef_char.h" int ef_map_ucs4_to_viet(ef_char_t *viet, ef_char_t *ucs4); int ef_map_viscii_to_tcvn5712_3_1993(ef_char_t *tcvn, ef_char_t *viscii); #endif mlterm-3.8.9/encodefilter/src/ef_xct_conv.c010064400017600000144000000201411356600661000174250ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_xct_conv.h" #include /* strcasecmp */ #include #include /* bl_get_codeset() */ #include #include "ef_locale_ucs4_map.h" #include "ef_ucs4_map.h" #include "ef_zh_tw_map.h" #include "ef_zh_cn_map.h" #include "ef_iso2022_conv.h" #include "ef_iso2022_intern.h" /* --- static functions --- */ static void remap_unsupported_charset(ef_char_t *ch) { ef_char_t c; if (ch->cs == ISO10646_UCS4_1) { if (!ef_map_locale_ucs4_to(&c, ch)) { return; } *ch = c; } if (strcasecmp(bl_get_codeset(), "GBK") == 0) { if (ch->cs == GB2312_80) { if (ef_map_gb2312_80_to_gbk(&c, ch)) { *ch = c; } return; } else if (ch->cs == GBK) { return; } } else { if (ch->cs == GBK) { if (ef_map_gbk_to_gb2312_80(&c, ch)) { *ch = c; } return; } else if (ch->cs == GB2312_80) { return; } } if (strcasecmp(bl_get_codeset(), "BIG5") == 0 || strcasecmp(bl_get_codeset(), "BIG5HKSCS") == 0) { if (ch->cs == CNS11643_1992_1) { if (ef_map_cns11643_1992_1_to_big5(&c, ch)) { *ch = c; } return; } else if (ch->cs == CNS11643_1992_2) { if (ef_map_cns11643_1992_2_to_big5(&c, ch)) { *ch = c; } return; } else if (ch->cs == BIG5) { return; } } else { if (ch->cs == BIG5) { if (ef_map_big5_to_cns11643_1992(&c, ch)) { *ch = c; } return; } else if (ch->cs == CNS11643_1992_1 || ch->cs == CNS11643_1992_2) { return; } } ef_iso2022_remap_unsupported_charset(ch); } static size_t convert_to_xct_intern(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser, int big5_buggy) { size_t filled_size; ef_char_t ch; ef_iso2022_conv_t *iso2022_conv; iso2022_conv = (ef_iso2022_conv_t*)conv; filled_size = 0; while (ef_parser_next_char(parser, &ch)) { int count; remap_unsupported_charset(&ch); if (IS_CS94SB(ch.cs) || IS_CS94MB(ch.cs)) { if (ch.cs != iso2022_conv->g0) { if (IS_CS94SB(ch.cs)) { if (filled_size + ch.size + 2 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = '\x1b'; *(dst++) = '('; *(dst++) = CS94SB_FT(ch.cs); filled_size += 3; } else { if (filled_size + ch.size + 3 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = '\x1b'; *(dst++) = '$'; *(dst++) = '('; *(dst++) = CS94MB_FT(ch.cs); filled_size += 4; } iso2022_conv->g0 = ch.cs; } else { if (filled_size + ch.size - 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } } for (count = 0; count < ch.size; count++) { *(dst++) = ch.ch[count]; } filled_size += ch.size; } else if (IS_CS96SB(ch.cs) || IS_CS96MB(ch.cs)) { if (ch.cs != iso2022_conv->g1) { if (IS_CS96SB(ch.cs)) { if (filled_size + ch.size + 2 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = '\x1b'; *(dst++) = '-'; *(dst++) = CS96SB_FT(ch.cs); filled_size += 3; } else { if (filled_size + ch.size + 3 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } *(dst++) = '\x1b'; *(dst++) = '$'; *(dst++) = '-'; *(dst++) = CS96MB_FT(ch.cs); filled_size += 4; } iso2022_conv->g1 = ch.cs; } else { if (filled_size + ch.size - 1 >= dst_size) { ef_parser_full_reset(parser); return filled_size; } } for (count = 0; count < ch.size; count++) { *(dst++) = MAP_TO_GR(ch.ch[count]); } filled_size += ch.size; } /* * Non-Standard Character Sets */ else if (ch.cs == BIG5 || ch.cs == HKSCS || ch.cs == GBK) { char *prefix; if (ch.cs == BIG5 || ch.cs == HKSCS) { /* * !! Notice !! * Big5 CTEXT implementation of XFree86 4.1.0 or before is very BUGGY! */ if (big5_buggy) { prefix = "\x1b\x25\x2f\x32\x80\x89" "BIG5-0" "\x02\x80\x89" "BIG5-0" "\x02"; iso2022_conv->g0 = BIG5; iso2022_conv->g1 = BIG5; } else { prefix = "\x1b\x25\x2f\x32\x80\x89" "big5-0" "\x02"; } } else /* if( ch.cs == GBK) */ { prefix = "\x1b\x25\x2f\x32\x80\x88" "gbk-0" "\x02"; } if (filled_size + strlen(prefix) + ch.size > dst_size) { ef_parser_full_reset(parser); return filled_size; } memcpy(dst, prefix, strlen(prefix)); dst += strlen(prefix); *(dst++) = ch.ch[0]; *(dst++) = ch.ch[1]; filled_size += (strlen(prefix) + 2); } else if (IS_ISCII(ch.cs) || ch.cs == KOI8_R || ch.cs == KOI8_U || ch.cs == VISCII) { char *prefix; if (IS_ISCII(ch.cs)) { prefix = "\x1b\x25\x2f\x31\x80\x8b" "iscii-dev" "\x02"; } else if (ch.cs == KOI8_R) { prefix = "\x1b\x25\x2f\x31\x80\x88" "koi8-r" "\x02"; } else if (ch.cs == KOI8_U) { prefix = "\x1b\x25\x2f\x31\x80\x88" "koi8-u" "\x02"; } else /* if( ch.cs == VISCII) */ { prefix = "\x1b\x25\x2f\x31\x80\x8d" "viscii1.1-1" "\x02"; } if (filled_size + strlen(prefix) + ch.size > dst_size) { ef_parser_full_reset(parser); return filled_size; } memcpy(dst, prefix, strlen(prefix)); dst += strlen(prefix); *(dst++) = ch.ch[0]; filled_size += (strlen(prefix) + 1); } else if (conv->illegal_char) { size_t size; int is_full; size = (*conv->illegal_char)(conv, dst, dst_size - filled_size, &is_full, &ch); if (is_full) { ef_parser_full_reset(parser); return filled_size; } dst += size; filled_size += size; } } return filled_size; } static size_t convert_to_xct(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_xct_intern(conv, dst, dst_size, parser, 0); } static size_t convert_to_xct_big5_buggy(ef_conv_t *conv, u_char *dst, size_t dst_size, ef_parser_t *parser) { return convert_to_xct_intern(conv, dst, dst_size, parser, 1); } static void xct_conv_init(ef_conv_t *conv) { ef_iso2022_conv_t *iso2022_conv; iso2022_conv = (ef_iso2022_conv_t*)conv; iso2022_conv->gl = &iso2022_conv->g0; iso2022_conv->gr = &iso2022_conv->g1; iso2022_conv->g0 = US_ASCII; iso2022_conv->g1 = ISO8859_1_R; iso2022_conv->g2 = UNKNOWN_CS; iso2022_conv->g3 = UNKNOWN_CS; } static void conv_destroy(ef_conv_t *conv) { free(conv); } /* --- global functions --- */ ef_conv_t *ef_xct_conv_new(void) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } xct_conv_init((ef_conv_t*)iso2022_conv); iso2022_conv->conv.convert = convert_to_xct; iso2022_conv->conv.init = xct_conv_init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t*)iso2022_conv; } ef_conv_t *ef_xct_big5_buggy_conv_new(void) { ef_iso2022_conv_t *iso2022_conv; if ((iso2022_conv = malloc(sizeof(ef_iso2022_conv_t))) == NULL) { return NULL; } xct_conv_init((ef_conv_t*)iso2022_conv); iso2022_conv->conv.convert = convert_to_xct_big5_buggy; iso2022_conv->conv.init = xct_conv_init; iso2022_conv->conv.destroy = conv_destroy; iso2022_conv->conv.illegal_char = NULL; return (ef_conv_t*)iso2022_conv; } mlterm-3.8.9/encodefilter/src/ef_xct_conv.h010064400017600000144000000003461356600661000174370ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_XCT_CONV_H__ #define __EF_XCT_CONV_H__ #include "ef_conv.h" ef_conv_t *ef_xct_conv_new(void); ef_conv_t *ef_xct_big5_buggy_conv_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_xct_parser.c010064400017600000144000000124461356600661000177650ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_xct_parser.h" #include /* strncmp */ #include #include /* malloc */ #include "ef_iso2022_parser.h" typedef struct ef_xct_parser { ef_iso2022_parser_t iso2022_parser; size_t left; ef_charset_t cs; int8_t big5_buggy; } ef_xct_parser_t; /* --- static functions --- */ static int xct_non_iso2022_is_started(ef_iso2022_parser_t *iso2022_parser) { ef_xct_parser_t *xct_parser; u_char m; u_char l; size_t len; u_char *cs_str; size_t cs_len; #ifdef __DEBUG { int i; bl_msg_printf("non iso2022 sequence -->\n"); for (i = 0; i < iso2022_parser->parser.left; i++) { bl_msg_printf("%.2x ", iso2022_parser->parser.str[i]); } bl_msg_printf("\n"); } #endif xct_parser = (ef_xct_parser_t *)iso2022_parser; /* * parsing string len. */ m = *xct_parser->iso2022_parser.parser.str; if (ef_parser_increment(xct_parser) == 0) { ef_parser_reset(xct_parser); return 0; } l = *xct_parser->iso2022_parser.parser.str; len = ((m - 128) * 128) + (l - 128); /* * parsing charset name. */ cs_str = xct_parser->iso2022_parser.parser.str + 1; cs_len = 0; while (1) { if (len == 0) { return 1; } if (ef_parser_increment(xct_parser) == 0) { ef_parser_reset(xct_parser); return 0; } len--; if (*xct_parser->iso2022_parser.parser.str == 0x02) { break; } cs_len++; } if (xct_parser->iso2022_parser.non_iso2022_cs == XCT_NON_ISO2022_CS_1) { if (cs_len == 9 && strncmp((char *)cs_str, "iscii-dev", cs_len) == 0) { /* XXX */ xct_parser->cs = ISCII_HINDI; } else if (cs_len == 6 && strncmp((char *)cs_str, "koi8-r", cs_len) == 0) { xct_parser->cs = KOI8_R; } else if (cs_len == 6 && strncmp((char *)cs_str, "koi8-u", cs_len) == 0) { xct_parser->cs = KOI8_U; } else if (cs_len == 11 && strncmp((char *)cs_str, "viscii1.1-1", cs_len) == 0) { xct_parser->cs = VISCII; } else { /* unknown cs */ return 0; } } else if (xct_parser->iso2022_parser.non_iso2022_cs == XCT_NON_ISO2022_CS_2) { if (cs_len == 6 && strncmp((char *)cs_str, "big5-0", cs_len) == 0) { xct_parser->cs = BIG5; } else if (cs_len == 6 && strncmp((char *)cs_str, "BIG5-0", cs_len) == 0) { /* * !! Notice !! * Big5 CTEXT implementation of XFree86 4.1.0 or before is very BUGGY! */ if (xct_parser->iso2022_parser.parser.left >= 10 && memcmp(xct_parser->iso2022_parser.parser.str, "\x02\x80\x89" "BIG5-0" "\x02", 10) == 0) { /* skip to next 0x2 */ xct_parser->iso2022_parser.parser.str += 9; xct_parser->iso2022_parser.parser.left -= 9; xct_parser->big5_buggy = 1; } xct_parser->cs = BIG5; } else if (cs_len == 5 && strncmp((char *)cs_str, "gbk-0", cs_len) == 0) { xct_parser->cs = GBK; } else { /* unknown cs */ return 0; } } else { /* unknown cs */ return 0; } xct_parser->left = len; /* * ok. */ #ifdef __DEBUG bl_debug_printf(BL_DEBUG_TAG " parsing str of cs %x len %d.\n", xct_parser->cs, len); #endif ef_parser_increment(xct_parser); return 1; } static int xct_next_non_iso2022_byte(ef_iso2022_parser_t *iso2022_parser, ef_char_t *ch) { ef_xct_parser_t *xct_parser; xct_parser = (ef_xct_parser_t *)iso2022_parser; if (xct_parser->left == 0) { /* * !! Notice !! * Big5 CTEXT implementation of XFree86 4.1.0 or before is very BUGGY! */ if (xct_parser->big5_buggy && xct_parser->cs == BIG5 && 0xa1 <= *xct_parser->iso2022_parser.parser.str && *xct_parser->iso2022_parser.parser.str <= 0xf9) { xct_parser->left = 2; } else { xct_parser->cs = UNKNOWN_CS; xct_parser->big5_buggy = 0; return 0; } } ch->ch[ch->size++] = *xct_parser->iso2022_parser.parser.str; xct_parser->left--; ch->cs = xct_parser->cs; ef_parser_increment(xct_parser); return 1; } static void xct_parser_init(ef_parser_t *parser) { ef_xct_parser_t *xct_parser; ef_parser_init(parser); xct_parser = (ef_xct_parser_t *)parser; xct_parser->iso2022_parser.g0 = US_ASCII; xct_parser->iso2022_parser.g1 = ISO8859_1_R; xct_parser->iso2022_parser.g2 = UNKNOWN_CS; xct_parser->iso2022_parser.g3 = UNKNOWN_CS; xct_parser->iso2022_parser.gl = &xct_parser->iso2022_parser.g0; xct_parser->iso2022_parser.gr = &xct_parser->iso2022_parser.g1; xct_parser->iso2022_parser.non_iso2022_cs = UNKNOWN_CS; xct_parser->iso2022_parser.is_single_shifted = 0; } /* --- global functions --- */ ef_parser_t *ef_xct_parser_new(void) { ef_xct_parser_t *xct_parser; if ((xct_parser = malloc(sizeof(ef_xct_parser_t))) == NULL) { return NULL; } ef_iso2022_parser_init_func(&xct_parser->iso2022_parser); xct_parser_init(&xct_parser->iso2022_parser.parser); xct_parser->left = 0; xct_parser->cs = UNKNOWN_CS; xct_parser->big5_buggy = 0; /* overrride */ xct_parser->iso2022_parser.non_iso2022_is_started = xct_non_iso2022_is_started; xct_parser->iso2022_parser.next_non_iso2022_byte = xct_next_non_iso2022_byte; xct_parser->iso2022_parser.parser.init = xct_parser_init; return (ef_parser_t *)xct_parser; } mlterm-3.8.9/encodefilter/src/ef_xct_parser.h010064400017600000144000000003001356600661000177540ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_XCT_PARSER_H__ #define __EF_XCT_PARSER_H__ #include "ef_conv.h" ef_parser_t *ef_xct_parser_new(void); #endif mlterm-3.8.9/encodefilter/src/ef_zh_cn_map.c010064400017600000144000000021721356600661000175440ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_zh_cn_map.h" #include "ef_iso2022_intern.h" #include "ef_ucs4_map.h" #include "ef_ucs4_gb2312.h" #include "ef_ucs4_gbk.h" /* --- static variables --- */ static ef_map_ucs4_to_func_t map_ucs4_to_funcs[] = { ef_map_ucs4_to_gb2312_80, ef_map_ucs4_to_gbk, }; /* --- global functions --- */ int ef_map_ucs4_to_zh_cn(ef_char_t *zhcn, ef_char_t *ucs4) { return ef_map_ucs4_to_with_funcs(zhcn, ucs4, map_ucs4_to_funcs, sizeof(map_ucs4_to_funcs) / sizeof(map_ucs4_to_funcs[0])); } int ef_map_gbk_to_gb2312_80(ef_char_t *gb2312, ef_char_t *gbk) { if (0xa1 <= gbk->ch[0] && gbk->ch[0] <= 0xfe && 0xa1 <= gbk->ch[1] && gbk->ch[1] <= 0xfe) { gb2312->ch[0] = UNMAP_FROM_GR(gbk->ch[0]); gb2312->ch[1] = UNMAP_FROM_GR(gbk->ch[1]); gb2312->size = 2; gb2312->cs = GB2312_80; return 1; } else { return 0; } } int ef_map_gb2312_80_to_gbk(ef_char_t *gbk, ef_char_t *gb2312) { gbk->ch[0] = MAP_TO_GR(gb2312->ch[0]); gbk->ch[1] = MAP_TO_GR(gb2312->ch[1]); gbk->size = 2; gbk->cs = GBK; return 1; } mlterm-3.8.9/encodefilter/src/ef_zh_cn_map.h010064400017600000144000000005261356600661000175520ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ZH_CN_MAP_H__ #define __EF_ZH_CN_MAP_H__ #include "ef_char.h" int ef_map_ucs4_to_zh_cn(ef_char_t *zhcn, ef_char_t *ucs4); int ef_map_gbk_to_gb2312_80(ef_char_t *gb2312, ef_char_t *gbk); int ef_map_gb2312_80_to_gbk(ef_char_t *gbk, ef_char_t *gb2312); #endif mlterm-3.8.9/encodefilter/src/ef_zh_hk_map.c010064400017600000144000000010321356600661000175400ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_zh_hk_map.h" #include "ef_ucs4_map.h" #include "ef_ucs4_big5.h" /* --- static variables --- */ static ef_map_ucs4_to_func_t map_ucs4_to_funcs[] = { ef_map_ucs4_to_hkscs, ef_map_ucs4_to_big5, }; /* --- global functions --- */ int ef_map_ucs4_to_zh_hk(ef_char_t *zhhk, ef_char_t *ucs4) { return ef_map_ucs4_to_with_funcs(zhhk, ucs4, map_ucs4_to_funcs, sizeof(map_ucs4_to_funcs) / sizeof(map_ucs4_to_funcs[0])); } mlterm-3.8.9/encodefilter/src/ef_zh_hk_map.h010064400017600000144000000003241356600661000175500ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ZH_HK_MAP_H__ #define __EF_ZH_HK_MAP_H__ #include "ef_char.h" int ef_map_ucs4_to_zh_hk(ef_char_t *zhhk, ef_char_t *ucs4); #endif mlterm-3.8.9/encodefilter/src/ef_zh_tw_map.c010064400017600000144000000023241356600661000175750ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include "ef_zh_tw_map.h" #include #include "ef_ucs4_map.h" #include "ef_ucs4_cns11643.h" #include "ef_ucs4_big5.h" /* --- static variables --- */ static ef_map_ucs4_to_func_t map_ucs4_to_funcs[] = { ef_map_ucs4_to_big5, ef_map_ucs4_to_cns11643_1992_1, ef_map_ucs4_to_cns11643_1992_2, ef_map_ucs4_to_cns11643_1992_3, }; /* --- global functions --- */ int ef_map_ucs4_to_zh_tw(ef_char_t *zhtw, ef_char_t *ucs4) { return ef_map_ucs4_to_with_funcs(zhtw, ucs4, map_ucs4_to_funcs, sizeof(map_ucs4_to_funcs) / sizeof(map_ucs4_to_funcs[0])); } /* * BIG5 <=> CNS11643_1992_[1-2] */ int ef_map_big5_to_cns11643_1992(ef_char_t *cns, ef_char_t *big5) { ef_char_t ucs4; if (!ef_map_to_ucs4(&ucs4, big5)) { return 0; } if (!ef_map_ucs4_to_cs(cns, &ucs4, CNS11643_1992_1) && !ef_map_ucs4_to_cs(cns, &ucs4, CNS11643_1992_2)) { return 0; } return 1; } int ef_map_cns11643_1992_1_to_big5(ef_char_t *big5, ef_char_t *cns) { return ef_map_via_ucs(big5, cns, BIG5); } int ef_map_cns11643_1992_2_to_big5(ef_char_t *big5, ef_char_t *cns) { return ef_map_via_ucs(big5, cns, BIG5); } mlterm-3.8.9/encodefilter/src/Makefile.in010064400017600000144000000064501356600661000170400ustar kenuserstop_builddir = .. top_srcdir = @top_srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ libdir = @libdir@ CC = @CC@ LIBTOOL = @LIBTOOL@ INSTALL = @INSTALL@ LIBDIR = $(DESTDIR)$(libdir) INCDIR = $(DESTDIR)$(prefix)/include VPATH = $(top_srcdir)/src INCDIR_TMP = $(top_builddir)/include CFLAGS = $(CFLAGS_LOCAL) @DEB_CFLAGS@ @POBL_CFLAGS@ @TABLE_CFLAGS@ @CFLAGS@ @CPPFLAGS@ \ -DLIBDIR=\"$(libdir)\" -I/usr/local/include PARSER_OBJ = ef_parser.o ef_iso2022_parser.o ef_iso8859_parser.o ef_xct_parser.o \ ef_eucjp_parser.o ef_euckr_parser.o ef_euccn_parser.o ef_iso2022jp_parser.o \ ef_iso2022kr_parser.o ef_sjis_parser.o ef_big5_parser.o ef_euctw_parser.o \ ef_utf16_parser.o ef_iso2022cn_parser.o ef_hz_parser.o ef_utf8_parser.o \ ef_johab_parser.o ef_8bit_parser.o ef_utf32_parser.o ef_codepoint_parser.o CONV_OBJ = ef_iso8859_conv.o ef_iso2022_conv.o ef_iso2022jp_conv.o ef_iso2022kr_conv.o \ ef_sjis_conv.o ef_utf8_conv.o ef_big5_conv.o ef_euctw_conv.o ef_iso2022cn_conv.o \ ef_hz_conv.o ef_utf16_conv.o ef_eucjp_conv.o ef_euckr_conv.o ef_euccn_conv.o \ ef_johab_conv.o ef_8bit_conv.o ef_xct_conv.o ef_utf32_conv.o MAP_OBJ = ef_ucs4_map.o ef_locale_ucs4_map.o ef_zh_cn_map.o ef_zh_tw_map.o ef_zh_hk_map.o \ ef_ko_kr_map.o ef_viet_map.o ef_ja_jp_map.o ef_ru_map.o ef_uk_map.o ef_tg_map.o PROP_OBJ = ef_ucs_property.o ef_jis_property.o UCS_TABLE_OBJ = ef_ucs4_iso8859.o ef_ucs4_viscii.o ef_ucs4_tcvn5712_1.o \ ef_ucs4_koi8.o ef_ucs4_georgian_ps.o ef_ucs4_cp125x.o ef_ucs4_iscii.o \ ef_ucs4_jisx0201.o ef_ucs4_jisx0208.o ef_ucs4_jisx0212.o \ ef_ucs4_jisx0213.o ef_ucs4_ksc5601.o ef_ucs4_uhc.o ef_ucs4_johab.o \ ef_ucs4_gb2312.o ef_ucs4_gbk.o ef_ucs4_big5.o ef_ucs4_cns11643.o \ ef_gb18030_2000_intern.o OBJ = $(PARSER_OBJ) $(CONV_OBJ) $(MAP_OBJ) ef_char.o ef_sjis_env.o ef_tblfunc_loader.o \ $(PROP_OBJ) $(UCS_TABLE_OBJ) INC = $(PARSER_OBJ:.o=.h) $(CONV_OBJ:.o=.h) $(MAP_OBJ:.o=.h) ef_char.h ef_sjis_env.h \ ef_property.h ef_ucs_property.h ef_charset.h ef_conv.h LIBNAME = libmef LIBNAME_DEB = libmef_deb MAJOR = 3 MINOR = 0 LIBTOOL_CC = $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) LIBTOOL_LINK = $(LIBTOOL) --mode=link $(CC) @LDFLAGS@ LIBTOOL_INSTALL = $(LIBTOOL) --mode=install $(INSTALL) all : $(LIBNAME).la collect-headers debug : $(MAKE) LIBNAME=$(LIBNAME_DEB) $(LIBNAME_DEB).a $(LIBNAME).a : $(OBJ) $(LIBTOOL_LINK) -o $(LIBNAME).a $(OBJ:.o=.lo) $(LIBNAME).la : $(OBJ) $(LIBTOOL_LINK) -o $(LIBNAME).la $(OBJ:.o=.lo) -rpath $(libdir) \ @NO_UNDEFINED_FLAG@ @DEXPORT@ -version-info $(MAJOR):$(MINOR):0 @POBL_LIBS@ $(INCDIR_TMP)/mef : mkdir -p $(INCDIR_TMP)/mef collect-headers : $(INCDIR_TMP)/mef $(INC) for file in $(INC) ; do \ if test -f $${file} ; \ then cp $${file} $(INCDIR_TMP)/mef ; \ else cp $(top_srcdir)/src/$${file} $(INCDIR_TMP)/mef ; \ fi \ done touch collect-headers install: install-inc install-la install-deb : $(MAKE) LIBNAME=$(LIBNAME_DEB) install-ar install-inc : $(INCDIR)/mef cp $(INCDIR_TMP)/mef/*.h $(INCDIR)/mef install-la : $(LIBDIR) $(LIBTOOL_INSTALL) *.la $(LIBDIR) install-ar : $(LIBDIR) $(LIBTOOL_INSTALL) *.a $(LIBDIR) uninstall: rm -rf $(LIBDIR)/*mef.* $(INCDIR)/mef $(INCDIR)/mef : mkdir -p $(INCDIR)/mef $(LIBDIR) : mkdir -p $(LIBDIR) clean : rm -rf $(OBJ) $(OBJ:.o=.lo) .libs *.la *.a $(INCDIR_TMP) collect-headers .SUFFIXES : .c.o .c.o : $(LIBTOOL_CC) -c $< mlterm-3.8.9/encodefilter/src/ef_zh_tw_map.h010064400017600000144000000006441356600661000176050ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #ifndef __EF_ZH_TW_MAP_H__ #define __EF_ZH_TW_MAP_H__ #include "ef_char.h" int ef_map_ucs4_to_zh_tw(ef_char_t *zhtw, ef_char_t *ucs4); int ef_map_big5_to_cns11643_1992(ef_char_t *cns, ef_char_t *big5); int ef_map_cns11643_1992_1_to_big5(ef_char_t *big5, ef_char_t *cns); int ef_map_cns11643_1992_2_to_big5(ef_char_t *big5, ef_char_t *cns); #endif mlterm-3.8.9/encodefilter/util004075500017600000144000000000001356600661000151005ustar kenusersmlterm-3.8.9/encodefilter/util/big5_table.pl010064400017600000144000000007031356600661000175060ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my @all_lines = ; my @big5_lines ; foreach $line (@all_lines) { # %IRREVERSIBLE% may be at the begginig of line. if( $line =~ /.*[ ]*\/x([0-9a-f]*)\/x([0-9a-f]*).*/) { push( @big5_lines , "0x$2$3 $1") ; } } ucs_mappings::parse( '([^ ]*)[ ]*([^ ]*).*$' , \@big5_lines) ; ucs_mappings::output_table_to_ucs( "big5" , 2) ; ucs_mappings::output_table_ucs_to( "big5" , 2) ; mlterm-3.8.9/encodefilter/util/big5hkscs_table.pl010064400017600000144000000013271356600661000205450ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my @all_lines = ; my @big5_lines ; my @hkscs_lines ; foreach $line (@all_lines) { # %IRREVERSIBLE% may be at the begginig of line. if( $line =~ /.*[ ]*\/x([0-9a-f]*)\/x([0-9a-f]*).*/) { my $ucs = $1 ; my $big5_str = "0x$2$3" ; my $big5 = oct $big5_str ; if( ( 0xa140 <= $big5 and $big5 <= 0xa3bf) or ( 0xa440 <= $big5 and $big5 <= 0xc67e) or ( 0xc940 <= $big5 and $big5 <= 0xf9d5)) { # excluded } else { push( @hkscs_lines , "$big5_str $ucs") ; } } } ucs_mappings::parse( '([^ ]*)[ ]*([^ ]*).*$' , \@hkscs_lines) ; ucs_mappings::output_table_to_ucs( "hkscs" , 2) ; ucs_mappings::output_table_ucs_to( "hkscs" , 2) ; mlterm-3.8.9/encodefilter/util/cns11643_1992_table.pl010064400017600000144000000015711356600661000205320ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "cns11643_1992" ; my @all_lines = ; my @cns1 ; my @cns2 ; my @cns3 ; foreach $line (@all_lines) { if( $line =~ /^0x1(.*)$/) { push( @cns1 , "0x$1") ; } elsif( $line =~ /^0x2(.*)$/) { push( @cns2 , "0x$1") ; } elsif( $line =~ /^0xE(.*)$/) { push( @cns3 , "0x$1") ; } } ucs_mappings::parse( '([^ ]*)[ ]*([^ ]*).*$' , \@cns1) ; ucs_mappings::output_table_to_ucs( "${cs}_1" , 2) ; ucs_mappings::output_table_ucs_to( "${cs}_1" , 2) ; ucs_mappings::reset ; ucs_mappings::parse( '([^ ]*)[ ]*([^ ]*).*$' , \@cns2) ; ucs_mappings::output_table_to_ucs( "${cs}_2" , 2) ; ucs_mappings::output_table_ucs_to( "${cs}_2" , 2) ; ucs_mappings::reset ; ucs_mappings::parse( '([^ ]*)[ ]*([^ ]*).*$' , \@cns3) ; ucs_mappings::output_table_to_ucs( "${cs}_3" , 2) ; ucs_mappings::output_table_ucs_to( "${cs}_3" , 2) ; mlterm-3.8.9/encodefilter/util/cp1250_table.pl010064400017600000144000000006671356600661000176030ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "cp1250" ; my @all_lines = ; my @cp1250 ; foreach $line (@all_lines) { if( $line =~ /^(0x[0-9A-F]*)[ ]*(0x[0-9A-F]*).*$/) { $code = oct "$1" ; if( $code >= 0x80) { push( @cp1250 , "$1 $2") ; } } } ucs_mappings::parse( '^(0x[0-9A-F]*) (0x[0-9A-F]*)$' , \@cp1250) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/cp1251_table.pl010064400017600000144000000006671356600661000176040ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "cp1251" ; my @all_lines = ; my @cp1251 ; foreach $line (@all_lines) { if( $line =~ /^(0x[0-9A-F]*)[ ]*(0x[0-9A-F]*).*$/) { $code = oct "$1" ; if( $code >= 0x80) { push( @cp1251 , "$1 $2") ; } } } ucs_mappings::parse( '^(0x[0-9A-F]*) (0x[0-9A-F]*)$' , \@cp1251) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/cp1252_table.pl010064400017600000144000000006671356600661000176050ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "cp1252" ; my @all_lines = ; my @cp1252 ; foreach $line (@all_lines) { if( $line =~ /^(0x[0-9A-F]*)[ ]*(0x[0-9A-F]*).*$/) { $code = oct "$1" ; if( $code >= 0x80) { push( @cp1252 , "$1 $2") ; } } } ucs_mappings::parse( '^(0x[0-9A-F]*) (0x[0-9A-F]*)$' , \@cp1252) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/cp1253_table.pl010064400017600000144000000006671356600661000176060ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "cp1253" ; my @all_lines = ; my @cp1253 ; foreach $line (@all_lines) { if( $line =~ /^(0x[0-9A-F]*)[ ]*(0x[0-9A-F]*).*$/) { $code = oct "$1" ; if( $code >= 0x80) { push( @cp1253 , "$1 $2") ; } } } ucs_mappings::parse( '^(0x[0-9A-F]*) (0x[0-9A-F]*)$' , \@cp1253) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/cp1254_table.pl010064400017600000144000000006671356600661000176070ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "cp1254" ; my @all_lines = ; my @cp1254 ; foreach $line (@all_lines) { if( $line =~ /^(0x[0-9A-F]*)[ ]*(0x[0-9A-F]*).*$/) { $code = oct "$1" ; if( $code >= 0x80) { push( @cp1254 , "$1 $2") ; } } } ucs_mappings::parse( '^(0x[0-9A-F]*) (0x[0-9A-F]*)$' , \@cp1254) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/cp1255_table.pl010064400017600000144000000006671356600661000176100ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "cp1255" ; my @all_lines = ; my @cp1255 ; foreach $line (@all_lines) { if( $line =~ /^(0x[0-9A-F]*)[ ]*(0x[0-9A-F]*).*$/) { $code = oct "$1" ; if( $code >= 0x80) { push( @cp1255 , "$1 $2") ; } } } ucs_mappings::parse( '^(0x[0-9A-F]*) (0x[0-9A-F]*)$' , \@cp1255) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/cp1256_table.pl010064400017600000144000000006671356600661000176110ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "cp1256" ; my @all_lines = ; my @cp1256 ; foreach $line (@all_lines) { if( $line =~ /^(0x[0-9A-F]*)[ ]*(0x[0-9A-F]*).*$/) { $code = oct "$1" ; if( $code >= 0x80) { push( @cp1256 , "$1 $2") ; } } } ucs_mappings::parse( '^(0x[0-9A-F]*) (0x[0-9A-F]*)$' , \@cp1256) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/cp1257_table.pl010064400017600000144000000006671356600661000176120ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "cp1257" ; my @all_lines = ; my @cp1257 ; foreach $line (@all_lines) { if( $line =~ /^(0x[0-9A-F]*)[ ]*(0x[0-9A-F]*).*$/) { $code = oct "$1" ; if( $code >= 0x80) { push( @cp1257 , "$1 $2") ; } } } ucs_mappings::parse( '^(0x[0-9A-F]*) (0x[0-9A-F]*)$' , \@cp1257) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/cp1258_table.pl010064400017600000144000000006671356600661000176130ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "cp1258" ; my @all_lines = ; my @cp1258 ; foreach $line (@all_lines) { if( $line =~ /^(0x[0-9A-F]*)[ ]*(0x[0-9A-F]*).*$/) { $code = oct "$1" ; if( $code >= 0x80) { push( @cp1258 , "$1 $2") ; } } } ucs_mappings::parse( '^(0x[0-9A-F]*) (0x[0-9A-F]*)$' , \@cp1258) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/gb18030_2000_table.pl010064400017600000144000000033351356600661000203110ustar kenusers#!/usr/pkg/bin/perl sub print_range { my $u_first = shift ; my $u_last = shift ; my $b_first = shift ; my $b_last = shift ; printf TO " { 0x%.4x , 0x%.4x , { $b_first } , { $b_last } } ,\n" , $u_first , $u_last ; } my @all_lines = ; open TO , ">ef_gb18030_2000_range.table" ; print TO << "EOF" ; /* * ef_gb18030_2000_range.table */ #ifndef __EF_GB18030_2000_RANGE_TABLE__ #define __EF_GB18030_2000_RANGE_TABLE__ /* ---> static variables <--- */ static gb18030_range_t gb18030_ranges[] = { EOF my $u_first = -1 ; my $u_last = 0 ; my $b_first = 0 ; my $b_last = 0 ; foreach $line (@all_lines) { if( $line =~ //) { if( $u_first eq 0 or $u_first eq -1) { $u_first = oct "0x$1" ; $b_first = "0x$2 , 0x$3 , 0x$4 , 0x$5" ; } else { $u_last = oct "0x$1" ; $b_last = "0x$2 , 0x$3 , 0x$4 , 0x$5" ; } } elsif( $line =~ //) { my $u_first = oct "0x$1" ; my $u_last = oct "0x$2" ; my $b_first = "0x$3 , 0x$4 , 0x$5 , 0x$6" ; my $b_last = "0x$7 , 0x$8 , 0x$9 , 0x$10" ; print_range( $u_first , $u_last , $b_first , $b_last) ; } else { if( $u_first eq -1) { next ; } elsif( $u_first ne 0) { if( $u_last eq 0) { $u_last = $u_first ; $b_last = $b_first ; } print_range( $u_first , $u_last , $b_first , $b_last) ; # reset $u_first = $u_last = $b_first = $b_last = 0 ; } } } print TO "} ;\n\n\n" ; print TO "#endif\n" ; close TO ; mlterm-3.8.9/encodefilter/util/gbk_table.pl010064400017600000144000000006351356600661000174270ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "gbk" ; # or CP936 my @gbk_lines ; my @all_lines = ; for $line (@all_lines) { if( $line =~ /^(0x[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z])[ ]+[^ ]+.*$/) { push( @gbk_lines , $line) ; } } ucs_mappings::parse( '^([^ ]+)[ ]+([^ ]+).*$' , \@gbk_lines) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 2) ; mlterm-3.8.9/encodefilter/util/georgian_ps_table.pl010064400017600000144000000007121356600661000211550ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "georgian_ps" ; my @all_lines = ; my @georgian ; foreach $line (@all_lines) { if( $line =~ /^[ ]*\/x([0-9a-f]*).*$/) { $code = oct "0x$2" ; if( $code >= 0x80) { push( @georgian , "0x$2 0x$1") ; } } } ucs_mappings::parse( '^(0x[0-9a-f]*) (0x[0-9A-F]*)$' , \@georgian) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/iso8859_10_table.pl010064400017600000144000000006461356600661000203160ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "iso8859_10_r" ; my @all_lines = ; my @iso8859 ; foreach $line (@all_lines) { if( $line =~ /^([^ ]*)(.*)$/) { $code = oct $1 ; if( $code >= 0xa1) { push( @iso8859 , $line) ; } } } ucs_mappings::parse( '^([^ ]*)[ ]*([^ ]*).*$' , \@iso8859) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/iso8859_13_table.pl010064400017600000144000000006461356600661000203210ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "iso8859_13_r" ; my @all_lines = ; my @iso8859 ; foreach $line (@all_lines) { if( $line =~ /^([^ ]*)(.*)$/) { $code = oct $1 ; if( $code >= 0xa1) { push( @iso8859 , $line) ; } } } ucs_mappings::parse( '^([^ ]*)[ ]*([^ ]*).*$' , \@iso8859) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/johab_table.pl010064400017600000144000000013551356600661000177470ustar kenusers#!/usr/pkg/bin/perl # # this eats hangul-codes.txt and outputs tables. # use ucs_mappings () ; my @all_lines = ; %to_johab ; %from_johab ; my $to_johab_start ; my $from_johab_start ; for $line (@all_lines) { if( $line =~ /^[A-Z0-9]+[ ]+[A-Z0-9]+[ ]+([A-Z0-9]+)[ ]+([A-Z0-9]+).*$/) { $_uhc = $1 ; $_johab = $2 ; if( ! ($_uhc =~ /0x.*/)) { $uhc = oct "0x${_uhc}" ; } else { $uhc = oct $_uhc ; } if( ! ($_johab =~ /0x.*/)) { $johab = oct "0x${_johab}" ; } else { $johab = oct $_johab ; } $to_johab{$uhc} = $johab ; $from_johab{$johab} = $uhc ; } } ucs_mappings::output_separated( "johab" , "uhc" , 2 , \%from_johab) ; ucs_mappings::output_separated( "uhc" , "johab" , 2 , \%to_johab) ; mlterm-3.8.9/encodefilter/util/iso8859_14_table.pl010064400017600000144000000006461356600661000203220ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "iso8859_14_r" ; my @all_lines = ; my @iso8859 ; foreach $line (@all_lines) { if( $line =~ /^([^ ]*)(.*)$/) { $code = oct $1 ; if( $code >= 0xa1) { push( @iso8859 , $line) ; } } } ucs_mappings::parse( '^([^ ]*)[ ]*([^ ]*).*$' , \@iso8859) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/iso8859_16_table.pl010064400017600000144000000006461356600661000203240ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "iso8859_16_r" ; my @all_lines = ; my @iso8859 ; foreach $line (@all_lines) { if( $line =~ /^([^ ]*)(.*)$/) { $code = oct $1 ; if( $code >= 0xa1) { push( @iso8859 , $line) ; } } } ucs_mappings::parse( '^([^ ]*)[ ]*([^ ]*).*$' , \@iso8859) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/iso8859_2_table.pl010064400017600000144000000006441356600661000202350ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "iso8859_2_r" ; my @all_lines = ; my @iso8859 ; foreach $line (@all_lines) { if( $line =~ /^([^ ]*)(.*)$/) { $code = oct $1 ; if( $code >= 0xa1) { push( @iso8859 , $line) ; } } } ucs_mappings::parse( '^([^ ]*)[ ]*([^ ]*).*$' , \@iso8859) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/iso8859_3_table.pl010064400017600000144000000006441356600661000202360ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "iso8859_3_r" ; my @all_lines = ; my @iso8859 ; foreach $line (@all_lines) { if( $line =~ /^([^ ]*)(.*)$/) { $code = oct $1 ; if( $code >= 0xa1) { push( @iso8859 , $line) ; } } } ucs_mappings::parse( '^([^ ]*)[ ]*([^ ]*).*$' , \@iso8859) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/iso8859_4_table.pl010064400017600000144000000006441356600661000202370ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "iso8859_4_r" ; my @all_lines = ; my @iso8859 ; foreach $line (@all_lines) { if( $line =~ /^([^ ]*)(.*)$/) { $code = oct $1 ; if( $code >= 0xa1) { push( @iso8859 , $line) ; } } } ucs_mappings::parse( '^([^ ]*)[ ]*([^ ]*).*$' , \@iso8859) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/jisx0208_1983_table.pl010064400017600000144000000004201356600661000206270ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "jisx0208_1983" ; my @all_lines = ; ucs_mappings::parse( '[^ ]*[ ]*([^ ]*)[ ]*([^ ]*).*$' , \@all_lines) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 2) ; mlterm-3.8.9/encodefilter/util/jisx0208_nec_ext_table.pl010064400017600000144000000006021356600661000216520ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "jisx0208_nec_ext" ; my @jis_lines ; my @all_lines = ; for $line (@all_lines) { if( $line =~ /^(0x[A-Z0-9]+)[ ]+[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]+(0x[A-Z0-9]+).*$/) { push( @jis_lines , "$2 $1") ; } } ucs_mappings::parse( '^([^ ]+)[ ]+([^ ]+).*$' , \@jis_lines) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; mlterm-3.8.9/encodefilter/util/jisx0208_necibm_ext_table.pl010064400017600000144000000006201356600661000223420ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "jisx0208_necibm_ext" ; my @jis_lines ; my @all_lines = ; for $line (@all_lines) { if( $line =~ /^(0x[A-Z0-9]+)[ ]+[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]+(0x[A-Z0-9]+).*$/) { push( @jis_lines , "$2 $1") ; } } ucs_mappings::parse( '^([^ ]+)[ ]+([^ ]+).*$' , \@jis_lines) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; mlterm-3.8.9/encodefilter/util/jisx0212_1990_table.pl010064400017600000144000000004061356600661000206240ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "jisx0212_1990" ; my @all_lines = ; ucs_mappings::parse( '^([^ ]*)[ ]*([^ ]*).*$' , \@all_lines) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 2) ; mlterm-3.8.9/encodefilter/util/jisx0213_2000_table.pl010064400017600000144000000016421356600661000206070ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs1 = "jisx0213_2000_1" ; my $cs2 = "jisx0213_2000_2" ; my @all_lines = ; my @jisx0213_1 ; my @jisx0213_2 ; foreach $line (@all_lines) { if( $line =~ /^[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,0,[^,]*,.*$/) { next ; } if( $line =~ /^[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,ffff,[^,]*,.*$/) { next ; } if( $line =~ /^1,.*$/) { push( @jisx0213_1 , $line) ; } elsif( $line =~ /^2,.*$/) { push( @jisx0213_2 , $line) ; } } ucs_mappings::parse( '^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*),[^,]*,[^,]*,([^,]*),[^,]*,.*$' , \@jisx0213_1) ; ucs_mappings::output_table_to_ucs( ${cs1} , 2) ; ucs_mappings::output_table_ucs_to( ${cs1} , 2) ; ucs_mappings::reset ; ucs_mappings::parse( '^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*),[^,]*,[^,]*,([^,]*),[^,]*,.*$' , \@jisx0213_2) ; ucs_mappings::output_table_to_ucs( ${cs2} , 2) ; ucs_mappings::output_table_ucs_to( ${cs2} , 2) ; mlterm-3.8.9/encodefilter/util/koi8_t_table.pl010064400017600000144000000006711356600661000200610ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "koi8_t" ; my @all_lines = ; my @koi8 ; foreach $line (@all_lines) { if( $line =~ /^[ ]*\/x([0-9a-f]*).*$/) { $code = oct "0x$2" ; if( $code >= 0x80) { push( @koi8 , "0x$2 0x$1") ; } } } ucs_mappings::parse( '^(0x[0-9a-f]*) (0x[0-9A-F]*)$' , \@koi8) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/sjis_ibm_ext_table.pl010064400017600000144000000005351356600661000213420ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "sjis_ibm_ext" ; my @ibm_lines ; my @all_lines = ; for $line (@all_lines) { if( $line =~ /^(0x[A-Z0-9]+)[ ]+(0x[A-Z0-9]+).*$/) { push( @ibm_lines , "$2 $1") ; } } ucs_mappings::parse( '^([^ ]+)[ ]+([^ ]+).*$' , \@ibm_lines) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; mlterm-3.8.9/encodefilter/util/tcvn_table.pl010064400017600000144000000007671356600661000176440ustar kenusers#!/usr/pkg/bin/perl # source file is vscii.txt use ucs_mappings () ; my $cs = "tcvn5712_1993" ; my @all_lines = ; my @tcvn ; foreach my $line (@all_lines) { if( $line =~ /^(0x[0-9a-z]*).*$/) { my $code = oct $1 ; if( 0x20 <= $code and $code <= 0x7e) { next ; } else { push( @tcvn , $line) ; } } } ucs_mappings::parse( '^(0x[0-9a-z]+)[ ]+(0x[0-9a-z]+).*$' , \@tcvn) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/ucs_mappings.pm010064400017600000144000000165741356600661000202170ustar kenusers# # ucs parser module. # package ucs_mappings ; $start = 0 ; $end = 0 ; %to_ucs ; %ucs_to ; sub reset() { %to_ucs = 0 ; %ucs_to = 0 ; } sub parse($$;$) { my $regexp = shift ; my $all_lines = shift ; # # property # 0x1 = NON UCS decimal # 0x2 = UCS decimal # 0x4 = UCS/NON_UCS position swap($1 is ucs , $2 is non ucs) # my $prop = 0 ; if( @_) { $prop = shift ; } %to_ucs = () ; %ucs_to = () ; foreach $line (@$all_lines) { if( $line =~ /^#.*$/) { next ; } if( $line =~ /$regexp/) { my $_code ; my $_ucs ; my $code ; my $ucs ; if( ($prop & 0x4) == 0) { $_code = $1 ; $_ucs = $2 ; } else { $_code = $2 ; $_ucs = $1 ; } if( ($prop & 0x1) == 0) { if( ! ($_code =~ /0x.*/)) { $code = oct "0x${_code}" ; } else { $code = oct $_code ; } } else { $code = $_code ; } if( ($prop & 0x2) == 0) { if( ! ($_ucs =~ /0x.*/)) { $ucs = oct "0x${_ucs}" ; } else { $ucs = oct $_ucs ; } } else { $ucs = $_ucs ; } $to_ucs{$code} = ${ucs} ; $ucs_to{$ucs} = $code ; } } } sub output($$$$) { my $fromcs = shift ; my $tocs = shift ; my $tocs_bytelen = shift ; my $hash = shift ; my $bits = $tocs_bytelen * 8 ; my @keylist = keys %{$hash} ; if( @keylist eq 0) { print "table [${fromcs} to ${tocs}] has no keys.\n" ; return ; } my $fromcs_uc = uc $fromcs ; my $tocs_uc = uc $tocs ; open TO , ">ef_${fromcs}_to_${tocs}.table" ; print TO << "EOF" ; /* * ef_${fromcs}_to_${tocs}.table */ #ifndef __EF_${fromcs_uc}_TO_${tocs_uc}_TABLE__ #define __EF_${fromcs_uc}_TO_${tocs_uc}_TABLE__ #include /* u_xxx */ #ifdef REMOVE_MAPPING_TABLE #define CONV_${fromcs_uc}_TO_${tocs_uc}(ch) 0x0 #else #define CONV_${fromcs_uc}_TO_${tocs_uc}(ch) \\ ( (ch) < ${fromcs}_to_${tocs}_beg || ${fromcs}_to_${tocs}_end < (ch) ? \\ 0 : ${fromcs}_to_${tocs}_table[ (ch) - ${fromcs}_to_${tocs}_beg]) EOF print TO "static u_int${bits}_t ${fromcs}_to_${tocs}_table[] = \n{" ; my $code = -1 ; my $start = 0 ; foreach $key ( sort {$a <=> $b} keys %$hash) { if( $code == -1) { $start = $code = $key ; } while( $code < $key) { if( $code % 16 == $start % 16) { printf TO "\n /* 0x%x */\n" , $code ; } print TO " 0x00 ,\n" ; $code ++ ; } if( $code % 16 == $start % 16) { printf TO "\n /* 0x%x */\n" , $code ; } if( $tocs_bytelen eq 4) { printf TO " 0x%.8x ,\n" , $$hash{$key} & 0xffffffff ; } elsif( $tocs_bytelen eq 2) { printf TO " 0x%.4x ,\n" , $$hash{$key} & 0xffff ; } elsif( $tocs_bytelen eq 1) { printf TO " 0x%.2x ,\n" , $$hash{$key} & 0xff ; } $code ++ ; } print TO "} ;\n\n" ; printf TO "static u_int ${fromcs}_to_${tocs}_beg = 0x%x ;\n\n" , $start ; printf TO "static u_int ${fromcs}_to_${tocs}_end = 0x%x ;\n\n" , $code - 1 ; printf TO "#endif\n\n\n#endif\n" ; } sub output_separated($$$$) { my $fromcs = shift ; # SB charset is not supported. my $tocs = shift ; my $tocs_bytelen = shift ; my $hash = shift ; my $bits = $tocs_bytelen * 8 ; my @keylist = keys %{$hash} ; if( @keylist eq 0) { print "table [${fromcs} to ${tocs}] has no keys.\n" ; return ; } my $fromcs_uc = uc $fromcs ; my $tocs_uc = uc $tocs ; open TO , ">ef_${fromcs}_to_${tocs}.table" ; print TO << "EOF" ; /* * ef_${fromcs}_to_${tocs}.table */ #ifndef __EF_${fromcs_uc}_TO_${tocs_uc}_TABLE__ #define __EF_${fromcs_uc}_TO_${tocs_uc}_TABLE__ #include /* NULL */ #include /* u_xxx */ #ifdef REMOVE_MAPPING_TABLE #define CONV_${fromcs_uc}_TO_${tocs_uc}(ch) 0x0 #else typedef struct ${fromcs}_to_${tocs}_range { u_int32_t beg ; u_int32_t end ; } ${fromcs}_to_${tocs}_range_t ; typedef struct ${fromcs}_to_${tocs}_table { u_int${bits}_t * table ; ${fromcs}_to_${tocs}_range_t * range ; } ${fromcs}_to_${tocs}_table_t ; EOF my @indexes ; my $code = -1 ; my $start = 0 ; my $_start = 0 ; my $hi_code = 0 ; foreach $key ( sort {$a <=> $b} keys %{$hash}) { my $next_hi_code = ($key >> 8) & 0xff ; if( $code == -1) { $_start = $start = $code = $key ; $hi_code = $next_hi_code ; printf TO "static u_int${bits}_t ${fromcs}_to_${tocs}_table_%x[] =\n{" , ${hi_code} ; } if( $hi_code < $next_hi_code) { print TO "} ;\n\n" ; printf TO "static ${fromcs}_to_${tocs}_range_t ${fromcs}_to_${tocs}_range_%x =\n{\n" , ${hi_code} ; printf TO " 0x%x , 0x%x\n} ;\n\n" , $_start , $code - 1 ; push( @indexes , $hi_code) ; $hi_code = $next_hi_code ; printf TO "static u_int${bits}_t ${fromcs}_to_${tocs}_table_%x[] =\n{" , ${hi_code} ; $_start = $code = $key ; } while( $code < $key) { if( $code % 16 == $start % 16) { printf TO "\n /* 0x%x */\n" , $code ; } print TO " 0x00 ,\n" ; $code ++ ; } if( $code % 16 == $_start % 16) { printf TO "\n /* 0x%x */\n" , $code ; } if( $tocs_bytelen eq 4) { printf TO " 0x%.8x ,\n" , ${$hash}{$key} & 0xffffffff ; } elsif( $tocs_bytelen eq 2) { printf TO " 0x%.4x ,\n" , ${$hash}{$key} & 0xffff ; } elsif( $tocs_bytelen eq 1) { printf TO " 0x%.2x ,\n" , ${$hash}{$key} & 0xff ; } $code ++ ; } print TO "} ;\n\n" ; printf TO "static ${fromcs}_to_${tocs}_range_t ${fromcs}_to_${tocs}_range_%x =\n{\n" , ${hi_code} ; printf TO " 0x%x , 0x%x\n} ;\n\n" , $_start , $code - 1 ; push( @indexes , $hi_code) ; printf TO "static u_int32_t ${fromcs}_to_${tocs}_beg = 0x%x ;\n\n" , $start ; printf TO "static u_int32_t ${fromcs}_to_${tocs}_end = 0x%x ;\n\n" , $code - 1 ; my $prev_idx = -1 ; print TO "static ${fromcs}_to_${tocs}_table_t ${fromcs}_to_${tocs}_tables[] =\n{\n" ; foreach my $idx (@indexes) { if( $prev_idx == -1) { $prev_idx = $idx ; } while( $idx > $prev_idx + 1) { print TO " { NULL , NULL , } ,\n" ; $prev_idx ++ ; } printf TO " { ${fromcs}_to_${tocs}_table_%x , &${fromcs}_to_${tocs}_range_%x } ,\n" , $idx , $idx ; $prev_idx = $idx ; } print TO "} ;\n\n" ; if( ${fromcs} eq "ucs4") { print TO << "EOF" ; /* 'i' is UCS4(32bit) */ #define HI(i) ( ((i)>>8) & 0xffffff ) #define LO(i) ( (i) & 0xff ) EOF } else # if( keys %${hash} > 256) { # MB charset (SB charset is not supposed.) print TO << "EOF" ; #define HI(i) ( ((i)>>8) & 0xff ) #define LO(i) ( (i) & 0xff ) EOF } print TO << "EOF" ; static u_int${bits}_t CONV_${fromcs_uc}_TO_${tocs_uc}( u_int32_t ch ) { u_int32_t hi_ch ; u_int32_t hi_beg ; u_int${bits}_t * table ; ${fromcs}_to_${tocs}_range_t * range ; if( ch < ${fromcs}_to_${tocs}_beg || ${fromcs}_to_${tocs}_end < ch) { return 0 ; } hi_ch = HI(ch) ; hi_beg = HI(${fromcs}_to_${tocs}_beg) ; if( ! ( table = ${fromcs}_to_${tocs}_tables[ hi_ch - hi_beg].table)) { return 0 ; } range = ${fromcs}_to_${tocs}_tables[ hi_ch - hi_beg].range ; if( ch < range->beg || range->end < ch) { return 0 ; } return table[ LO(ch) - LO(range->beg)] ; } #undef HI #undef LO EOF printf TO "#endif /* REMOVE_MAPPING_TABLE */\n\n\n#endif\n" ; } sub output_table_to_ucs($$) { if( keys %to_ucs > 256) { # MB charset output_separated( shift , "ucs4" , shift , \%to_ucs) ; } else { # SB charset output( shift , "ucs4" , shift , \%to_ucs) ; } } sub output_table_ucs_to($$) { output_separated( "ucs4" , shift , shift , \%ucs_to) ; } # module return 1 ; mlterm-3.8.9/encodefilter/util/ucs_property.pl010075500017600000144000000066761356600661000202710ustar kenusers#!/usr/pkg/bin/perl my %props ; sub parse_line($) { $_ = shift ; if(/^([^;]*);([^;]*);([^;]*);[^;]*;([^;]*);[^;]*;[^;]*;[^;]*;[^;]*;[^;]*;[^;]*;[^;]*;[^;]*;[^;]*;[^;]*/) { # Unicode Data # code , prop , comment return ( $1 , [$3 , "DIR_$4"] , $2) ; } elsif( /^([0-9A-F]*);([^ ]*) . (.*)$/) { # East Asian Width # code , prop , comment return ( $1 , ["EAW_$2"] , $3) ; } elsif( /^([0-9A-F]*)..([0-9A-F]*);([^ ]*) . (.*)$/) { # East Asian Width(code..code , prop , comment..comment) # code , prop , code , comment return ( $1 , ["EAW_$3"] , $2 , $4) ; } else { return my @dummy ; } } sub parse($) { my $all_props = shift ; my $first = 0 ; my $last = 0 ; foreach $line (@{$all_props}) { my $prop ; if( $line =~ /^#.*/) { # comment next ; } if( (my @ret = parse_line( $line))) { my $code = oct "0x${ret[0]}" ; $prop = 0 ; foreach $_prop (@{${ret[1]}}) { $_prop = uc $_prop ; if( $_prop =~ /^M[CEN]$/) { $_prop = "EF_COMBINING" ; } elsif( $_prop =~ /^EAW_[WF]$/) { $_prop = "EF_FULLWIDTH" ; } elsif( $_prop eq "EAW_A") { $_prop = "EF_AWIDTH" ; } else { next ; } if( $prop) { $prop = "${prop} | ${_prop}" ; } else { $prop = "${_prop}" ; } } if( ! $prop) { next ; } if( @ret == 4) { $first = $code ; $last = oct "0x${ret[2]}" ; } else # ( @ret == 3) { $comment = ${ret[2]} ; if( $first ne 0) { if( $comment =~ /<.* Last>/) { $last = $code ; } else { die "illegal format.\n" ; } } else { $first = $code ; if( $comment =~ /<.* First>/) { $first = $code ; # $last is not set and process continued ... next ; } else { $last = $code ; } } } } else { next ; } for( my $code = $first ; $code <= $last ; $code ++) { if( exists $props{$code}) { $props{$code} = "$props{$code} | ${prop}" ; } else { $props{$code} = "${prop}" ; } } $first = 0 ; $last = 0 ; } } sub output() { open TO , ">ef_ucs_property.table" ; print TO << "EOF" ; /* * ef_ucs_property.table */ #ifndef __EF_UCS_PROPERTY_TABLE__ #define __EF_UCS_PROPERTY_TABLE__ #include typedef struct ef_ucs_property { u_int32_t first ; u_int32_t last ; u_int8_t prop ; /* ef_property_t */ } ef_ucs_property_t ; static ef_ucs_property_t ucs_property_table[] = { { 0x00000000 , 0x00000000 , 0 } , EOF my $start = 0 ; my $prev_code = 0 ; my @array = sort {$a <=> $b} keys %props ; foreach $code (@array) { if( $prev_code == 0) { $start = $code ; $prev_code = $code ; next ; } elsif( $prev_code + 1 == $code && $props{$prev_code} eq $props{$code}) { $prev_code ++ ; next ; } printf TO " { 0x%.8x , 0x%.8x , $props{$prev_code} } ,\n" , $start , $prev_code ; $start = $code ; $prev_code = $code ; } printf TO " { 0x%.8x , 0x%.8x , $props{$prev_code} } ,\n" , $start , $prev_code ; print TO " { 0xffffffff , 0xffffffff , 0 } ,\n" ; print TO "} ; \n\n" ; print TO "\n\n#endif\n" ; close TO ; } my @all_lines = ; parse( \@all_lines) ; output ; print "Add 0x1160-0x11ff (Jamo medial vowels and final consonants) = EF_COMBINING | EF_FULLWIDTH manually.\n" ; print "Check awidth range and fix x_calculate_char_width() in x_font.c.\n" ; mlterm-3.8.9/encodefilter/util/uhc_table.pl010064400017600000144000000003741356600661000174430ustar kenusers#!/usr/pkg/bin/perl use ucs_mappings () ; my $cs = "uhc" ; my @all_lines = ; ucs_mappings::parse( '^([^ ]+)[ ]+([^ ]+).*$' , \@all_lines) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 2) ; mlterm-3.8.9/encodefilter/util/viscii_table.pl010064400017600000144000000005071356600661000201500ustar kenusers#!/usr/pkg/bin/perl # source file is unicode.html use ucs_mappings () ; my $cs = "viscii" ; my @all_lines = ; # NON UCS is decimal ucs_mappings::parse( '^([0-9]+)[ ]+[^ ]+[ ]+([0-9A-Z]+).*$' , \@all_lines , 0x1) ; ucs_mappings::output_table_to_ucs( ${cs} , 2) ; ucs_mappings::output_table_ucs_to( ${cs} , 1) ; mlterm-3.8.9/encodefilter/util/Makefile010064400017600000144000000045171356600661000166230ustar kenusersSRCDIR=src ucs_map: jisx0208 jisx0212 jisx0213 iso8859-2 iso8859-3 iso8859-4 iso8859-10 \ iso8859-13 iso8859-14 iso8859-16 johab tcvn viscii koi8-t georgian-ps \ cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 \ cp1257 cp1258 big5 big5hkscs cns11643 gbk uhc property # Manually maintained tables. ucs_map2: jisx0208-nec jisx0208-ibm sjis-ibm jisx0208: cat ${SRCDIR}/JIS0208.TXT.fixed | ./jisx0208_1983_table.pl jisx0208-nec: cat ${SRCDIR}/nec98.txt | ./jisx0208_nec_ext_table.pl jisx0208-ibm: cat ${SRCDIR}/necibm.txt | ./jisx0208_necibm_ext_table.pl sjis-ibm: cat ${SRCDIR}/ibmibm.txt | ./sjis_ibm_ext_table.pl jisx0212: cat ${SRCDIR}/JIS0212.TXT | ./jisx0212_1990_table.pl jisx0213: cat ${SRCDIR}/jisx0213code-csv.txt | ./jisx0213_2000_table.pl iso8859-2: cat ${SRCDIR}/8859-2.TXT | ./iso8859_2_table.pl iso8859-3: cat ${SRCDIR}/8859-3.TXT | ./iso8859_3_table.pl iso8859-4: cat ${SRCDIR}/8859-4.TXT | ./iso8859_4_table.pl iso8859-10: cat ${SRCDIR}/8859-10.TXT | ./iso8859_10_table.pl iso8859-13: cat ${SRCDIR}/8859-13.TXT | ./iso8859_13_table.pl iso8859-14: cat ${SRCDIR}/8859-14.TXT | ./iso8859_14_table.pl iso8859-16: cat ${SRCDIR}/8859-16.TXT | ./iso8859_16_table.pl johab: cat ${SRCDIR}/hangul-codes.txt | ./johab_table.pl uhc: cat ${SRCDIR}/KSC5601.TXT | ./uhc_table.pl tcvn: cat ${SRCDIR}/vscii.txt | ./tcvn_table.pl viscii: cat ${SRCDIR}/unicode.html | ./viscii_table.pl koi8-t: cat ${SRCDIR}/KOI8-T | ./koi8_t_table.pl georgian-ps: cat ${SRCDIR}/GEORGIAN-PS | ./georgian_ps_table.pl cp1250: cat ${SRCDIR}/CP1250.TXT | ./cp1250_table.pl cp1251: cat ${SRCDIR}/CP1251.TXT | ./cp1251_table.pl cp1252: cat ${SRCDIR}/CP1252.TXT | ./cp1252_table.pl cp1253: cat ${SRCDIR}/CP1253.TXT | ./cp1253_table.pl cp1254: cat ${SRCDIR}/CP1254.TXT | ./cp1254_table.pl cp1255: cat ${SRCDIR}/CP1255.TXT | ./cp1255_table.pl cp1256: cat ${SRCDIR}/CP1256.TXT | ./cp1256_table.pl cp1257: cat ${SRCDIR}/CP1257.TXT | ./cp1257_table.pl cp1258: cat ${SRCDIR}/CP1258.TXT | ./cp1258_table.pl big5: cat ${SRCDIR}/BIG5 | ./big5_table.pl big5hkscs: cat ${SRCDIR}/BIG5HKSCS | ./big5hkscs_table.pl cns11643: cat ${SRCDIR}/CNS11643.TXT | ./cns11643_1992_table.pl gbk: cat ${SRCDIR}/CP936.TXT | ./gbk_table.pl property: cat ${SRCDIR}/UnicodeData-11.0.0.txt ${SRCDIR}/EastAsianWidth-11.0.0.txt | ./ucs_property.pl clean: rm -f mef_*.table mlterm-3.8.9/encodefilter/conv004075500017600000144000000000001356600661000150705ustar kenusersmlterm-3.8.9/encodefilter/conv/Makefile010064400017600000144000000006551356600661000166120ustar kenusersCC = gcc CFLAGS = -Wall -O3 $(CFLAGS_LOCAL) LIBS = -lmef -lpobl $(LIBS_LOCAL) INSTALL = install -c PREFIX = $(HOME) BINDIR = $(PREFIX)/bin .SUFFIXES : .c .o mef : mef.o $(CC) $(CFLAGS) -o mef mef.o $(LIBS) install : mef strip mef $(INSTALL) -m 755 mef $(BINDIR) .c.o : $(CC) $(CFLAGS) -c $< wc : find . -name "*.[ch]" -a \! -name "test_*" -o -name "*.pl" -o -name "*.pm" | xargs wc -l clean : rm -f mef mef.o *.core mlterm-3.8.9/encodefilter/conv/README010064400017600000144000000004171356600661000160260ustar kenuserscomment -*- mode: txt -*- comment $Id$ * Build $ make $ make install * Options -h: help -i [input code]: Specify input encoding. -o [output code]: Specify outout encoding. * Notice Encoding is not automatically recognized, so -i option is always required. mlterm-3.8.9/encodefilter/conv/mef.c010064400017600000144000000206601356600661000160630ustar kenusers/* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */ #include #include #include #include /* getopt */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct ef_factory_table { char *encoding; ef_parser_t* (*parser_new)(void); ef_conv_t* (*conv_new)(void); } ef_factory_table_t; /* --- static variables --- */ static ef_factory_table_t factories[] = { {"iso8859-1", ef_iso8859_1_parser_new, ef_iso8859_1_conv_new}, {"iso8859-2", ef_iso8859_2_parser_new, ef_iso8859_2_conv_new}, {"iso8859-3", ef_iso8859_3_parser_new, ef_iso8859_3_conv_new}, {"iso8859-4", ef_iso8859_4_parser_new, ef_iso8859_4_conv_new}, {"iso8859-5", ef_iso8859_5_parser_new, ef_iso8859_5_conv_new}, {"iso8859-6", ef_iso8859_6_parser_new, ef_iso8859_6_conv_new}, {"iso8859-7", ef_iso8859_7_parser_new, ef_iso8859_7_conv_new}, {"iso8859-8", ef_iso8859_8_parser_new, ef_iso8859_8_conv_new}, {"iso8859-9", ef_iso8859_9_parser_new, ef_iso8859_9_conv_new}, {"iso8859-10", ef_iso8859_10_parser_new, ef_iso8859_10_conv_new}, {"tis620", ef_tis620_2533_parser_new, ef_tis620_2533_conv_new}, {"iso8859-13", ef_iso8859_13_parser_new, ef_iso8859_13_conv_new}, {"iso8859-14", ef_iso8859_14_parser_new, ef_iso8859_14_conv_new}, {"iso8859-15", ef_iso8859_15_parser_new, ef_iso8859_15_conv_new}, {"iso8859-16", ef_iso8859_16_parser_new, ef_iso8859_16_conv_new}, {"tcvn5712", ef_tcvn5712_3_1993_parser_new, ef_tcvn5712_3_1993_conv_new}, {"xct", ef_xct_parser_new, ef_xct_conv_new}, {"viscii", ef_viscii_parser_new, ef_viscii_conv_new}, {"koi8-r", ef_koi8_r_parser_new, ef_koi8_r_conv_new}, {"koi8-u", ef_koi8_u_parser_new, ef_koi8_u_conv_new}, {"cp1250", ef_cp1250_parser_new, ef_cp1250_conv_new}, {"cp1251", ef_cp1251_parser_new, ef_cp1251_conv_new}, {"cp1252", ef_cp1252_parser_new, ef_cp1252_conv_new}, {"cp1253", ef_cp1253_parser_new, ef_cp1253_conv_new}, {"cp1254", ef_cp1250_parser_new, ef_cp1254_conv_new}, {"cp1255", ef_cp1250_parser_new, ef_cp1255_conv_new}, {"cp1256", ef_cp1250_parser_new, ef_cp1256_conv_new}, {"cp1257", ef_cp1250_parser_new, ef_cp1257_conv_new}, {"cp1258", ef_cp1250_parser_new, ef_cp1258_conv_new}, {"cp874", ef_cp874_parser_new, ef_cp874_conv_new}, {"isciiassamese", ef_iscii_assamese_parser_new, ef_iscii_assamese_conv_new}, {"isciibengali", ef_iscii_bengali_parser_new, ef_iscii_bengali_conv_new}, {"isciigujarati", ef_iscii_gujarati_parser_new, ef_iscii_gujarati_conv_new}, {"isciihindi", ef_iscii_hindi_parser_new, ef_iscii_hindi_conv_new}, {"isciikannada", ef_iscii_kannada_parser_new, ef_iscii_kannada_conv_new}, {"isciimalayalam", ef_iscii_malayalam_parser_new, ef_iscii_malayalam_conv_new}, {"isciioriya", ef_iscii_oriya_parser_new, ef_iscii_oriya_conv_new}, {"isciipunjabi", ef_iscii_punjabi_parser_new, ef_iscii_punjabi_conv_new}, {"isciitamil", ef_iscii_tamil_parser_new, ef_iscii_tamil_conv_new}, {"isciitelugu", ef_iscii_telugu_parser_new, ef_iscii_telugu_conv_new}, {"eucjp", ef_eucjp_parser_new, ef_eucjp_conv_new}, {"eucjisx0213", ef_eucjisx0213_parser_new, ef_eucjisx0213_conv_new}, {"sjis", ef_sjis_parser_new, ef_sjis_conv_new}, {"sjisx0213", ef_sjisx0213_parser_new, ef_sjisx0213_conv_new}, {"utf8", ef_utf8_parser_new, ef_utf8_conv_new}, {"utf16", ef_utf16_parser_new, ef_utf16_conv_new}, {"utf16le", ef_utf16le_parser_new, ef_utf16le_conv_new}, {"utf32", ef_utf32_parser_new, ef_utf32_conv_new}, {"utf32le", ef_utf32le_parser_new, ef_utf32le_conv_new}, {"junet8", ef_iso2022jp_8_parser_new, ef_iso2022jp_8_conv_new}, {"junet7", ef_iso2022jp_7_parser_new, ef_iso2022jp_7_conv_new}, {"iso2022jp2", ef_iso2022jp2_parser_new, ef_iso2022jp2_conv_new}, {"iso2022jp3", ef_iso2022jp3_parser_new, ef_iso2022jp3_conv_new}, {"euckr", ef_euckr_parser_new, ef_euckr_conv_new}, {"uhc", ef_uhc_parser_new, ef_uhc_conv_new}, {"iso2022kr", ef_iso2022kr_parser_new, ef_iso2022kr_conv_new}, {"johab", ef_johab_parser_new, ef_johab_conv_new}, {"euccn", ef_euccn_parser_new, ef_euccn_conv_new}, {"gbk", ef_gbk_parser_new, ef_gbk_conv_new}, {"gb18030", ef_gb18030_2000_parser_new, ef_gb18030_2000_conv_new}, {"iso2022cn", ef_iso2022cn_parser_new, ef_iso2022cn_conv_new}, {"hz", ef_hz_parser_new, ef_hz_conv_new}, {"big5", ef_big5_parser_new, ef_big5_conv_new}, {"big5hkscs", ef_big5hkscs_parser_new, ef_big5hkscs_conv_new}, {"euctw", ef_euctw_parser_new, ef_euctw_conv_new}, }; /* --- static functions --- */ static void usage() { bl_msg_printf("usage: mef -i [input code] -o [output code] ([file])\n"); bl_msg_printf( "supported codes: iso8859-[1-10] tis620 iso8859-[13-16] tcvn5712 xct " "viscii iscii koi8-r koi8-u cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 " "cp1256 cp1257 cp1258 cp874 " "iscii(assamese|bengali|gujarati|hindi|kannada|malayalam|oriya|punjabi|" "tamil|telugu) eucjp eucjisx0213 sjis sjisx0213 utf8 utf16 utf16le " "utf32 utf32le junet8 junet7 iso2022jp2 iso2022jp3 euckr uhc iso2022kr johab " "euccn gbk gb18030 iso2022cn hz big5 big5hkscs euctw\n"); } /* --- global functions --- */ int main(int argc, char **argv) { extern char *optarg; extern int optind; int c; char *in; char *out; int count; FILE* fp; u_char output[1024]; u_char input[1024]; u_char *input_p; ef_parser_t *parser; ef_conv_t *conv; size_t size; if (argc != 5 && argc != 6) { usage(); return 1; } in = NULL; out = NULL; while ((c = getopt(argc, argv, "i:o:")) != -1) { switch (c) { case 'i': in = optarg; break; case 'o': out = optarg; break; default: usage(); return 1; } } argc -= optind; argv += optind; if (argc == 0) { fp = stdin; } else if (argc == 1) { if ((fp = fopen(*argv, "r")) == NULL) { bl_error_printf("%s not found.\n", *argv); usage(); return 1; } } else { bl_error_printf("too many arguments.\n"); usage(); return 1; } parser = NULL; for (count = 0; count < sizeof(factories) / sizeof(factories[0]); count++) { if (strcmp(factories[count].encoding, in) == 0) { parser = (*factories[count].parser_new)(); } } if (parser == NULL) { bl_error_printf("input encoding %s is illegal.\n", in); usage(); return 1; } conv = NULL; for (count = 0; count < sizeof(factories) / sizeof(factories[0]); count++) { if (strcmp(factories[count].encoding, out) == 0) { conv = (*factories[count].conv_new)(); } } if (conv == NULL) { bl_error_printf("output encoding %s is illegal.\n", out); usage(); return 1; } input_p = input; while ((size = fread(input_p, 1, 1024 - parser->left, fp)) > 0) { (*parser->set_str)(parser, input, size + parser->left); if ((size = (*conv->convert)(conv, output, 1024, parser)) == 0) { break; } fwrite(output, 1, size, stdout); if (parser->left > 0) { memcpy(input, parser->str, parser->left); input_p = input + parser->left; } else { input_p = input; } } if (parser->left > 0) { (*parser->set_str)(parser, input, parser->left); size = (*conv->convert)(conv, output, 1024, parser); fwrite(output, 1, size, stdout); } (*parser->destroy)(parser); (*conv->destroy)(conv); return 0; } mlterm-3.8.9/encodefilter/aclocal.m4010064400017600000144000012064741356600661000160550ustar kenusers# generated automatically by aclocal 1.15.1 -*- Autoconf -*- # Copyright (C) 1996-2017 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | msys* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin* | msys*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | msys* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc* | msys*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin* | msys*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin* | msys*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | msys* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-msys* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | msys* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | msys* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | msys* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | msys* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | msys* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | msys* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | msys* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | msys* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | msys* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | msys* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS # Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-msys* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) # ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) mlterm-3.8.9/encodefilter/configure010075500017600000144000014264221356600661000161210ustar kenusers#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS DEXPORT POBL_LIBS EF_CHAR_LO NO_UNDEFINED_FLAG MAKE_DIRS TABLE_CFLAGS DEB_CFLAGS POBL_CFLAGS CPP LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL AWK RANLIB STRIP ac_ct_AR AR LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED LIBTOOL OBJDUMP DLLTOOL AS INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CC CFLAGS host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_libtool enable_shared enable_static with_pic enable_fast_install with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock enable_debug with_map_table with_prop_table enable_dl_table ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS LT_SYS_LIBRARY_PATH CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-debug debug [default=disabled] --disable-dl-table dynamic loading table [default=enable] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-libtool[=ARG] libtool path [default=without] --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-aix-soname=aix|svr4|both shared library versioning (aka "SONAME") variant to provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --without-map-table mapping table [default=with] --without-prop-table property table [default=with] Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory LT_SYS_LIBRARY_PATH User-defined run-time library search path. CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in script "$srcdir"/script; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in script \"$srcdir\"/script" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # for CFLAGS="..." ./configure ... ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' enable_win32_dll=yes case $host in *-*-cygwin* | *-*-msys* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. set dummy ${ac_tool_prefix}as; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AS+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AS"; then ac_cv_prog_AS="$AS" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AS="${ac_tool_prefix}as" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AS=$ac_cv_prog_AS if test -n "$AS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 $as_echo "$AS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AS"; then ac_ct_AS=$AS # Extract the first word of "as", so it can be a program name with args. set dummy as; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AS+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AS"; then ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AS="as" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AS=$ac_cv_prog_ac_ct_AS if test -n "$ac_ct_AS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 $as_echo "$ac_ct_AS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AS" = x; then AS="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AS=$ac_ct_AS fi else AS="$ac_cv_prog_AS" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi ;; esac test -z "$AS" && AS=as test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$OBJDUMP" && OBJDUMP=objdump # Check whether --with-libtool was given. if test "${with_libtool+set}" = set; then : withval=$with_libtool; libtool=$with_libtool fi if test "${libtool}" != "" ; then LIBTOOL=${libtool} else case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.6' macro_revision='2.4.6' ltmain=$ac_aux_dir/ltmain.sh # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case $ECHO in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | msys* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n "$lt_cv_sys_max_cmd_len"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | msys* | mingw* | pw32* | cegcc*) if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) if test yes = "$GCC"; then reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin* | msys*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | msys* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | msys* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 $as_echo "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 $as_echo_n "checking for a working dd... " >&6; } if ${ac_cv_path_lt_DD+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} if test -z "$lt_DD"; then ac_path_lt_DD_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in dd; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_lt_DD" || continue if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi $ac_path_lt_DD_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_lt_DD"; then : fi else ac_cv_path_lt_DD=$lt_DD fi rm -f conftest.i conftest2.i conftest.out fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 $as_echo "$ac_cv_path_lt_DD" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 $as_echo_n "checking how to truncate binary pipes... " >&6; } if ${lt_cv_truncate_bin+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 $as_echo "$lt_cv_truncate_bin" >&6; } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[012][,.]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac else pic_mode=default fi # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac else enable_fast_install=yes fi shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[5-9]*,yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 $as_echo_n "checking which variant of shared library versioning to provide... " >&6; } # Check whether --with-aix-soname was given. if test "${with_aix_soname+set}" = set; then : withval=$with_aix_soname; case $withval in aix|svr4|both) ;; *) as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 ;; esac lt_cv_with_aix_soname=$with_aix_soname else if ${lt_cv_with_aix_soname+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_with_aix_soname=aix fi with_aix_soname=$lt_cv_with_aix_soname fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 $as_echo "$with_aix_soname" >&6; } if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o func_cc_basename $compiler cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/${ac_tool_prefix}file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi lt_prog_compiler_pic='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | msys* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; esac ;; mingw* | cygwin* | msys* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | msys* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | msys* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) export_dynamic_flag_spec='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct=no hardcode_direct_absolute=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' allow_undefined_flag=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | msys* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test yes = "$GCC"; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test yes = "$lt_cv_prog_compiler__b"; then archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler ld_shlibs=yes archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' else archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; osf3*) if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test yes = "$GCC"; then wlarc='$wl' archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='$wl-z,text' allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | msys* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc* | msys*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin* | msys*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test relink = "$hardcode_action" || test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin* | msys*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen=shl_load else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen=dlopen else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi fi fi fi fi fi ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report what library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC ac_config_commands="$ac_config_commands libtool" # Only expand once: LIBTOOL='${top_builddir}/libtool' fi if test -d ${top_srcdir-$srcdir}/baselib ; then POBL_BUILDDIR='${top_builddir}/baselib' SUBDIRS="baselib" elif test -d ${top_srcdir-$srcdir}/../baselib ; then POBL_BUILDDIR='${top_builddir}/../baselib' SUBDIRS="../baselib" else POBL_BUILDDIR="" SUBDIRS="" fi POBL_CFLAGS="-I${POBL_BUILDDIR}/include" # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; debug=$enable_debug fi if test "$debug" = "yes" ; then DEB_CFLAGS="-DDEBUG -DBL_DEBUG" fi # Check whether --with-map-table was given. if test "${with_map_table+set}" = set; then : withval=$with_map_table; map_table=$with_map_table else map_table="yes" fi if test "$map_table" = "no" ; then TABLE_CFLAGS="${TABLE_CFLAGS} -DREMOVE_MAPPING_TABLE" fi # Check whether --with-prop-table was given. if test "${with_prop_table+set}" = set; then : withval=$with_prop_table; prop_table=$with_prop_table else prop_table="yes" fi if test "$prop_table" = "no" ; then TABLE_CFLAGS="${TABLE_CFLAGS} -DREMOVE_PROPERTY_TABLE" fi # Check whether --enable-dl-table was given. if test "${enable_dl_table+set}" = set; then : enableval=$enable_dl_table; dl_table=$enable_dl_table else dl_table="yes" fi if test "$dl_table" = "no" ; then TABLE_CFLAGS="${TABLE_CFLAGS} -DNO_DYNAMIC_LOAD_TABLE" MAKE_DIRS="src" else MAKE_DIRS="src module" fi # # --- check for undefined symbol --- # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for undefined symbol" >&5 $as_echo_n "checking for undefined symbol... " >&6; } if test "x$allow_undefined_flag" = "xunsupported" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not supported" >&5 $as_echo "not supported" >&6; } NO_UNDEFINED_FLAG="-no-undefined" # link ef_char.lo to module/*.dll to resolve addresses in creating dll. EF_CHAR_LO="../src/ef_char.lo" if test "x${POBL_BUILDDIR}" != "x" ; then POBL_LIBS="${POBL_BUILDDIR}/src/libpobl.la" else POBL_LIBS='-lpobl' fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: supported" >&5 $as_echo "supported" >&6; } NO_UNDEFINED_FLAG="" EF_CHAR_LO="" POBL_LIBS="" fi if test "$with_gnu_ld" = "yes" ; then DEXPORT="-Wl,--version-script=\$(top_srcdir)/src/dexport.map" fi # This should be uncommented if mef and pobl alone are distributed in a package. #if test "${SUBDIRS}" != "" ; then # AC_CONFIG_SUBDIRS(${SUBDIRS}) #fi ac_config_files="$ac_config_files Makefile src/Makefile module/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Configuration commands: $config_commands Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in AS \ DLLTOOL \ OBJDUMP \ SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ lt_cv_nm_interface \ nm_file_list_spec \ lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ configure_time_dlsearch_path \ configure_time_lt_sys_library_path; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "module/Makefile") CONFIG_FILES="$CONFIG_FILES module/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "libtool":C) # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # The names of the tagged configurations supported by this script. available_tags='' # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG # Assembler program. AS=$lt_AS # DLL creation program. DLLTOOL=$lt_DLLTOOL # Object dumper program. OBJDUMP=$lt_OBJDUMP # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shared archive member basename,for filename based shared library versioning on AIX. shared_archive_member_spec=$shared_archive_member_spec # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm into a list of symbols to manually relocate. global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name lister interface. nm_interface=$lt_lt_cv_nm_interface # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot # Command to truncate a binary pipe. lt_truncate_bin=$lt_lt_cv_truncate_bin # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Detected run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path # Explicit LT_SYS_LIBRARY_PATH set during ./configure time. configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi mlterm-3.8.9/encodefilter/configure.in010064400017600000144000000052521356600661000165140ustar kenusers# -*- mode:sh; sh-basic-offset:2; tab-width:2; indent-tabs-mode:t -*- AC_INIT() AC_CONFIG_AUX_DIR(script) AC_CANONICAL_HOST AC_CANONICAL_BUILD # for CFLAGS="..." ./configure ... AC_SUBST(CFLAGS) AC_PROG_CC AC_C_INLINE AC_PROG_INSTALL AC_LIBTOOL_WIN32_DLL AC_ARG_WITH(libtool, [ --with-libtool@<:@=ARG@:>@ libtool path @<:@default=without@:>@], libtool=$with_libtool) if test "${libtool}" != "" ; then LIBTOOL=${libtool} else AM_PROG_LIBTOOL LIBTOOL='${top_builddir}/libtool' fi AC_SUBST(LIBTOOL) if test -d ${top_srcdir-$srcdir}/baselib ; then POBL_BUILDDIR='${top_builddir}/baselib' SUBDIRS="baselib" elif test -d ${top_srcdir-$srcdir}/../baselib ; then POBL_BUILDDIR='${top_builddir}/../baselib' SUBDIRS="../baselib" else POBL_BUILDDIR="" SUBDIRS="" fi POBL_CFLAGS="-I${POBL_BUILDDIR}/include" AC_SUBST(POBL_CFLAGS) AC_ARG_ENABLE(debug, [ --enable-debug debug @<:@default=disabled@:>@], debug=$enable_debug) if test "$debug" = "yes" ; then DEB_CFLAGS="-DDEBUG -DBL_DEBUG" fi AC_SUBST(DEB_CFLAGS) AC_ARG_WITH(map-table, [ --without-map-table mapping table @<:@default=with@:>@], map_table=$with_map_table,map_table="yes") if test "$map_table" = "no" ; then TABLE_CFLAGS="${TABLE_CFLAGS} -DREMOVE_MAPPING_TABLE" fi AC_ARG_WITH(prop-table, [ --without-prop-table property table @<:@default=with@:>@], prop_table=$with_prop_table,prop_table="yes") if test "$prop_table" = "no" ; then TABLE_CFLAGS="${TABLE_CFLAGS} -DREMOVE_PROPERTY_TABLE" fi AC_ARG_ENABLE(dl-table, [ --disable-dl-table dynamic loading table @<:@default=enable@:>@], dl_table=$enable_dl_table,dl_table="yes") if test "$dl_table" = "no" ; then TABLE_CFLAGS="${TABLE_CFLAGS} -DNO_DYNAMIC_LOAD_TABLE" MAKE_DIRS="src" else MAKE_DIRS="src module" fi AC_SUBST(TABLE_CFLAGS) AC_SUBST(MAKE_DIRS) # # --- check for undefined symbol --- # AC_MSG_CHECKING([for undefined symbol]) if test "x$allow_undefined_flag" = "xunsupported" ; then AC_MSG_RESULT([not supported]) NO_UNDEFINED_FLAG="-no-undefined" # link ef_char.lo to module/*.dll to resolve addresses in creating dll. EF_CHAR_LO="../src/ef_char.lo" if test "x${POBL_BUILDDIR}" != "x" ; then POBL_LIBS="${POBL_BUILDDIR}/src/libpobl.la" else POBL_LIBS='-lpobl' fi else AC_MSG_RESULT(supported) NO_UNDEFINED_FLAG="" EF_CHAR_LO="" POBL_LIBS="" fi AC_SUBST(NO_UNDEFINED_FLAG) AC_SUBST(EF_CHAR_LO) AC_SUBST(POBL_LIBS) if test "$with_gnu_ld" = "yes" ; then DEXPORT="-Wl,--version-script=\$(top_srcdir)/src/dexport.map" fi AC_SUBST(DEXPORT) # This should be uncommented if mef and pobl alone are distributed in a package. #if test "${SUBDIRS}" != "" ; then # AC_CONFIG_SUBDIRS(${SUBDIRS}) #fi AC_OUTPUT(Makefile src/Makefile module/Makefile) mlterm-3.8.9/encodefilter/Makefile.in010064400017600000144000000005241356600661000162450ustar kenusersMAKE_DIRS=@MAKE_DIRS@ all .DEFAULT: # "cd $${dir}" must be enclosed by () because it may not return # to the $(top_builddir) at the next line. for dir in $(MAKE_DIRS) ; do (cd $${dir} ; $(MAKE) $@) || exit $? ; done distclean : clean rm -f Makefile config.log config.cache config.status libtool config.mk src/Makefile module/Makefile mlterm-3.8.9/win32004075500017600000144000000000001356600661000124225ustar kenusersmlterm-3.8.9/win32/plink004075500017600000144000000000001356600661000135375ustar kenusersmlterm-3.8.9/win32/plink/LICENCE010064400017600000144000000027361356600661000146100ustar kenusersplink.exe in this directory is derived from "plink" of PuTTY project. (http://www.chiark.greenend.org.uk/~sgtatham/putty/) Original license is as follows. ------------------------------------------------------------------- PuTTY is copyright 1997-2007 Simon Tatham. Portions copyright Robert de Bath, Joris van Rantwijk, Delian Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus Kuhn, and CORE SDI S.A. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. mlterm-3.8.9/win32/plink/plink.diff010064400017600000144000000023351356600661000155650ustar kenusersCommon subdirectories: putty-src/WINDOWS/MSVC and mlterm/putty-src/WINDOWS/MSVC diff -u putty-src/WINDOWS/WINPLINK.C mlterm/putty-src/WINDOWS/WINPLINK.C --- putty-src/WINDOWS/WINPLINK.C Wed Mar 18 00:06:07 2009 +++ mlterm/putty-src/WINDOWS/WINPLINK.C Mon Mar 16 20:03:32 2009 @@ -240,6 +240,23 @@ noise_ultralight(len); if (connopen && back->connected(backhandle)) { if (len > 0) { + int i ; + unsigned char *d = data ; + for( i = 0 ; i < len ; i++) { + if( d[i] == 0xff && i + 5 <= len) { + int col ; + int row ; + int ret = 0 ; + if( i > 0) ret += back->send(backhandle, data, i) ; + col = ((d[++i] << 8) & 0xff) + d[++i] ; + row = ((d[++i] << 8) & 0xff) + d[++i] ; + back->size( backhandle, col, row) ; + if( ++i < len) ret += back->send(backhandle, d + i, len - i) ; + fprintf( stderr, "RET VALUE %d\n", ret) ; + return ret ; + } + } + return back->send(backhandle, data, len); } else { back->special(backhandle, TS_EOF); mlterm-3.8.9/win32/plink/plink.exe010075500017600000144000012120001356600661000154320ustar kenusersMZÿÿ¸@€º´ Í!¸LÍ!This program cannot be run in DOS mode. $PELXÈIà 8þ:€@€'Ä P”`4.texttüþ``.data @À.rdata@æ è@@.bss 8€À.idata”Pî@À.rsrc4`þ@ÀU‰åƒì‰]ø‹E1Û‰uü‹1ö‹=‘ÀwC=Àr[¾Ç$1Ò‰T$èÌøƒøtz…ÀtÇ$ÿлÿÿÿÿ‰Ø‹uü‹]ø‰ì]Â=”ÀtÂwJ=“Àt´‰Ø‹uü‹]ø‰ì]Â=Àt[=ÀuÅÇ$1ö‰t$èhøƒøtj…ÀtªÇ$ÿÐëš=–ÀëÑÇ$¸‰D$è8ø…ö„vÿÿÿè“ñélÿÿÿÇ$ 1À‰D$èøƒøt0…À„RÿÿÿÇ$ ÿÐé?ÿÿÿÇ$¹‰L$èä÷é%ÿÿÿÇ$ ¸‰D$èÊ÷é ÿÿÿ¶¼'U‰åSƒì$Ç$@èEùƒìèðèñÇEøEø‰D$¡PDÇ$E‰D$ Eô‰D$¸E‰D$è}÷¡°EE…Àtd£`D‹äSE…Ò…¡ƒúàt¡°EE‰D$¡äSE‹@0‰$è;÷‹äSEƒúÀt(¡°EE‰D$¡äSE‹@P‰$è÷ë èûö‹`D‰èïƒäðèöîèÑö‹‰D$¡E‰D$¡E‰$èÕ«‰Ãè¦ö‰$èFø¶‰D$¡äSE‹@‰$è¤ö‹äSEé@ÿÿÿU‰åƒìÇ$ÿØSEè¸þÿÿ´&U‰åƒìÇ$ÿØSEè˜þÿÿ´&U‹ TE‰å]ÿát&U‹ ìSE‰å]ÿáU‰å]éGðU‰åƒì‰uø‰Æ‹E‰]ô‰}ü@‰×…‹ƒ<E;ƒ@E}"‹“8E‰4‰|Â@‰ƒ<E‹]ô‹uø‹}ü‰ì]ÃÀ º‰ƒ@E‰T$‰D$‹ƒ8E‰$è<3‰ƒ8E‰Â‹ƒ<E‰4‰|Â@‰ƒ<E‹]ô‹uø‹}ü‰ì]ÃvU‰åƒì‰]ø»‰uü¾8E‹ƒÆ ‰$èÝ4Kyð‹]ø‹uü‰ì]ÃU‰åƒì‰]ø‹ E‹U ‰uü‹]…É”À…Ò• Шuƒ{t¸ÿÿÿÿ‹]ø‹uü‰ì]Ãv‹s‹‹B…Àuâ1Àƒ=(EuÜ‹B ‰L$‰D$‹1ö‹@‰$èõ‹C‹‹P‹@ ÆDÿ‹E‰$èñô‰D$‰t$‰$èéô¹¸‰ (Eë‚ë U1ɉåƒì…EuɉÈÉT$Ç$0 Dè,£ɹ‰ÈÃvU¹‰åüƒì8‰]ô‹]‰uø‰}ü‰ÞÇEð¿W Dó¦uH‹E ºþÿÿÿ…Àt-‹Eº…Àx!‹E‰D$‹U ‰$èܲ¸£0GEº‹]ô‰Ð‹uø‹}ü‰ì]Ãü¿] D¹‰Þó¦uo‹Eº…ÀxÔ‰Ú¸è5ÿÿÿ…Àºu¿‹}…ÿ… ‹Eº¾»¹‰°‰0HE‰ˆ‰€GEº‹]ô‰Ð‹uø‹}ü‰ì]Ãü¿b D¹‰Þó¦um‹Eº…ÀˆPÿÿÿ‰Ú¸è±þÿÿ…Àº…7ÿÿÿ‹E…À…‹U¸‰‚¸£0HE¸‰‚¸£€GEºéuÿÿÿfü¿j D¹‰Þó¦ub‹}º…ÿˆÒþÿÿ‰Ú¸è3þÿÿ…Àº…¹þÿÿ‹u…ö…‹E»¹º‰˜‰ 0HE‰¸é|ÿÿÿü¿r D¹‰Þó¦„rü¿w D¹‰Þó¦uÇEð‹Eº…ÀˆCþÿÿƒ ÐGEü¿z D¹‰Þó¦uu‹E ºþÿÿÿ…À„þÿÿÇEð‹Eº…Àˆþÿÿ‰Ú¸èeýÿÿ…Àº…ëýÿÿ‹E…À…P¸d‰D$‹E ‰D$‹Eð‰$èýñ‹UÆ‚Sü¿} D¹‰Þó¦t$¿€ D¹‰Þó¦t¿ƒ D¹‰Þó¦…Ž‹} ºþÿÿÿ…ÿ„qýÿÿÇEð‹uº…öˆZýÿÿ‰Ú¸è»üÿÿ…Àº…Aýÿÿ‹M…É…¦ü‰Þ¿ƒ D¹ó¦”À‹u¶À‰Eè‹EÆ$!€¸$!„»F€>uúF€>ëîÇEð‹}º…ÿˆâüÿÿ‰Ú¸èCüÿÿ…Àº…Éüÿÿ‹u…öu‹U1É1À‰Š£0HEé@þÿÿÇ$‹U ‰ØèwúÿÿºéýÿÿÇ$‹U ‰Øè\úÿÿéuüÿÿ¸þ)ø‰D$‹E ‰4$‰D$èð‹}è…ÿuH‰4$¹:‰L$èmð‰Eì…À‰Çt.Gº:‰T$‰$èPð…Àt‰}ì…À‰Çuß‹Eì…Àt‹UìÆ ‹EÆ€#%Æ€"%‰4$è%ðÆD0ü¿† D¹‰Þó¦…Ï‹} ºþÿÿÿ…ÿ„ÎûÿÿÇEð‹uº…öˆ·ûÿÿ‰Ú¸èûÿÿ…Àº…žûÿÿ‹M…É…ÿÿÿ‹u ¶„À•Â<:•À¶À…„*F¶„É•À1Ò€ù:•Â…Ðuë„É„‹U ‰ð)Ð=ÿv¸ÿ‰D$‹E ‰D$‹E¬ ‰$èjï‹UFÆ‚«‰$è5ï‹U‰‚¬ü¿Š D¹‰Þó¦…‹E ºþÿÿÿ…À„êúÿÿÇEð‹Eº…ÀˆÓúÿÿ‰Ú¸è4úÿÿ…Àº…ºúÿÿ‹E…À…þÿÿÇEภD1ÿÇEä‰D$‹E ‰$èÐî‰EÜ…ÀuéM;}àó¶UØ‹EäˆGFt`‹E܉$èrî‰E؃øÿ‰ÆuÔÇEØëË‹U‰ð)иÜÞÿÿ¶Cˆ‹U F‰$èXÀ)ú9ІŸýÿÿÇ$ DèÊœéúÿÿ‹U1ö¹‰‚0 ‰²4 ‰Š8 ü¿² D¹‰Þó¦u_‹E ºþÿÿÿ…À„ËùÿÿÇEð‹Eº…Àˆ´ùÿÿ‰Ú¸èùÿÿ…Àº…›ùÿÿ‹E…À…6‹E ‰$è¢í‹U‰‚ü¿µ D¹‰Þó¦ug‹E ºþÿÿÿ…À„[ùÿÿÇEð‹Eº…ÀˆDùÿÿ‰Ú¸è¥øÿÿ…Àº…+ùÿÿ‹E…À…Æ‹Eƒ¸„öÇ$¼ DèÁ›ü¿ò D¹‰Þó¦t ¿ù D¹‰Þó¦t¿!D¹ ‰Þó¦uIÇEð‹uº…öˆ¼øÿÿ‰Ú¸èøÿÿ…Àº…£øÿÿ‹M…É…íûÿÿ‹Eº‰d ü¿ !D¹ ‰Þó¦t ¿!D¹ ‰Þó¦t¿!D¹ ‰Þó¦uFÇEð‹Eº…ÀˆBøÿÿ‰Ú¸è£÷ÿÿ…Àº…)øÿÿ‹E…À…sûÿÿ‹U1ÿ‰ºd ü¿(!D¹‰Þó¦uIÇEð‹uº…öˆë÷ÿÿ‰Ú¸èL÷ÿÿ…Àº…Ò÷ÿÿ‹M…É…ûÿÿ‹Eº‰h ü¿+!D¹‰Þó¦uFÇEð‹Eº…Àˆ‘÷ÿÿ‰Ú¸èòöÿÿ…Àº…x÷ÿÿ‹E…À…Âúÿÿ‹U1ÿ‰ºh ü¿.!D¹‰Þó¦uIÇEð‹uº…öˆ:÷ÿÿ‰Ú¸è›öÿÿ…Àº…!÷ÿÿ‹M…É…kúÿÿ‹Eº‰” ü¿1!D¹‰Þó¦uFÇEð‹Eº…Àˆàöÿÿ‰Ú¸èAöÿÿ…Àº…Çöÿÿ‹E…À…úÿÿ‹U1ÿ‰º” ü¿4!D¹‰Þó¦uFÇEð‹uº…öˆ‰öÿÿ‰Ú¸èêõÿÿ…Àº…pöÿÿ‹M…É…€‹E1Ò‰8 ü¿7!D¹‰Þó¦uIÇEð‹Eº…Àˆ2öÿÿ‰Ú¸è“õÿÿ…Àº…öÿÿ‹E…À…)‹U¿‰º8 ü¿:!D¹‰Þó¦uIÇEð‹uº…öˆØõÿÿ‰Ú¸è9õÿÿ…Àº…¿õÿÿ‹M…É… ùÿÿ‹Eº‰¨ ü¿=!D¹‰Þó¦uIÇEð‹Eº…Àˆ~õÿÿ‰Ú¸èßôÿÿ…Àº…eõÿÿ‹E…À…¯øÿÿ‹U¿‰º< ü¿@!D¹‰Þó¦uFÇEð‹uº…öˆ$õÿÿ‰Ú¸è…ôÿÿ…Àº… õÿÿ‹M…É…Uøÿÿ‹E1Ò‰Œ ü¿C!D¹‰Þó¦uIÇEð‹Eº…ÀˆÍôÿÿ‰Ú¸è.ôÿÿ…Àº…´ôÿÿ‹E…À…þ÷ÿÿ‹U¸‰‚Œ ü¿F!D¹‰Þó¦ue‹E ºþÿÿÿ…À„zôÿÿÇEð‹Eº…Àˆcôÿÿ‰Ú¸èÄóÿÿ…Àº…Jôÿÿ‹}…ÿ…¯÷ÿÿ‹E‹U ˆ ‰T$‰$è…gƒìü¿I!D¹‰Þó¦t¿L!D¹‰Þó¦u*ƒ}ÇEðºŒîóÿÿ…‹E¾‰°ü¿R!D¹‰Þó¦t¿U!D¹‰Þó¦u*ƒ}ÇE𺌣óÿÿ…¸‹U¹‰Š‹Uðé‡óÿÿt&—¸‰Uà‰D$‰T$‹Eä‰$èï$‰EäéäøÿÿÇ$éÅöÿÿ‹U ¶ éà÷ÿÿÇ$\!Dèô•é-óÿÿ‹U Ç$ˆ!D‰T$èÜ•éóÿÿ‹U 1ÿ‰$èê#£E‹E ‰$è*ç‰D$‰|$‹U ‰$èçéáùÿÿÇ$é5öÿÿ¶U‰åWV1öSƒì‹}ÇEð‹†<E1Û…À~;ë ‰|$ 1À‰D$‹†8E‹T؉T$‹ØC‰$èòÿÿ9ž<EÔÿEðƒÆ ƒ}ð~­ƒÄ[^_]ÃU‰å‹E ‹U‹Æ ÿ]ö¼'U‰åWVSìl‹u‹†¨&…À…£~4–‰û‰•œþÿÿ…À„àƒ¾°&ÿ„Ó…ÀuY€½Øþÿÿ…è¶…Ùþÿÿ„À„øƒ~@¶À‰†¨&„‹†¨&…À„’9†¬&|¢1ÀÄl[^_]ô&ƒ¾°&ÿ„$‰$èk‹–´&9ÐŒo‰T$…Øþÿÿ‰D$‰$臋†´&‰$‰D$èõ$‹†°&ƒø„öd…Àup€½Øþÿÿ…ÇF@ëZ‰<$èHŽ ‰<$¸‰D$…Øþÿÿ‰D$è ‰<$¸‰D$è$‹†¨&éçþÿÿt&ƒø„k´&ÿ†¬&¸ÿÿÿÿƒ~@‰†°&…ëþÿÿ‹†¨&9†¬&Œßþÿÿ1À1É1Ò‰†´&1À‰Ž¨&‰–¬&érþÿÿt&9†¬&ŒQþÿÿé»þÿÿ¶…Øþÿÿ‰†°&¶…Ùþÿÿ‰†´&é½þÿÿÆ…¸þÿÿÆ…¹þÿÿÆ…ºþÿÿÆ…»þÿÿ‹–´&‰•¤þÿÿè{‰… þÿÿ‹…œþÿÿ‰$è?äƒø@ŽÆ‰D$‹…œþÿÿ•¨þÿÿ‰T$‰$èšz¹•¨þÿÿ‰L$‰T$‹… þÿÿ‰$èéz‹…¤þÿÿ•¼þÿÿ‰T$ •Øþÿÿ‰D$‹… þÿÿ‰T$‰$è­|‹• þÿÿ‰$èŸz‹Fº‹‰T$•¸þÿÿ‰T$‰$ÿQéœþÿÿ€½Øþÿÿ…„þÿÿ‹F »@1ö¹°!D‹‰t$ ‰\$‰L$ë,‰D$‹•œþÿÿéVÿÿÿ‹F 1ÿ¾@»"D‹‰|$ ‰t$‰\$‰$ÿR¸éRýÿÿ‹F 1Û¹@¿8"D‹‰\$ ‰L$‰|$ëÑ‹F »@1ö¹p"D‹‰t$ ‰\$‰L$ë²¶U‰åVSì ‹u€¾œu €¾„ñÆ…èýÿÿžœ‰ÙÆ…éýÿÿÆ…êýÿÿÆ…ëýÿÿÆ…ìýÿÿ…Æ…íýÿÿv¼'‹ƒÃÿþþþ÷Ð!Â €€té÷€€uÁêƒÃÒƒÛ)Ëûÿ~v»ÿˆîýÿÿ…ïýÿÿ‰\$‰L$‰$è[â‹VC‹ ‰D$…èýÿÿ‰D$‰$ÿQÇF@1À‰†¨&1À‰†¬&¸ÿÿÿÿ‰†°&1À‰†´&Ä ¸[^]Ã…Û‹»ë„‹F »@1ö¹¨"D‹‰t$ ‰\$‰L$‰$ÿRÄ ¸[^]ÃU‰åƒì‰T$‹M1Ò‰T$‰L$ ‹@‰$èþÉö¿U‰ÁˆÐ, ‰å<^Svb€úŸwB„Ò»y4‹ ‹Ü…ÀtX€ú¿»w‹™Ü…Ûu]‹Œx éýtN»‰Ø[]Ë‹˜Ü…Ûu²‹€Œx éýt£»‰Ø[]ö‹Œx éýt™‹™Ü…Ût£¾ÂÁè€ú¿–Â1Û…Âu¥»ëž´&¼'UˆÑ‰åV‰ÆˆÐS, ƒì0ˆUç<^†‹‹Ü…Òt1„Éx}€ù²?tˆÊ€Â@ÆEä^EäˆP‰ÂÇ$‰ðè¿þÿÿƒÄ0[^]Ë€Œ‹X ûéý•Â1À€ùŸ—À…Âu2ûéýt©„Éy©¶Á]è‰D$¸ð"D‰D$‰$è;àÇ$‰Úë¢Ç$Uç‰ðèWþÿÿƒÄ0[^]ÃU‰åV‰ÆSƒì‰ÓëfÇ$º÷"D‰ðè-þÿÿKƒûÿuçƒÄ[^]ÃU¹$‰åƒì‰L$‰]ô‰uø‹u ‰}ü‹}Ç$è&Ç@‰Ã…öÇ@Ç@Ç@ ‹E‰{‰3‰C‹E‰C ‹E‰Ct‰ž€…ÿt ‰\$‹E‰$ÿW0‰Ø‹uø‹]ô‹}ü‰ì]ô&U‰åSƒì‹]‹…Àt1Ò‰€‹S…Òu‹C…Àu*‰]ƒÄ[]éM1À‰D$‹C ‰$ÿR0‹C…ÀtÝ´&‰$è(‰]ƒÄ[]ét&¼'U‰åWVSƒì‹}ÇEè‹E ‹U…ÿ‹]‰Eð‰Uì…¶‹K1ö‹(…Àu.¾‰u‹$1ö…Àtsƒøt9‰u ‹C‰EƒÄ[^_]éyƒøuÒ1Ò‹C‰T$‹S ‰$ÿP,…À„U‹K뮿‹C‰|$‹S ‰$ÿP,…Àu¹‰L$‹‰$è…Àt—t&‹C¾‰u ‰EƒÄ[^_]é¶‹C‰$è5Q…ÿˆ‹C‹€(…À…̶¿Oƒÿÿ„¨‹Uð¾‹UèÿEð4‹Eì…À”Â1Àƒþ ”À…ÂtÆ‹C …Àu6ƒþ„¿Wƒþ „c¶ƒþ„Xƒþ„<¶‹S‹K;Sò‰ðˆ ‹CÿC‹€$…À„ȃø„•ÇC Oƒÿÿ…XÿÿÿƒÄ[^_]öƒø„‹S…Ò…E…ÿ~Ú‹C‹€$…À„ƒø„á‹Eè…Àt‹K‹±ƒþ”À1Òƒÿ”Â…Ð…=‹Uð‹C‰}‰U ‹S ‹H ‰UƒÄ[^_]ÿẋC‰T$‹S ‰$ÿP,…À„â¶¼'‰ð¶Ð‰Øè”ûÿÿé0ÿÿÿ‚º‰C‰T$‰ $‰D$è‰C‹S‰Áéãþÿÿt&ƒþtuƒþ„ðƒþ…·þÿÿƒ{ëƒø„w‹CH…À‰CŽ‹C‹€$…ÀuÛ‹C‹S¶Tÿ‰ØèIúÿÿ‰Â‰ØèÀûÿÿëÇÇC éòýÿÿƒþ„^ƒþë—þ „ÔŽüþ…6þÿÿ‹K…ÉJéºýÿÿƒø„Z‹S‹KBÿ‰C‹¶Tÿ‹ˆÜ…Éu‹€Œx éý…ýÿÿ€Â€€ú?‡uýÿÿ‹C‹€$…Àu®‹C‹S¶Tÿ‰Øè–ùÿÿ‰Â‰Øè ûÿÿëš‹C‹…Ò…ªýÿÿ‹S…ÒŽ¢ýÿÿ‹K€|ÿ …—ýÿÿ‹€$…À„’ƒø„fBÿ‰C‹S…Ò~‹C‰T$‹S‰T$‹S ‰$ÿP ‹S‹‚…À„»Hu‹‚…À…¸‹S‰D$¸û"D‰D$‹C ‰$ÿR ‹C‹€$…À„ƒø„ØÇCé€üÿÿ‹Eð‰$è%ÚÇEè‰ÇéJüÿÿ´&‹S…ÒŽUüÿÿ‹C‹€$…À„÷ƒø„ÎBÿ…À‰C~Ñ‹K¶Tÿ¡ÌSEƒ8…˜¡ðSE‹·Pƒà…Àt©¡ÌSE‹S‹Kƒ8¶ …P¡ðSE‹·Pƒà…À…{ÿÿÿéÖûÿÿþéÿýÿÿ¹‰L$‹‰$èxˆ…À„Qüÿÿé ýÿÿ‹Uð¾ƒø „Á®ƒø„Fƒø…œüÿÿ‹…À„Žüÿÿ‹CÇE ‹S ‹H‰UƒÄ[^_]ÿá‹S…Ò…K‹S¹ ‰L$‹C ‰$ÿRé5ûÿÿ1À‰D$‹‰$è凅À…“úÿÿ‹KéCúÿÿt&º‹C‰T$‹S ‰$ÿP‹C‹€…À„Zûÿÿƒþ„ƒþ„pƒþ…Ïúÿÿ‹S¹é{ÿÿÿfº‹C‰T$‹S ‰$ÿP,…À…ˆüÿÿ¹‰L$‹‰$èP‡…À„Qüÿÿéhüÿÿ‰$¾‰t$èRØé`þÿÿº‹C‰T$‹S ‰$ÿP,…À„h‹S‹C¶Tÿ‰Øè~öÿÿ‰Â‰Øèõ÷ÿÿ‹Séòýÿÿº‹C‰T$‹S ‰$ÿP,…Àu¸‰D$‹‰$èÁ†…À„ëúÿÿ‰<$‰Ø‹UðèüõÿÿéÙúÿÿ‹C‰T$‹S‰T$‹S ‰$ÿP ‹Së!‹C¶Tÿ‰Øèüõÿÿ‰Â‰Øès÷ÿÿ‹CH‰Â‰C…ÒÛéuúÿÿ‰$¹‰L$èp×é¨ýÿÿ‹C‹€$…Àt&ƒø…uùÿÿº‹C‰T$‹S ‰$ÿP,…À„KÇ$‰Øºý"DèUõÿÿ‹C1ö…ÀŽ8ùÿÿ‹C¶‰ØFè)öÿÿ9sìéùÿÿ1Ò‹C‰T$‹S ‰$ÿP,…À…ùÿÿ1À‰D$‹‰$èµ……À„¶ùÿÿéèøÿÿ¸‰D$‹‰$è•……À„˜þÿÿ‹Séxþÿÿ‹S¸ ‰D$éqýÿÿ¾‹C‰t$‹S ‰$ÿP,…Àu¹‰L$‹‰$èH……À„ôûÿÿÇ$º#D‰Øè}ôÿÿéÜûÿÿ‹S¾ ‰t$éýÿÿº‹C‰T$‹S ‰$ÿP,…À…Òúÿÿ¾‰t$‹‰$èç„…À„núÿÿé²úÿÿ‹S¸‰D$¸#DéQûÿÿ‹C‰T$‹S‰T$‹S ‰$ÿP é\ûÿÿƒøtƒøéQüÿÿN„ª‹CÇEÇE û"Déâøÿÿ¸‹S‰D$‹C ‰$ÿRéþúÿÿ¹‹C‰L$‹S ‰$ÿP,…À„š‹S‹K¶Tÿ‰Øèµóÿÿ‰Â‰Øè,õÿÿ‹SéZúÿÿ‹‰…É„nøÿÿ‹CÇE éÛûÿÿ‹±…ö„Qøÿÿ‹CÇE é¾ûÿÿ‹…À„Hÿÿÿ‹CÇE é¡ûÿÿ¸‰D$‹‰$躃…À„òöÿÿé•ýÿÿº‰T$‹‰$蚃…À…Kÿÿÿ‹SéÀùÿÿU‰å‹E‹ …Ò~ƒxt]ˉE]é¥Ô¶¼'U‰åSƒì‹]‹…ÀuÇCY[]Ãt&‰$è`ÔÇÇCY[]ô&U¸X'‰åSƒì‰D$Ç$ètljÓÇ@‹E‰ƒ¸<&‰D$‹E ‰$‰D$èÎÓC‰$è3 ƒÄ‰Ø[]Ãt&¼'U‰åSƒì‹]‰$è>ÿÿÿC‰$裉]X[]鸴&U‰åWVS윋E‹X…Ûu ‹ˆ …Éueô[^_]ÃU¸¨þÿÿ‰$èG¸‹Eƒìº‹}‰T$ƒÇ‰D$‰$è!Ó‹E•ˆýÿÿ‰•xýÿÿ‰…„ýÿÿ¸‰…|ýÿÿ‰$èdR‰ÆëBˆ…˜þÿÿF»;|ýÿÿ~‹|ýÿÿ‰\$‹•€ýÿÿ‰T$‹…xýÿÿ‰$èºÒxýÿÿ)|ýÿÿ¶„Àth•˜þÿÿ<&‰•€ýÿÿu§F1Û¶„Àˆ…wýÿÿt£¾ÀF‰$è“Òƒèdƒø†ˆ€½wýÿÿ&Æ…˜þÿÿ&»„rÿÿÿ¶…wýÿÿ»ˆ…™þÿÿé[ÿÿÿ‹•xýÿÿ…ˆýÿÿƉD$‰<$è4Qƒì¸#D‰D$‰<$èÒ‹U…À‰º…‰T$‹U‰$èeô[^_]Ãÿ$…$#DU¸¸#D‰T$ ‰D$ë"U¸¸#D‰T$ ‰D$ëU¸»#D‰T$ ‰\$¹ …˜þÿÿ‰L$‰$èÅщÃéªþÿÿ‹•„ýÿÿ‰•€ýÿÿ‰$èZщÃéþÿÿU¸‰T$ º#D‰T$뵉$èÑ‹U‹‚ƒøÿt1Òƒø”ÂBé?ÿÿÿ‹E1ÒL$‰„$ ¸?@‰„$¶ˆBúrð‹U‹‚‰$è?…À‰Â‰÷þÿÿ‹EÇ@é†ýÿÿ¶U1Ò‰åWVSì ‹} ‹uœ$ìë ¶ˆBúrð1ÒŽ´&¶ˆBúrðèûO…Àt‹‡ð1Û9† t ‰4$»èúûÿÿ‰|$†º<&‰T$‰$è?Ð…Ûu Ä [^_]ÉuÄ [^_]éžüÿÿ´&¼'U‰åƒì(‰]ô‰Ã‰uø‰Ö‰}ü‹@‹}…Àtƒøt.ƒøtI‹]ô‹uø‹}ü‰ì]É$èTüÿÿ‹CƒøuÞ¶¿‰|$C‰t$‰$è­ ‹]ô‹uø‹}ü‰ì]Ë…Àt&‰|$¹‰4$‰D$ ‰L$èÁÏ‹]ô‹uø‹}ü‰ì]ÃÇ$|#D¾-»†#D‰t$‰\$èžÏ¶U‰åESƒì‰D$‹E ‰$è' ‰$‰Ãè ω$‹E‰Úèÿÿÿ‰$èHƒÄ[]ÃfU1À‰åWV1öS쬋U‰…|ÿÿÿ‹} ‹]ÇE„‹‚ ‹MÇE€ƒøtƒø•À…É” Ш…Î…É„G‰L$…ÿ¸“#D‰\$‰\$ t¸œ#D‰D$‹M¿¨#D‰|$‰ $è6ÿÿÿ;u€1É1ÿ‰tÿÿÿv‹U 9U„}H‹M$‹D‹Ð9ð8‹•tÿÿÿfÿE„ƒÇ ‹E ƒ…tÿÿÿ ƒÂ 9E„}‹M$‹D ‹ Ø9ð~Ø´&‹E 1Û9E„}&‹U$‹9ð‹LÈ9ð~‹\´&¼'ƒû•À1Òƒ}€•Â…Ðt6ƒ}€¸Ê#Dt¸Ë#D‰D$ ¸Í#D‹M€‰D$‹E‰L$‰$è^þÿÿÇE€‹•|ÿÿÿ U€u7¸Ê#D…ö‰D$¸C‰D$ ‰ðˆƒàð¹å#D‰D$E˜‰L$‰$èm̓û„ÓK…•fÇEˆXXºX…ö‰•xÿÿÿ‰ðÆEŠˆ¥ƒàð‰ó)ÃUè[жUˆˆP¼¶U‰ˆP½¡ÌSEƒ8…+¡ðSE‹xÿÿÿ‹·H%W¶•xÿÿÿ…Àu².ˆT+Õ…ö‰ðˆYƒàð‰ò)‰Ð@‰…|ÿÿÿF÷Æ”À;u” Шu‹E€…Àtq‹…|ÿÿÿ…Àtg‹|ÿÿÿfÇD Õ ÆD ×M˜´&¼'‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁÒE˜‰ÂƒÙ)Á‹E‰ $è4üÿÿ1À‰…|ÿÿÿ;uŒÃýÿÿ‹E€…Àt/ƒ}€¸Ê#Dt¸Ë#D‰D$ ‹U€¿Í#D‰|$‹M‰T$‰ $è­üÿÿ‹E‰$èb÷ÿÿĬ[^_]ô&¸W‰D$‹…xÿÿÿ‰$èÙËéÏþÿÿt&‹M¸ñ#D¶ ‰D$Eˆ‰$‰xÿÿÿ‰L$è£Ë…ö‰ð‰[þÿÿFéSþÿÿÿE€é·þÿÿFéŸþÿÿFéñýÿÿ…ÿ¸“#Dt¸œ#D‰D$‹E»ö#D‰\$‰$èûûÿÿéÀüÿÿ¶U‰åƒì‰]ø‹]‰uü¡ÐGE‹u ¨t¨uG…Ût‹ƒ ƒèƒøv‹]ø‹uü‰ì]Ãt&‰t$¸$D‰$‰D$è›ûÿÿ‰]‹uü‹]ø‰ì]éJöÿÿ‰t$¸$D‰D$¡äSEƒÀ@‰$èÝÊ¡äSEƒÀ@‰$èåÊëŠt&¼'U‰åƒì‹E ‹MˆEÿ‹ …À~;EtÉÃÇ$Uÿ‰Èè_úÿÿÉö¼'U‰åWVSì\‹E ‹u…À…ÇF~ƒ~„2‰<$èšI‰D$ º$D‹† ƒøt&ƒøº$Dtƒøº"$Dtƒøº.$Dtº;$Dv‰T$‹U ¸C$D…Òtƒ} ¸T$Dt¸^$D‰D$Ç$l$Dè@‰D$‰Ã‹†‰$èÜ9‰$^èу~uOé嶉$…´þÿÿ‰D$…°þÿÿ‰D$è‹…´þÿÿ‹•°þÿÿ‰$‰ðèNùÿÿ‰$‹…´þÿÿ‰D$蜉$èÔ…Àu°eô[^_]Ã} ¸‘$Dt¸”$D‰D$~‰<$èɉƒøÀ÷ЃÀ‰Fƒ~…Îþÿÿ¸þÿÿ‰$èò­ƒì¸—$D‰\$ »‰\$èþÿÿ‰D$‰$èûȉ\$¹¬$D‰L$‰4$èfùÿÿéþÿÿÇ$ë$D¸w‰D$¸†#D‰D$èÛÈUº ‰åSEøƒì‰D$‹E‰T$‰$èöÈ‹Uø‰Ã€:tdëf¡ðSE‹·Hƒà…Àt0B‰Uø¶„Àt%¶È¡ÌSEƒ8tÖ‰ $¸‰D$è5È…À‹UøuоƒèGƒø&wÿ$…%DÁã‰ö¼'ƒÄ‰Ø[]ÃÁãëóÁã ëî´&¼'U‰åƒì‰]ø‹]‰uü‹u ÆE÷€;^tǾE÷‹]ø‹uü‰ì]ÃC¶ „Étã€ùt ÆE÷éhÿÿÿ@‰똴&U‰åVS‹M‹] ‹u¶Áâƒû~ ¶AÁà ƒû~¶A ‰ÐÁèƒà?¶€°%Dˆ‰ÐÁè ƒà?ƒû¶€°%DˆF~3‰ÐÁèƒà?¶€°%DˆFƒû~ƒâ?¶‚°%DˆF[^]ÃvÆF=[^]ÃÆF=ëÙfU‰å‹EÇ@ÇÇ@]Ãt&U‰å‹E]‹@Ãt&U‰å‹E‹‹H‹P)Ê‹M‰‹PЋU ƒÀ ‰]ö¿U‰åWVSƒì‹E‹]‹U ‹89X‰Uð}6ë^f…ÿ‰Þt8‹G‹W)Ð9؉Ɖt$D: )ó‰D$‹Eð‰$èãÅuð‹?…ÛʃÄ[^_]ÃÇ$ñ%D¾¶»ý%D‰t$‰\$èüÅÇ$&D¸²¿ý%D‰D$‰|$èÞŶU1Ò‰åìè¸ÿÿÿ‹M ‰uü‹u÷ñ‰]ø1Û9ðr¯Î…Éu¹‰ $è¸Å…À‰ÃuDfÆ…6ÿÿÿ¸Out ‰…(ÿÿÿ¸of m‰…,ÿÿÿ¸emor‰…0ÿÿÿ¸y!f‰…4ÿÿÿ…(ÿÿÿ‰$è>r‰Ø‹uü‹]ø‰ì]ÃfU‰åWVSƒì‹}‹E …ÿ‰Eð„ËU‹Bz…À„®‹PúÿŸ»)Ó9û~‰û‰\$D ‹Uð‰$)߉T$è Ä]ð‹U‹BX…ÿ~mÿ‰þ~¾Ç$¸ )÷‰D$èÚþÿÿÇ@‹Uð‰Ã‰p@ ‰T$‰t$‰$èHÄuð‹U‹B…Àu‹E‰X‰‹UljZ…ÿ“ƒÄ[^_]Ãt&¼'U‰åWVu Sƒì ‹E‰$èÙÉÃët&‰$èÈÃÃ‰ð‹ƒÆ…ÀuëºCu ‰T$‰$è4þÿÿ‰Ç‹E‰<$‰D$è+ĉ<$è‹Ã8붉$‰D$è ĉ$èlÃÃ‰ð‹ƒÆ…Àu៎ ‰ø[^_]Ãt&U‰åƒì‰uü‹u‰]ø1Û…öt(‰4$è3Ã@¹‰L$‰$è±ýÿÿ‰$‰Ã‰t$è«Ã‰Ø‹uü‹]ø‰ì]ô&U¸$‰åƒì‰D$Ç$èuýÿÿÇ@‹UÇ@Ç@ ‰PÇÇ@ Ç@Ç@Ç@ÉöU1Ò‰åìø¸ÿÿÿ‹M‰uø‹u ÷ñ‰]ô1Û‰}ü‹}9ðr&¯Î…ÿtp‰L$‰<$èÛÂ…À‰ÃuO¶¼'Æ…&ÿÿÿ¸Out ‰…ÿÿÿ¸of m‰…ÿÿÿ¸emor‰… ÿÿÿ¸y!f‰…$ÿÿÿ…ÿÿÿ‰$è^o‰Ø‹uø‹]ô‹}ü‰ì]É $èwÂë’t&Uº‰åWV¾Sƒì‹} ‰T$Ç$èZüÿÿ‰Ãë ¶q‰$¸‰D$‰t$èÿÿÿ‰Ã‰|$ ‹E‰t$‰$‰D$è‰Á÷ÐÁè9ñœÂ…Âu …É»Æ붃ĉØ[^_]Éö¼'U‰åE ƒì‰D$‹E‰$èXÿÿÿÉöU¸‰åƒì‰}ü‹}‰]ô‰uø‹u‰D$Ç$è¦ûÿÿ‰<$‰Ã¸‰D$è“ûÿÿ‹U ‰C¹‰‹U‰{ ‰S‹F@‰F‰L$‰D$‹F‰$è3þÿÿ‰F‹V‰\ü‹]ô‹uø‹}ü‰ì]ö¿U‰å‹E…Àt]éÁ]ô&¼'U‰åWVSƒì‹}‹] 9_Œ~…Û~T‹ë؉A)w)ó…Û~B‰Mð…ɉÞtA‹Q‹A)Â9ÚÝ‹ ‰Ö‹Eð‰‰$èŒÿÿÿ‹…ÉuË)w)ó…ÛÇGĶƒÄ[^_]ÃÇ$&D¸–‰D$¸ý%D‰D$èbÀÇ$&D¸“‰D$¸ý%D‰D$èDÀ¶¿U‰åSƒì‹]‹…Òt‰Ð‹‰‰$èÿÿÿ‹…ÒuìÇCÇCZ[]Ãv¼'U‰åW1ÿVSƒì »‰\$»Ç$èûùÿÿ‰Æë5´&‰$èX¿Ç€|>ÿ t9‰4$¹Ÿ‰L$‰\$è”üÿÿ‰Æ‹E)û‰\$>‰D$‰$袿…Àu¶…ÿtÆ7‰ðƒÄ [^_]É4$èLþÿÿ1Àëì´&U‰åW1ÿVSƒì ‹u‹F…Àu0‹F‰$è þÿÿ‹F‰$èþÿÿ‹F ‰$è þÿÿ‰uƒÄ [^_]éûýÿÿ‹F‹¸G‹C ‹S‰D$1À‰$‰D$蔾‹C‰$èÑýÿÿ‹‰$èÇýÿÿ‰$è¿ýÿÿ9~w¿ë´&U‰åE Sƒì‰D$‹E‰$èWüÿÿ‰$‰Ãè½>‰$è…ýÿÿƒÄ[]Ãë U‰åWVSƒìL‹E‹} ‰EÄ‹E…À….…ÿŽât&¼'Ç$.&Dèd>‹E…À…ìÇEÈ....1ö9þÇEÌ....ÇEÐ....ÇEÔ....ÆEØ}[‹]Ä;]‚§¶;]‰D$„‡÷Ƹ.tz‰D$Ç$1&Dèÿÿÿ¶ˆÐ, <^wˆT.ÈFCƒþžÀ1Ò9þœÂ…Ðu¨ÆD.ÈEȃï‰D$ ¸:&D‰D$¸)ðÇ$;&DD@‰D$èÅþÿÿƒEÄ…ÿ)ÿÿÿƒÄL[^_]ø é|ÿÿÿ¶Ç$B&Dèt=ÆD.È ë‚Ç$F&D‹EĉD$èzþÿÿéüþÿÿ‰|$‰|$Ç$K&Dèaþÿÿ‹EăàÇ)EÄé®þÿÿU‰å‹Eƒ¸t€8]•À¶Àö€¸À]•À¶ÀÃU‰å‹Uƒº‰Ðt]Ã]‚ÀÃU‰åSƒì‰Ã‹…ÀuÇCƒÄ[]Ãt&‰\$iÀè¹@M@‰L$‰$èÕ‹S…Òt9C~ωCÇCƒÄ[]Éö¼'U‰åSƒì‹]‹E ‹S…Òt-;Cx(¸‹S ‰D$‹C‰$ÿRÇCƒÄ‰Ø[]é_ÿÿÿƒÄ[]Éö¼'U¹‰åSƒì‰L$Ç$è$öÿÿ‰Ã‹E‹€ÇC‰‹E ‰C ‹E‰C‰Øè ÿÿÿƒÄ‰Ø[]Ãt&U‰å‹E‹M‹‹E 9t ‰‰È]éÜþÿÿ]Ãv¼'U‰åSƒì‹]‰$èn‰][[]écúÿÿU‰å]Ãt&¼'U‰å‹E‹@…Àu]ÉE]éçã´&U‰åƒì‰uü‹u‰]ø…öt3‹‰4$ÿP‰Ã‹€,‰$èúÿÿ‰$èýùÿÿ‹‰u‹]ø‹uü‹H‰ì]ÿá‹]ø‹uü‰ì]ÃU‰åWVSƒì\‹]‹u‹K…É„6¶Nƒþÿ„F‹“(ú‡²‹M¶A‰MˆD B‹S‰ƒ(ƒú„A‰ÐÁø ƒø„3ƒút‰ÐÁø ƒø…à€{ …Öƒú„}úP„xúP…µü1ÀÇEÀ¹}Øó«fÇÆEØÆEÛ‹“(ƒúŽEÿÿÿ¶K#ƒù„ȃù„³ƒù„à‹EÀƒÀ9ÂŒÿÿÿ‹C %ÿÿ=…¡‹UÀ¶D$¶T%Áà Љƒ(ƒù„Jƒùt<ÆEÙ¹ ‹C ‹‰L$M؉L$‰$ÿR‹C ‰$èEþÿÿt&ƒÄ\¸[^_]ËC ¿ ‹‰|$}؉|${ ‰$ÿR‰<$‹EÀH‰D$C%‰D$莹‹EÀÆD‹C ‰D$‹C‰$è$™‰C…À‰Ât‹¸p&D‰D$ ‹ƒ(‰$‰|$‰D$èÌ™ÇC‹C ¹‹‰L$‰$ÿR…ö~=‰4$¸‰D$èüòÿÿ‰ƒ,‹U‰t$‰$‰T$ès¸‰³0¶¼'‹{…ÿ„ÿÿÿ‰t$‹M‰L$‹C‰$èò…ÀŽ÷þÿÿÇC‹C ¹‹‰L$‰$ÿRé×þÿÿ´&€{ …ÃýÿÿJ„狃(ƒøŽ`ýÿÿ€{!…ƒøŽMýÿÿ€|…Býÿÿ÷C$ÿÿÿ…!€{'„{@…-ÇC@¿ë}ÇCP‹“(ƒúŽúüÿÿ¶K!A9ÂŒëüÿÿ1Òƒù¿ÿ~‰È¶¼'€|"„ŒB9ÐðÆEƉøºˆEÇ1ÿ‹C ‹‰T$UƉT$‰$ÿQÇCP‰»(éˆüÿÿÇC@é ÿÿÿÇEÀéJýÿÿÇEÀé>ýÿÿÆEÙ¹ }Ø‹C ‹‰L$‰|$é€ýÿÿ¶C$@‰EÀéýÿÿ1ÿérÿÿÿ‹CÁø ƒø…cýÿÿÇEкÇEÔÆEÑ[‹C ‹‰T$UЉT$‰$ÿQé1ýÿÿÆC ‹C ¹ÆC!Z{ ‹‰L$‰|$‰$ÿR¶C"‹‹(¶S#Áàƒé Љƒ(C(‰L$‰D$‰<$è¿¶é4ýÿÿ‹C ¹ ¿{&D‹‰L$M؉L$‰$ÿR¶C'‰D$¶C&‰D$¶C%‰D$ ¶C$‰|${ ‰D$‰<$èãµéàüÿÿÇEȾEÈÇEÌÆEÉ[‹S ‹ ‰t$‰D$‰$ÿQéTüÿÿÆC ‹C ¿ÆC!Z‹‰|${ ‰|$‰$ÿR¶C"¹{&D¶S#Áà Љƒ(¶C'‰D$¶C&‰D$¶C%‰D$ ¶C$‰L$‰D$é]ÿÿÿU‰åSƒì‹]‹C…Àu‹C ‰$è$úÿÿ[¸[]É$èÓð‹C ‰$èúÿÿ[¸[]Ãë U‰åƒì8‰]ô‹E‹U‰uø‰D$‹E‰T$‰}ü‰D$ Eð‰D$‹E ‰$èÊ ‰$‰ÆèZ…À‰Ãt‰4$è’G‰Ø‹]ô‹uø‹}ü‰ì]ÃvÇ$¸4‰D$èëîÿÿ‰Ç1À‹U‰‡,‹ELj&DÇG‰G‹EÇGÇGÇGÇG‰D$ 1À‰D$1À‰D$¸‰D$1À‰D$ ‹Eð‰T$‰|$‰D$‰4$è¶ ‹U‰‰G ‹‹‰$ÿR …À‰Ãt ‰<$èóÿÿé?ÿÿÿ‹U‹‹‰$‰|$ÿR1Àé)ÿÿÿ‰ö¼'U¸4‰åƒì(‰]ô‰uø‰}ü‹}‰D$Ç$è îÿÿ‰Ã1À‰ƒ,‹GÇœ&DÇC‰C‰\$‹E ‰$èÝF‰C ‰Æ‹‰4$ÿP …Àt‰$è„òÿÿ‹]ô¸‹uø‹}ü‰ì]Ãf‹‰\$‰4$ÿPÇC‹GÇCÇC…Àt,ÇC‹1É1ÿ‰»(‰L$‰4$ÿP1À‹]ô‹uø‹}ü‰ì]ÃÇCG ‰D$C ‰Eð‰$èH³‹‡(‰ƒ(‰t$‹G‰$èõ’‰C…À„Nÿÿÿºp&D‰T$ ‹ƒ(‰D$‹Eð‰D$‹C‰$è•“1ÀëˆU¸4‰åWVSƒì‹u‰D$‹}Ç$èÌìÿÿ‰Ã1À…ö‰ƒ,ǰ&DÇC„‰t$C ‰$覲‹E ÇC‰ƒ(ÇC‹EÇCÇC‰C‹E$‰|$‰D$1Àƒ¿!‰\$”À‰D$ ‹E‰D$‹E‰$è2‰C ‰Æ‹‰4$ÿP …À‰Çt‰$èçðÿÿ‰øƒÄ[^_]ÃÇC놋‰\$‰4$ÿP‹E ‰01ÀëÚë U‰å]éwöÿÿ´&U‰åSƒì‹]…Ût&‹‰$ÿP‹Ç@‹@‰$…À•À¶À‰D$ÿRƒÄ[]öU‰åƒì‰]ø‹]‰uü‹u …ÛtJ‹‰$ÿP1É‹‰p‹@…Àt‰]¹‹]ø‰M ‹uü‹J‰ì]ÿá…öuã‰M ‹uü‹J‰]‹]ø‰ì]ÿáv‹]ø‹uü‰ì]öU‰åS‹U…Òt [‹]‹Hÿá[1À]ô&U‰åƒì‰]ø‹]‰uü…Ût=‹‰$ÿP1Ò‰ÆÇ@‹‰T$‰$ÿP‹1É1Ò‰L$‰T$‰$ÿP‹Ž,…Éu‹]ø‹uü‰ì]ö‹†0‰D$‹†,‰D$‹F‰$èñ鋆,‰$èCïÿÿ1Ò‰–,‹]ø‹uü‰ì]ÃU‰åW¿VSƒì‹EÇ@@‹@‹‰|$‰$ÿR‹uƒÆ$‰4$è[éÿÿ‹}‰ÃƒÇ‰<$èKéÿÿÉ]è1ÛëEf‰4$Eð‰D$Eì‰D$è:éÿÿ‹E‹P‹Eð‹ ‰D$‹Eì‰$‰D$ÿQ ËEð‰4$‰D$è½îÿÿ‰4$èõèÿÿ…À±‰<$èéèÿÿ…À~Tt&‰<$Eð‰D$Eì‰D$èÚèÿÿ‹E‹P‹Eð‹ ‰D$‹Eì‰$‰D$ÿQËEð‰<$‰D$è]îÿÿ‰<$è•èÿÿ…À±;]è|‹E‹p0…öu.‹E‹XD…Ût9ƒÄ[^_]ËU‹B ‹‰$‰\$ÿR ‹E‹p0…ötÒ‹@‹‰$ÿR‹E‹XD…Ûulj‹1ɉL$‰$ÿPƒÄ[^_]ô&U‰å‹U ‹M…Ò‹A t‰Q ]Ãt&¼'U‰åSƒì‹]‹C‹‰$ÿR‹C‰$è@A‰]X[]éuíÿÿt&U‰åSƒì‹E‹] ‹M‹P@…Òt ‰\$X‰$‰L$èéÿÿ‰]ƒÄ[]é™çÿÿ‹@‹‰M‰] ‹J‰EƒÄ[]ÿáU‰åƒì‰]ô‹]‰uø‹u‰}ü‹K@‹} …Éu‹C‹uø‹]ô‹‰E‹}ü‹J ‰ì]ÿáCƒÃ$‰$èºíÿÿ‰$è²íÿÿ‰t$‰|$‰$è’èÿÿ‰ð‹]ô‹uø‹}ü‰ì]ÃvU‰å‹E‹P@…Òt Ç@0]Ë@‹‰E]‹Jÿá¶¿U‰å‹E‹@‹‰E]‹Jÿá¶¿U‰å‹E‹@‹‰E]‹Jÿá¶¿U‰åWVSì,‹u‹F@…Àt‹E ‰FDÄ,[^_]Ã^4‰$ènæÿÿ…À޼‹E ½èýÿÿ‰FDéˆt&‰$…äýÿÿ‰D$…àýÿÿ‰D$èDæÿÿ‹…äýÿÿ=v¸‰…äýÿÿ¸‰D$‹…àýÿÿ‰<$‰D$èq¬‰$‹…äýÿÿ‰D$è¯ëÿÿ‹V ‹…äýÿÿ‹ ‰D$ 1À‰|$‰D$‰$ÿQ‹FD…À…Aÿÿÿ‰$è½åÿÿ…Àeÿÿÿ‹ND…É…&ÿÿÿ‹F‹M ‹‰L$‰$ÿRéÿÿÿvU‰å‹E‹H…Éu‹P…Òu]‰ÈˉU]‹H ÿá¶¼'U‰å‹E‹@‹P ‹ ‰U]‹ ÿáv¼'U‰åƒì‰$‰t$‹E‹u ‹]‹@‹M‹P@…Òt"‰HT‹HH‰pL‰XPÇE ‰E‹$‹t$‰ì]ÿá‹@ ‹‰M‰]‹J‰u ‰E‹$‹t$‰ì]ÿát&¼'U‰åƒì(‰uø‹E ‹u‰}ü‹}‰Eð‹E‰]ô‹X‹K@…Ét:‰t$C4‰|$‰$èæÿÿ‰{\‹Mð‰s`‰KX‹uø‰]‹KHÇE ‹]ô‹}ü‰ì]ÿá‹C ‹Mð‹]ô‹‰u‹uø‰}‹}ü‰M ‹J‰E‰ì]ÿá‰ö¼'U‰å‹E‹M ‹@‹P@…Òt‰Hd‹HHÇE ‰E]ÿá‹@ ‹‰M ‰E‹J ]ÿá‰ö¼'U‰å‹E‹M ‹@‹P@…Òt‰Hh‹HHÇE ‰E]ÿá‹@ ‹‰M ‰E‹J]ÿá‰ö¼'U‰åW1ÿVSƒì|‰E¤‹E ‰U ‹€$…À„'‹E¤…Àt^¸@]¨‰D$‰\$‹E¤‰$èÜ8‰]œ‰ö¼'‹Uœ‹ƒÂ‰Uœÿþþþ÷Ð!Â €€tã÷€€uƒEœÁêÒƒ]œ)]œëÇEœ‹E ‰$èw©‰E˜‹U ‹u ¶‚ Æ „ÀˆÂ„m„Ò„e¡ÌSE¶Òƒ8…a¡ðSE‹·Pƒà…À…M¶7€ú,„@„Ò„)‰û¶3„ÀtR‰ö¼'¶Ð¡ÌSEƒ8…ï¡ðSE‹·P%…Àu¶3<-t<.t<*ut&¼'C¶3„Àu·€<7*„€|ÿ*„m‹E¤…À„™‰Ø>)ø‰D$E¨‰U”‰T$‰$訅À„‰Ø)ø‰D$‹U”‰T$‹E ‰$èø§…À„³‰ßë ¡ðSE‹·Hƒà…À…ßþÿÿ€ú,„ÖþÿÿG¶7„Òt:¡ÌSE¶Êƒ8tˉ $»‰\$è6¨¶7ë‰$¸‰D$è¨é ÿÿÿ¸ƒÄ|[^_]É$¸‰D$èü§é—þÿÿ‰$è¿7…Àu‹E¤…À„'þÿÿ‹U¤‰$èå8…À„¯ýÿÿƒÄ|1À[^_]ËM¤…É„•‰Ø)øH‰D$>‰E”@‰D$‹UœD¨‰ú)ÚD‰$èý¦…Àt¼‰Ø)øH‰D$)ß‹E”@‰D$‹E ‹U˜ÐD8éÕþÿÿ‹E¤…ÀtC‰Ø>)øH‰D$E¨‰U”‰T$‰$è°¦…À„kÿÿÿ‰Ø)øHéþÿÿ>‰E”éþÿÿ>‰E”ë’>‰E”‰Ø)øHémþÿÿG¶7ézýÿÿU‰åƒì(‰]ô‹U‹E‰uø‹]‹u‰}ü‹Š(‰Eð‹} …Ét‹‚ …Àt+ƒøt‰u‹Eð‹uø‰]‹}ü‹]ô‰E ‰ì]é™1ItඉT$1À‰Ú‰<$èPüÿÿ…ÀtƉ$èãÿÿ‹Uð‰‹uø‰]‹}ü‹]ô‰ì]é{4t&¼'U‰åƒì8‰]ô‹E(‹]$‰uø‹u‰}ü‹(‹}…Òt‰D$‹U ‰ø‰4$èêûÿÿ…Àu=‰\$‹M ‹E‰t$‹U‰L$‹M‰D$‰T$ ‰L$‰<$èZ>‰Â‹]ô‰Ð‹uø‹}ü‰ì]É\$‹U(‹M ‰t$‹E‰T$ ‹U‰L$‹M‰D$‹E ‰T$‰L$ ‰D$‰<$è/l…À‰Âu±Ç$¹¸&‰L$èôßÿÿÇÐ&Dº<&‰T$‹U(‰EìƒÀl‰T$‰$è`¥‹Mì‰ÈƒÀ4‰Y ‰y‰qÇAÇA0ÇAD‰$è¢Þÿÿ‹EìƒÀ‰$è”Þÿÿ‹EìƒÀ$‰$è†Þÿÿ‹Eì‹U(Ç@@ÿÿÿÿÇ@‹‚(ƒøt1ƒø„ƒø„%ƒø„+‹EìÇ@HÇ@'DéÜþÿÿ‹MìÇAH f@Ç$»‰\$èßÿÿÇô&D‹M(‰Ã‹Uì‰P‹‰D$Eð‰D$‰È,‰$èv/‰$‰ÆèÌI…Àt‹EìÇ@,'Déoþÿÿ‹Eð‰$è~ãÿÿ‰\$‹U ‹M‹E‰T$‹U‰L$‹M(‰T$‰D$ ‹,‰4$‰D$è‰<‹Uì‰B‹‰$ÿR ‹Uì…À…þÿÿ‹B1É‹‰L$‹Mì‹A‰$ÿR‹Eìºÿÿÿÿ‰T$‰$ÿPH‹Uìéçýÿÿ‹EìÇ@H l@éÿÿÿ‹UìÇBHp@éõþÿÿ‹MìÇAH†@éæþÿÿfU‰å‹E‰E]éá<U‰åV‰Æ1ÀS9Ð}v€<0 t@9Ð|õ¸ÿÿÿÿ[^]Ã@ƒø~öX9Ó}¶L€ù t€ù uà‰Ø@ëÒt&¼'U‰åWVSì ‹E‹M ‹P@ƒúÿ„I…ÉtN1Àƒùt9ƒù„Šƒùti‹M1ö»A‹A ¹\'D‹‰t$ ‰\$‰L$‰$ÿR¸Ä [^_]Ãv‹E‹P ‰Ã‹@T‹ ‰D$ ‹CP‰D$‹CL‰$‰D$ÿQÄ [^_]Ãú„8ƒúu‰‹MƒÁ4‰ûÿÿ‰ $èÜÿÿ…À‰ÆŽ‰4$¸‰D$èÓÜÿÿ‰…ûÿÿ‰Ç‰D$‰t$‹ûÿÿ‰$èÜÿÿ‹…ûÿÿ‰òè¨þÿÿ…À‰Ãˆ©ƒû~/‰ö¼'‰\$ß)Þ‹•ûÿÿ‰$èZáÿÿ‰ò‰øèqþÿÿ‰ÃƒûÚƒû„‹•ûÿÿ‰$èáÿÿ¸éûþÿÿèýÿÿ¿‰\$‰|$‹@‰$è«0‹M‹A‰\$ ‰\$‰D$‰D$Ç$€'Dèàÿÿ‰$‰Ãèo¡‹M‹Q‹ ‰\$‰$‰D$ÿQ‰$è¡àÿÿ‹]€»œu €»„ ‹E¾¦'D‰D$ ‹E‰t$µèüÿÿœ‰D$…èüÿÿ‰$è+¡v‹ƒÆÿþþþ÷Ð!Â €€té÷€€„“¸izatÒ•èüÿÿ‰…4ûÿÿ¸ion:ƒÞ»Prox‰…8ûÿÿ¸ Bas)Ö‰…<ûÿÿ¹y-Auºthor‰(ûÿÿ¸ic 1ÿ‰,ûÿÿ(ûÿÿ‰•0ûÿÿ‰…@ûÿÿt&¼'‹ƒÃÿþþþ÷Ð!Â €€té÷€€uÁêƒÃÒ(ûÿÿƒÛ)Ëë4…(ûÿÿ؉D$‰ð)øƒø~¸‰D$…èüÿÿø‰$ƒÇè ÙÿÿƒÃ9÷|ȸ (ûÿÿf‰„+(ûÿÿ1Àˆ„+*ûÿÿ´&‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁÒ‹U(ûÿÿƒÙ‹B)Ù‹‰L$‰\$‰$ÿR‹]¾¹¬'D‹C‹‰t$‰L$‰$ÿRÇC@Ä 1À[^_]ËU‹B ‹Rh‹‰T$‰$ÿQéŒüÿÿÁêƒÆébþÿÿ‹}ƒÇ4‰<$èáØÿÿ‰Æ…ö¸YŽá¸‰D$F‰$èžÙÿÿ‰…ûÿÿ‰D$‰t$‰<$èèØÿÿ‹…ûÿÿ‰òÆ‹…ûÿÿèqûÿÿ…À‰Ãˆýÿÿ¸ÿÿÿÿ¾¯'D‰…$ûÿÿ…$ûÿÿ‰D$… ûÿÿ‰D$ …ûÿÿ‰D$‰t$‹ûÿÿ‰ $èOŸH~ ƒ½$ûÿÿÿu]‹]¹@¿À'D‹C 1Û‹‰\$ ‰L$‰|$‰$ÿR‹…ûÿÿ‰$è§Ýÿÿéüÿÿ¿‰|$‹ûÿÿ‰ $è«Ýÿÿ‹]‰$èPîÿÿëɉ\$‰<$è’Ýÿÿ‹…$ûÿÿ‹•ûÿÿ€<2„©Æ‹$ûÿÿ9Ë~E¶Dÿ< ”Â< ”À Шt0‹ûÿÿKÆ‹$ûÿÿ9Ë~‹•ûÿÿ¶Dÿ< ”Â< ”À ШuЋ…ûÿÿÇ$æ'D1öȉD$è?Üÿÿ‹M‰Ã‹A ¹@‹‰L$‰\$‰t$ ‰$ÿR‰$èÆÜÿÿ‹ûÿÿ‰$è¸Üÿÿé ûÿÿ‹…ûÿÿ‰$è¥Üÿÿ‹UÇB@éÔúÿÿ¸‰D$¸ö'D‰D$Ç$(Dè´&U‰åWVSì<‹u‹E ‹V@ƒúÿ„…ÀtN1Ƀøt6ƒø„¡ƒøti‹F »A1ö¹\'D‹‰t$ ‰\$‰L$‰$ÿR¹Ä<‰È[^_]Ãt&‹V ‹FT‹ ‰D$ ‹FP‰D$‹FL‰$‰D$ÿQ‰ÁÄ<‰È[^_]ÃJu”^4‰$è"Öÿÿƒø¹~§‰$¸‰D$…Øýÿÿ‰D$è=Öÿÿ€½Øýÿÿ…L¶…Ùýÿÿë‰$è6ºÿÿ‹U‹‚‰T$ ‹U‰D$‹E‰T$‰4$‰D$èïÓÿÿ‰$‰Æè5 …À‰Ãt‰4$è· ‰ØƒÄ,[^_]ËE…Àˆ‰|$‹E»‰\$ ‹U‰D$ ‹E$‰T$‹U‰D$‹E ‰D$1À‰D$‹‰4$‰D$è"Ôÿÿ‰G‹‰$ÿR …ÀužÆEó¹‹G‹Eó‰L$‰D$‹G‰$ÿR‹UšT‰Ù‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁ‹GÒƒÙ)Ù‹‰L$‰\$‹G‰$ÿR‹G‹¸‰D$Eó‰D$‹G‰$ÿR‹Ušð‰Ù‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁ‹GÒƒÙ)Ù‹‰L$‰\$‹G‰$ÿR‹G‹¸‰D$Eó‰D$‹G‰$ÿR‹Uš°‰Ù‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁÒ‹GƒÙ)Ù‹‰L$‰\$‹G‰$ÿR‹G‹¸‰D$¸ä,D‰D$‹G‰$ÿR‹uÆÐ‰ó¶¡ÌSEƒ8u ¡ðSE‹·Pƒà…Àt0¡ÌSEC¶ƒ8tà‰$¸‰D$èÅxëÛvÇEéòýÿÿ‹G‹‹E‰t$)Ã0ñÿÿ‰D$»‹G‰$ÿR‹G‹Eó‰\$‰D$‹G‰$ÿR‰G1Àé–ýÿÿt&¼'U‰åSƒì‹]‹S…Òu‰]X[]éd·ÿÿt&‹‰$ÿP‰]X[]éM·ÿÿ¶¼'U‰å]Ãt&¼'U1À‰åSƒì‹]‹K…Éu ƒÄ[]ô&‹E‹‰D$‹E ‰ $‰D$ÿR‰CƒÄ[]ÃU‰å‹E]‹@Ãt&U‰å]Ãt&¼'U1À‰å]Éö¼'U‰å‹E]‹@…À•À¶Àö¼'U¸‰å]öU‰å‹E‹P1À} ‹ ‰UŸÀ‹I‰E ]ÿá¶¼'U1À‰å]Éö¼'U‰å]Ãt&¼'U‰å]Ãt&¼'U‰å‹E]‹@ƒøÀ÷Ðô&¼'U1À‰å]ÃU‰åƒì(‰uø‹u‰}ü‹} ‰]ô‰Ó‰t$ ‰|$‰T$‰$èUK…Àt‹]ô‹uø‹}ü‰ì]Ãt&‰$èØê…À‰Ãt*‰t$‰D$‰<$èbv‰$èšµÿÿÆD7ÿ‹]ô‹uø‹}ü‰ì]Ét$‹E‰<$‰D$è5vÆD7ÿëÙ´&¼'U‰åƒì‰uü‹u‰]ø‰Ó‰t$‰T$‰$èK…Àt ‹]ø‹uü‰ì]É\$‰4$èDéƒì‹]ø‹uü‰ì]ô&U‰åƒì‰uü‹u‰]ø‰Ó‰t$‰T$‰$è?M…Àt ‹]ø‹uü‰ì]É\$‰4$ètéƒì‹]ø‹uü‰ì]ô&U‰åƒì‰uü‰Æ‹E‰$‰]ø‰Ó‰D$èê‰D$‰\$‰4$èqJ‹U ‰‹]ø‹uü‰ì]ÃfU‰åW‰×VSƒì‹u‰Eð‹E ‰E츉D$‹]Û‰$蓯ÿÿ‰Eè‰ú‰\$‰4$‰D$‹Eðè;þÿÿ‹]è‹uì¶„ÀˆÁu ëGƒø\t'ˆF¶ „É•À1Ò€ù,•Â…Ðt¾ÁCƒø=uÛ¸ ëÙ¾CëÓÆ1À€ù,”ÀÃF¶ „ÉuÄÆ‹Uè‰UƒÄ[^_]éγÿÿ´&¼'U‰åWVSƒì‹]‰U캉Eð‰T$‹E À‰$èØ®ÿÿ‰Ç‰Æ¶„ÀuëWƒù\t%ƒù t)ˆF¶„Àt7¾ÈCƒù=”Àƒù,” ШtÖÆ\Fƒù u×¹=ˆF¶„ÀuÒ‰ö¼'Æ,CF¶„Àu½Æ‰|$‹Eì‰D$‹Eð‰$è G‰}ƒÄ[^_]é ³ÿÿ¶¿U‰åM˜WVSƒì|‰M”»P‰L$‹MÇEŒ‹}‰\$‰ $èÏüÿÿÇE´&‹]”¾à/D‰t$‰$è,tÇE”…À‰Æt/1Û9û}$‰ö¼'‰t$‹U ‹Ú‰$èt…ÀtLC9û|å9}|°1Ò9ú}4v¼'‹E ‹LЃùY¸Óà…EŒu ‹]‹E‰ ˜C‰]B9ú|ÖƒÄ|[^_]ËE ‹L؃ùÿt­¸Óà…EŒu¡ EŒ‹U‹]‰ “B‰U9}Œ=ÿÿÿë‹Ç$â/D»È¹ô/D‰\$‰L$èõr¶¼'U¹O‰åWV1öSƒì|‹] ‰E”¶0D‰U1Ò‰L$ˆE˜E™‰T$‰$èPrÇEŒO9ÞÆEç};‰ö¼'‹E‹°1À9Ø}t&‹M9TÁt:@9Ø|ò‹}ŒF…ÿŸÀ1Ò9ޜ…Ðu΋MU˜‹E”‰T$‰L$‰$è%EƒÄ|[^_]ËU‹<Â…ÿtÁ‰<$èËq‰Eˆ…ö~‹MŒ¸à/D‰D$E˜‰L$‰$èqrÿMŒ‰|$‹UŒM˜‰ $F‰T$èWr‹Eˆ)EŒ‹}Œ…ÿŸÀ1Ò9ޜ…ЅBÿÿÿéoÿÿÿ¶¼'U¹R0D‰åWVS쌻‰L$‹E|$‰\$‰$èÓD‹U ‹M‰T$ºZ0D‰T$‰ $èXD‹M 1ÒÁì¶¼'¶ˆBúrð¸c0D‰D$‹E‰$è¼H‹U ‹M‹‚ð‰ $‰D$¸o0D‰D$è[D‹U ‹M‹‚ô‰ $‰D$¸w0D‰D$è:D‹U ‹M‹‚ø‰ $‰D$¸„0D‰D$èD‹U ‹M‹‚ü‰ $‰D$¸0D‰D$èøC‹U ‹M‹‚‰ $‰D$¸¡0D‰D$è×C‹5D¹°0D…öt$‹E ‹1À9D„%ƒÀ ‹˜D…Ûuç‰L$‹U¹´0D‰L$¾VUUU»‰ˆˆˆ‰$è"C‹M º½0D‹‰T$‰D$‹E‰$èaC‹U ‹Š ƒÁ‰È÷î‰ÈÁø)ÂR¸È0D‰D$)Ñ‹U‰L$‰$è-C‹M 1Àƒ¹•À‰D$¸Ô0D‰D$‹E‰$èC‹U ‹Š‰È÷ë‰ÈÁøÊÁú)‰T$‹U¸à0D‰D$‰$èÕB‹M ‹‰‰È÷ë»í0D‰„þÿÿ‹…„þÿÿ‰ÑÁ‹…„þÿÿÁùÁø)Á‰ÈÁà)ÈÁà)…„þÿÿ¸û0D‰D$‹„þÿÿ‹E‰L$‰$èwB‹U ‹M‹‚‰ $‰D$¸ 1D‰D$èVB‹U ‹M‹‚‰\$‰ $‰D$è:B‹E ¹1D‰L$°‰D$‹E‰$èºA‹E º$1D‰T$‹UЉD$‰$èšA¸º21D‰D$‹E ð‰$‹EèÉùÿÿ‹M ‹‰D$¸@1D‰D$‹E‰$è¸A‹E ‹U ‰D$¸N1D‰D$‰$è8A‹M ‹™ ƒÃ‰Ø÷î‰Ø¾_1D‰Ñ™)ÑI¸i1D)Ó‰\$‹U»r1D‰D$‰$èZA‹M ‹$‰D$¸|1D‰D$‹E‰$è9A‹U ‹M‹‚(‰ $‰D$¸‹1D‰D$èA‰t$‹E ¾—1D,‰D$‹E‰$è˜@‹U ‹M‹‚,‰\$» 1D‰D$‰ $è×@‹E ¹©1D‰L$0‰D$‹E‰$èW@‹E º·1D‰T$‹U°‰D$‰$è7@‹E ‹M0‰D$¸Å1D‰ $‰D$è@¸ºØ1D‰D$‹E ð‰$‹EèFøÿÿ‹E ð‰D$¸ä1D‰D$‹E‰$èÖ?‹E ‹UT‰D$¸í1D‰$‰D$è¶?‹M ‹8 ‰D$¸û1D‰D$‹E‰$èõ?‹U ‹M‹‚< ‰ $‰D$¸2D‰D$èÔ?‹U ‹M‹‚d ‰t$¾ 2D‰D$‰ $è³?‹U ‹M‹‚h ‰\$»2D‰D$‰ $è’?‹U ¹ 2D‹‚l ‰L$‹M‰D$‰ $èq?Ç$°/D‹E º‰T$º/2Dp ‰D$‹Eè(ùÿÿÇ$p/D‹E º62D@ ‰D$¸‰D$‹Eèÿøÿÿ‹U ‹M‹‚P ‰ $‰D$¸:2D‰D$èþ>‹E T ‰D$¸D2D‰D$‹E‰$è~>‹U ‹M‹‚” ‰ $‰D$¸O2D‰D$è½>‹U ‹M‹‚˜ ‰ $‰D$¸Y2D‰D$èœ>‹U ‹M‹‚œ ‰ $‰D$¸a2D‰D$è{>‹U ‹M‹‚¨ ‰ $‰t$‰D$è_>‹U ‹M‹‚Œ ‰ $‰\$‰D$èC>‹U ¹h2D‹‚ ‰L$‹M‰D$‰ $è">‹M 1ÒÁˆ ´&¶ˆBúrð‹Eºp2D¾~2D‰T$»2D‰$è"B‹E ‹U0 ‰D$¸¥2D‰$‰D$èb=‹M ‹¸‰D$¸³2D‰D$‹E‰$è¡=‹U ‹M‹‚¼‰ $‰D$¸¾2D‰D$è€=‹U ‹M‹‚Ô‰ $‰D$¸Ì2D‰D$è_=‹U ‹M‹‚؉ $‰D$¸Þ2D‰D$è>=‹U ‹M‹‚܉ $‰D$¸ê2D‰D$è=‹U ‹M‹‚ä‰t$¾ü2D‰D$‰ $èü<‹U ‹M‹‚à‰\$»3D‰D$‰ $èÛ<‹U ¹3D‹‚è‰L$‹M‰D$‰ $èº<‹U ‹M‹‚ì‰ $º-3D‰T$‰D$è™<‹U ‹M‹‚ð‰ $‰D$¸<3D‰D$èx<‹U ‹M‹‚ô‰ $‰D$¸H3D‰D$èW<‹U ‹M‹‚‰ $‰D$¸Y3D‰D$è6<‹U ‹M‹‚ø‰ $‰D$¸l3D‰D$è<‹U ‹M‹‚ü‰ $‰D$¸y3D‰D$èô;‹U ‹M‹‚‰ $‰D$¸‰3D‰D$èÓ;‹U ‹M‹‚‰t$¾Ÿ3D‰D$‰ $è²;‹U ‹M‹‚ ‰\$»©3D‰D$‰ $è‘;‹U ¹´3D‹‚‰L$‹M‰D$‰ $èp;‹U ‹M‹‚‰ $ºº3D‰T$‰D$èO;‹U ‹M‹‚ ‰ $‰D$¸Ã3D‰D$è.;‹U ‹M‹‚@‰ $‰D$¸Ë3D‰D$è ;‹U ‹M‹‚D‰ $‰D$¸Ö3D‰D$èì:‹U ‹M‹‚‰ $‰D$¸â3D‰D$èË:‹U ‹M‹‚‰ $‰D$¸ì3D‰D$èª:‹U ‹M‹‚$‰ $‰D$¸ö3D‰D$è‰:‹U ‹M‹‚(‰ $‰t$¾4D‰D$èh:‰\$‹E ‰D$‹E‰$èí9‹U ¹4D‹‚,‰L$‹M‰D$‰ $è,:‹U ‹M‹‚0‰ $º4D‰T$‰D$è :‹U ‹M‹‚‰ $‰D$¸)4D‰D$èê9‹U ‹M‹‚‰ $‰D$¸64D‰D$èÉ9‹U ‹M‹‚ ‰ $‰D$¸A4D‰D$è¨9‹U ‹M‹‚X‰ $‰D$¸N4D‰D$è‡9‹U ‹M‹‚\‰ $‰D$¸V4D‰D$èf9‹U ‹M‹‚`‰ $‰D$¸_4D‰D$èE9‹U ‹M‹‚d‰ $‰t$‰D$è)9‹M 1ÒÁx´&¼'¶ˆBúrð‹E»d4D¾q4D‰\$»†4D‰$è"=‹U ¹’4D‹‚h‰L$‹M‰D$‰ $èÁ8‹U ‹M‹‚l‰ $ºŸ4D‰T$‰D$è 8‹U ‹M‹‚p‰ $‰D$¸­4D‰D$è8‹U ‹M‹‚t‰ $‰D$¸»4D‰D$è^8‹U ‹M‹‚H‰ $‰D$¸É4D‰D$è=8‹U ‹M‹‚L‰ $‰D$¸Ù4D‰D$è8‹U ‹M‹‚P‰ $‰D$¸ç4D‰D$èû7‹U ‹M‹‚T‰ $‰D$¸ô4D‰D$èÚ7‹U ‹M‹‚‰ $‰t$‰D$è¾7‹U ‹M‹‚”‰ $‰\$‰D$è¢7‹U ¹5D‹‚‰L$‹M‰D$‰ $è7‹E º5D‰T$H‰D$‹E‰$è7‹U ‹M‹‚”‰ $‰D$¸5D‰D$è@7‹U ‹M‹‚˜‰ $‰D$¸!5D‰D$è7‹M 1ÒÁœ¶ˆBƒúLró¸,5D¾15D»<5D‰D$‹E‰$è:‹U ‹M‹‚è‰ $‰D$¸G5D‰D$èÈ6‹U ‹M‹‚ ‰ $‰D$¸S5D‰D$è§6‹U ‹M‹‚ ‰ $‰D$¸^5D‰D$è†6‹U ‹M‹‚¤‰t$1ö‰D$‰ $èh6‹U ‹M‹‚˜‰\$‰ $‰D$èL6‹U ¹o5D‹‚œ‰L$‹M‰D$‰ $è+6‹U ‹M‹‚¨‰ $º~5D‰T$‰D$è 6‹] ‰t$¸‹5DF‰D$Eȉ$èvb¶ƒ®U¨‰D$¶ƒ­‰D$ ¶ƒ¬ƒÃ‰$‰D$¸”5D‰D$è>b‹UM¨EȉL$‰D$‰$è=5ƒþ~‘‹M ¾5D‹ø‰D$¸«5D‰D$‹E‰$èr5‹U ‹M‹‚ü‰ $‰D$¸²5D‰D$èQ5‹U ‹M‹‚ð‰ $‰D$¸»5D‰D$è05‹U ‹M‹‚ô‰ $‰D$¸È5D‰D$è5‹U ‹M‹‚‰t$1ö‰D$‰ $èñ4‰t$»Ó5DEˆ‰\$‰óv ‰$è\aÆ…ˆþÿÿ¶¼'ˆþÿÿv¼'‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁ҉ʋM ƒÚ€½ˆþÿÿ¿„Y‰D$ ¸à/Du¸Þ5D‰D$¹ß5DC‰L$‰$èÔ`9Þˆ‹M…ˆþÿÿUˆ‰D$‰T$‰ $èÌ3þÿŽ/ÿÿÿ‹E ºä5D¾ñ5D‰T$»ý5D ‰D$‹E‰$è–3‹U ‹M‹‚ˆ ‰ $‰D$¸ 6D‰D$èÕ3‹U ‹M‹‚Œ ‰ $‰D$¸6D‰D$è´3‹E ‰D$¸$6D‰D$‹E‰$è43‹U ‹M‹‚ ‰ $‰D$¸,6D‰D$ès3‹U ‹M‹‚|‰ $‰D$¸86D‰D$èR3‹U ‹M‹‚€‰ $‰D$¸B6D‰D$è13‹U ‹M‹‚4‰t$¾V6D‰D$‰ $è3‹U ‹M‹‚8‰\$»‰D$‰ $èï2‹U ¹j6D‹‚<‰L$‹M‰D$‰ $èÎ2‹U ‹M‹‚„‰ $º|6D‰T$‰D$è­2‹U ‹M‹‚ˆ‰ $‰D$¸…6D‰D$èŒ2‹U ‹M‹‚Œ‰ $‰D$¸‰6D‰D$èk2‹U ‹M‹‚” ‰ $‰D$¸“6D‰D$èJ2‹E ˜ ‰D$¸ž6D‰D$‹E‰$èÊ1‹U ‹M‹‚!‰ $‰D$¸©6D‰D$è 2‹U ‹M‹‚!‰ $‰D$¸µ6D‰D$èè1‹U ‹M‹‚ !‰ $‰t$¾È6D‰D$èÇ1‰\$‹E ºÓ6D»$!‰$‹Eè–éÿÿ‹U ‰Ø‹Š$%‰t$¾ã6D)ȉD$‹M‰ $è1‹U ‰Ø‹Š(%‰t$¾ï6D)ȉD$‹M‰ $è\1‹U ‰Ø‹Š,%‰t$¾÷6D)ȉD$‹M‰ $è71‹U ‰Ø‹Š0%‰t$¾7D)ȉD$‹M‰ $è1‹U ‰Ø‹Š4%‰t$)È‹M‰D$‰ $èò0‹U ‰Ø‹Š8%)È‹M‰D$¸7D‰D$‰ $èÍ0‹U ¹7D‰Ø‹²<%‰L$‹M)ð‰D$¾&7D‰ $è£0‹E ‹@%¸17D‰D$)Ó‹U‰\$»;7D‰$è{0‹M ‹D%‰D$¸K7D‰D$‹E‰$èZ0‹U ‹M‹‚H%‰ $‰t$‰D$è>0‹U ‹M‹‚L%‰ $‰\$‰D$è"0‹M 1ÒÁT%¶ˆBƒúLró‹E¹U7D‰L$‰$è&3‹M 1ÒÁ %¶ˆBƒúLróº^7D‰T$‹U‰$èú2‹M 1ÒÁì%¶ˆBƒúLró‹M¸g7D¿t7D‰D$¾‡7D»”7D‰ $è¿2‹U ‹M‹‚P%‰ $‰D$¸¦7D‰D$èn/‹U ‹M‹‚8&‰ $‰D$¸±7D‰D$èM/‹E À‰D$¸Â7D‰D$‹E‰$èÍ.‹U ‹M‹‚À‰ $‰D$¸Í7D‰D$è /‹U ‹M‹‚ĉ $‰D$¸Ù7D‰D$èë.‹U ‹M‹‚ȉ|$‰ $‰D$èÏ.‹U ‹M‹‚̉t$‰ $‰D$è³.‹U ‹M‹‚Љ\$‰ $‰D$è—.ÄŒ[^_]ˈDéÝêÿÿU‰åEøSƒì‰D$‹E‰$è÷,…À‰Ãu ‹EøƒÄ[]ËE ‰$‰D$èIéÿÿ‰$è.ƒÄ1À[]Éö¼'U1ɉåWº}ØV1öSìÌ1Û‹E Æ€¬ ‰ˆ4 ‰°  1ö‰˜0 ‰D$‹E‰T$ºZ0DÇ$Þ5DèŒãÿÿ‹E ºc0Dì‰$‹EèdäÿÿÇ$‹E ºo0Dð‰D$‹Eè”äÿÿÇ$ÿÿÿÿ‹E ºw0Dô‰D$‹EètäÿÿÇ$‹E º„0Dø‰D$‹EèTäÿÿÇ$‹E º0Dü‰D$‹Eè4äÿÿÇ$‹E º¡0D‰D$‹Eèäÿÿ‰|$¸ º´0D‰D$‹EÇ$:Dè³âÿÿ¡0HE‹U ‰‚¡€GE‰‚1À‰…tþÿÿ¡D…Àt41Û‰<$‹ƒD‰D$èýY…À„AFƒÃ ‰Æ‰…tþÿÿ‹ƒD…ÀuÎÇ$‹E º@1D¿ ¾ ‰D$‹EèkãÿÿÇ$‹Etþÿÿ‰L$ºÈ0DèMãÿÿ‹tþÿÿºVUUUA‰È÷ê‰ÈÁø)ÂR)Ñ‹U ‰Ð‰Š ºÔ0D‰D$‹EÇ$è ãÿÿÇ$…pþÿÿºà0D‰D$‹EèëâÿÿÇ$…lþÿÿºû0D‰D$‹EèÍâÿÿ‹•pþÿÿ‹M ‰ÐÁà)Ћ•lþÿÿ‚º 1D‰‰È‰D$‹EÇ$èâÿÿÇ$‹E ºí0D‰D$‹Eèoâÿÿ‰|$‹E º1DÇ$˜:D1ÿ°‰D$‹Eè áÿÿ‰t$‹E º$1DÇ$ž:DЉD$‹EèåàÿÿÇ$Þ5Dè9”ÿÿ‰Æ¡P.Dë(‰t$G‰D$Ç$ª:Dè –ÿÿ‰4$‰Ã‰Þ诖ÿÿ‹½P.D…ÀuÔ‰4$‹E º21D»‰\$ð‰D$‹Eèÿáÿÿ‰4$èw–ÿÿÇ$Þ5D‹E ¹‰L$ºN1D ‰D$‹EèNàÿÿÇ$…tþÿÿºi1D‰D$‹Eèpáÿÿ‹tþÿÿºVUUUA‰È÷ê‰ÈÁø)ÂR)Ñ‹U ‰Ð$‰Š º|1D‰D$‹EÇ$è,áÿÿÇ$ÿÿÿÿ‹E º‹1D(‰D$‹Eè áÿÿ‹M ƒ¹(ÿ„ Ç$²:D‹E ¹‰L$º_1D¿°/D,‰D$‹EèŽßÿÿÇ$P‹E ºr1D,‰D$‹Eè®àÿÿÇ$Þ5D‹E º€‰T$º©1D0‰D$‹EèEßÿÿÇ$Þ5D¸€º·1D‰D$‹E °‰D$‹EèßÿÿÇ$¸:D¸ºÅ1D‰D$‹E 0‰D$‹EèóÞÿÿÇ$Þ5D¸ºØ1D‰D$‹E ð‰D$‹EèJàÿÿÇ$Þ5D¸dºä1D‰D$‹E ð‰D$‹Eè¡ÞÿÿÇ$Þ5D¸dºí1D‰D$‹E T‰D$‹EèxÞÿÿÇ$‹E ºû1D8 ‰D$‹Eè˜ßÿÿÇ$‹E º2D< ‰D$‹EèxßÿÿÇ$‹E º—1Dd ‰D$‹EèXßÿÿÇ$‹E º 1Dh ‰D$‹Eè8ßÿÿÇ$‹E º 2Dl ‰D$‹Eèßÿÿ‰|$‹E º/2DÇ$Î:Dp ‰D$ ¸‰D$‹Eè«àÿÿÇ$…tþÿÿºÐ:D‰D$‹EèÍÞÿÿ‹µtþÿÿ¸ºÜ:D)ð…À‰…tþÿÿtº ;D‰$‹E ¹p/D‰L$»º62D‰\$u¸@ ‰D$ ‹E]˜½Xþÿÿè2àÿÿÇ$<‹E º:2DP ‰D$‹EèRÞÿÿÇ$<;D¸ºD2D‰D$‹E T ‰D$‹EèéÜÿÿÇ$‹E º2DŒ ‰D$‹Eè ÞÿÿÇ$‹E ºh2D ‰D$‹EèéÝÿÿÇ$‹E ºO2D” ‰D$‹EèÉÝÿÿÇ$‹E ºY2D˜ ‰D$‹Eè©ÝÿÿÇ$‹E ºa2Dœ ‰D$‹Eè‰ÝÿÿÇ$‹E º 2D¨ ‰D$‹EèiÝÿÿ‹E ºp2Dˆ ‰$‹EèÝÿÿÇ$Þ5D¸º¥2D‰D$‹E 0 ‰D$‹EèèÛÿÿÇ$‹E º³2D¸‰D$‹EèÝÿÿÇ$‹E º¾2D¼‰D$‹EèèÜÿÿÇ$‹E ºÌ2DÔ‰D$‹EèÈÜÿÿÇ$‹E ºÞ2D؉D$‹Eè¨ÜÿÿÇ$‹E ºê2D܉D$‹EèˆÜÿÿÇ$‹E º~2Dä‰D$‹EèhÜÿÿÇ$‹E º2Dà‰D$‹EèHÜÿÿÇ$‹E º3Dè‰D$‹Eè(ÜÿÿÇ$‹E º-3Dì‰D$‹EèÜÿÿÇ$‹E º<3Dð‰D$‹EèèÛÿÿÇ$‹E ºH3Dô‰D$‹EèÈÛÿÿÇ$…dþÿÿº?;D‰D$‹EèªÛÿÿ‹E ºY3Dƒ½dþÿÿ‰D$À÷ЃÀ‰$‹Eè€ÛÿÿÇ$‹E ºl3Dø‰D$‹Eè`ÛÿÿÇ$‹E ºy3Dü‰D$‹Eè@ÛÿÿÇ$‹E º‰3D‰D$‹Eè ÛÿÿÇ$‹E ºü2D‰D$‹EèÛÿÿÇ$‹E º3D ‰D$‹EèàÚÿÿÇ$‹E º´3D‰D$‹EèÀÚÿÿÇ$‹E ºº3D‰D$‹Eè ÚÿÿÇ$‹E ºÃ3D ‰D$‹Eè€ÚÿÿÇ$‹E ºË3D@‰D$‹Eè`ÚÿÿÇ$‹E ºÖ3DD‰D$‹Eè@ÚÿÿÇ$‹E ºâ3D‰D$‹Eè ÚÿÿÇ$‹E ºì3D‰D$‹EèÚÿÿÇ$‹E ºö3D$‰D$‹EèàÙÿÿÇ$‹E ºŸ3D(‰D$‹EèÀÙÿÿÇ$N;D¸º©3D‰D$‹E ‰D$‹EèWØÿÿÇ$‹E º4D,‰D$‹EèwÙÿÿÇ$‹E º4D0‰D$‹EèWÙÿÿÇ$‹E º)4D‰D$‹Eè7ÙÿÿÇ$‹E º64D‰D$‹EèÙÿÿÇ$‹E ºA4D ‰D$‹Eè÷ØÿÿÇ$‹E ºN4DX‰D$‹EèרÿÿÇ$‹E ºV4D\‰D$‹Eè·ØÿÿÇ$‹E º_4D`‰D$‹Eè—ØÿÿÇ$‹E º4Dd‰D$‹EèwØÿÿ‹E ºd4Dx‰$‹EèØÿÿÇ$‹E º’4Dh‰D$‹Eè?ØÿÿÇ$‹E ºŸ4Dl‰D$‹EèØÿÿÇ$ЋE•tþÿÿ‰T$º­4DèØÿÿ‹M º»4D‹…tþÿÿ‰p…tþÿÿ‰D$‹EÇ$ˆèÔ×ÿÿ‹U ‹…tþÿÿ‰‚t‰ÐH‰D$‹EºÉ4DÇ$Èè¦×ÿÿÇ$‹E ºÙ4DL‰D$‹Eè†×ÿÿÇ$‹E ºç4DP‰D$‹Eèf×ÿÿÇ$‹E ºô4DT‰D$‹EèF×ÿÿÇ$‹E ºq4D‰D$‹Eè&×ÿÿÇ$‹E º†4D”‰D$‹Eè×ÿÿÇ$‹E º5D‰D$‹EèæÖÿÿÇ$Þ5D¸º5D‰D$‹E H‰D$‹Eè}ÕÿÿÇ$P‹E º5D”‰D$‹EèÖÿÿÇ$‹E º!5D˜‰D$‹Eè}Öÿÿ‹E º,5Dœ‰$‹EèÅÕÿÿÇ$‹E ºG5Dè‰D$‹EèEÖÿÿÇ$‹E ºS5D ‰D$‹Eè%ÖÿÿÇ$‹E º^5D ‰D$‹EèÖÿÿÇ$‹E º15D¤‰D$‹EèåÕÿÿÇ$‹E º<5D˜‰D$‹EèÅÕÿÿÇ$‹E ºo5Dœ‰D$‹Eè¥ÕÿÿÇ$‹E º~5D¨‰D$‹Eè…Õÿÿ1À‰…tþÿÿ1Àë‹…tþÿÿ@ƒø‰…tþÿÿʼnD$¸‹5D‰D$‰4$èæJ‰\$‹…tþÿÿ¹‰L$‰ò‹…8D‰$‹EèçÓÿÿ‰|$`þÿÿº”5D‰L$…\þÿÿ‰D$ ‰T$‰$è&Kƒøu€‹…tþÿÿ‹•Xþÿÿ‹M @ˆ”¬‹…tþÿÿ‹•\þÿÿ@ˆ”­‹…tþÿÿ‹•`þÿÿ@ˆ”®‹…tþÿÿ@‰…tþÿÿƒøŽ;ÿÿÿÇ$‹E º«5Dø‰D$‹Eè~ÔÿÿÇ$‹E º²5Dü‰D$‹Eè^ÔÿÿÇ$‹E º»5Dð‰D$‹Eè>ÔÿÿÇ$‹E ºÈ5Dô‰D$‹EèÔÿÿÇ$‹E º5D‰D$‹EèþÓÿÿ1À‰…tþÿÿ1À‰D$¸Ó5D‰D$…xÿÿÿ‰$èqI¸•xþÿÿ‰D$‹…tþÿÿ‰T$…Àˆ‰Áø‹…p:D•xÿÿÿxþÿÿ‰$‹EèWÒÿÿ‹•tþÿÿ‰Öë ¶ ‰ßëC¶ „É•À1Ò€ù,•Â…Ðuë€ù,„#‰<$è³H‹M ‹•tþÿÿf‰„qFB 9𺉅tþÿÿ=ÿŽ5ÿÿÿÇ$Þ5D¸€ºä5D‰D$‰È¿ »‰D$‹Eè·ÑÿÿÇ$‹E º 6Dˆ ‰D$‹Eè×ÒÿÿÇ$‹E º6DŒ ‰D$‹Eè·ÒÿÿÇ$Þ5D¸€º$6D‰D$‹E ‰D$‹EèNÑÿÿÇ$‹E º,6D ‰D$‹EènÒÿÿÇ$‹E º86D|‰D$‹EèNÒÿÿÇ$‹E ºB6D€‰D$‹Eè.ÒÿÿÇ$‹E ºñ5D4‰D$‹EèÒÿÿÇ$‹E ºý5D8‰D$‹EèîÑÿÿÇ$‹E ºj6D<‰D$‹EèÎÑÿÿÇ$‹E º|6D„‰D$‹Eè®ÑÿÿÇ$‹E º…6Dˆ‰D$‹EèŽÑÿÿÇ$‹E º‰6DŒ‰D$‹EènÑÿÿÇ$‹E º“6D” ‰D$‹EèNÑÿÿÇ$Þ5D¸€ºž6D‰D$‹E ˜ ‰D$‹EèåÏÿÿÇ$‹E º©6D!‰D$‹EèÑÿÿÇ$‹E ºµ6D!‰D$‹EèåÐÿÿÇ$‹E ºV6D !‰D$‹EèÅÐÿÿ‰|$‹E ºÓ6DÇ$Þ5D½Tþÿÿ$!‰D$‹EèÛÐÿÿÇ$…tþÿÿºÈ6D‰D$‹Eè}Ðÿÿ‹µtþÿÿ‰Ø‹U )ðµtþÿÿ‰‚$%‹Eºã6D‰t$Ç$èLÐÿÿ‹tþÿÿ‰Øºï6D)È‹M ‰(%‹E‰t$Ç$è!Ðÿÿ‹•tþÿÿ‰Ø)ЋU ‰‚,%‹Eº÷6D‰|$Ç$èöÏÿÿ‹…Tþÿÿ‹M )É™0%ƒû„µ‰t$‹Eº7DÇ$»è¿Ïÿÿ‹µtþÿÿ‰Ø‹U )ðµtþÿÿ‰‚4%‹Eº7D‰t$Ç$èŽÏÿÿ‹tþÿÿ‰Øº7D)È‹M ‰8%‹E‰t$Ç$ècÏÿÿ‹•tþÿÿ‰Ø)ЋU ‰‚<%‹Eº17D‰t$¾Ç$è3Ïÿÿ‹M ºK7D‹½tþÿÿ‰È)ûD%‰™@%‰D$‹EÇ$èÏÿÿÇ$‹E º&7DH%‰D$‹EèãÎÿÿÇ$‹E º;7DL%‰D$‹EèÃÎÿÿÇ$‹E º¦7DP%‰D$‹Eè£Îÿÿ‹E ºU7DT%‰$‹EèëÍÿÿ‹E º^7D %‰$‹EèÓÍÿÿ‹E ºg7Dì%‰$‹Eè»ÍÿÿÇ$‹E º±7D8&‰D$‹Eè;Îÿÿ‰t$‹E ºÂ7DÇ$Þ5DÀ‰D$‹Eè×ÌÿÿÇ$€%‹E ºÍ7DÀ‰D$‹Eè÷ÍÿÿÇ$‹E ºÙ7DĉD$‹Eè×ÍÿÿÇ$‹E ºt7DȉD$‹Eè·ÍÿÿÇ$‹E º‡7D̉D$‹Eè—ÍÿÿÇ$‹E º”7DЉD$‹EèwÍÿÿÄÌ[^_]ËU ‹ƒD‰‚‰Ð‰D$¡€GEº½0D‰$‹Eè=Íÿÿé£éÿÿÆCéÔùÿÿƒÀéoùÿÿ‰|$‹EºT;DÇ$èÍÿÿƒ½Tþÿÿ…&ýÿÿ‹E 1ÿ‰¸0%éýÿÿÇ$‹Ehþÿÿ‰\$º];DèÔÌÿÿ‹…hþÿÿ…Àu‹E 1Ò‰(é¾ëÿÿƒøt=ƒøt^ƒøtF‰\$‹Eºg;DÇ$è“Ìÿÿ1Àƒ½hþÿÿ‹M ”À@‰(é|ëÿÿ‹M ¿‰¹(éiëÿÿ‹U »‰š(éVëÿÿ‹E ¾‰°(éCëÿÿë U‰åƒì‰]ø‹E‹] ‰uü‰$膉$‰Æ‰\$èèæÿÿ‰u‹]ø‹uü‰ì]éw´&U‰å]ëºv¼'U¹‰åüƒì‹E‰uø‰}ü¿y;D‰]ô‹‰Eð‹uð‹E 󦋗’À8¹ÿÿÿÿt7¹‰Þ¿y;Dó¦—Â’À8¹t‰] ‹Eð‹]ô‹uø‹}ü‰E‰ì]é¶A‹]ô‰È‹uø‹}ü‰ì]Ãë U‰åWVSìL‹u …ö„r‹E1Û‰ä÷ÿÿ1ÛÇ@èP‰…Ü÷ÿÿ…À„¼µè÷ÿÿ¶¿‰t$¹‰L$‹•Ü÷ÿÿ‰$èu…À‰Çt{‰ñ¶¼'‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁÒƒÙ)ñD;…ä÷ÿÿ‰t$‹M‹A؉$èˆ@‹U‹B؉$èà?…ÿ\…dÿÿÿ‹Ü÷ÿÿ‰ $èæC¾‰t$‰D$‹U‹B‰$è}ÿÿ‹M‰AÆ‹Alj…Ä÷ÿÿ¶„ÛtTü´&‹µÄ÷ÿÿ¸¿y;D‰Áó¦t‹E‹•Ä÷ÿÿÿ¶„Ûëÿ…Ä÷ÿÿ‹Ä÷ÿÿ€9uïÿ…Ä÷ÿÿ‹…Ä÷ÿÿ¶„Ûu´¹‰L$‹U‹@‰$è­yÿÿÇy;D‹Mº‰…Ø÷ÿÿ‰•à÷ÿÿ‰A‹A‰…Ä÷ÿÿ¶„Û„ü‹•Ø÷ÿÿ‰•Ô÷ÿÿë ‹µÄ÷ÿÿ¸¿y;D‰Áó¦t‹…à÷ÿÿ‹Ä÷ÿÿ‹•Ø÷ÿÿ‰ ‚@‰…à÷ÿÿ¶„Ûë´&ÿ…Ä÷ÿÿ‹…Ä÷ÿÿ€8uïÿ…Ä÷ÿÿ‹•Ä÷ÿÿ¶„Ûuœ¸ðÇ@¿‰|$‰D$ ‹…à÷ÿÿ‰D$‹•Ô÷ÿÿ‰$è?ÄL[^_]ËM‹A‰$èy}ÿÿ‹U‹B‰$èk}ÿÿ‹MÇAÇAÄL[^_]ú‰…ä÷ÿÿ‰T$‰D$‹M‹A‰$è9{ÿÿ‹U‰BéÊýÿÿ‹M‹I‰Ô÷ÿÿéQÿÿÿU‰åSƒì‰Ã€;¸ÿu ƒÄ[]ô&ÇEøEø‰D$‰$èºuÿÿ‹Uø¾À…ÒuÓ¾ƒÄ[]ô&Uº0AD‰åSƒì‰Ã‰T$‰$èî<…Àu¸ƒÄ[]ô&‰$¸4AD‰D$èÇ<…ÀtÙ‰$¸7AD‰D$è²<…Àtĉ$¸AD‰D$èˆ<…Àu1À뛉$¸AAD‰D$èo<…Àtç‰$¸EAD‰D$èZ<…ÀtÒ‰$¹KAD‰L$èE<…Àt½‰$è<…À•À¶ÀéGÿÿÿt&Uƒø‰åºMAD„ƒøºaAD„ƒøºvAD„óƒøºŒAD„åƒøº›AD„׃øº®AD„ɃøºËAD„»ƒø ºçAD„­ƒø ºÿAD„Ÿƒø ºBD„‘ƒø º+BD„ƒƒø º@BD„uƒøºSBD„gƒøºeBD„YƒøºwBD„KƒøºŒBD„=ƒøº¢BD„/ƒøº¸BD„!ƒøºÆBD„ƒøºÜBD„ƒøºÿBD„÷ƒøºCD„éƒøº3CD„ÛƒøºLCD„̓øºpCD„¿ƒøº„CD„±ƒøº£CD„£ƒøº¸CD„•ƒøºÛCD„‡ƒø ºðCD„yƒø!ºDDtoƒø"ºDDteƒø#º=DDt[ƒø$ºWDDtQƒø%ºfDDtGƒø'º„DDt=ƒø(º—DDt3ƒø)º´DDt)ƒøFºÐDDtƒøGºèDDtƒøHºEDt º%ED¶]‰Ðö¿Uƒú‰Á‰å¸-ED„ƒú¸AED„ƒú¸QED„qƒú¸hED„cƒú¸wED„Uƒú¸ED„Gƒú¸¨ED„9ƒú¸¹ED„+ƒú„$ƒú„6ƒú„ƒú„.ƒú ¸ÊED„ ƒú!¸ãED„üƒú2¸ýED„݃ú3¸FD„σú4¸1FD„Áƒú5¸KFD„³ƒú<„؃ú=„íƒúP¸dFD„“ƒúQ¸|FD„…ƒúR¸•FDt{ƒúZ¸®FDtqƒú[¸ÄFDtgƒú\¸çFDt]ƒú]¸GDtSƒú^¸'GDtIƒú_¸@GDt?ƒú`¸_GDt5ƒúa¸tGDt+ƒúb¸‹GDt!ƒúc¸¤GDtƒúd¸½GDt ¸%ED´&]ÃöÁ¸ÖGDuô¸êGDöÁuê¸%EDëãöÁ¸HDuÙ¸HDëãöÁ¸5HDuÈöÁ ¸PHDu¾¸tHDöÁ@ëȸ”HDöÁ@ë¾v¼'U1À‰å]Éö¼'U‰å]Ãt&¼'U1À‰å]Éö¼'U1À‰å]Éö¼'U‰åESƒì‰D$‹E ‰$èvÿÿ‰D$‰Ã‹E‹€Ô‰$è0¨‰$è(wÿÿƒÄ[]ÃfU‹ˆä‰å…Ét‹E‰B$]Ãt&¼'U‹€è‰å…Àt‹E‰B$]Ãt&¼'U‰å]ÇB$Ãt&U‰åW‰×VSƒì‰Eð€:„£‰ö¼'‰<$¸ ‰D$èG7‰Æ‰ó¸‰D$)ûC‰$èÅqÿÿ‰Eì‰\$‰|$‰$è27‹EìÆ€~AtWF‰$èºsÿÿ…À‰Ãt‰D$‹U ‹Eì‰$‰D$ÿU‹Eì‰$è5vÿÿ‰$è-vÿÿ‰<$èÕ6øx€x…fÿÿÿƒÄ[^_]ÉD$‹Uð‹‚Ô‰$èæë´&U¹ÿÿÿÿ‰å‹E ‹P‹E9Pr—À¶È]‰ÈÃU¹ÿÿÿÿ‰å‹E ‹P‹E9r—À¶È]‰ÈÃU‰åƒì‰]ø‹] ‰uü‹uC‰D$V‰$è7…Àt™ƒÊ‹]ø‰Ð‹uü‰ì]ËCº9FwçÒ‹]ø‹uü‰ì‰Ð]ö¼'U¹‰å‹E ‹‹E9wÉ]‰ÈöU1ɉåS‰Ãƒì Ót …À¹ÿÿÿÿt…Ò¹t‰T$‰$è‹6‰ÁƒÄ‰È[]Éö¼'Uº‰åƒì‰}ü‹}‰uø‹u ‰]ô‹_;^^|‹F$º9G$O|p‹V‹Gè‚ÿÿÿ…ÀuN‹Fº9Gw1rRƒûDt‹V‹Gè_ÿÿÿ…Àu+‹F º9G wr/1Òv¼'‹]ô‰Ð‹uø‹}ü‰ì]Ë]ô™‹uø‹}ü‰ìƒÊ]‰ÐúÿÿÿÿëÖ¶U‰åW¿ÿÿÿÿVSƒì‰Eì‹€è‰$è!Œ‰Æ@ƒøv7´&‹Uì>Ñë‰\$‹‚è‰$è¶’“9PtC‰Þ‰ð)øƒøwиÀÒ@‹U쟉D$Eð‰D$‹‚è‰]ð‰$è¶”…ÀuƒÄ‰Ø[^_]É߉ð)øë»Ç$´HD¸‰D$¸èHD‰D$èš4fU‰åW‰ÇV‰ÖSƒì 1Û;]}I¶¿¶3€ú t.…ÿu€ú töÂ`t ‰ö¼'¡äSEƒÀ@‰D$¾Â‰$èÉ4C;]|ÃƒÄ [^_]Ãt&¼'U‰åƒìöÐGE‹Mtɸésÿÿÿv‰T$º‰L$ ‰T$‹€Ô‰$èãÉÃë U‰åƒì‰$‰]ø‰Ó‰uü‰ÆèX3‰$‰Ú‰ðèŒÿÿÿ‹]ø‹uü‰ì]ÃfU‰åSƒì‰Ã‹@‰$è|rÿÿ‰$ètrÿÿY[]ÃU¸0‰åƒì‰D$Ç$è•mÿÿÇ@Ç@Ç@Ç@$Ç@(Ç@,ÉÉö¼'U‰åƒì‰]ô‰Ã‰uø‰}ü9P}8‹p…öt>‹H‰÷)ω $‚º‰C‰T$‰D$èîoÿÿ‰C…ötø‰C‹]ô‹uø‹}ü‰ì]ËH1ÿë´&¼'U‰åW‰×VSƒì<‰Eè‹@…À‰EØ…Ë‹G,‰$è‰qÿÿÇG(‹MèÇG,‹Y<…Û…‹P‰øèAÿÿÿ‹ZøB‰…ۉ؉]܈y‹U܃àø)‰к‰Ñ)Á)ʉȉUà‹M܉Öȃú ‰Eä‹_è8öˆFƒþ ~ï‹Eä‹Wƒè‰D$‹EàЃÀ‰$èrv‹w‰Â‹Mä‹]àÁêñˆ‰Ù‹_‰ÂÁêÙ‹]äˆT‹W‹MàщÂÁêˆT‹Uà‹wòˆD‹EÜ‹W‹MàÁøˆ‹EÜ‹WÁøˆD ‹EÜ‹WÁøˆD ‹G¶]܈\‹Eè‹PT…Ò…ö‹M…Ét‹Eà‹U‰‹EäƒÄ<[ƒÀ^_]ÃEð‰D$Eì‰D$ ‹ƒè ‰D$‹GƒÀ ‰D$‹ˆ‰$èQ[‹Eð‹W‰D$‹EìƒÂ ‰$‰D$èÕ0‹Eì‰$èúoÿÿ‹EðƒÀ P‰‰øèÈýÿÿ‹ZøB‰…ۉ؉]܉‡þÿÿBÿéþÿÿ‹r¶F èíóÿÿ‰D$ ‹W,‹_‰T$‹W(‰Ù‰\$)ñ‰T$‹)ʉT$‹UضF ¾‰t$‰$‰D$èF9Þ~å1ö9Þ/€?u*€ët&F9Þ€<>u€|7yî´&¼'‰<$)ó7‰D$C‰\$èš)‹E쉃ĉø[^_]ÃPéUÿÿÿvU‰åƒì‰$‰t$‰ÆèœõÿÿljÃÇ@‰ð¶Ð‰Øèñùÿÿ‹s‹ð‰C‹t$‰Ø‹$‰ì]Ãv¼'U‰åW‰×VSƒì<‰Eè‹@…À‰EÜ…È‹G,‰$è©gÿÿÇG,‹MèÇG(‹‘€…Ò…C‹U蹋B`…Àt‹HƒùŒë ÇEà‹‹WC9Ð})Ú‰Uà‹Uà™÷ù‰È)Й÷ùUà}àÿöÇEä‹Mè‹Ap…À…·‹Eà1ö‹E䉸èßôÿÿ¶Uà‹GˆP;uà}‹‹GÃèìˆ3F;uà|ë‹Eà‹‹W؃èÁøˆ‹‹Eà‹WȃèÁøˆB‹Eà‹7‹WðƒèÁøˆB‹W¶Eà,ˆB‹Mè‹Qp…Ò…+‹Eè‹P`ÿ€\…Ò…â‹Eà‹ЉG ‹}äƒÄ<[ø^_]Ë@‰Eäé>ÿÿÿ¹éçþÿÿEð‰D$Eì‰D$ ‹ƒè‰D$‹GƒÀ‰D$‹ˆ‰$ÿR …À„ˆþÿÿÇ‹Eð‹Uì‰$‰øè÷ÿÿ‹Eì‰$èñeÿÿébþÿÿ‹r‹Mè¶V‹@è7ìÿÿ‹W,‰T$‹W(‰T$‹_‹‰D$ ‰Ù)ñ‰\$)ʉT$¶F‰D$¸‰D$‹E܉$èVWÿÿéÝýÿÿ‹‹EàȉD$‹G‰D$‹Mè‹Ah‰$ÿR‹Eà‹ЉG ‹}äƒÄ<[ø^_]Ë\‰D$ ‹Eà‹؉D$‹G‰D$‹Ax‰$ÿR é«þÿÿÇ$ ID¸ä‰D$¸èHD‰D$è,&t&U‰åƒì‰uø‰Æ‰}ü‰×‹U‰]ô‹@`…Àtö@$um¶¼'‰ú‰ðèýÿÿ‹–(‰Ã;†,t‹Ž$‹Gʉ\$‰$‰D$èy%ž(‹G †T,‰ø‹]ô‹uø‹}ü‰ì]é÷ñÿÿ´& –(u˜¸èNüÿÿ‰ÃèWøÿÿÇ$‰Ú‰ðèGÿÿÿérÿÿÿfƒè€º‰†,‰T$‰D$‹†$‰$è„Gô=Ü„˜ =ÿu½‹] …Û„‹Hÿÿÿ‹u ‹C49F„æÇ$`ODéÇ$¿à‰|$èë7ÿÿ‰…Hÿÿÿ‹•Tÿÿÿ‰‚ˆéÿÿÿt&‹} …ÿ„`‹•Hÿÿÿ‹B@‹H ‹BD‹P 9ÊŒh‹Hÿÿÿ‹Tÿÿÿ‰‹‹‹A‹@ Áà9Â~‹µHÿÿÿ‰‹q…ö…;»OD‰\$‹½Tÿÿÿ‹‡Ô‰$èmƒ@‹•Hÿÿÿ‹‰ÁIˆÖ Áù¸Óà‹Hÿÿÿ‰A¸èÅÓÿÿ‹Hÿÿÿ‹S‰ƒÐè1Îÿÿ‹“Ћ…Tÿÿÿè$‹µPÿÿÿ1ÀÇÜfÄì[^_]Ã…À„‹=Ó…bþÿÿ‹] …Û„¥‹} ƒ„ÑÇ$´ODè¾:ÿÿ‰Ã‹…Tÿÿÿ1ÒèÝÿÿ‰\$‹•Tÿÿÿ‹‚Ô‰$èGl‰\$¸…ID‰D$‹Tÿÿÿ‹Ô‰$èÆ©‰$è;ÿÿ‹Pÿÿÿ1ÀÇé[ÿÿÿ=„ŽŽ'=…¿ýÿÿ‹E …Àt ‹} ƒt‹E …À•ÀC• Ш…û ‹E …À…¡‹TÿÿÿöAP@…Š ‰t$»àOD‰\$‹µTÿÿÿ‰4$è3Ãÿÿ‹Tÿÿÿ1À‹µHÿÿÿƒ£@ð1Û‰†”¶‹½Tÿÿÿ‹„Ÿ( ƒø„4Žvƒø„Iƒø„¬fCƒû~Ê‹…Hÿÿÿ1ÿ1Û‰¸¨v¼'‹•Tÿÿÿ‹„šX ƒø‡zÿ$…ØVD‰Êé‘ýÿÿ‹µTÿÿÿƒŽ@‰ $è—k‰†¼‹†‹½Hÿÿÿ‹@ÇG0ÇG4‰D$¸PD‰D$‰4$èOÂÿÿ‹•Tÿÿÿ¿‹‚‹@‹@‰$‰D$¸0PD‰D$è#Âÿÿ‰|$‹Tÿÿÿ‹Ô‰$è[e‹Hÿÿÿ‹À‰D$‹µTÿÿÿ‹†¼‰$è l‰C‹C0èÑÿÿ‹½Hÿÿÿ‰Ã•\ÿÿÿ‰‡Ð‹Gè2Ðÿÿ‰Æ‰Øè Íÿÿ‹…\ÿÿÿ‰ò‰$‰Øè·Íÿÿ‰4$¾èú8ÿÿ‹—Ћ…Tÿÿÿè)!‰t$‹•Tÿÿÿ‹‚Ô‰$èÁd‹Pÿÿÿ1ÀÇÿéýÿÿ‹} …ÿ„’Ç$`PDè÷7ÿÿ‰Ã‹…Tÿÿÿ1ÒèÈÚÿÿ‰\$‹½Tÿÿÿ‹‡Ô‰$è€i‰\$¸…ID‰D$‹‡Ô‰$觉$è]8ÿÿ1À‰‡x1Àéžüÿÿ‹M …Ét Ç$¨PDë’…Ûë ‹•Tÿÿÿ‹Hÿÿÿ‹‚,(‰Ô‹…Tÿÿÿ1ÒèñÙÿÿ‹Hÿÿÿ‹“Ô…Ò„u‹½Hÿÿÿ‹G …À…š ‹•Hÿÿÿ‹J…É…Œ‹µTÿÿÿ‹†‹@ÿ‹½Tÿÿÿ‹_‰G ‰Æ‰$èdø‹—‹J‰ò‰D$‰È‰$èûÊÿÿ‹_‰$è@ø‹‹W ‹I‰D$‰$‰ÈèÖÊÿÿ‹Hÿÿÿ‹‡‹W ‹K,‹@‰L$‹K(‰ $è²Êÿÿ‹C(‰$èG7ÿÿ‹u ‹ƒùu‹½Hÿÿÿ‹‡Ü…À„ úÿÿ‹…PÿÿÿǸ1Àébûÿÿ‹…Hÿÿÿ1Ò1ɉȋ•Tÿÿÿ‰ˆÌÇ@DöBPÇ@@Ç@LÇ@HÇ@TÇ@P„ƒÇ@8€DÇ@<éüÿÿ‹µHÿÿÿ¹°D‹†¨‰Œ†¬@‰†¨CƒûŽfüÿÿ‹…Tÿÿÿ‹€$ …À„Æ‹•Hÿÿÿ¸€ÎD‰‚Ä‹Tÿÿÿ¾¿¸‰³\,‰» »èÎÿÿ‹µHÿÿÿ‰†Ðv¼'è;»‹½Hÿÿÿ¶Ð‹‡ÐèÈÿÿKy䋇Ð1ÛèçÉÿÿ‹‡”1ÒƒøŽ‚‹Hÿÿÿ‹´™˜…ötQ‹1ÿ…É~I…Òt‹•Hÿÿÿ‹‚кäPDèÃÉÿÿ‹F‹Hÿÿÿ‹¸‹ÐG‹è©Éÿÿ9>ºÇ‹µHÿÿÿ‹†”C9Øë“‹Hÿÿÿ¾0xD‹¨‰´¬@‰¨éËþÿÿ‹Hÿÿÿ¾°žD‹¨ëÚ‹•Hÿÿÿ¿¼µD‹‚¨‰¼‚¬@‰‚¨é”þÿÿƒû‹þÿÿ‹½Hÿÿÿ1Ò‹‡¨‰”‡¬@‰‡¨éjþÿÿ‹µTÿÿÿ‹Žx…É„Vþÿÿ‹½Hÿÿÿº0µD‹‡¨ëÆ=¥…˜÷ÿÿ‹E …À„F‹} ƒ„ Ç$èPDèô3ÿÿ‰Ã‹…Tÿÿÿ1ÒèÅÖÿÿ‰\$‹•Tÿÿÿ‹‚Ô‰$è}e‰\$¸…ID‰D$‹Tÿÿÿ‹Ô‰$èü¢‰$èT4ÿÿ‹Tÿÿÿ1À‰ƒx1Àéøÿÿ‹HÿÿÿÇA8tDÇA<é“ùÿÿ‹µHÿÿÿ¹ðÂD‹†”‰Œ†˜@‰†”éÂùÿÿ‹Hÿÿÿ¾„ÁD‹”‰´˜@‰”éžùÿÿ…À…–ùÿÿƒûùÿÿ‹½Hÿÿÿ1Ò‹‡”‰”‡˜@‰‡”élùÿÿ‹Hÿÿÿ¸°;D‰Äé5ýÿÿ‹•Hÿÿÿ¿ðÀD‹‚”‰¼‚˜@‰‚”é2ùÿÿ‹•Hÿÿÿ¹‰ŠÌémøÿÿ‹M …É„‘÷ÿÿ‹} ƒ„/Ç$QDéþÿÿ‹E …À„2Ç$¨PDéxþÿÿ…Ûð‹•Tÿÿÿ‹Hÿÿÿ‹‚,(‰Ô‹…Tÿÿÿ1ÒèÔÔÿÿ‹Hÿÿÿ‹³Ô…ö„ü ‹½Hÿÿÿ‹—È…Ò„€‹Hÿÿÿ‹Cd‰$è»2ÿÿ‹C`‰$è°2ÿÿ‹µTÿÿÿ‹Cp‹–”‰$ÿR‹ƒÈ…À…ƒ‹Ct‰†˜‹Cx‰†œ‹C|‰† ‹ƒ€‰†¤‹ƒ„‰†¨‹ƒˆ‰†¬‹ƒŒ‰†°‹ƒ‰†´‹†‹@‹@ ƒø ‰†¸‡`‹½Hÿÿÿ¸‰‡È¸èàÉÿÿ‹•Hÿÿÿ‰‚Љ‹…Tÿÿÿè'‹Tÿÿÿ1À‹Qh‰P,…Ò…Í ‹Hÿÿÿ‹µTÿÿÿ‹C@‰F`ÿ‹Vx…Ò‰Fh… ‹½Hÿÿÿ‹•Tÿÿÿ‹GH‰Bpÿ‹Tÿÿÿ‹‘ˆ‰Ax…Ò…Ž ‹Hÿÿÿ‹µTÿÿÿ‹CP‰†€ÿP‰†ˆ‹†‹@‹@ Àƒø@‡¯‹½Hÿÿÿ¾C]¨‹W$‰t$‰þƒÆt‰\$‰4$‹…Tÿÿÿèpòÿÿ‹…Tÿÿÿ‹H`‹A ‰ÂƒÂˆÛ‹½TÿÿÿÁú‹‡‹@‹@ À9Âk‰\$‹•Tÿÿÿ‹Bh‰$ÿQ ‹Hÿÿÿ¸A‹Q$‰\$‰D$‰4$‹…Tÿÿÿèòÿÿ‹½Tÿÿÿ‹‡‹W`‹@‹@ À9B-‰\$‹Tÿÿÿ‹Ah‰$ÿR‹½Hÿÿÿ¸E‹W$‰\$‰D$‰4$‹…Tÿÿÿè¬ñÿÿ‹…Tÿÿÿ‹Pp‹€‹@‹@ À9B¸‰\$‰ß‹µTÿÿÿ»@QD‹Fx‰$ÿRü1À¹ó«‹F`¿pQD‹@(‰|$‰4$‰D$è¸ÿÿ‹Fp‹@‰\$‰4$‰D$臸ÿÿ‹†€‹@ …À… ‹½Tÿÿÿ1Ò1Û‰— ‹‡…À~0‹•Tÿÿÿ‹‚‹˜Ç$C‹…TÿÿÿèŠÊÿÿ‹Tÿÿÿ9™ЋTÿÿÿ1À‰ƒ‰Øè÷‹µPÿÿÿ1ÀÇ¥é´óÿÿ‹½Hÿÿÿ1Û‹‡ÐèAÃÿÿ‹lD‹Hÿÿÿ‹P0‹ÐèFÃÿÿ…Û„öCƒûv׋½Hÿÿÿ1Û‹‡ÐèÃÿÿ‹‡¨1ÒƒøŽ&‹Hÿÿÿ‹´™¬…ötR‹1ÿ…É~J…Òt‹•Hÿÿÿ‹‚кäPDèáÂÿÿ‹F‹Hÿÿÿ‹¸G‹P‹ÐèÆÂÿÿ9>ºÆ‹µHÿÿÿ‹†¨C9Øë’‹E …À„Ç$¨PDèÕ-ÿÿ‰Ã‹…Tÿÿÿ1Òè¦Ðÿÿ‰\$‹µTÿÿÿ‹†Ô‰$è^_‰\$¹…ID‰L$‹†Ô‰$è㜉$è;.ÿÿ1Ò1À‰–xé|òÿÿH>é"òÿÿ‰t$¸ QD1ÿ‰D$‰ $è­¶ÿÿ‹Tÿÿÿ1À‰ƒP,‹ƒ8 ‰»L,…Àt!‰\$iÀ`ê¾ ÜA‰t$‰$è4C‰ƒ`,‹PÿÿÿÇé™ðÿÿ‹½Hÿÿÿ‹µTÿÿÿ‹Gp‹–”‰$ÿR‹–”‰G`‹Gp‰$ÿR$º‰Gd‰ðèaÏÿÿ‰t$¸rA‰D$‹Gd‰D$‹G`‰D$‹†”‹@4‰D$ ‹†Ä‰D$‹†À‰D$‹†Ô‰$èWY‰‡Ô…À‰(úÿÿ‹…PÿÿÿÇ>1Àéfñÿÿ‹½Hÿÿÿ‰_T…dÿÿÿ1Û•`ÿÿÿ‰$‹E è¤Êÿÿ…dÿÿÿ•`ÿÿÿ‰$‹E èÊÿÿ‹E èUÊÿÿ…Àt‹•Hÿÿÿ‹‚Ø…Àu»‹Hÿÿÿ‹A‰™Ü…À„¨ôÿÿ‹…Tÿÿÿº¿rA¾ÉQDèkÎÿÿ‹Tÿÿÿ‰|$ ‰\$‹ƒ‹‰t$‰D$‹ƒÔ‰$èZ‹µHÿÿÿ…À‰†Ô‰-ôÿÿ‹½Pÿÿÿ1ÀÇjéˆðÿÿ‹µHÿÿÿºäPD‹†Ðè2Àÿÿéïüÿÿ¸àQD‰D$‹•Tÿÿÿ‹‚Ô‰$è]éhñÿÿ…Ûù‹Tÿÿÿ‹µHÿÿÿ‹ƒ,(‰†Ô‹…Tÿÿÿ1Òè®Íÿÿ‹½Hÿÿÿ‹¿Ô…ÿ…ÎóÿÿÇ$¾1Û‰t$ºRD‰\$‹…Tÿÿÿè)‹…PÿÿÿÇ1ÀéÑïÿÿ…Û‚‹½Tÿÿÿ‹•Hÿÿÿ‹‡,(‰‚Ô‹…Tÿÿÿ1Òè4Íÿÿ‹Hÿÿÿ‹Ô…À…eóÿÿÇ$¸ºRD‰D$1À‰D$‹…TÿÿÿèŠ(é÷ïÿÿ‹E è Êÿÿ‹µHÿÿÿ‰F‹E èüÉÿÿ‰F‹V…Òt…À…ò Ç$$RDé2òÿÿ‹½Hÿÿÿ1Û‹‡Ð軾ÿÿ‹‡¨1ÒƒøŽ”‹Hÿÿÿ‹´™¬…ötR‹1ÿ…É~J…Òt‹•Hÿÿÿ‹‚кäPDè—¾ÿÿ‹F‹Hÿÿÿ‹¸G‹P‹Ðè|¾ÿÿ9>ºÆ‹µHÿÿÿ‹†¨C9Øë’‹…Tÿÿÿºè"Ìÿÿ‹…Tÿÿÿ‰D$¸rA‰D$ ‹G@‹@‰D$¸VRD‰D$‹•Tÿÿÿ‹‚Ô‰$è8X‰‡Ô…À‰þÿÿ‹Pÿÿÿ1Àǃé7îÿÿ¹‰L$‹•Tÿÿÿ‹‚Ô‰$èºU‹…Hÿÿÿ‹•HÿÿÿƒÀh‰$ƒÂX‹E è]Çÿÿ‹E è¥Èÿÿ‹Hÿÿÿ…À‰A …ßÇ$pRDéþúÿÿÇ$¸ºšRD‰D$1À‰D$‹…TÿÿÿèÒ&‹µPÿÿÿ1ÀÇéŸíÿÿ‹…TÿÿÿºèËÿÿ‹TÿÿÿºrA‰T$ ‰L$‹Hÿÿÿ‹CD‹@‰D$¸¶RD‰D$‹Ô‰$è5W‰ƒÔ…À‰–ýÿÿ‹µPÿÿÿ1ÀÇœé4íÿÿÇ$»1ɉ\$ºÐRD‰L$éWÿÿÿ‹‡ƒé‹W ‹@‰L$‹NƒÁ‰ $è¼ÿÿéeñÿÿ‹½Tÿÿÿ1À‹Wl‰‡L,…Ò… ‹•Hÿÿÿ‹Tÿÿÿ‹BD‰Adÿ‹½Tÿÿÿ‹W|‰Gl…Ò…Y ‹•Hÿÿÿ‹Tÿÿÿ‹BL‰Atÿ‹½Tÿÿÿ‹—Œ‰G|…Ò… ‹•Hÿÿÿ‹Tÿÿÿ‹BT‰„ÿP‹½Tÿÿÿ‰‡Œ‹‡‹@‹@ Àƒø@‡‹…Hÿÿÿhÿÿÿ‰Ç‹P$ƒÇt‰L$¹D‰L$‰<$‹…Tÿÿÿèéÿÿ‹…Tÿÿÿ‹Hd‹A ‰ÂƒÂˆ\ ‹…TÿÿÿÁú‹€‰…Dÿÿÿ‹@‹@ ‰…4ÿÿÿÀ9¬•hÿÿÿ‰T$‹•Tÿÿÿ‹Bl‰$ÿQ ‹Hÿÿÿ…hÿÿÿ‹Q$‰D$¸B‰D$‰<$‹…Tÿÿÿè“èÿÿ‹Tÿÿÿ‹‹Qd‹@‹@ À9B……hÿÿÿ‰D$‹Tÿÿÿ‹Al‰$ÿR‹…Hÿÿÿhÿÿÿ‹P$‰<$¸F‰L$‰D$‹…Tÿÿÿè0èÿÿ‹½Tÿÿÿ‹‡‹Wt‹@‹@ À9B…hÿÿÿ½hÿÿÿ‰D$‹Tÿÿÿ‹A|‰$ÿRü1À¹ó«‹½Tÿÿÿ‹Gd‹@(‰<$‰D$¸øRD‰D$è¯ÿÿ‹Gt‹@‰<$‰D$¸(SD‰D$èû®ÿÿ‹‡„‹@ …À…¯‹•Hÿÿÿ‹B ‰$èé ‹Hÿÿÿ‹A$‰$èØ ‹½Tÿÿÿ‹‡‹x…ÿ„O‹½Tÿÿÿ‹‡h,…À…‹…Tÿÿÿ1ɉˆ\,è è‹•Tÿÿÿ‰‚d,‹‚8 …À…O‹½Hÿÿÿ‹¿Ì…ÿ„Jòÿÿ‹…PÿÿÿÇ1Àéùéÿÿ‹E 1Ò1É‹µTÿÿÿ‹½Hÿÿÿƒ@‰–”•dÿÿÿ‰ŽÇG@ÇGDÇGHÇGLÇGPÇGTÇGÇG ÇG1ÿ‰$•`ÿÿÿèáÂÿÿ‹Hÿÿÿ1À‰…Lÿÿÿ‹”…ÀŽW‹µLÿÿÿ‹…Hÿÿÿ‹œ°˜…Û„¥‹1ö…À'ëE‹K‹…dÿÿÿ‹ ±‹•`ÿÿÿ‰$‹èôäÿÿ…ÀuF93~ …ÿu׋K‹±‹8ëЋC‹•Tÿÿÿ‹°‰‚‹Tÿÿÿ‹…À…íÿ…Lÿÿÿ‹µHÿÿÿ‹Lÿÿÿ9ž”dÿÿÿ‹…`ÿÿÿ…Àu¸XSD‰D$Ç$`SDèª#ÿÿéçèÿÿÇ@롸˜SD‰D$‹•Tÿÿÿ‹‚Ô‰$è/U‹Gd‰D$‹Tÿÿÿ‹Ô‰$èUéCñÿÿ‹Fp‰$ÿPéUòÿÿ‹A`‰$ÿPé%òÿÿ‹€‰$ÿPéaòÿÿ‹µPÿÿÿÇÓ1Àéèÿÿ‰D$¹±SD‰L$‰4$èZ¬ÿÿéßóÿÿ‹…Hÿÿÿ‹•HÿÿÿƒÀl‰$ƒÂ\‹E èHÁÿÿ‹½Hÿÿÿ‹G ‰D$‹•Tÿÿÿ‹‚¼‰$èÇW‰G$1Ò‰T$‹Tÿÿÿ‹Ô‰$èJO‹Tÿÿÿ‹Oh‹ƒ‹S ‹@‰L$‹OX‰ $è–¶ÿÿ‹‹‹A…À„Ø‹½Tÿÿÿ‹Hÿÿÿ‹A‹W ‹K‰ $èØ¿ÿÿ‹‡‹W ‹K ‹@‰ $èÁ¿ÿÿ‹‡‹W ‹K$‹@‰ $調ÿÿ‹‡‹Pƒz ‡ ‹HÿÿÿƒÃt‰\$‹µTÿÿÿ‹F ‰$ÿR‹†¼‰$èýT‹½Hÿÿÿ1À‹–”‰†¼‹Gh‰D$‹GX‰$ÿ‰Gp…Àt9‹†‹–”‹@‹@ ‰\$ ‰D$‹Gl‰D$‹G\‰D$‹Gp‰$ÿR(…À…}ôÿÿÇ$ÌSD黿ÿÿPéñÿÿ‹½Hÿÿÿ1Û‹‡Ðè¶ÿÿ‹G<…ÀëJC9Ú~E‹•Hÿÿÿ‹Hÿÿÿ‹B8‹˜‹P‹Ðèõµÿÿ‹µHÿÿÿ‹V‹µHÿÿÿ‹žÄ‹…dÿÿÿ‹•`ÿÿÿ‰$‹èáÙÿÿ…À…£ìÿÿÿ…Lÿÿÿƒ½Lÿÿÿv½é˜ìÿÿ‹½Lÿÿÿ‹½`Dë¿‹•Lÿÿÿ‹•`DéKÿÿÿÇ$XUD¸Ž‰D$¸èHD‰D$è~ÚÇ$”UD¸Š‰D$¸èHD‰D$è`ÚÇ$ØUD¸‰D$¸èHD‰D$èBÚ‹µHÿÿÿ‰^Péÿÿÿ‹µHÿÿÿ‹½Lÿÿÿ‹F8‹¸‰FHé!þÿÿ‹•Hÿÿÿ‹Lÿÿÿ‹B8‹ˆ‰BLévþÿÿ¾Å‰t$éFýÿÿÇ$ VD¸È‰D$¸èHD‰D$èÔÙÇ$XVD¸Ð‰D$¸èHD‰D$è¶ÙÇ$”VD¹ÌºèHD‰L$‰T$è˜ÙU‰åVSƒì‰Ã‹$‹€(‰$‰Øè©ÿÿ‰Æ1À‰ƒ,1À‰ƒ(‹ƒ$‰$è@ÿÿ1Àþ€‰ƒ$@‹‹P,‹ƒT,‹“\,È…Ò‰ƒP,u‹“X,…Òt9Ðw%t&1À‰ƒT,ƒÄ[^]É4$º‰ØèáÇÿÿë¯Ç$ÿÿÿÿ1ÀºðVD‰D$‰ØèÚÿÿëÄt&U‰åV‰ÖSƒì‰Ã‹@`…Àtö@$uw‰ò‰Øèίÿÿ‹V‰$‰ØèA¨ÿÿ=€z‹F ‹‹P,‹“\,È…Ò‰ƒP,u/‹“X,…Òt%9Ðv!Ç$ÿÿÿÿ1ÀºðVD‰D$‰Øè˜Ùÿÿ´&ƒÄ‰ð[^]飤ÿÿvÇ$‰Øè²ÿÿƒÄ‰Ø[^]é•þÿÿt&‰$º‰ØèÇÿÿérÿÿÿ¶¿U‹ˆ ‰å…Ét]éͲÿÿ]éÿÿÿ´&U‰åƒì‰uø‰Æ‰}ü‰×‰]ô‹‰Eð‹F…Àu ‹F,À9Ðr ‹]ô‹uø‹}ü‰ì]ø]èq®ÿÿ‹V‰Ãèç¨ÿÿ‹F,‰ú)‰ØèÙ¨ÿÿ‹Eð‰Úèÿÿÿ‰~,‹]ô‹uø‹}ü‰ì]Ãë U‰åƒì‰$‰t$‹]‹u ‹ ƒ¹tBƒ¹Htº@‰Ø)ò‹$‹t$‰ì]éAÿÿÿ‹C…À•À1ÒþÿžÂ…Ðu‰ö¼'‹$‹t$‰ì]Ãt&ÇCºÿÿÿÿ‰È‹$‹t$‰ì]é#ÅÿÿvU‰åWV1öSìl‰…äûÿÿ‹€‰Ó‰•àûÿÿÃ$!…ÀuéÀÇ‹•äûÿÿF‹‚‰t$‰$è04…Àuݶ¿¶ „É„•Æ…ÛûÿÿA€ùA”ÀÆ…ÚûÿÿL€ù4” Ш…ø€ù6„ï€ùL”À€ùR” Ш…ù€ùD„ðÆ…èüÿÿ1ö„É•À1Ò€ù •Â…Ðt.€ù:„6þþwÞˆŒ.èþÿÿCF¶ „É•À1Ò€ù •Â…ÐuÒ1Àˆ„.èþÿÿ€½ÚûÿÿD„ê€ù „é1ö„É•À1Ò€ù:•Â…Ðt%þþw爌.èûÿÿCF¶ „É•À1Ò€ù:•Â…ÐuÛ1À€ù:ˆ„.èûÿÿ„–1ö¶„ÉtþþwôˆŒ.èýÿÿCF¶ „Éuè1ÉCˆŒ.èýÿÿµèýÿÿ‰4$è¼Ô‰…Ôûÿÿ1Ò…À‰•Ìûÿÿ„y•èþÿÿ‰$è˜Ô‰Ç1À…ÿ‰…Ðûÿÿ„Ü…ÿ•À1Òƒ½Ôûÿÿ•…ЄmþÿÿÇ$¹,‰L$èøÿÿ‰Æ¾…Úûÿÿ‰F1À€½èüÿÿ…»‰F‹•Ðûÿÿ1À…Ò…Q‰F1À‰~€½èûÿÿ…_‰F‹½Ìûÿÿ1À…ÿ…m€½Ûûÿÿ4‰F‹…ÔûÿÿÇF(ÇF ‰F ¸t1À€½Ûûÿÿ6”ÀÀ‰F$‹•äûÿÿ‰t$‹‚‰$èq19ð„)Ç…öt,‹F‰$èôÿÿ‹F‰$èéÿÿ‹F‰$èÞÿÿ‹F‰$èÓÿÿ‰4$èËÿÿ¶ „É…kýÿÿ1Û‰Üûÿÿéó‹•äûÿÿƒºHt^¸Pèzªÿÿ‰ÃºWDè§ÿÿ1Ò‰ØèU¦ÿÿ‹V…Òu‹…äûÿÿºWD‹€#…Àuº WD‰Øèݦÿÿ‹V‰Øè³¤ÿÿ‹…äûÿÿ‰ÚèVûÿÿ‰|$‹•äûÿÿ‹‚‰$è:…ÿ…Ú‰<$èÿÿ‹…Üûÿÿ‹•äûÿÿ‰D$‹‚‰$è 9‹F‰$èõÿÿ‹F‰$èêÿÿ‹F‰$èßÿÿ‹F‰$èÔÿÿ‰4$èÌÿÿÿÜûÿÿÿ…Üûÿÿ‹…Üûÿÿ‹•äûÿÿ‰D$‹‚‰$èb0…À‰Æ„æ‹…ÉuÌ‹F‰D$‹V¸*WD…Òu¸uND‰D$ ‹F…Àu¸uND‰D$º,WD‹FƒøLtƒøRº2WDtº9WD‰T$Ç$DWDèŠÿÿƒ~D‰Çt*‹F ‰D$ ‹F‰|$Ç$cWD‰D$èdÿÿ‰<$‰Ã‰ßèÿÿ‰|$¸oWD‰D$‹…äûÿÿ‰$è™ÿÿ‰<$èåÿÿ‹~ …ÿ…'þÿÿ‹F(…À„±þÿÿ‰$è ÿÿé¤þÿÿC¶ éaüÿÿC¶ éüÿÿ1ÀCˆ„.èþÿÿ‹…äûÿÿƒ¸H”À1Ò€½ÚûÿÿR”Â…Ðt+¸€WD•èþÿÿ1ö‰D$‹…äûÿÿ‰T$‰$è™ÿÿ¶ é}ûÿÿ•èþÿÿ1ö…èüÿÿ‰T$‰$è‰Ñ¶ é[ûÿÿˆÛûÿÿC¶ €ùL”À€ùR” Ш„ûÿÿˆÚûÿÿC¶ éûÿÿ¿…èþÿÿ‰½Ðûÿÿ‰$èÁw…À‰Ç…üÿÿ‹…äûÿÿ•èþÿÿ¾ÀWD‰T$‰t$‰$èf˜ÿÿéÛûÿÿ„ÉëC€;uúÆ…èûÿÿ¸ÿÿÿÿC‰…Ìûÿÿ¸ÿÿÿÿÆ…èýÿÿ‰…Ôûÿÿé‡ûÿÿ‰4$¸‰…ÌûÿÿèJw‰…Ôûÿÿ…À…fûÿÿ‰t$¸ìWD‰D$‹…äûÿÿ‰$èñ—ÿÿéFûÿÿ‹‡‰$è>ÿÿéýÿÿ•èþÿÿ‰$è‹ ÿÿ‰F1À‰~€½èûÿÿ„¡ûÿÿ…èûÿÿ‰$èh ÿÿ‰F‹½Ìûÿÿ1À…ÿ„“ûÿÿ…èýÿÿ‰$èG ÿÿé€ûÿÿ…èüÿÿ‰$è4 ÿÿé2ûÿÿÇ$ Ó@èó%‹•äûÿÿ‰‚éRùÿÿ1Û‰Üûÿÿëÿ…Üûÿÿ‹•Üûÿÿ‰T$‹•äûÿÿ‹‚‰$èD-…À‰Æ„ƒ>uÍ‹N¸XD…Éu¸uND‰D$‹F‰D$‹V¸XD…Òu¸uND‰D$‹F…Àu¸uND‰D$ ‹~¸*WD…ÿu¸uND‰D$‹F…Àu¸uND‰D$1ÛÇ$ XDèQ ÿÿƒ~D‰…Èûÿÿ‰Äûÿÿ„V‹N¸XD…Éu¸uND‰D$‹F ‰D$‹V¸XD…Òu¸uND‰D$ ‹F…Àu¸uND‰D$‹FÇ$-XD‰D$èç ÿÿ‰…Äûÿÿ‹FƒøL„°ƒøD„ç‹•äûÿÿ‹Š…Éu%ƒºH„4Ç$@Ó@èƒ$‹•äûÿÿ‰‚Ç$º‰T$èrÿÿ‰Ã¸ÿ‰D$‹F‰D$C‰$èÕÍƃ‹F ‹•äûÿÿ‰C‹F‰‰\$‹‚‰$èK+9؄ӋF ‰D$ ‹F‰D$¸ƒ¿tC‹F…Àu<‹F…ÀtEÇF‹F ƒøt^ƒèƒøwÇF0¹àND‰L$‹‡Ô‰$è4‹]ô‹uø‹}ü‰ì]Ãvƒ¿Ht1¸aèÍšÿÿ‹V‰ÃèC•ÿÿ‰Ú‰øèêëÿÿë“ÇF0»¼ND‰\$ë¨1À‰D$‹F‰<$‰D$ ¸‰D$¸‰D$è³ÿÿéUÿÿÿv¼'U‰åƒì8‰}ü‰Ç‹E ‰uø…Ò‹u‰Eð‹E‰]ô‰Eìtl‰T$Ç$YDè¬ÿÿ…ö‰Ãt‹‡Hƒøtaƒø„~‹Eì¹1Ò‰ø‰‡ü1À‰\$‰<$‰T$ ‰D$覰ÿÿ‰]‹uø‹]ô‹}ü‰ì]éÿÿf…ö‰òuŽÇ$/YDèNÿþÿ‰Ã먉t$ 1À¾‰D$¸‰D$‰t$‰<$è¶²ÿÿ낸èš™ÿÿ‰Eè‹Uðè”ÿÿ‹Eè‰òè%–ÿÿ‹Eèºúÿÿ=à t+= …v÷ÿÿ…ÿ„gÇ$ˆ[Dé¨ùÿÿÇ$È[Déœùÿÿ…ÿ„+ ‹•ÔýÿÿöBP„´ ‹¸ýÿÿÇAÇA‹•¸ýÿÿ‹µÔýÿÿÇB$Æp ÇB 1Ò´&¼'¶ˆBúrðèk3…À„:‹…¸ýÿÿ1Ò‰ ƒ„󋕸ýÿÿ‹‚ éöÿÿ¹ô[D‰L$‹Ôýÿÿ‹Ô‰$è#‹•¸ýÿÿ‹‚ é ôÿÿ1ÿ¾¹‰|$»‰t$‹•¸ýÿÿ‹‚°‹@‹‹@‰\$ ‰L$‰D$‹‚¸‰D$‹Ôýÿÿ‰ $è+£ÿÿ¸\D‰D$‹•Ôýÿÿ‹‚Ô‰$è#‹¸ýÿÿ‹°‰$èÊóþÿ‹…ÐýÿÿÇ-驸ÿÿ‰$èññþÿ‹¸ýÿÿ‹¨‰$èÝñþÿéµõÿÿ‹•¸ýÿÿ¾ ‹Ôýÿÿ‰²¸‹™L …Û…h‹¸ýÿÿ‹ é3óÿÿ…ÿ„®ƒG„Z ¸(\D‰D$‹•Ôýÿÿ‹‚Ô‰$ès"‹…ÔýÿÿºL\Dè£~ÿÿ‹¸ýÿÿÇA$‹Géõÿÿ…ÿ„À‹•ÐýÿÿÇ¢ éå÷ÿÿ…ö.‹•Ôýÿÿ‹¸ýÿÿ‹‚,(‰ ‹…Ôýÿÿ1Òèè’ÿÿ‹…¸ýÿÿ‹ …Ò„Ü ‹¸ýÿÿ‹A8ƒø„øû ƒø„™1À¿¾‰D$@»‹Ôýÿÿ‹AD‰|$8‰D$<‹•¸ýÿÿ‹‰D$4‹B‰t$,‰D$0‹‰\$$Áà%ÿ‰D$(‹ÁàÁø‰D$ ¸‰D$¸‰D$…þÿÿ‰D$¸‰D$‹B8‰ $‰D$ ¸‰D$¸‰D$è"¡ÿÿ¸t\D‰D$‹Ôýÿÿ‹Ô‰$è!‹•¸ýÿÿ‹B‰$èðþÿ‹¸ýÿÿº|ŸD‹A8ƒøtƒøºà´DtºµD‹…Ôýÿÿ¿“\D¾°\D‰PTÿ‹•Ôýÿÿ‹JT‰BXƒÂ‰T$‰$ÿQ‹Ôýÿÿ‹AT‹@‰ $‰|$‰D$è8xÿÿèCõ‹•Ôýÿÿ‰B\‰t$‹‚Ô‰$èx ‹EÀ…À…Î ‹EÄ…À…¯ ‹E…À… ‹E”…À…q ‹ÐýÿÿÇ éëõÿÿ…ÿ„ƒ„N¸Ü\D‰D$‹•Ôýÿÿ‹‚Ô‰$è é‹ïÿÿöÐGE„"ýÿÿºü\D‹…Ôýÿÿè*|ÿÿ‹Gé¢òÿÿ‹Ôýÿÿ¾‰±È‹…ÐýÿÿÇŸépõÿÿ‰øèyÿÿ‰…Äýÿÿ…À„x‹…¸ýÿÿ1Û¾܉D$‹•Äýÿÿ‰$èGz‹¸ýÿÿ‰Ç‹ì‰$è!Ö‰<$‰ð)؉D$è舄+HþÿÿCƒû~ã(ÿÿÿµHþÿÿ‰$èÐ:‰t$º ‰T$‰$èû:¸‰D$‹…¸ýÿÿ‰$ƒÀ(‰D$èÝ:‰\$‰4$èD‰t$ 1À‰D$¸‰D$¸‰D$¸‰D$‹…Ôýÿÿ‰$辞ÿÿ‹•Äýÿÿ‰$èpÕ‰<$èhÕ‹ÐýÿÿÇ"éWôÿÿ‹•¸ýÿÿ‹‚°‰$èSïþÿÇ$*]D¸1Ò‰D$1À‰D$‹…Ôýÿÿèàêÿÿ‹ÐýÿÿÇéôÿÿ…ÿ„cüÿÿ‹…Ôýÿÿº»rAè"ÿÿ‹•Ôýÿÿ‰\$ ‰T$‹Ìýÿÿ‰L$¹A]D‰L$‹‚Ô‰$èC‹•¸ýÿÿ…À‰‚ ‰êûÿÿ‹ÐýÿÿÇJ éžóÿÿ‰<$èæìþÿ‹ðýÿÿé(íÿÿºH]D‰T$‹•Ôýÿÿ‹‚Ô‰$辋‹W)ЃøŒBW‰G„ ‹‰…þÿÿ‹BU¸‰…þÿÿ‹…¸ýÿÿƒÀ‰$‰øèÈŠÿÿ…Àt‹…¸ýÿÿUˆƒÀ ‰$‰øè®Šÿÿ…À…éÇ$`]DéÖëÿÿ¨…·‹•¸ýÿÿ‹‚°‹@‹‹X‰ß‰$èÔ¬ƒø?‰Æ†þ ¸˜]D»‰D$‹•Ôýÿÿ‹‚Ô‰$è÷‰t$1À¹‰D$$º¸‰D$ ‰|$‰\$‰t$‰L$ ‰T$‹¸ýÿÿ‹¸‰D$‹…Ôýÿÿ‰$蘜ÿÿéhùÿÿ…ÿ„‹…ÐýÿÿÇÈ é:òÿÿ…ÿ…±üÿÿ‰t$‰\$‹•¸ýÿÿ‹‚°‰$è&\…Àˆ|üÿÿ‹Ôýÿÿ1Û‰™Èé{íÿÿèÆV…À„ˆ‹…¸ýÿÿ‹H…É…zùÿÿÇ@1Ò¿¸]D‰Ø¾pÚA»‰|$‹•Ôýÿÿ‹‚Ô‰$è÷‹¸ýÿÿƼƽƾƿÆÀ‹…Ôýÿÿ‰t$‰\$‰D$‰È̉D$ …øýÿÿ‰D$‰È¼‰$èHV…À…Ö‹•ÐýÿÿÇ é/ñÿÿ‹™°ÇÇ$Ý]DèÇçþÿ‰C‹•Ôýÿÿ‹‚À‰D$‹…¸ýÿÿÇ$ê]DƒÀ<‰D$è‹éþÿ‰D$¹d1Ò‰L$ ‰T$‹¸ýÿÿ‹°‰$è„éþÿéìÿÿ‹ÐýÿÿÇ¢ é®ðÿÿ¸^D¿¾‰D$‹Ôýÿÿ‹Ô‰$è׉|$1À‰D$¸‰D$C‰D$ ‰t$‹…Ôýÿÿ‰$蛚ÿÿ‰$è£éþÿ‹•ÐýÿÿÇ éBðÿÿÇ$ ^DèÖèþÿ‰Ã‹…Ôýÿÿ1Òè§‹ÿÿ‰\$‹Ôýÿÿ‹Ô‰$è_‰\$¸…ID‰D$‹•Ôýÿÿ‹‚Ô‰$èÞW‰$è6éþÿéÁûÿÿ¹X^D»H‰˜¸‰L$‹•Ôýÿÿ‹‚Ô‰$è 1Ò¸F‰T$‰D$‹Ôýÿÿ‰ $èÜ™ÿÿ‹…ÐýÿÿÇhé‹ïÿÿ¹|^D‰L$‹Ôýÿÿ‹Ô‰$è¾öÐGE…3 ‹…¸ýÿÿº‰Øééÿÿ»)‰™¸¹˜^D‰L$‹‚Ô‰$èy1Ò¸'‰T$‰D$‹Ôýÿÿ‰ $èL™ÿÿ‹…ÐýÿÿÇ=éûîÿÿ‹…Ôýÿÿº¸^Dè{uÿÿé¬ñÿÿ…àýÿÿ•Üýÿÿ‰$‰øèÐ…ÿÿ‹…Üýÿÿ…À„€¸Ü^D‰D$‹•Ôýÿÿ‹‚Ô‰$èõ‹¸ýÿÿ‹™°ÇÇ$ú^Dè7åþÿ‰C‹•¸ýÿÿ‹àýÿÿ‹‚°Ç@¸ ‰\$‰D$‹…Üýÿÿ‰$è0©…À„é Ç$uNDèìäþÿ‰Ã‹…Üýÿÿ‰D$‹…àýÿÿÇ$_D‰D$èºæþÿ‹¸ýÿÿ‰Æ¸_D‹¹°‰\$€;u¸uND‰D$Ç$ _Dè‰æþÿ‰G ‹•¸ýÿÿ1ÿ‹‚°Ç@¸d‰D$ ‰|$‰t$‹‚°‰$èræþÿ‰$èúæþÿéêèÿÿ‹•¸ýÿÿ¾d‹‚°‰ÓƒÃ<‹@‹‹@‰t$‰$‰D$è—§‹¸ýÿÿ‹°‰$èsèþÿ‰\$ ¸1Ò‰D$¸‰D$‰T$‹•Ôýÿÿ‰$èy—ÿÿ‰\$Ç$E_DèÉåþÿ‰D$‰Ã‹Ôýÿÿ‹Ô‰$è_¡ÐGE¨t%¨t¨u‹…Ôýÿÿ‰Úèsÿÿ‹…ÔýÿÿºX_Dèqsÿÿ‰$è)æþÿ‹…ÐýÿÿÇà éÈìÿÿÇ$¸ºRD‰D$1À‰D$‹…Ôýÿÿèbãÿÿ‹•ÐýÿÿÇé‘ìÿÿƒø…õÿÿ¸[_D‰D$‹•Ôýÿÿ‹‚Ô‰$è»éãôÿÿ‹•¸ýÿÿ‹‚ é6çÿÿ‹…Ôýÿÿºu_DèÕrÿÿéeïÿÿ‹…¸ýÿÿÇ@Ç@éGòÿÿ¿_D‰|$éIöÿÿ‹…Ôýÿÿº°_Dè™rÿÿ‰4$è‘%‰Â‹…Ôýÿÿè„rÿÿ‹…ÔýÿÿºÐ_Dètrÿÿ‹•ìýÿÿ‹…Ôýÿÿècrÿÿ‹…ÔýÿÿºÓ_DèSrÿÿé§æÿÿ…ö ‹Ôýÿÿ‹•¸ýÿÿ‹,(‰‚ ‹…Ôýÿÿ1Ò1Û迆ÿÿ‹¸ýÿÿ‹¹ …ÿ„q ‹¸ýÿÿƒû‹Q‹Ôýÿÿ¶Dˆ‹…¸ýÿÿ‹P¶D(0Cƒû~Í‹E¼9EŒŽ*E¸¹ ‰D$‰L$‹•¸ýÿÿ‹B‰$è›k…À…! Ç$Ø_Déããÿÿ1ö¹»‰t$‹•¸ýÿÿ‹‚ä‰\$‰L$‰D$ ‹Ôýÿÿ‰ $è•ÿÿ‹…ÐýÿÿÇü éÀêÿÿ¸`D‰D$‹Ôýÿÿ‹Ô‰$èó‹…ÔýÿÿèhËÿÿ‰<$èàãþÿé ñÿÿ‰$èÓãþÿÇE”é{ôÿÿ‰$è¿ãþÿÇEé\ôÿÿ‰$è«ãþÿÇEÄé=ôÿÿ‰$è—ãþÿÇEÀéôÿÿ‹•¸ýÿÿ‹‚°‹@‹‹@‰$褉ø=`D‰D$‹Ôýÿÿ‹Ô‰$èP‰\$1À‰D$$¸‰D$ ‹•¸ýÿÿ‹‚°‹@‹‹@‰\$‰D$¸‰D$¸‰D$ ¸‰D$‹‚¸‰D$‹Ôýÿÿ‰ $èÞ“ÿÿé®ðÿÿ1À»F‰D$¸‰D$‹¸ýÿÿ‹°‹@‹‹@‰\$‰D$¸‰D$ ‹¸‰D$‹…Ôýÿÿ‰$èçxÿÿévåÿÿÇ$X`DéÆèÿÿ‰t$‰\$‹¸ýÿÿ‹°‰$è*S…Àˆ1‹•Ôýÿÿ1ɉŠÈ…À…Wûÿÿ‹¸ýÿÿ1ÿ‹°‰$èöãþÿ‰|$¸º…`D‰D$Ç$‹…Ôýÿÿè‚ßÿÿéîáÿÿ…öu÷ÿÿ‹Ôýÿÿ‹•¸ýÿÿ‹™$(‹((‰øýÿÿ‰‚Ì‹…¸ýÿÿ…Û‰˜Ätƒ¸ÌŽ'ïÿÿ€{„céÿÿ‹¸ýÿÿ‹ é&ãÿÿ‰4$èá!‰D$¸œ`D‰D$‹Ôýÿÿ‰ $è&jÿÿ‰4$èŽ`ƒø‰Ã„S‰$èb‰D$¸À`D‰D$‹•Ôýÿÿ‰$èðiÿÿ‰$èøa‰4$‰Ãè~!‰D$‰\$Ç$ä`Dèzàþÿ‰Ã‰Â‹…Ôýÿÿè[nÿÿ‰$1Ûèáþÿ‹¸ýÿÿ‰™ é+îÿÿ» aD‰\$‹•Ôýÿÿ‹‚Ô‰$èã¡äSEƒÀ ‰$èÛ¡‹Ôýÿÿ€¹Ø…à‹Ô1ÿ1ö‰$è^Þþÿ‰Ã‹…¸ýÿÿlj˜°Ç$,aDèîÝþÿ‰CÇ$;aDèßÝþÿ‰D$¹dº‰L$ ‰T$‹•¸ýÿÿ‹‚°‰$èÅßþÿ‰|$‰t$‹¸ýÿÿ‹°‰$èùP…À‰Ýýÿÿ‹…Ôýÿÿ»‰˜ÈéÕîÿÿ‰\$½þÿÿF‰<$èP¡ƒþ?‡æóÿÿMèFèeˆƒ þÿÿƒþ?vééÊóÿÿ‰D$Ç$HaDè#ßþÿé_ßÿÿ‹Ôýÿÿ»‰™Èéôÿÿ…èýÿÿ•äýÿÿ‰$‰øèR}ÿÿ‹…äýÿÿ…À„ï¸iaD‰D$‹•Ôýÿÿ‹‚Ô‰$èw‹¸ýÿÿ‹™°ÇÇ$€aDè¹Üþÿ‰C‹èýÿÿ¸ ‰D$‰\$‹…äýÿÿ‰$èÅ …À„Ç$uNDèÜþÿ‰Ã‹…äýÿÿ‰D$‹…èýÿÿÇ$_D‰D$èOÞþÿ‰Æ‹…¸ýÿÿ‹¸°‰\$¸_D€;u¸uND‰D$Ç$—aDèÞþÿ‰G ‹•¸ýÿÿ1ÿ‹‚°Ç@¸d‰D$ ‰|$‰t$‹‚°‰$èÞþÿ‰$èÞþÿ‹Ôýÿÿ‹€éXàÿÿ‹…ÔýÿÿºµaDè®kÿÿ‹…¸ýÿÿ‹‹€‰$‹…Ôýÿÿè>kÿÿ‹…ÔýÿÿºÓaDè~kÿÿéˆõÿÿ‹…ÔýÿÿºâaDèikÿÿéÿéÿÿöÐGE…•¸bD‰D$‹•Ôýÿÿ‹‚Ô‰$èú‹Gé²áÿÿ9щÈ}‰Ð‹•¸ýÿÿ¿¾d‰¸‰D$‹‰$èÙþÿ‹¸ýÿÿ‰AEˆ‰$èi‰$‰|$èåØþÿ‰$Uˆ‰Ã‰T$èôi‰t$Mˆµhþÿÿ‰L$‰4$èk‹…ÔýÿÿºèKÿÿ‹…Ôýÿÿ¹rAºbD‰L$‰T$ ‰Â‰D$‰t$‰\$‹€Ä‰D$‹‚À‰D$‹‚Ô‰$èC ‹¸ýÿÿ‰ ‰$èÝþÿ‹…¸ýÿÿ‹€ …À‰ øÿÿ‹•ÐýÿÿÇø éšãÿÿ¸bDé ÷ÿÿ¹d‰L$‹…Ôýÿÿ؉D$‹¸ýÿÿƒÃ<‰$èw‹…¸ýÿÿÆ€ŸéòõÿÿÇ$4bDéÙâÿÿ‰t$‰\$‹•¸ýÿÿ‹‚°‰$è=M…Àˆ§üÿÿ‹Ôýÿÿ1Ò‰‘ÈédçÿÿEˆº ‰D$‰T$‹•¸ýÿÿ‹B‰$èqc…À„Ö÷ÿÿE¸‰D$‹EŒ‰D$‹¸ýÿÿ‹A‰$èJc…À„¯÷ÿÿ¸ZbD1ö1ÿ‰D$1Û‹•Ôýÿÿ‹‚Ô‰$èï 1À‰…Ìýÿÿ‹Ôýÿÿ‹„™X …Àu;¿C…ö”À1ÒƒûžÂ…ÐuØ…ö…Xîÿÿ‹¸ýÿÿöA…VÇ$pbDé'Ûÿÿƒø„æƒø„µ‰H„¼‹…¸ýÿÿ‹•¸ýÿÿ‹H8¸Óà…Bt¾ë‰Ç$¾1Û‰t$ºÐRD‰\$éùÿÿ¸±bD‰D$‹Ôýÿÿ‹Ôé]õÿÿ…üýÿÿ‰D$‹…¸ýÿÿ¨‰D$ ‹…¸ýÿÿ¤‰D$‹…¸ýÿÿ‰4$ ‰D$èÁ;…À„8‰4$1À‰D$èû:‹•¸ýÿÿ‰‚¬éåçÿÿ‹øýÿÿéÎøÿÿ‹…Üýÿÿ‰\$Ç$_D‰D$èåÙþÿÇ$ÍbD‰Ãèç×þÿéóÿÿ‹…ÔýÿÿºØbDè²gÿÿéVüÿÿ¸˜SDµØþÿÿ‰D$‹•Ôýÿÿ‹‚Ô‰$èJ Æ…Þþÿÿ¸ ‰ñ‰…Øþÿÿ¸ f‰…ÜþÿÿÇE¨‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁÒ»PƒÙ)ñ)ˉñ‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁ‰\$ÒEˆƒÙ‰D$(ÿÿÿ‰ $èKg‰t$‹•Ôýÿÿ‹‚Ô‰$è“ ‰øè¬vÿÿ‹Ôýÿÿ‰A@‰øèœvÿÿ‹•¸ýÿÿ‰B‰øèŒvÿÿ‹¸ýÿÿ‰A‹…ÔýÿÿÇ@D‰$èÞ%‹EŒ‰D$‹•¸ýÿÿ‹B ‰$‰D$è&‹E¼‰D$‹¸ýÿÿ‹A‰$‰D$èæ%‰$¸‰D$…þÿÿ‰D$èË%‰\$‹…¸ýÿÿ1ÛƒÀ(‰$èô.èÿ]‹•ÔýÿÿˆDCƒû~ë‹UŒÕ9Eˆ‹M¼Í9E¸Ž»úÿÿÇ$èbDéïÿÿ‹…üýÿÿ‰D$¸cD‰D$‹Ôýÿÿ‰ $è aÿÿ‰4$踋•üýÿÿ‰D$Ç$0cD‰T$è®×þÿ‰Ã‰Â‹…Ôýÿÿèeÿÿ‰$èGØþÿé_åÿÿEˆ‰D$‹E¼éüÿÿÇ$È[Dé³×ÿÿ‹…äýÿÿ‰\$Ç$_D‰D$è]×þÿÇ$ÍbD‰Ãè_Õþÿéûøÿÿƒø…uüÿÿ‹•¸ýÿÿ¸`cDÇB8‰…ÌýÿÿéXüÿÿ‹…¸ýÿÿÇ@8¸kcDëዸýÿÿ¸tcDÇA8ë͸|cD‰D$‹•Ôýÿÿ‹‚Ô‰$èé¹ûÿÿÇ$¤cD¸ï ¿èHD‰D$‰|$脘Ç$ÐcD¸ç‰D$¸èHD‰D$ëàÇ$ðcDéÑÖÿÿt&U‰åW‰ÇVSƒìèÐsÿÿ‹G`…ÀtqÇEì‹—(‹H)Uì‹EìDÿ‰Eì™÷ù)Uì‹—€…ÒuS¸1öèÐnÿÿ‰ÃèÙjÿÿ;uì}#t&èû[ˆEóUó‰ØÇ$Fèvkÿÿ;uì|á‰Ú‰øèXsÿÿ‰øè1¾ÿÿƒÄ[^_]ˇˆ‰$ÿR)Eì뜴&U‰åSƒì‹]‹E ƒ»H‰ƒ,(t$Ç$ÿÿÿÿ1À1Ò‰D$‰Øè®˜ÿÿƒÄ‰Ø[]é‚wÿÿfÇ$ÿÿÿÿ1À1Ò‰D$‰Øè*ÕÿÿƒÄ‰Ø[]é^wÿÿ´&¼'U‰åƒì(‰uø‹M ‹u‰]ôƒù ‰}ü„óƒù”Àƒù” Ш…“ƒù„ƒƒù„÷1ÿƒù„$ƒù„¥ƒù„¦ƒù„Œƒù„žƒù„ùƒù„úƒù„ûƒù„üƒù„ýƒù„þƒù„ÿƒù„…ÿ…»ëi‹†ƒø”Â…À”À ШuRƒ¾H„R¸è mÿÿ‰Ãèiÿÿ‹}ü‰Ú‰ð‹]ô‹uø‰ì]éO½ÿÿƒ¾„㸉†´&‹]ô‹uø‹}ü‰ì]ˆƒø”Â…À”À Шu܃¾H„ ‹†ì…ÀtŸbè‹lÿÿ‰Ã‹†ì‹P‰Øèùfÿÿ‰Øº dDè iÿÿ‰Ø1ÒèThÿÿ‰Ø1ÒèÛfÿÿ‹}ü‰Ú‰ð‹]ô‹uø‰ì]év½ÿÿ¶‹†\,…À…bÿÿÿƒ¾H…UÿÿÿÇE ‹]ô‰ðÇEÿÿÿÿ‹uøºdD‹}ü‰ì]éo–ÿÿƒ¾H„A‹†ì…À…ÇE !dD‹†Ô‹]ô‹uø‰E‹}ü‰ì]éãöFP…éþÿÿ‰4$1ÿ»uND‰|$¹º ‰\$ ‰L$‰T$è „ÿÿé»þÿÿ¿2dD¶ƒ¾H…£þÿÿ‹†ì…À„•þÿÿ¸bè[kÿÿ‰Ã‹†ì‹P‰ØèÉeÿÿ‰Øº7dDèÝgÿÿ1Ò‰Øè$gÿÿ‰ú‰ØèËgÿÿ‰ð‰ÚèR¼ÿÿ‰|$¸>dD‰D$‰4$èÍ[ÿÿé8þÿÿ¿PdDë¿TdDéwÿÿÿ¿YdDémÿÿÿ¿]dDécÿÿÿ¸`èÙjÿÿ‰Ã‹†ì‹P‰ØèGeÿÿ‰ð‰Úèî»ÿÿ1À‰†ÈéÍþÿÿ‰4$1À‰D$¸‰D$誃ÿÿé±þÿÿÇE ddDé¬þÿÿ¿‰dDéÿþÿÿ¿ä;Déõþÿÿ¿dDéëþÿÿ¿Ù;Déáþÿÿ¿’dDé×þÿÿ¿—dDéÍþÿÿ¿œdDéÃþÿÿ¿¡dDé¹þÿÿ‰ö¼'U‰å츉uø‹u‰]ô‹]‰}ü‹} ƒ¾tl…Ût‹C‹”†@(…Òuj‹ŽÜ…Ʉމ}„†t‹}‰E€‹†t=»„ìZ…À„D=“„ú‹E€Ç´&¼'‹]ô‹uø‹}ü‰ì]Ãv‰\$‰4$ÿ”†@(‹]ô‹uø‹}ü‰ì]Ãt&=÷„V%=äu¡…Û„¯‹SBòƒø‡!ƒú„d‹†Ü¹¨dD‰D$ ‹†Ø‰L$‰4$‰D$èÓYÿÿ鳉\$‰ú‹E‰$‰ðè Ðÿÿ…À„Sÿÿÿº‰–Üé÷þÿÿv…Û„‹SBòƒø‡©ƒú„M¹ÓdD‰L$‹†Ô‰$èÉÇFLºpþ@‰–¬(‰ð–èèêºÿÿ¸PA‰†´(‹† …À„庸‰–̉†Ð‹†$ …À…º‹† …À„è‹–ˆ…Òt‹– …Ò…Ž€8„i‰D$ 1Û¹‰\$º ‰L$‰T$‰4$è ÿÿ¸êdD‰D$‹†Ô‰$踉†‹† …À…n‹†…À… ‹F…À…v¸‰†ÈÇ$ Ò@èêæ‰†è‹E€Ç1‹]ô‹uø‹}ü‰ì]øý@‹ŽP ¿°@A‰†ˆ(¸ý@»GA‰†„(¸ A…ɉ†”(¸pA‰†˜(¸A‰†¤(¸A‰† (‰¾œ(‰ž(…‹†|"…À„sþÿÿ¿údD»@‰|$‹†Ô}ˆ‰$è ‹†#¹‰\$ ž€"‰D$EȉL$‰|$‰$èŸu‰†D‰\$‰$èmwöFD„W‰$»èÖx‰D$$¸1Ò‰D$ ¸¹‰D$EȉT$(º‰D$ ¸"‰|$‰\$‰L$‰T$‰D$‰4$èXÿÿ‹E€Ç»éšüÿÿ=1…xüÿÿ…Û„þ‹Cƒø„‡þÿÿƒø„~þÿÿ‰D$Ç$eDèrÍþÿ‰Ã1Ò‰ðèGpÿÿ‰\$‹†Ô‰$èÿ‰\$¸…ID‰D$‹†Ô‰$èŠ<‰$èâÍþÿ1À‰†téüÿÿ‰4$1À‰D$¸ ‰D$è®~ÿÿéŸýÿÿ¿‰Ð‰¾0é`ýÿÿÿ‰û~»‰\$1À¹‰D$$¸º‰D$ )ß‹E„‰\$‰L$ ‰D$¸‰D$¸‰T$‰D$‰4$è<~ÿÿ]„…ÿžéŒýÿÿÇ$5eDè„Ìþÿé ÿÿÿ…Û„‹SBòƒøw܃ú„ò¿HeD»\eD‰|$‹†Ô‰$è÷ýÇF<èÛ¶‰†ˆ‰\$‹†Ô‰$èÓý轉†Œ¹„eD‰L$‹†Ô‰$è±ýé?üÿÿ¸–‰†Ø¸–‰†Ü†Ü‰D$ †Ø‰D$¸­eD‰D$†¸‰$èÓ¸ è^ÿÿ–˜‰ÃèÔ`ÿÿ‹–䉨è§^ÿÿ‹–à‰Øèš^ÿÿ1Ò‰Øè‘^ÿÿ1Ò‰Øèˆ^ÿÿ‰\$–؉ðÇ$ Aè@UÿÿºÀ‰Øè^ÿÿ‹–܉ØèW^ÿÿºÁ‰Øèë]ÿÿ‹–؉Øè>^ÿÿ1Ò‰ØèÕ]ÿÿ‰ð‰Úè\|ÿÿ¸‰†‹E€Çäéóùÿÿ‰4$1À‰D$¸‰D$ ¸‰D$¸%‰D$èz|ÿÿ‹E€Ç÷é¼ùÿÿ‹†ä‰D$‹†à‰4$‰D$è°Æÿÿéqûÿÿ‰$1Û1ɉ\$ 1Ò‰L$‰T$è1­þÿékûÿÿ‰4$¿ ‰|$è õÿÿéJûÿÿè¡6…À„áûÿÿº³eD‰T$‹†Ô‰$èü‰4$1À‰D$¸‰D$èÛ{ÿÿ‹E€Ç“éùÿÿ…Ûtî‹SBòƒø‡Šýÿÿƒú„±¸ÏeD‰D$‹†Ô‰$èªûÇFH¸PA‰†¼(é[ûÿÿ»èeD‰\$‹†Ô‰$è|ûéÀùÿÿ† é úÿÿ‰|$1À¿"‰D$ ¸‰D$¸‰D$¸‰D$EȉD$ ¸‰D$‰|$‰4$è{ÿÿé¹ûÿÿºÿeD‰ðèUWÿÿéýüÿÿ¸fD‰D$‹†Ô‰$èùúé¼úÿÿº8fD‰ð¿è#Wÿÿ‰¾Ì»‰žÐéuøÿÿ¶¼'U1ɉåWVSƒìl1Û‹U‹E‰Uì‰Eð‰D$1À‰D$ ¸ÿÿÿÿ‰D$1À‰L$‰\$‰T$‰D$‹U‹B‰$è4»þÿ‹u‹M‹†lÁl‰Mè= t~6=: „þ‹U踋MÇ‹‘ƒút?ƒÄl[^_]ô&…ÀuÑ‹Eð…Àu<‹}èÇ ‹E‹¸ƒúuʉö¼'‹EºèkÿÿƒÄl1À[^_]ËU‹Eì‹’€¶…Ò‰U°„e‹}‹u‹‡hÆh‰uä=Y „†³=U „Ý‹…À…Ž€ûS…c‹EäÇU ´&¼'¸ÿEìÿMð…À…1ÿÿÿ‹Uš4(ë;f‹M‹±0(…ö…V‰$è‡Âþÿ…Àޝ‹EèGiÿÿ‹uƒ¾„ÿÿÿ‰$è_Âþÿ…À»‹Mð…É´‹}èÇ: éÚþÿÿ=_ „[ÿÿÿŽó=h …Ø‹}°‹O‹Aÿ9ˆ‹M°‹Aˆ‹u°‹Fÿ…Àˆ«€û-„‘ƒøw ‹}°ˆ\8@‰G‹uäÇh éÿÿÿ´&EðUì‰$‹Eè/hÿÿéCÿÿÿÇ$¸$‰D$è…Âþÿ‰E°‹M‹}‹u‰€‹‡hÆh‰uä=Y …zþÿÿ€û-t{€û „²‹uäÇ^ éþÿÿ=W „§‹EäÇ1Àé‡þÿÿ=^ uéëÅ‹Eð‰D$‹Eì‰$‰D$è“Âþÿ‹EðEìÇEðé½þÿÿ€ûSu˜‹U¿W ‰ºhé9þÿÿ‹E°»Ç@‰\$‹@‰$è»Áþÿ‹M°‰AÇSSH-Æ@ÇÇAéÔþÿÿ‹}äÇ_ éëýÿÿ€ûH….ÿÿÿ‹M¾Y ‰±héÏýÿÿA¹‰G‰L$‹G‰D$‹G‰$èÄþÿ‰G‹éSþÿÿÆD0ÇFÿÿÿÿénþÿÿ€û …eþÿÿ‹E1Ò¿YfD‹M°Ç@H‰Ô‹‹AƸX_D‰D$‹A‰$èK‡‹u°‹VÆ‹F‰|$‰D$‹}‰<$è3Nÿÿ‹^¾KAD‰t$‰$è‡ùKAD¶‰L$<ƒÛÿ‰$èü†Ã¶ÇGP<‹‡ 'ƒÛÿ…À„)ƒø„‡‹M‹'…À„Sƒø„!‹M‹'…À„íƒø„Í‹M‹'…À„™ƒø„‹}‹‡'…À„܃ø„‹M‹ '…À„[ƒø„&‹}‹‡$'…À„ïƒø„΋M‹('…À„šƒø„‹]°ºlfDƒÃ‰ØèWÿÿ‹}°ÁèºpfD‰G‰ØèÿVÿÿ÷ЋMÁè‰G ‹‘t…Ò…a‹O…É„B…À„JŽóÇ$ufD¹`D‰L$ègÃþÿ‰E´‹Eº‰H‹M´€9S…·‹u´€~S…Œ‹}´€H…a‹E´€x-…J‹U´‹]´¶BƒÃ„À•Â<-•À¶À…„pC¶ „É•À1Ò€ù-•Â…Ðuë€ù-…úC¶ „Ét€ù-”À€ù ” ШtæÆ_C¶ „Éuã‹Mƒ¹H„‹}¸@vA‰‡à1À‹U1ÿ‰¼‚@(@=ÿ~ì¾ A» A¹àA‰²D(¸`ì@‰šÀ(‰ŠÐ(‰‚ä¸X_D‰D$‹M´‰ $è’„‹u´‰D$¸‚fD‰D$‰t$ ‹}‰<$è{Kÿÿ‰4$胃‰$‰ò‰øèwSÿÿ‰4$è¿Âþÿ‹‡Hƒø„5‰D$¸™fD¿ D‰D$‹E‰$è3Kÿÿ‹U‹‚Ô‰$è¢ð‹M¸‰‰Èè‰|$‰L$‰$è]Çþÿ‹u‹}°‰†H,‹G‰$èFÂþÿéOûÿÿ¶ éþÿÿ‹}°‹w…ö„ÿýÿÿº·fD‰Øè¿Tÿÿ…À‰Ú~º·fD‰T$¸`D‰D$Ç$»fDèKÁþÿ‰E´‹U¸‰‚Héßýÿÿƒú…¡ýÿÿ…À…¡ýÿÿÇ$ÈfDèÁþÿ‰Ã‹E1Ò¿…IDèçcÿÿ‰\$‹U‹‚Ô‰$è¢ò‰\$‰|$‹M‹Ô‰$è)0‰$èÁþÿ‹uä1ÀÇéùÿÿ‰\$Ç$ gDè¡ë…Àuh‰\$Ç$gDèë…ÀuT‰\$Ç$(gDèyë…Àu@‰\$Ç$;gDèeë…Àu,‰\$Ç$GgDèQë…Àu‰\$Ç$UgDè=ë…À„oüÿÿ‹u»`gDƒNP@‰\$‹†Ô‰$è×ñéLüÿÿ‰\$Ç$ŽgDèë…À„üÿÿ‹E¾ gDHP€‰t$‹€Ô‰$è™ñéôûÿÿ‰\$Ç$ÞgDèÄê…Àu‰\$Ç$ïgDè°ê…À„®ûÿÿ‹u¿hDƒNP‰|$‹†Ô‰$èJñé‹ûÿÿ‰\$Ç$4hDèuê…À…Yûÿÿ‰\$Ç$=hDè]ê…Àu‰\$Ç$DhDèIê…À„-ûÿÿ‹EºLhDƒHP ‰T$‹€Ô‰$èãðé ûÿÿ‰\$Ç$4hDèê…À…Øúÿÿ‰\$Ç$ƒhDèöé…ÀuT‰\$Ç$ŠhDèâé…Àu@‰\$Ç$hDèÎé…Àu,‰\$Ç$—hDèºé…Àu‰\$Ç$žhDè¦é…À„púÿÿ‹u¹¤hDƒNP‰L$‹†Ô‰$è@ðéMúÿÿü¸ÑhD¹ ‰Þ‰Çó¦…úÿÿ‹E¾ÜhDƒHP‰t$‹€Ô‰$èðéùùÿÿü¸ÑhD¹ ‰Þ‰Çó¦t¸iD¹‰Þ‰Çó¦…¶ùÿÿ‹E¿,iDƒHP‰|$‹€Ô‰$èºïé“ùÿÿü¸ciD¹‰Þ‰Ç󦄂¸jiD¹‰Þ‰Çó¦tp¸qiD¹‰Þ‰Çó¦t^¸xiD¹‰Þ‰Çó¦tL¸iD¹‰Þ‰Çó¦t:¸ÑhD¹ ‰Þ‰Çó¦t(¸iD¹‰Þ‰Çó¦t¸†iD¹‰Þ‰Çó¦…àøÿÿ‹Eº”iDƒHP‰T$‹€Ô‰$èþîé½øÿÿÇ$ÄiDè=½þÿ‰Ã‹E1Òè`ÿÿ‰\$‹u‹†Ô‰$èÌî‰\$¸…ID‰D$‹†Ô‰$èQ,‰$詽þÿ‹}ä1ÀÇé>õÿÿ¸9 ‰D$¸èHD‰D$Ç$jDè“~Ç$ÿÿÿÿ1À1Ò‰D$‰øèµÿÿ‹‡Héªúÿÿ¸X_D‰D$‹u´‰4$èÞ~‰Ã¸‰D$C‰$èp¸þÿ‹}‰G‰\$‰t$¾‰$èå}‹GƸX_D‰D$‹U°‹B‰$è~‰t$‰Ã@‰$è&¸þÿ‰G‹M°‹Q‰\$‰$‰T$è}‹G¹ðÜAÆ1À‰à‹uº`ÜA‰”†@(@=ÿ~é1À1ÿ1Û‰†L(1À1ɉ†T(1À1Ò‰†X(1À‰†(1À‰†Ä(1À‰†)1À‰† )1À‰†)1À‰†)1À‰†0)1À‰†¨)1À‰†¬)1À‰†°)1À‰†´)1À‰†¸)1À‰†¼)1À‰†Ð)¸ÐÚA‰†D(¸ A‰¾”(1ÿ‰ž¸(1Û‰Ž¼(1ɉ–À(1Ò‰†H(¸ÜA‰¾4)1ÿ‰ž€)1Û‰Ž„)1ɉ–ˆ)1Ò‰†P(¸Pñ@‰¾À)‰žÄ)‰ŽÈ)‰–Ì)‰†äé{øÿÿ¸7 éëýÿÿÇ$jD¹6 ºèHD‰L$‰T$éáýÿÿ¾5 ‰t$Ç$jD»èHD‰\$éÃýÿÿ¿4 ‰|$ëà´&U‰åSƒì‰Ã‹@…ÀtX[]ÉØèu±ÿÿ…Àuñ‹C ƒøtƒøuä‹C0‰$èYÊþÿX[]ËC0‰$èºhX[]öU‰åSƒì‹E èñWÿÿ‰Eø¸ÀÒ@‰D$Eø‰D$‹E‹€è‰$è­Û…À‰Ãt‹@…ÀtƒÄ[]ËE è²WÿÿC$‰ØèXÿÿÿƒÄ[]ÃfU‰åWV¾ÀÒ@Sƒì,‹} ‰øèˆWÿÿ‰EðEð‰t$‰D$‹U‹‚è‰$èIÛ…À‰ÆtSƒ_tUEìUè‰$‰øèÝWÿÿ‹Mè…Ét6‹V 1À‹]ì)^,ƒú„½Žyƒút1ƒú„¾º@)‰ðè £ÿÿƒÄ,[^_]ÉøèWÿÿHt¡ƒÄ,[^_]Ã…Ût&Ž0‹V8ƒúw7‹Eì»)Ó9Ãv‰Ã‰\$D24‹Uè‰$‰T$èkz]è‹F8)]ì؉‰F8ƒú„Ÿƒúv:‹Eì…À~3‹^<)Ó9Ãv‰Ã‹N0‰\$‹Eèʉ$‰D$è#z]è‹F8)]ì؉‰F8;V…‡‹E´€8uu¸c‰…tÿÿÿé;ýÿÿ‹EèÇ$dkD‰D$è °þÿ‰Ã1À1Ò‰D$¸‰D$‰$‹Eè ®ÿÿ‰$è”°þÿéýÿÿ‰Øè¨Mÿÿ‹U‰‚ô‰D$¸@YD‰D$‰$è 9ÿÿ닉$è`°þÿë‰4$èV°þÿélÿÿÿ‹E¨…À”À1Òƒ}¤•…Є‚ÇE¼é—þÿÿEäUà‰$‰ØèÌMÿÿ‹Mä…ɉpÿÿÿ…ƒ½pÿÿÿ„Žƒ½pÿÿÿ„Ѓ½pÿÿÿt>‹U¾€‰²ôé‹þÿÿ‹E؉T$Ç$˜kD‰D$è¯þÿ‰E´é‘þÿÿÇEÀéþÿÿƒ½pÿÿÿ¸‹Uàü‰Á‰U€‹u€º’dD‰×ó¦…‘‹Eº‹‰ôé&þÿÿÇE”‹Eàº2dDü‰×¹‰Æó¦u©‹Eº–ë΋Eà‰L$Ç$¢kD‰D$è‚®þÿ‰E¸‹u䉵pÿÿÿéÿÿÿü‹Uà¸YdD‰Ç‰U‹uº‰Ñó¦u>‹E¿ˆ‰¸ôé¨ýÿÿƒ½pÿÿÿº—dD‹u€ü¸‰×‰Áó¦…éþÿÿ‹E¿ëʃ½pÿÿÿº]dD‹uü¸‰×‰Áó¦u‹E¾„‰°ôéMýÿÿÇE¤éÖüÿÿƒ½pÿÿÿº‰dD‹uü¸‰×‰Áó¦…‚þÿÿ‹E¹‚‰ˆôé ýÿÿ´&U‰åEøSUôƒì‹] ‰$‰ØèæKÿÿ‰Øè¯Kÿÿ…Àu ƒÄ[]Ãt&¸RèöEÿÿ‰Â‹Eè—ÿÿƒÄ[]öU1Ò‰åW…ÔþÿÿVSì|‹] ‰•¼þÿÿ•Ðþÿÿ‰$‰ØèƒKÿÿÇ$¸@‰D$èþ¨þÿ‰…¤þÿÿ‹U‰‰ØèÌJÿÿ‰…¸þÿÿ‰Øè¿Jÿÿ‰…´þÿÿ‰Øè²Jÿÿ‰…°þÿÿ‹…Ôþÿÿƒø„½ƒø„tƒø„¾¬kD‰µ¼þÿÿ‹¼þÿÿ‹½¤þÿÿ‹…¸þÿÿ…ÛÇG‰G„̸\èEÿÿ‹W‰Ãèˆ?ÿÿ‰Øºè|?ÿÿ‹•¼þÿÿ‰ØèAÿÿ‰Øº‹<ÿÿÿƒÊ¿ÿÿ…\ÿÿÿ•Xÿÿÿ‰$‹E èº>ÿÿ…Tÿÿÿ•Pÿÿÿ‰$‹E è£>ÿÿ‹µ<ÿÿÿ‹†Ô‰$èžþÿÇ‹•dÿÿÿ‰Ã‹½ÿÿÿ…Ò‰G,…ßÇ$YmDèžþÿ‰C‹…ÿÿÿ‹X,ÇC‹…Xÿÿÿº_D‰D$ ‹…\ÿÿÿ…À‰D$uºuND‰T$Ç$tmD迟þÿ‰C ‹•ÿÿÿ1Û‹B,Ç@‹E èr=ÿÿ‹ÿÿÿƒø‰A0鉵Lÿÿÿ•Hÿÿÿ‰4$‹E èÙ=ÿÿ‹E è¡=ÿÿ‹•Lÿÿÿ‰Æ…Òu¿ D¹ º ‰½Hÿÿÿ‰Lÿÿÿ‹…Hÿÿÿ‰T$CÇ$_D‰D$è/Ÿþÿ‰D$ºd‰T$ ‰t$‹½ÿÿÿ‹G,‰$è-Ÿþÿ‹G09Ørÿÿÿ…À…‘ ¸=1Ûè~7ÿÿ‹•ÿÿÿ‰‚‹R0èê1ÿÿ‹µÿÿÿ‹~0…ÿ~Y¶¼'‹½ÿÿÿ‹—Ç$‹…<ÿÿÿè2(ÿÿ‹G,‹@‹˜C‹P‹‡èº3ÿÿ‹—‹…<ÿÿÿèI(ÿÿ9_0´‹…ÿÿÿ‹Ç$‹…<ÿÿÿèÆÇÿÿ‹•8ÿÿÿÇ_Ä [^_]Ë8ÿÿÿÇ)vÄ [^_]ËM …É„‹U ƒz[„¾ Ç$¨mDèžþÿ‰Ã‹…<ÿÿÿ1ÒèÒ@ÿÿ‰\$‹<ÿÿÿ‹Ô‰$èŠÏ‰\$¸…ID‰D$‹µ<ÿÿÿ‹†Ô‰$è ‰$èažþÿ1À‰†|étÿÿÿ‹E …Àé§úÿÿ‰D$Ç$ÌmDèŠþÿ‰Ã‹…<ÿÿÿ1Òè[@ÿÿ‰\$‹µ<ÿÿÿ‹†Ô‰$èω\$¸…ID‰D$‹†Ô‰$è˜ ‰$èðþÿ‹½8ÿÿÿÇÄ [^_]Ã=„j=ê„î‹…8ÿÿÿÇÄ [^_]Ã=3„f=”u׋E …À„ ‹U ƒz[„2"Ç$nDéÀþÿÿ=º„ä =ÿu¡‹E …À„²Ç$ˆ[Dèœþÿ‰Ã‹…<ÿÿÿ1Òèn?ÿÿ‰\$‹•<ÿÿÿ‹‚Ô‰$è&Ή\$¸…ID‰D$‹<ÿÿÿ‹Ô‰$è¥ ‰$èýœþÿ‹<ÿÿÿ1À‰ƒ|é þÿÿ=ù„=…ÿÿÿ‹} …ÿ„¶"‹U ‹Bƒøc„L%ƒød„¯"‰D$Ç$4nDèñ›þÿéëýÿÿ‹ÿÿÿ‹C…Àt ‹C$…À„p ‹µÿÿÿ‹^…Û„l‹½<ÿÿÿƒÊ ‹‡Ô‰—@‰$èšþÿ‰F,‰ÃÇÇ$Ý]D蟙þÿ‰C‹‡À1ÿÇ$ê]D‰D$‰ðƒÀ4‰D$èk›þÿ‰D$1Ò¹d‰L$ ‰T$‹F,‰$èm›þÿ‰|$1À‰D$‹F,‰$è¨ …ÀˆŸ…À„O‹µÿÿÿ¿\D‹F,‹@‹‹@‰$è™þÿ‰†˜‹F,‰$èiþÿ¸2è3ÿÿ‰†‰òƒÂ4è0ÿÿ‹†º-mDèÿ/ÿÿ‹†ºtnDèï/ÿÿ‹†1Òè2/ÿÿ‹–Ç$‹…<ÿÿÿè*$ÿÿ‹–˜‹†è¹/ÿÿ‹–‹…<ÿÿÿèH$ÿÿ‹–Ç$‹…<ÿÿÿèÐÃÿÿ‰|$‹½<ÿÿÿ‹‡Ô‰$èøËÇ‹…8ÿÿÿǯéüÿÿ‹…`ÿÿÿ‰T$Ç$}nD‰D$èšþÿ‰C‹_,ÇCéúÿÿ‹u …ö„—øÿÿ‹E ƒx<„Á‹•ÿÿÿÇBÇéØöÿÿ‹M …É„Ÿ‹•8ÿÿÿÇîé‰ûÿÿ‹E …À„£‹} ƒ…S‹…ÿÿÿÇ@(é7óÿÿ‹E …À„ž‹U ‹Bƒøc„—ƒød„ ‰D$Ç$nDè\™þÿéVûÿÿÇ$ÄnD1ÿ¾‰|$‰t$‹…<ÿÿÿ1ÒèT—ÿÿéïûÿÿ»ònD‰\$‹µ<ÿÿÿ‹†Ô‰$èÂÊ‹½ÿÿÿÇG(‹…ÿÿÿ‹X(…ÛéQóÿÿ‰$¸‰D$èÔ”þÿ‰…,ÿÿÿ‰\$‰D$‰4$è”þÿöÐGE„L‰$1À‹•,ÿÿÿèá%ÿÿ‹,ÿÿÿ‰ $èS™þÿéØõÿÿÇ$»@‰\$èy”þÿ‹µ<ÿÿÿ‰Ã‰†ì‰0‰ðèâ$ÿÿ‰C¸Zèõ0ÿÿ‹½ÿÿÿºoD‰‡è-ÿÿ‹†ì‹P‹‡èK+ÿÿ‹†ìÇ@,@‹†ì‹P,‹‡è*+ÿÿ‹‡º@è+ÿÿ‹—‰ðè½ÿÿ‹…8ÿÿÿÇ´é¼ùÿÿ‹•<ÿÿÿ1ɉŠ)‹ÿÿÿ‹ …À…V ‹µÿÿÿ‹†¼…À…5 Ç$ Ò@芯‹½<ÿÿÿº°A‰‡è¸@šA‰‡€)‹‡‰—´)…À„€1À‰‡ì‹µ<ÿÿÿ¸ŽA¿ “A»€”A¹šA‹–쉆¼)¸ŽA…Ò‰†¸)¸€A‰†À)¸‘A‰†Ä)¸à’A‰†¬)‰¾°)‰žÈ)‰Ž¨)t‹†ð…Àu‹†|"…À…P‹•<ÿÿÿ‹…<ÿÿÿÂèèËÿÿ‹<ÿÿÿ‹ƒì…Àt:‹‹ð…Éu‹“P …Ò…ó…Àt‹µ<ÿÿÿ‹Žð…Éu‹– …Ò„> ‹<ÿÿÿ¿¾‰»Ì‰³Ð…À„®‹µ<ÿÿÿ‹žð…Û…«€¾Ø„ž‹½ÿÿÿ1ɉóÃØ‰¶†Ø„À„åˆÁ‰ÿÿÿëC¶ „É•À1Ò€ù •Â…Ðuë€ù ‰Þ„( ‰ÿÿÿ„ÉëC€;uú¸bCèr.ÿÿ‹<ÿÿÿ‹•ÿÿÿ‰‚‹‘ì‹RèÒ(ÿÿ‹½ÿÿÿº oD‹‡èÜ*ÿÿ‹‡ºè*ÿÿ‹‡è1*ÿÿ‹•ÿÿÿ‹‡)Ö‰4$‹•ÿÿÿèÕ*ÿÿ‹‡‹•ÿÿÿè”*ÿÿ‹—‹…<ÿÿÿèÿÿÿ‡¶ „É…ÿÿÿ‹•ÿÿÿ1ÿ‹‚‰D$¸ oD‰D$‹<ÿÿÿ‰ $èiÿÿ‹ÿÿÿ‹ƒ‰»…À‰ƒ `ôÿÿ‹ÿÿÿ‹‘9„K%…Ò…"¹,oD‰L$‹µ<ÿÿÿ‹†Ô‰$èpƉðºPoDè¤"ÿÿ‹†ì…À„ç‹<ÿÿÿ‹ð…À…Ó‹<ÿÿÿ‹»0…ÿ„M‹³Œ‹› ¸bèø,ÿÿ‹•ÿÿÿ‹<ÿÿÿ‰‚‹‘ì‹RèX'ÿÿ…ö…;€;„•‹½ÿÿÿº~oD‹‡èQ)ÿÿ‹‡ºè‘(ÿÿ‹‡‰Úè4)ÿÿ‹ÿÿÿ‹…<ÿÿÿ‹“è­}ÿÿ‹µ8ÿÿÿǺé¬õÿÿ¸ƒoD‰D$‹•<ÿÿÿ‹‚Ô‰$èoÅ‹<ÿÿÿ¸‰‹ …À…;‹<ÿÿÿ‹»…ÿ…‹µ<ÿÿÿ‹F…À…7‹½<ÿÿÿ‹‡ì…Àt ¸‰‡È‹…8ÿÿÿÇãéõÿÿ‹E è1ÿÿ‹½<ÿÿÿ‹Ÿì;C„ Ç$œoDè&“þÿ‰Ã1Ò‰øèû5ÿÿ‰\$‹‡Ô‰$è¹Ä‰\$¸…ID‰D$‹‡Ô‰$è>‰$è–“þÿ1À‰‡|é©ôÿÿ‹…ÿÿÿ‹•<ÿÿÿÇ@Ç@(‹’|…Ò…Hìÿÿ¸è7+ÿÿ‹ÿÿÿºÎoD‰èÁ'ÿÿ‹ÿÿÿ‹…<ÿÿÿ‹“è:|ÿÿ‹µ8ÿÿÿÇ0é9ôÿÿ1ÿ1ö‰|$‰t$‹•ÿÿÿ‹B,‰$è¼…Àˆ× …À…Bóÿÿ‹•ÿÿÿ‹B,‰$è›”þÿÇ$*]D¸1Ò‰D$¸ ‰D$‹…<ÿÿÿè%ÿÿ‹8ÿÿÿÇéÄóÿÿ=ã…Öôÿÿ‹} 1À‹•ÿÿÿ…ÿ‰‚„ü‹u ‹FÇ$eD‰D$躑þÿ‰Ã‹…<ÿÿÿ1Òè‹4ÿÿ‰\$‹½<ÿÿÿé…þÿÿ=>…~ôÿÿ‹M …É„>‹8ÿÿÿÇ>éEóÿÿ‰\$‹½,ÿÿÿ‰|$‹•<ÿÿÿ‹‚Ô‰$è“éøÿÿÇ$ÜoDé ôÿÿ¸èÈ)ÿÿ‹ÿÿÿº-mD‰èR&ÿÿ‹ÿÿÿ‹…<ÿÿÿ‹“èËzÿÿ‹µ8ÿÿÿÇ;éÊòÿÿ‹…<ÿÿÿ€¸”„IøÿÿÇ$¸@‰D$èÂŒþÿ‹•<ÿÿÿ‰Ã‰‚쉉Ðè+ÿÿ‰C‹<ÿÿÿ‹”‰ $‰ËÔ‰D$ ¸üoD‰D$‰\$èÛÿÿ¸Zè)ÿÿ‹µÿÿÿº6pD‰†è›%ÿÿ‹½<ÿÿÿ‹‡ì‹P‹†èa#ÿÿ‹‡ìÇ@,@‹‡ì‹P,‹†è@#ÿÿ‹†º@è0#ÿÿ‹†‰ÚèC%ÿÿ‹—”‹†è#ÿÿ‹†ºWDè"%ÿÿ‹†1Òèõ"ÿÿ‹–‰øè˜yÿÿ‹…8ÿÿÿÇ”é—ñÿÿ‹M …É„‹•8ÿÿÿÇ~é{ñÿÿ‹E …À„¸‹E ƒx<„ ïÿÿ‹•ÿÿÿÇBƒx3„ó‹ÿÿÿÇÇC$égìÿÿÇ‹µ<ÿÿÿƒÊ@¸2‰–@èÕ'ÿÿ‰ƒ‰ÚƒÂ4èe$ÿÿ‹ƒº-mDèU$ÿÿ‹ƒºCpDèE$ÿÿ‹ƒºuNDè5$ÿÿ‹ƒºuNDè%$ÿÿ‹“‰ðè¨xÿÿ‹½8ÿÿÿÇîé§ðÿÿ‹] …Û„:‹U ƒz<„¢‹ÿÿÿÇA‹µÿÿÿ‹¾È…ÿ„• ÇF ÇFéŽëÿÿ‹E …À„ï ‹] 1Àƒ{<éáêÿÿ‹u …ö„zúÿÿ‹} ‹Gƒøc„|úÿÿƒød…Ï ‹…<ÿÿÿ‹˜0…Ûu‹ˆ …É…FÇ$XpDè%Žþÿé–ðÿÿ‹E …À„¨ ‹M ‹Aƒøc„’ƒød„ª‰D$¿…IDÇ$€pDèèþÿ‰Ã‹…<ÿÿÿ1Òè¹0ÿÿ‰\$‹µ<ÿÿÿ‹†Ô‰$èq¿‰\$‰|$éíïÿÿ‹E …À„> Ç$ˆ[DèþÿéÞûÿÿ…|ÿÿÿ•xÿÿÿ‰$‰Øèâ+ÿÿ‰Øè«+ÿÿ…À…ó ‹…Òt2Bþƒø‡Wƒú„½¸¾pD‰D$‹½<ÿÿÿ‹‡Ô‰$è뾋…|ÿÿÿ1Û‹•xÿÿÿ‰$¸OmDèðMÿÿ‹½ÿÿÿ‹•xÿÿÿ‰G‹…|ÿÿÿ‰$¸tnDèÎMÿÿ‰G‹…<ÿÿÿ‹¸„…ÿ…‘ ‹•ÿÿÿ‰ZéJêÿÿ‹ÿÿÿ¿ ‹C,‰$è3þÿ‰|$¸1Ò‰D$Ç$*]D‹…<ÿÿÿèŠÿÿ‹µ8ÿÿÿÇéaîÿÿ‹…<ÿÿÿ»‰˜Èé¿üÿÿ‰$¾ ‰t$èú¶ÿÿéÙøÿÿ‹ä‰D$‹à‰ $‰D$èIˆÿÿ餸ÿÿ‰$1Û1ɉ\$ 1Ò‰L$‰T$èÊnþÿéªøÿÿ‹} …ÿ„Ÿ‹½8ÿÿÿÇêéÙíÿÿƒÊ¾hZD‰‘@‹ƒÌ‰t$‰ $‰D$è5ÿÿ‹µÿÿÿ‹½ÿÿÿ‹žÀ¶ ¶CÁáÁà Á¶CÁà Á¶C Á‰Žàs ‰À‰·Ô¶SƒÃ¶FÁâÁà ¶FÁà ¶F‰ŸØ ‰—ä¶¶AÁâÁà ¶AÁà ¶AƒÁ‰Ü ÂщÀ¸2‰—èèÀ#ÿÿ‰‡‰úƒÂ4èP ÿÿ‹‡º-mDè@ ÿÿ‹‡ºOmDè0 ÿÿ‹‡1Òèsÿÿ‹‡èˆÿÿ‹—؋䋇‰ $è. ÿÿ‹‡ècÿÿ‹—Ô‹‡‹à‰ $è ÿÿ‹—‹…<ÿÿÿèXtÿÿÇ‹…8ÿÿÿǺéQìÿÿ‰$è)‹þÿé¾òÿÿ‰$è‹þÿ‹ÿÿÿ‹ƒ°‰$è‹þÿé‰òÿÿ‰ð¿–܉¾Ø»–¹­eD‰žÜ‰D$ ƒè‰D$à‰L$‰$è-L¸bè›"ÿÿ‹–싽ÿÿÿ‹R‰‡èÿÿ‹‡ºØpDèÿÿ‹‡ºèQÿÿ‹‡‰ò˜èîÿÿ‹–à‹‡è½ÿÿ‹–䋇è¬ÿÿ‹‡1ÒèŸÿÿ‹‡1Òè’ÿÿ‹‡èÿÿ‹‡‰òÂØÇ$ A‰D$‰ðè7ÿÿ‹‡º€è÷ÿÿ‹–Ü‹‡èFÿÿ‹‡ºèÖÿÿ‹–Ø‹‡è%ÿÿ‹‡ºàpDÇ$è^ÿÿ‹—‰ðè±rÿÿº‰–‹…8ÿÿÿÇDé¥êÿÿC¶ éÏòÿÿ‹…<ÿÿÿº8fDè¬ÿÿ‹½<ÿÿÿ¸‰‡Ì¸‰‡Ð‹‡ìé òÿÿ¸d‰D$‹…<ÿÿÿ؉D$‹µÿÿÿƒÆ4‰4$èÜI‹½ÿÿÿƇ—¡ÐGE¨u¨„¨ãÿÿ‰t$Ç$âpDè>ˆþÿ‰Ã‰Â‹…<ÿÿÿèÿÿ‰$è׈þÿé|ãÿÿ‹E èê%ÿÿ‰C‹…<ÿÿÿ‹˜ì‹E ÇCÇC ÇCè¾%ÿÿ‰C$‹•<ÿÿÿ‹E ‹šìè§%ÿÿ‰C(‹<ÿÿÿ‹ìƒÀ‰$è­‚þÿ‹<ÿÿÿ‹ƒì‰D$‹ƒè‰$详‹ƒÔ‰$èa¶ºùpD‰T$‹ƒÔ‰$è*¹1À‰ƒðéûïÿÿ‹<ÿÿÿ»‰™ÈéÑõÿÿ…À»qDu»5qD‰\$¿d‹<ÿÿÿ‹Ô‰$èܸ‹…<ÿÿÿ‰Úèÿÿ‹…<ÿÿÿºX_Dèÿÿÿ…Dÿÿÿ•@ÿÿÿ‰$‹E èX%ÿÿ‹<ÿÿÿ‹ƒÔ‰$èD…þÿÇ‹µÿÿÿ‰Ã‰F,Ç$RqDèׄþÿ‰C‹…@ÿÿÿ‹^,‰D$‹…DÿÿÿÇ$_D‰D$衆þÿ‰C ‹F,1ÛÇ@Ç$dqDè–„þÿ‰D$1Ò¹d‰L$ ‰T$‹F,‰$舆þÿÇ$ŸqDèl„þÿ‰D$‰|$ ‰\$‹F,‰$èe†þÿÇ$´qDèI„þÿ‰D$¹d1Ò‰L$ ‰T$‹F,‰$è;†þÿ1ÿ1ö‰|$‰t$‹½ÿÿÿ‹G,‰$èn÷…Àxr…À„È ‹µÿÿÿ‹^,‹C‹‹@€8…g ‹C‹P‹H‹B‰D$‹A‰$èõG…ÀtG‹…<ÿÿÿºËqDè™ÿÿ1ÿ1ö‰|$‰t$‹½ÿÿÿ‹G,‰$èüö…ÀyŽ‹…<ÿÿÿ»‰˜Èé¨ëÿÿ¸2èøÿÿ‹½ÿÿÿ‰úƒÂ4‰‡è‚ÿÿ‹‡º-mDèrÿÿ‹‡ºtnDèbÿÿ‹‡ºè¢ÿÿ‹—Ç$‹…<ÿÿÿèšÿÿ‹—˜‹‡è)ÿÿ‹G,‹@‹@‹P‹‡èÿÿ‹G,‰$èG‡þÿ‹—‹…<ÿÿÿè–ÿÿ‹—Ç$‹…<ÿÿÿè®ÿÿ¸äqD‰D$‹•<ÿÿÿ‹‚Ô‰$èA¶‹8ÿÿÿÇ3éPæÿÿ‰D$Ç$øqDèp„þÿéÎçÿÿ…ö5‹…<ÿÿÿ‹ÿÿÿ‹ˆ$(‹€((‰M€‰ƒÄ‹ÿÿÿ…ɉ‹¼„¬ ƒ»ÄŽÚ€y „˽ÿÿÿ‹G(éQÞÿÿ‹½ÿÿÿ‹‡Ì@;‡Ð‰‡ÌŒíàÿÿÇG éáàÿÿ‹•<ÿÿÿ‹‚܉D$ ‹‚؉$‰D$¸¨dD‰D$è ÿÿ‹<ÿÿÿ‹ìé-íÿÿ¸údD]ˆ‰D$‹†Ô‰$è8µ‹†#uȉ\$‰D$¸@‰D$ ¸‰D$‰4$èÍ*‹½<ÿÿÿ‰‡DÇ€"‰½ÿÿÿ‰|$‰$è‰,¸bè¿ÿÿ‹<ÿÿÿ‹•ÿÿÿ‰‚‹‘ì‹Rèÿÿ‹½ÿÿÿº5rD‹‡è)ÿÿ‹‡ºèiÿÿ‹‡1Òè\ÿÿ‹‡‰òèÿÿÿ‹—Ç$‹…<ÿÿÿèG ÿÿ‹‡‰ÚèÚÿÿ‹—‹…<ÿÿÿèi ÿÿ‹…ÿÿÿ‰$è[-‰Â‹‡èŽÿÿ‹—‹…<ÿÿÿè-lÿÿ‹•8ÿÿÿÇùé,äÿÿè‡î…À…W ‹ÿÿÿ‹A(é‰Üÿÿ‰4$è)ÉD$¸œ`D‰D$‹…<ÿÿÿ‰$èn ÿÿ‰4$èÖƒø‰Ã„¤ ‰$èc‰D$¹À`D‰L$‹½<ÿÿÿ‰<$è8 ÿÿ‰$è@‰4$‰ÃèÆÂ‰D$‰\$Ç$ä`DèÂþÿ‰Â‰Ã‰øè§ÿÿ‰$è_‚þÿ‹…ÿÿÿ1Ò‰ é©Ûÿÿ‹•ÿÿÿƒÀ 1ɉ‚À‰ŠÌéƒÞÿÿ‹…<ÿÿÿº@rDè`ÿÿ¸drD‰D$‹µ<ÿÿÿ‹†Ôéôÿÿ‹…|ÿÿÿ‹•xÿÿÿ‰$¸CpDè Bÿÿ…À„Nôÿÿ»éDôÿÿ‰t$‰\$‹ÿÿÿ‹A,‰$è‚ò…Àˆ‚ûÿÿ‹<ÿÿÿ1Ò‰“Èéýúÿÿ…öD‹…<ÿÿÿ‹ÿÿÿ‹$(‹€((‰•tÿÿÿ‰ƒð‹µÿÿÿ‹†ü‰–‰$èaþÿ‹†…À„ññÿÿ€x„ Ç$„YDè€þÿ‰Ã‹…<ÿÿÿ1Òè^#ÿÿ‰\$‹•<ÿÿÿ‹‚Ô‰$貉\$¸…ID‰D$‹<ÿÿÿ‹Ô‰$è•ï‰$èí€þÿ‹8ÿÿÿÇéüáÿÿ»„rD‰\$‹<ÿÿÿ‹Ô‰$迱öÐGE…— ‹µÿÿÿ1Û‹Ž¨…É…½ ‰\$…pÿÿÿ‰D$‹…<ÿÿÿp ‰$è{鉅(ÿÿÿ…Ût"‰$èA‰D$1ɉL$‰$èA‰$èO€þÿ½(ÿÿÿ E‹•(ÿÿÿ”À…Ò” Ш„i …Ût½(ÿÿÿ Eº¡rD„% ‹…<ÿÿÿº´rDèD ÿÿ‹•pÿÿÿ‹…<ÿÿÿè3 ÿÿ‹…<ÿÿÿºÑrDè# ÿÿé1Üÿÿ‹½8ÿÿÿÇéíàÿÿöÐGE…× ¸2è–ÿÿ‹µÿÿÿ‰†ƒÆ4‰òè ÿÿ‹½ÿÿÿº-mD‹‡è ÿÿ‹‡ºOmDèúÿÿ‹‡ºè:ÿÿ‹‡èOÿÿ‹—؋䋇‰ $èõÿÿ‹‡è*ÿÿ‹—Ô‹‡‹à‰ $èÐÿÿ‹<ÿÿÿ‹‡‹<ÿÿÿ‹‘¸‹ÊJÿ‰ì€{Py Jû‰ì‹µÿÿÿ‹†àƒÀD‰†ô¸‰D$‹†ôƒÀ‰$èùyþÿ¾–÷‰†üˆ‹–ü¿†öˆB‹†ô‹–üÁøˆB‹–ü‹†ôˆB‹†üH‰ŽøÆ@ ‹–ø¾†ãJ‰ŽøˆB‹–ø¿†âˆB‹†à‹–øÁøˆB‹–ø‹†àˆB‹Žø‹–Ô‹†àƒÁ‰Žø‰D$‰T$‰ $èÁ>‹†ø‹ŽàÁ¾†ï‰Žøˆ‹–ø¿†îˆB‹†ì‹–øÁøˆB‹–ø‹†ìˆB‹½<ÿÿÿ‹–ø€PJ‰ŽøxJ¾‡»ˆB‹–ø¿‡ºˆB‹‡¸‹–øÁøˆB‹–ø‹‡¸ˆB‹ŽøƒÁ‰Žø‹<ÿÿÿ‹•<ÿÿÿ‹ƒ¸‰ $˜‰T$‰D$èæ=‹µÿÿÿ‹‹¸‹†‹¾ø‹‹@ùƒêƒÀ‰Žø‰T$‰ $‰D$è«=‹†‹–ø‹ÐPû‰–øÆ@û‹†øÆ@‹†øÆ@‹†øÆ@¸pÚA‰D$‰ðð‰D$ …tÿÿÿ‰\$‰D$‹†ôƒÀ‰D$‹†ü‰$èè…À…‰‹½8ÿÿÿÇÿéjÝÿÿ‹µ<ÿÿÿ¸‰†Èéjïÿÿ‹•ÿÿÿ‹B,‰$èã}þÿÇ$º1À‰T$º…`D‰D$éCéÿÿ¾èeD‰t$‹½<ÿÿÿ‹‡Ô‰$èæ¬é?äÿÿ‹…<ÿÿÿ‹˜ ‹°ˆ…Û…¥æÿÿ‰ÃÃ é˜æÿÿƒú„Æíÿÿ‹…<ÿÿÿºØbDèáÿÿ¸ÕrD‰D$‹•<ÿÿÿ‹‚Ô‰$脬‹ÿÿÿƒ9…Šíÿÿ‹<ÿÿÿ‹ƒT …À„víÿÿÇA(é áÿÿt&‹E èhÿÿ‹½<ÿÿÿ‹Ÿì;C…Qçÿÿ‹E ¿ãrD¾èAÿÿ‰C‹…<ÿÿÿ‹˜ì‹E ÇCÇC ÇCèÿÿ‰C$‹•<ÿÿÿ‹E ‹šìèþÿÿ‰C(‹<ÿÿÿ‹ìƒÀ‰$èuþÿ‹<ÿÿÿ‹ƒì‰D$‹ƒè‰$虋ƒÔ‰$踨‰|$‹ƒÔ‰$膫‰³ðéYâÿÿ¸sD‰D$‹ƒÔ‰$èd«¸bè:ÿÿ‹“싵ÿÿÿ‹R‰†è  ÿÿ‹†º*sDè°ÿÿ‹†ºèð ÿÿ‹–‰Øè#cÿÿ‹½8ÿÿÿÇé"Ûÿÿ¾fD‰t$‹½<ÿÿÿ‹‡Ô‰$è媋‡ìéwâÿÿ‹½ÿÿÿ1ö‹G,‰$è‡{þÿ‹Ÿ˜‰$èi:‰D$‰t$‰$èa:‹‡˜‰$è›yþÿÇ$*]D¹º ‰T$1Ò‰L$‹…<ÿÿÿèåvÿÿé­Ûÿÿèëä…À…èþÿÿ‹<ÿÿÿ‹ƒìéïáÿÿ‹•ÿÿÿ‹‚ºEsDè¼ ÿÿ‹ÿÿÿº‹èö ÿÿémäÿÿ‹ž˜‰$èÃ9‰D$1À‰$‰D$è¹9‹†˜‰$èóxþÿ‹F,‹@‹‹@‰$è@vþÿ‰†˜‹^,éJòÿÿ‹•tÿÿÿéL÷ÿÿ‹…ÿÿÿÇ@éœÑÿÿ‹µÿÿÿºKsD‹†è ÿÿ‹†ºè_ ÿÿ‹†éÉãÿÿ‹<ÿÿÿ‹ì…À…Û‹µÿÿÿ1Û‹Ž…Éu éIäÿÿè$½ÿÿC‰\$‹½<ÿÿÿ‹‡è‰$èû–…ÀuÞé"äÿÿ‹ÿÿÿ‹C(é¼Ñÿÿ»ÓdD‰\$‹•<ÿÿÿ‹‚Ô‰$è©‹<ÿÿÿÇALéSàÿÿ‰D$Ç$XsDè5wþÿé“Úÿÿ‹µÿÿÿÿ†ékÖÿÿ‰t$‰\$‹ÿÿÿ‹A,‰$èvè…Àˆmêÿÿ‹<ÿÿÿ1Ò‰“Èé»Ûÿÿº”sD‰T$‹€Ô‰$脨‹<ÿÿÿ¸‰0é,âÿÿ»ÏeD‰\$‹•<ÿÿÿ‹‚Ô‰$èQ¨‹<ÿÿÿ‹ìÇAHéÖßÿÿ¸ÀsD‰D$‹<ÿÿÿ‹Ô‰$è¨éëæÿÿE„‰D$‹…ÿÿÿ°‰D$ ‹…ÿÿÿ¤‰D$‹…ÿÿÿ‰4$¬‰D$è;ê‹•ÿÿÿ…À‰‚ „#‰4$1ÿ‰|$è)ì‹ÿÿÿ‰¨éÐÿÿº¸]D‰T$‹<ÿÿÿ‹ƒÔ‰$è‹§‹µÿÿÿ¸pÚAƆ´Æ†µÆ†¶Æ†·Ɔ¸ ‰D$‰ðĉD$ E€‰D$¸‰D$‰ð´‰\$‰$èÛá…À„Eöÿÿ‹M€é)ñÿÿ‹…<ÿÿÿºìsDèKÿÿ‹ÿÿÿ‹…<ÿÿÿ‹“°è4ÿÿº tD‹…<ÿÿÿè$ÿÿé-õÿÿ‹½<ÿÿÿ‹‡Ô1ÿ‰$èysþÿ‰F,‰ÃÇÇ$íZDèsþÿ‰C‹†°Ç$[D1Û‰D$èçtþÿ‰D$ºd‰T$ ‰|$‹F,‰$èëtþÿ‰\$1ɉL$‹F,‰$è&æ…Àˆ³…À„ú‹µÿÿÿ‹F,‹@‹‹@‰$èrþÿ‰Ã‹F,‰$èðvþÿéôÿÿ‰t$‰\$‹•ÿÿÿ‹B,‰$èÒå…ÀˆÀøÿÿ‹<ÿÿÿ1Û‰™ÈécÏÿÿ‹µÿÿÿ‹F(éÎÿÿ‹…<ÿÿÿºìsDèÿÿ‹ÿÿÿ‹ƒè‹“܉$‹…<ÿÿÿè©ÿÿ‹…<ÿÿÿºÓaDèéÿÿéäôÿÿ‹E„»cD‰\$‰D$‹<ÿÿÿ‰$è&ýþÿ‰4$è¾´‹U„‰D$Ç$0cD‰T$è·sþÿ‰Ã‰Â‹…<ÿÿÿè˜ÿÿ‰$èPtþÿé¨Íÿÿ‹…<ÿÿÿºtDè{ÿÿé.æÿÿ¸^D‰D$‹½<ÿÿÿ‹‡Ô‰$襋ž‹–¶K¶CÁáÁà Á¶CÁà Á¶C Á‰L$ ‹†ƒÀ ‰D$‹†à‰D$‹†Ô‰$‰øèÿÿ‹–‰øèÆ\ÿÿÇéIäÿÿ‹…<ÿÿÿº‰ÈéÍÑÿÿ‰4$‰Ú¾èÆ$ÿÿ‹ÿÿÿ‰³éûÿÿ)ЉD$¸,tD‰D$‹…<ÿÿÿ‰$èøûþÿ‹…<ÿÿÿºPtDèˆÿÿ‹•<ÿÿÿ‹‚ìéÙÝÿÿ‹‡éƒÝÿÿ‰t$‰\$‹ÿÿÿ‹A,‰$èÓã…Àˆ`ÿÿÿ‹<ÿÿÿ1ö‰³Èéšýÿÿ‰t$‰\$‹µÿÿÿ‹F,‰$èŸã…Àˆºêÿÿ‹½<ÿÿÿ1Ò‰—ÈéÐßÿÿ‹½(ÿÿÿ…ÿ„òÿÿ¸2èŒ ÿÿ‹½ÿÿÿ‰þƒÆ4‰‡‰òèÿÿ‹‡º-mDèÿÿ‹‡ºOmDèôÿÿ‹‡ºè4ÿÿ‹•(ÿÿÿ‹‹P0‹‡èÎÿÿ‹(ÿÿÿ…lÿÿÿ‹‰D$‹A‰$ÿR ‰…$ÿÿÿ‹‡èÿÿ‹•lÿÿÿ‹‡‰$‹•$ÿÿÿè¸ÿÿ‹<ÿÿÿ‹‡‹“¸‹0òrÿ€{P‰µ ÿÿÿy ƒê‰• ÿÿÿ¹1Û‰L$‹½ ÿÿÿ‰<$èmþÿ‰Æ‹…<ÿÿÿ€xPx3¾€»»ˆ‹•<ÿÿÿ¿‚ºˆF‹‚¸ÁøˆF‹‚¸ˆF‹½<ÿÿÿ 3‹•<ÿÿÿ‹‡¸Â˜‰T$‰ $‰D$è%2‹—¸Ó‹•ÿÿÿ 3‹‚‹‹@‰ $ƒêƒÀ‰T$‰D$èó1‹ÿÿÿ‹‹ØXû; ÿÿÿ…â‹(ÿÿÿ…hÿÿÿ‹‰D$ ‹½ ÿÿÿ‰t$‰|$‹C‰$ÿR,‰Ã‹…ÿÿÿ‹‹…hÿÿÿ‰\$‰D$ ‹…lÿÿÿ‰D$‹$ÿÿÿ‰ $‹…<ÿÿÿèáÿÿ‹½$ÿÿÿ‰<$è“pþÿ‰$è‹pþÿ‰4$èƒpþÿ‹…ÿÿÿ‹‹…<ÿÿÿè|Yÿÿ‹(ÿÿÿ‹•ÿÿÿ‹AÇ‹‰$ÿRéÌÿÿ»„tD‰\$‹<ÿÿÿ‹ƒÔ‰$è-¡‹ƒìéÄÚÿÿÇ$¯tD¸Ë‰D$¸èHD‰D$è1¶QqƒÁ ¶FÁâÁà ¶FÁà ¶F‰ÿÿÿ ¸ÀtD‰“ЉD$‰T$‹½<ÿÿÿ‰<$èXøþÿ‹ƒ …À‰…ÿÿÿ„3Éÿÿ‹“Ð1À‰…4ÿÿÿƒú‰•ÿÿÿŽêü‹‹¤‰ ÿÿÿëM‹•ÿÿÿH¶P¶AÁâÁà ¶AÁà ¶Aÿ…4ÿÿÿ‹4ÿÿÿ Â9ÿÿÿT ‰•ÿÿÿŽŽ‹µÿÿÿ‹½ÿÿÿ¶¶FÁãÁà öFÁà öF Ã; ÿÿÿ‰Ÿà…wÿÿÿ‰ð‹½ÿÿÿ‰ÙƒÀ‰Æ9Ûó¦…^ÿÿÿ‹µ4ÿÿÿ¸†4(‰$èhdþÿ‰4$è€cþÿƒÄ[^]é…èt&‹C0…À„~þÿÿ‰$è-iþÿéqþÿÿ‰$èÐhþÿ†4(‰$è"dþÿ‰4$è:cþÿƒÄ[^]é?躉ðèSÿÿévÿÿÿ‰$èöhÇF\é[ÿÿÿ‰$èB éõþÿÿ‹Ft‰$ÿPéýÿÿ‹Fp‰$ÿPéøüÿÿ‹Fd‰$ÿPéßüÿÿ‹F`‰$ÿPéÆüÿÿ‹FT‰$ÿPé­üÿÿ´&U‰åWVSƒì,‹EÇEð‹U ÆEï‰Eäè‰Uà‰T$‰Eè‰D$‹u䋆H,‰$è¿gþÿ‹ž…Û…Q‹}à‹U䋇P 9‚8 t…À…Õ‹}ä‹Eà‹ŸX,T ‰$èlZþÿ‰‡X,9Øt"…Àt9‡P,‡69‡L,‡*¶‹Uà‹uä‹‚< 9†$ t ÇEðãuDÆEï‹}à‹U䋇 9‚x„ÉÇEðÿuDÆEï¸<&‰D$‹Eà‰D$‹Uè‰$ès"‹Eð…Àt‹u䋾\,…ÿt_€}ït ‹Eð‹}䉇h,ƒÄ,[^_]Ãt&iØ`ꋊd,Ëè}#)È…‹u亠ÜA‰T$‰$‰t$èv‰†`,éíþÿÿfÇE ‹Uð‰ðÇEÿÿÿÿƒÄ,[^_]éa#ÿÿ‹Uà‰ðèFKÿÿé þÿÿü‰øÂX p ¹‰Ö‰Çó¦„#ÿÿÿéÿÿÿÇEðvDéÐþÿÿÇEð*vDéþÿÿt&U‰åSƒì‹E…ÀtF‹X…Ût?‹ˆà…Ét5‹T1Û…Òu5‹ˆH‰Úƒùt1Òƒùu‹€ì…Àt‹H…É~‰Úë1Ò‰ÐZ[]Ãt&‹˜PëÃÀ‰$è­ZþÿëÞ´&U‰åSƒì‹]‹M ‹U…Ût‹C…Àt‹ƒà…Àut&¼'ƒÄ1À[]É$ÇD$ ‰T$‰L$ÿЉ]ƒÄ[]é&ÿÿÿ¶U‰åƒì‹U‹‚HƒøtlƒøtÉ1ÀÃv¡hvD¹£`E¡lvD£dE¡pvD£hE¡tvD£lE‹‚ì…ÀuJAƒøwg¡¸wD‰Í`E¡¼wD‰ÍdE¸`EÉÃföBPu“¡LvD¹£`E¡PvD£dEë¶Ç$pE¸ˆ‰D$¸0wD‰D$èñ¹ë‘Ç$ÀwD¹H"ºèHD‰L$‰T$è ¶¿U¸@‰åVSƒì‹u‰D$Ç$èZþÿ‰0‰ÃÇ@‰ðè~êþÿ‰C‹E ÇCÇC ‰C0C‰$èÜXþÿ‰\$‹†è‰$èê|ƒÄ‰Ø[^]ÃU‰åS‹M‹] ƒ¹Htº@‹ì)Ú[]é‰Gÿÿ‹X…À•À1ÒûÿžÂ…Ðu[]Ã1Àºÿÿÿÿ‰X‰È[]é† ÿÿ¶U‰åƒì8‰uø‹E‹u‰}ü‹} ‰]ô‰Eð‹‰Eì‹Eð‰|$‰D$ ¸ôwD‰D$‹Eì‰$èæþÿ‹E샸Ht}¸Zè«õþÿº6pD‰Ãè?òþÿ‹V‰ØèðþÿÇF,@‰Øº@èðþÿ‰Øº@èöïþÿ‰ú‰Øè òþÿ‹Uð‰Øèãïþÿ‰ØºWDè÷ñþÿ‰Ø1ÒèÎïþÿ‹Eì‰Ú‹uø‹]ô‹}ü‰ì]éhFÿÿ1À»¹‰D$ º‹Eð‰|$‰\$‰D$¸‰D$‹F‰L$‰T$‰D$ ‹Eì‰$èÿÿ‹]ô‹uø‹}ü‰ì]Ãt&U‰å‹E]‹@…À•À¶Àö¼'U‰å‹E]‹€ÈÃfU‰å‹U ‹Mƒút1À…Òu‹Ð]Ãt&]‹Ìô&U‰å‹U ‹E‰P]ÃfU‰å‹U ‹E‰P]ÃfU¸ÿÿÿÿ‰å‹U‹J…Éu ‹‚ô…Àx]Ãf]¸ÿÿÿÉö¼'U‰å‹E]‹€HÃfU‰å‹E]‹€0ÃU‰åWVSƒì\‹}ÇEÔ‹‡ìHƒøŽ3‹E ‹U ‹M ‹u ‹‹R‹I‹^ ‰E¼‰U¸‰M´¶¼'‹7ƒÇ‹E¼‹U 1ð‰‹ƒÇ‰E¼‹E¸1ȉB‹7ƒÇ‰E¸‹E´1ð‰B‰E´‰Ø‹ƒÇ1؉ÉB ‹E¸‹U¼ÁèÁê%ÿ‹ •ИD‹4…ДD1΋M´¶Å‹…ÐD¶Ã‰EÐ1Ö‹U¸‰ÈÁèÁê%ÿ‹ •ИD‹…ДD1ȉE̶Nj…ÐD¶E¼Áë1UÌ‹U´‹ …ÐŒD1M̶ÃÁê‹ …ДDÁë‹•ИD‹U¼1Á¶Æ3 …ÐDÁê¶E¸3 …ÐŒD¶Â‹…ДD‹ИD‹]¸1ж׋•ÐD1ضU´‹•ÐŒD‹UÐ1Ø‹•ÐŒD1ó‰]¼‹u ‰M´‹UÌÿEÔ‰N‹M‰‰Ã‰V‰F ‹ì‰U¸H;EÔ¥þÿÿ‹ƒÇ‹E¼‹u 1ȉ‹ƒÇ‰E¼‹E¸1ЉF‹ƒÇ‰E¸‹E´1ȉF‹ƒÇ‰E´‰Ø1ЉF ‰Ã‹E¼‹U´Á趀ЊDÁà‰EÈ‹E¸Áè%ÿ¶€ÐŠDÁà Eȶƶ€ÐŠDÁà Eȶö€ÐŠD‰EÄ‹E¸Á趈ЊD‰ÐÁè%ÿÁᶀЊDÁà Á¶ÇÁ부ЊDÁà Á¶E¼¶€ÐŠD‰EÀ‰ÐÁè¶ÐŠD¶Ã¶€ÐŠDÁâÁà ‹E¼¶ô¶†ÐŠD‹uÄÁà ÂÁë¶E¸Ám¼¶›ÐŠD MÀ¶€ÐŠDÁã‰E¤¶E¼ U¤¶€ÐŠDÁà ËE¸‰M¸¶Ä¶€ÐŠDÁà öE´‰U´¶€ÐŠD‰E ‹EÈ ð‰E¼‹u ‰V‹U ‰‰N Ó‰^ ‹ƒÇ1Љ‹7ƒÇ‹E 1ñ‰H‹1U´‹M´‰H‹W1Ó‰X ƒÄ\[^_]Ë] ‹E ‹U ‹‹M ‹@‰]¼‹R‹Y ‰E¸‰U´é0þÿÿt&U‰åWVSƒì|‹]ÇEÄ‹ƒìHƒøŽ‹E ‹U ‹M ‹‹R‹I‰EŒ‹E ‰U ‹U ‹@ ‰Mœ‹M ‹R‰E˜‹I‰U”‰M´&‹3ƒÃ‹EŒ1ð‹u ‰EŒ‰‹ ƒÃ‹E 1ȉF‹ƒÃ‰E ‹Eœ1ЉF‹;ƒÃ‰Eœ‹E˜1ø‰F ‹ ƒÃ‰E˜‹E”1ȉF‹ƒÃ‰E”‹E1ЉF‹UŒ‰E‹E Áê¶u˜Áè‹<•ИD%ÿ‹Uœ‹…ДD1ø‰E„¶Æ‹ …ÐD1M„‰uÀ‹Eœ‹U ÁèÁê%ÿ‹<•ИD‹…ДD‹U˜Ám˜1ø‰E¼¶Æ‹ …ÐD¶E”‹Uœ1M¼‹4…ÐŒDÁê¶E˜1u¼Ám˜‹4…ДD‹•ИD‹U”1ƶƋ<…ÐD¶E1þ‹ …ÐŒD1΋M˜Áê‰U”¶Â‹…ДD‹ ИD‹U1ȉE¸¶Æ‹ …ÐD¶EŒÁê1M¸‹<…ÐŒD¶Â1}¸‹ …ДDÁm”‰UÁm‹E”‹…ИD1Ñ‹UŒ¶Æ‹<…ÐDÁê¶E 1ù‹<…ÐŒD¶Â‹…ДD1ù‹}‹½Ð˜D1‹E ¶Ä‹<…ÐD‰E€¶Eœ1ú‰uœ‹<…ÐŒD‹E„1ú‹}À3½ÐŒD‹} ‰EŒ‰‹E¼‰w‹u¸‰E ‰G‰u˜‰W‰U‹U‰w ‰O‹‚ìÿEĉM”H;EÄßýÿÿ‹;ƒÃ‹EŒ‹M 1ø‰‹3ƒÃ‰EŒ‹E 1ð‰A‹ƒÃ‰E ‹Eœ1ЉA‹;ƒÃ‰Eœ‹E˜1ø‰A ‹3ƒÃ‰E˜‹E”1ð‰A‹ƒÃ‰E”‹E1ЉE‹Uœ‰A‹EŒÁ趀ЊDÁà‰E´‹E Áè%ÿ¶€ÐŠDÁà E´¶Æ¶€ÐŠDÁà E´¶E˜¶€ÐŠD‰E°‹E Á趈ЊD‰ÐÁè%ÿ‹U˜ÁᶀЊDÁm˜Áà Á¶Æ¶€ÐŠDÁà Á¶E”¶€ÐŠD‰E¬‹EœÁè¶ÐŠDÁâ¶E˜Ám˜¶€ÐŠDÁà ‹E”Ám”¶ô¶†ÐŠDÁà ¶E¶€ÐŠD‰E¨‹E˜¶€ÐŠDÁà‰E˜¶E”¶€ÐŠDÁà E˜‹E¶ô¶†ÐŠDÁà E˜¶EŒÁm”Ám¶€ÐŠD‰E¤‹E”¶€ÐŠDÁà‰E”¶EÁm¶€ÐŠDÁà E”‹EŒÁmŒ¶ô¶†ÐŠDÁà E”¶E ¶°ÐŠD‹E¶€ÐŠDÁà‰E¶EŒ¶€ÐŠDÁà E‹E ¶Ä¶€ÐŠDÁà E‹}°¶Eœ¶€ÐŠD‰E€‹E´ ø‰EŒ‹} u”‹u€‰‹E¬ u Á‹E¨‰O‰M  ‹E¤ E˜‹M”‰W‹E‰Uœ‹U˜‰O‰G‰W ‹ƒÃ1UŒ‹MŒ‰‹3ƒÃ1u ‹E ‰G‹ƒÃ1Uœ‹Mœ‰O‹3ƒÃ1u˜‹E˜‰G ‹1U”‹M”‰O‹s1u‹E‰GƒÄ|[^_]ËM ‹E ‹U ‹ ‹@‹R‰MŒ‹M ‰E ‹E ‹I ‰Uœ‹U ‹@‰M˜‹R‰E”‰Uéýÿÿt&U‰åWVS윋uÇEÄ‹†ìHƒøŽ;‹E ‹U ‹M ‹] ‹‹R‹I‹[ ‰E„‹E ‰U€‹U ‹@‰|ÿÿÿ‹M ‰xÿÿÿ‹] ‰…tÿÿÿ‹R‹I‹[‰•pÿÿÿ‰lÿÿÿ‰hÿÿÿ‹ƒÆ‹E„1ЋU ‰E„‰‹>ƒÆ‹E€1ø‰B‹ƒÆ‰E€‹…|ÿÿÿ1؉B‹ƒÆ‰…|ÿÿÿ‹…xÿÿÿ1ȉB ‹>ƒÆ‰…xÿÿÿ‹…tÿÿÿ1ø‰B‹ƒÆ‰…tÿÿÿ‹…pÿÿÿ1؉B‹ƒÆ‰…pÿÿÿ‹…lÿÿÿ1ȉB‹>ƒÆ‰…lÿÿÿ‹…hÿÿÿ1ø‰B‹U„‰…hÿÿÿ‹E€Áê‹•ИDÁè%ÿ‹ …ДD1Ù‹xÿÿÿ¶Ç‹…ÐD¶…tÿÿÿ1щEÀ‹…|ÿÿÿ‹U€ÁèÁê%ÿ‹…ДD‹•ИD‹•tÿÿÿ1öƋ<…ÐD¶…pÿÿÿ1û‹…ÐŒD‹…xÿÿÿ1Ó‹•|ÿÿÿÁè%ÿÁê‹<…ДD‹•ИD‹•pÿÿÿ1ǶƋ…ÐD1×¶…lÿÿÿÁ­tÿÿÿ‹…ÐŒD¶…tÿÿÿ1׋•xÿÿÿ‹…ДDÁê‰E¼‹•ИD‹•lÿÿÿ1E¼¶Æ‹…ÐD¶…hÿÿÿ1U¼‹…ÐŒD1U¼Á­tÿÿÿ‹•tÿÿÿÁ­pÿÿÿÁ­lÿÿÿ‹•ИD¶…pÿÿÿÁ­pÿÿÿ‹…ДD1ЉE¸‹•hÿÿÿ¶Æ‹…ÐD¶E„1U¸‹…ÐŒD¶…lÿÿÿ1U¸‹•pÿÿÿ‹…ДD‹•ИD1ЋU„‰E´¶Æ‹…ÐD¶E€1U´‹…ÐŒD1U´Á­lÿÿÿ‹•lÿÿÿÁ­hÿÿÿÁm„‹•ИD¶…hÿÿÿÁ­hÿÿÿ‹…ДD1ЉE°‹U€¶Æ‹…ÐD¶…|ÿÿÿ1U°‹…ÐŒD1U°¶E„‹…ДD‹…hÿÿÿ3…ИD‹…|ÿÿÿ¶Ä3…ÐD‰…dÿÿÿ¶…xÿÿÿ3…ÐŒD‹EÀ3 …ÐŒD‹E ‰M„‰‹M ‰X‰]€‹]¼‰x‰•hÿÿÿ‰X ‹E¸‰xÿÿÿ‹]´‰A‰…tÿÿÿ‹E°‰Q‹U‰Y‰A‰…lÿÿÿ‹‚ìÿEĉ½|ÿÿÿH;Eĉpÿÿÿ›üÿÿ‹>ƒÆ‹E„‹M 1ø‰‹ƒÆ‰E„‹E€1؉A‹ƒÆ‰E€‹…|ÿÿÿ1ЉA‹>ƒÆ‰…|ÿÿÿ‹…xÿÿÿ1ø‰A ‹ƒÆ‰…xÿÿÿ‹…tÿÿÿ1؉A‹ƒÆ‰…tÿÿÿ‹…pÿÿÿ1ЉA‹>ƒÆ‰…pÿÿÿ‹…lÿÿÿ1ø‰A‹ƒÆ‰…lÿÿÿ‹…hÿÿÿ1؉…hÿÿÿ‰A‹E„Á趀ЊDÁà‰E¬‹E€‹xÿÿÿ‹•tÿÿÿÁè‹pÿÿÿ%ÿ¶€ÐŠDÁà E¬¶Ç¶€ÐŠDÁà E¬¶…tÿÿÿ¶€ÐŠD‰E¨‹E€Á趀ЊDÁà‰E¤‹…|ÿÿÿÁè%ÿ¶€ÐŠDÁà E¤¶Æ¶€ÐŠDÁà E¤¶…pÿÿÿ¶€ÐŠD‰E ‹…|ÿÿÿÁ趀ЊDÁà‰Eœ‰ØÁè%ÿ¶€ÐŠDÁà Eœ¶ÅÁ鶀ЊDÁà Eœ¶…lÿÿÿÁ­tÿÿÿ‰pÿÿÿÁ­pÿÿÿ¶€ÐŠD‰E˜‰ØÁè¶ÐŠD‹lÿÿÿ¶…tÿÿÿÁ­tÿÿÿÁⶀЊDÁà ¶Njpÿÿÿ¶€ÐŠD¶›ÐŠDÁà ¶…hÿÿÿÁ㶀ЊD‰E”‹…tÿÿÿ¶€ÐŠDÁà‰…tÿÿÿ¶Á‹hÿÿÿ¶€ÐŠDÁà …tÿÿÿ¶Å¶€ÐŠDÁà …tÿÿÿ¶E„¶€ÐŠD‰EÁ­lÿÿÿ‹M„¶…lÿÿÿ¶€ÐŠDÁà ÃÁ­hÿÿÿ¶Å‹M€¶€ÐŠDÁ­lÿÿÿÁm„Áà öE€‰pÿÿÿ‹lÿÿÿ¶€ÐŠD¶›ÐŠD‰EŒÁã¶…hÿÿÿÁ­hÿÿÿ¶€ÐŠDÁà öŋ|ÿÿÿ¶€ÐŠDÁà ö…|ÿÿÿ‰lÿÿÿ‹hÿÿÿ¶€ÐŠD¶›ÐŠD‰EˆÁã¶E„¶€ÐŠDÁà öŶ€ÐŠDÁà Éhÿÿÿ‹M¨‹]¬¶…xÿÿÿ‹}  ˉ]„‹M ¶€ÐŠD‰‹]¤ û‰Y‹Mœ‹}”‰]€‹]˜ ú‰•xÿÿÿ Ù‹] ‰|ÿÿÿ‰S ‹U •tÿÿÿ‰K‹tÿÿÿ‰K‹]Œ‹M pÿÿÿ‹]ˆ lÿÿÿ‹•pÿÿÿ‰Q‹•lÿÿÿ‰Q …hÿÿÿ‹hÿÿÿ‰Y‹ƒÆ1E„‹E ‹U„‰‹1M€ƒÆ‹]€‰X‹ƒÆ1•|ÿÿÿ‹|ÿÿÿ‰H‹ƒÆ1xÿÿÿ‹•xÿÿÿ‰P ‹ƒÆ1tÿÿÿ‹M ‹tÿÿÿ‰X‹ƒÆ1…pÿÿÿ‹•pÿÿÿ‰Q‹1lÿÿÿ‹…lÿÿÿ‰A‹V1•hÿÿÿ‹hÿÿÿ‰YÄœ[^_]ËM ‹] ‹E ‹U ‹ ‹[‹@‹R ‰M„‹M ‰]€‹] ‹I‰…|ÿÿÿ‹E ‰•xÿÿÿ‹U ‰tÿÿÿ‹[‹@‹R‰pÿÿÿ‰…lÿÿÿ‰•hÿÿÿé&ûÿÿU‰åWVSƒì\‹EÇEÔ‹Uà‰EЋ‚ìHƒøŽM‹M ‹] ‹E ‹U ‹ ‹[‹@‹z ‰MÀ‰]¼‰E¸f‹MЋEÀ‹] ‹ƒÁ1Љ‹1ƒÁ‰EÀ‹E¼1ð‰C‹ƒÁ‰E¼‹E¸1ЉC‹UÀ‹1‰E¸ƒÁÁê‰MЉø1ð‰C ‹ •ІD‰Ç‹U¸Áè%ÿ‹4…ЂD¶Æ‹…Ð~D1΋EÀ¶M¼1Ö‹U¼Áè%ÿÁê‰MÌ‹…ЂD‹•ІD‰ú1öƋ …Ð~D¶E¸1Ë‹…ÐzD‹E¼1Ó‹U¸Áè%ÿÁê‹ …ЂD‹•ІD‹UÀ1Á¶Æ‹…Ð~D‰ø%ÿÁï1Ñ‹…ÐzDÁm¸¶E¸1Ñ‹½Ð†D‰M¸‹…ЂD1ЋU¼‰]¼¶Ö‹<•Ð~D‰U´1ø¶UÀÿEÔ‹<•ÐzD1ø‹}Ì‹½ÐzD‰Ç1ò‹u ‰UÀ‰‹U‰^‰N‰F ‹‚ìH;EÔ•þÿÿ‹MЋEÀ‹] ‹ƒÁ1Љ‹1ƒÁ‰EÀ‹E¼1ð‰C‹ƒÁ‰E¼‹E¸1ЉC‰E¸‰ø‹9‹U¸ƒÁ‰MÐ1ø‰Ç‰C ‹EÀÁ趘ЋD‰øÁè%ÿÁ㶀ЋDÁà öƉú¶€Ð‹DÁà öE¼¶€Ð‹D‰EÈ‹E¼Á趈ЋD‹EÀÁè%ÿÁᶀЋDÁà Á¶Æ¶€Ð‹DÁà Á¶E¸¶€Ð‹D‰EÄ‹E¸Áè¶Ð‹D‹E¼Áè%ÿÁⶀЋDÁà ‹EÀ¶ô¶†Ð‹DÁà ‰ø%ÿÁﶀЋD‰E¤‹uÈÁm¸¶¿Ð‹D ó‹u ¶E¸Áç MÄ U¤¶€Ð‹D‰‰N‰VÁà ljU¸‹E¼‰M¼¶Ä‰E°¶€Ð‹DÁà ǶEÀ‰]À¶€Ð‹D Ç‹EЉ~ ƒEЋ‹UЃEÐ1É‹1щN‹MЋ 1M¸‹]¸‹E ‰^‹uЋN1ωx ƒÄ\[^_]ËM ‹] ‹E ‹U ‹ ‹[‹@‹z ‰MÀ‰]¼‰E¸éþÿÿU‰åWVS쌋UÇEÄ‹}‹‚ìÇàHƒøŽ1‹M ‹] ‹E ‹ ‹[‹U ‰M„‹M ‹@‰]˜‹] ‹R ‰E”‹I‹[‰U‰MŒ‰]ˆ¶¿‹ƒÇ‹E„‹u 1؉‹ƒÇ‰E„‹E˜1ȉF‹ƒÇ‰E˜‹E”1ЉF‹ƒÇ‰E”‹E1؉F ‹ƒÇ‰E‹EŒ1ȉF‹ƒÇ‰EŒ‹Eˆ‹]Œ1ЋU„‰F‰EˆÁèÁê%ÿ‹ •ІD‹…ЂD1ȉ…tÿÿÿ¶Ç‹4…Ð~D¶E1µtÿÿÿ‰EÀ‹E„‹U˜‹]ˆÁèÁê%ÿ‹ •ІD‹…ЂD1ȉE¼¶Ç‹4…Ð~D¶EŒ‹]„1u¼‹…ÐzD‹E˜1U¼‹U”Áè%ÿÁê‹…ЂD‹ •ІD1È‹M˜‰E¸¶Ç‹4…Ð~D¶Eˆ1u¸‹…ÐzD‹E”1U¸‹UÁêÁè‹4•ІD%ÿ‹…ЂD¶Å‹ …Ð~D¶E„1ó1Ë‹…ÐzD‹E1Ó‹UŒÁè%ÿ‹ …ЂDÁê‹•ІD‹U”1Á¶Æ‹4…Ð~D¶E˜1ñ‹…ÐzDÁmˆ‹uˆ1ÑÁmŒÿEĶEŒ‰MŒ‹…ЂD‹µÐ†D1‹E‰]¶Ä‹4…Ð~D‰…pÿÿÿ¶E”1ò‹4…ÐzD‹…tÿÿÿ1ò‹uÀ‰Uˆ3µÐzD‹u ‰E„‰‹E¼‰F‹u¸‰E˜‰ð‰u”‹u ‰V‹U‰F‰^ ‰N‹‚ìH;EÄÊýÿÿ‹ƒÇ‹E„‹u 1؉‹ƒÇ‰E„‹E˜1ȉF‹ƒÇ‰E˜‹E”1ЉF‹ƒÇ‰E”‹E1؉F ‹ƒÇ‰E‹EŒ1ȉF‹ƒÇ‰EŒ‹Eˆ1ЉEˆ‹UŒ‰F‹E„Á趀ЋDÁà‰E´‹EˆÁè%ÿ¶€Ð‹DÁà E´¶Æ¶€Ð‹DÁà E´‹Mˆ¶E¶€Ð‹D‰E°‹E˜Á趀ЋDÁà‰E¬‹E„Áè%ÿ¶€Ð‹DÁà E¬¶Å¶€Ð‹DÁà E¬¶Â‹U„¶€Ð‹D‰E¨‹E”Á趘ЋD‹E˜ÁèÁã%ÿ¶€Ð‹DÁà öƋU˜¶€Ð‹DÁà öÁ¶€Ð‹D‰E¤‹EÁ趈ЋD‹E”Áè%ÿÁᶀЋDÁà Á¶Æ¶€Ð‹DÁà Á¶E„¶€Ð‹D‰E ‹EŒÁmˆÁmŒÁè¶Ð‹D‹EÁè%ÿÁⶀЋDÁà ‹E”¶Ä¶€Ð‹DÁà ¶E˜¶€Ð‹D‰Eœ‹Eˆ¶€Ð‹DÁà‰Eˆ¶EŒ¶€Ð‹DÁà Eˆ‹E¶Ä¶€Ð‹DÁà Eˆ¶E”¶€Ð‹D‰…pÿÿÿ‹E´ E°‰E„‰‹E¬ E¨‰E˜‰F‹E¤ É^‰]”‹]  Ù‰N ‰M‹Mœ ʉV‰UŒ‹•pÿÿÿ Uˆ‹Mˆ‰N‹ƒÇ1]„‹E„‰‹ƒÇ1U˜‹M˜‰N‹ƒÇ1]”‹E”‰F‹ƒÇ1U‹M‰N ‹1]Œ‹EŒ‰F‹W1Uˆ‹Mˆ‰NÄŒ[^_]ËM ‹] ‹E ‹ ‹[‹U ‰M„‹M ‹@‰]˜‹] ‹R ‰E”‹I‹[‰U‰MŒ‰]ˆé ýÿÿ¶U‰åWVS쬋UÇEÄ‹}‹‚ìÇàHƒøŽ“‹M ‹] ‹E ‹U ‹ ‹[‹@‹R ‰xÿÿÿ‹M ‰tÿÿÿ‹] ‹I‰…pÿÿÿ‹E ‰•lÿÿÿ‹U ‰hÿÿÿ‹[‹@‹R‰dÿÿÿ‰…`ÿÿÿ‰•\ÿÿÿf‹ƒÇ‹…xÿÿÿ1È‹M ‰…xÿÿÿ‰‹ƒÇ‹…tÿÿÿ1ЉA‹7ƒÇ‰…tÿÿÿ‹…pÿÿÿ1ð‰A‹ƒÇ‰…pÿÿÿ‹…lÿÿÿ1؉A ‹ƒÇ‰…lÿÿÿ‹…hÿÿÿ1ЉA‹7ƒÇ‰…hÿÿÿ‹…dÿÿÿ1ð‰A‹ƒÇ‰…dÿÿÿ‹…`ÿÿÿ1؉A‹ƒÇ‰…`ÿÿÿ‹…\ÿÿÿ1ЉA‹•xÿÿÿ‰…\ÿÿÿÁèÁê%ÿ‹•ІD‹…ЂD1؉EÀ‹•dÿÿÿ¶hÿÿÿ¶Æ‹•tÿÿÿ‰]¼‹ …Ð~D‹…xÿÿÿ1MÀÁê‹4•ІD‹•`ÿÿÿÁè%ÿ‹ …ЂD¶Æ‹…Ð~D¶…dÿÿÿ1ñ1Ù‹…ÐzD‹…tÿÿÿ1Ñ‹•pÿÿÿÁè%ÿ‹…ЂDÁê‹•ІD‹•\ÿÿÿ1öƋ4…Ð~D1ó¶…`ÿÿÿ‹…ÐzD‹…pÿÿÿ1Ó‹•lÿÿÿÁè%ÿ‹4…ЂDÁê‹•ІD‹•xÿÿÿ1ƶƋ…Ð~D¶…\ÿÿÿ1Ö‹…ÐzD‹…lÿÿÿ1ÖÁè‹•hÿÿÿ%ÿ‹…ЂDÁê‰E¸‹•ІD‹•tÿÿÿ1E¸¶Æ‹…Ð~D¶…xÿÿÿ1U¸‹…ÐzD‹…hÿÿÿ1U¸‹•dÿÿÿÁèÁ­dÿÿÿ%ÿ‹…ЂDÁê‰E´‹•ІD‹•pÿÿÿ1E´¶Æ‹…Ð~D¶…tÿÿÿ1U´‹…ÐzD¶…dÿÿÿ1U´‹•`ÿÿÿ‹…ЂDÁê‰E°‹•ІD1E°‹•lÿÿÿÁ­`ÿÿÿÁ­\ÿÿÿ¶Æ‹…Ð~D¶…pÿÿÿ1U°‹…ÐzD1U°‹•\ÿÿÿ¶…`ÿÿÿ‹•ІD‹…ЂD1Љ…Tÿÿÿ‹…hÿÿÿ¶Ä‰…Pÿÿÿ‹…Ð~D¶…lÿÿÿ1•Tÿÿÿ‹…ÐzD‹EÀ1•Tÿÿÿ‹U¼3•ÐzD‹U ‰…xÿÿÿ‰‰tÿÿÿ‹E´‰Z‰pÿÿÿ‹]¸‰J‹M ‰Z‰B‰r ‹U°‰hÿÿÿ‹Tÿÿÿ‰Q‰•`ÿÿÿ‹U‰Y‰…dÿÿÿ‹‚ìÿEĉµlÿÿÿH;Eĉ\ÿÿÿeüÿÿ‹7ƒÇ‹…xÿÿÿ‹M 1ð‰‹ƒÇ‰…xÿÿÿ‹…tÿÿÿ1؉A‹ƒÇ‰…tÿÿÿ‹…pÿÿÿ1ЉA‹7ƒÇ‰…pÿÿÿ‹…lÿÿÿ1ð‰A ‹ƒÇ‰…lÿÿÿ‹…hÿÿÿ1؉A‹ƒÇ‰…hÿÿÿ‹…dÿÿÿ1ЉA‹7ƒÇ‰…dÿÿÿ‹…`ÿÿÿ1ð‰A‹ƒÇ‰…`ÿÿÿ‹…\ÿÿÿ1؉…\ÿÿÿ‰A‹…xÿÿÿÁ趀ЋDÁà‰E¬‹…\ÿÿÿ‹dÿÿÿ‹•`ÿÿÿÁè‹\ÿÿÿ%ÿ¶€Ð‹DÁà E¬¶Ç¶€Ð‹DÁà E¬¶…hÿÿÿ¶€Ð‹D‰E¨‹…tÿÿÿÁ趀ЋDÁà‰E¤‹…xÿÿÿÁè%ÿ¶€Ð‹DÁà E¤¶Æ¶€Ð‹DÁà E¤¶Ã¶€Ð‹D‰E ‹…pÿÿÿÁ趀ЋDÁà‰Eœ‹…tÿÿÿÁè%ÿ¶€Ð‹DÁà Eœ¶Å¶€Ð‹DÁà Eœ¶Â‹xÿÿÿ¶€Ð‹D‹•tÿÿÿ‰E˜‹…lÿÿÿÁ趀ЋDÁà‰E”‹…pÿÿÿÁè%ÿ¶€Ð‹DÁà E”¶Ç¶€Ð‹DÁà E”¶Á¶€Ð‹D‰E‹…hÿÿÿÁ趀ЋDÁà‰EŒ‹…lÿÿÿÁè%ÿ¶€Ð‹DÁà EŒ¶Æ¶€Ð‹DÁà EŒ¶Ã¶€Ð‹D‰Eˆ‹…dÿÿÿÁ趀ЋDÁà‰E„‹…hÿÿÿÁè%ÿ¶€Ð‹DÁà E„‹pÿÿÿ‹lÿÿÿÁ­dÿÿÿ¶Å¶€Ð‹DÁ­\ÿÿÿÁà E„¶Â¶€Ð‹D‰E€‹…`ÿÿÿÁ­`ÿÿÿÁè¶Ð‹D¶…dÿÿÿÁⶀЋDÁà ¶Ƕ€Ð‹DÁà ¶Á‹hÿÿÿ¶€Ð‹D‰…|ÿÿÿ‹…\ÿÿÿ¶€Ð‹DÁà‰…\ÿÿÿ¶…`ÿÿÿ¶€Ð‹DÁà …\ÿÿÿ¶Å‹M¨¶€Ð‹DÁà …\ÿÿÿ¶Ã‹]¬¶€Ð‹D ˉxÿÿÿ‹M ‹u  …\ÿÿÿ‰‹]¤‹…\ÿÿÿ ó‹u‰Y‹Mœ‰tÿÿÿ‹]˜ Ù‰pÿÿÿ‹] ‰K‹M” ñ‰K ‹]Œ‹u€‰lÿÿÿ‹Mˆ ˉhÿÿÿ‹M ‰Y‹]„‰A ó‹µ|ÿÿÿ‰Y‰dÿÿÿ ò‰Q‰•`ÿÿÿ‹ƒÇ1•xÿÿÿ‹xÿÿÿ‰‹1…tÿÿÿƒÇ‹E ‹•tÿÿÿ‰Q‹ƒÇ1pÿÿÿ‹pÿÿÿ‰X‹ƒÇ1•lÿÿÿ‹lÿÿÿ‰H ‹ƒÇ1hÿÿÿ‹•hÿÿÿ‰P‹ƒÇ1dÿÿÿ‹M ‹dÿÿÿ‰X‹1…`ÿÿÿ‹•`ÿÿÿ‰Q‹_1\ÿÿÿ‹…\ÿÿÿ‰AĬ[^_]ËM ‹] ‹E ‹U ‹ ‹[‹@‹R ‰xÿÿÿ‹M ‰tÿÿÿ‹] ‹I‰…pÿÿÿ‹E ‰•lÿÿÿ‹U ‰hÿÿÿ‹[‹@‹R‰dÿÿÿ‰…`ÿÿÿ‰•\ÿÿÿéûÿÿv¼'U‰Ñ‰åWVSƒì<ƒú‰Eð•À1Òƒù‹] •Â…Ðt ƒù …aƒû•À1Òƒû•Â…Ðt ƒû …(…ۉ؈ډljÊÁÿ…ɈËEðÁú9ú‰Uä‰è‰ÐŒ ƒÀƒ}ä‹Uð‰Eà‰‚ì„ ƒ}ä„—ƒ}ä„«ÇEè‹Eà‹]äÇEì@¯ÃƒøŽá‰EÜë@‹M‹Eì‹]ì¶¶DÁâÁà ¶D™Áà ¶D™ÿEì ‹Eð‰˜‹Eì9EÜŽœ9}ì|»‹Uì‹Mð‰Ð‹t‘ü™÷ÿ…Ò…’‰ð‰ñÁè%ÿ¶Õ‹M趀ЊD‰óãÿ¶’ЊDÁЊD1ÈÁà ÐÁà¶“ЊD ÐÁà Æ‹EèƒàÀ€}èyƒð‰Eè‹Eì‹Mð)ø‹1Þ‹]ìÿEì‰4™‹Eì9EÜdÿÿÿƒ}àÇEìŒÃÇEÌ1ÿƒ}䎛‹Eà‹Mì‹Uä)ȯ‹Uð4‚‹Eì‹…Àta‹Mì9MàtY‰Ø‰ÚÁèÁê%ÿ¶Ï¶’ЊD¶€ÐŠD‰Mжˋ…ЂD‹•ІD‹UÐ1ö‚ЊD‹…Ð~D¶ÐŠD1Ó‹…ÐzD1Ó‹M̃Æ‹UðG9}䉜‚àyÿÿÿÿEì‹MäMÌ‹]ì9]àDÿÿÿƒÄ<[^_]Éø‹UðƒÀƒ}ä‰Eà‰‚ì…óýÿÿ¸PõA‰‚À¸PB‰‚Äéìýÿÿƒú”À1ÒƒÿŸÂ…Є¶þÿÿ‰ò‰ðÁê‰óÁèæÿ‰uÔ%ÿ¶²ÐŠD¶ß¶€ÐŠD‹UÔ‰]ØÁæ Æ¶ƒÐŠDÁæ Æ¶‚ЊDÁæ ÆécþÿÿƒÂé5ýÿÿƒÀéýÿÿ‹Mð¸àïA‰À¸°B‰ÄéUýÿÿ‹]ð¸`ìA¾þA‰ƒÀ‰³Äé7ýÿÿÇ$0Dº§¸]D‰T$‰D$è›õÇ$lD»¦¹]D‰\$‰L$è}õt&U‰åƒì‰T$‰$ÿÀÉÃt&¼'U‰åWV‰ÖSƒì<ö‰Åù‹E…ö‹¸È‰}Ø‹ˆÌ‰M܋ЉUà‹€Ô‰EÔ‰E䎡}Øt&1É´&¼'¶D‹¶‹ÁàÁâ ¶D‹Áà ¶D‹ Â1TØAƒù~Ô‹E‰úèJÿÿÿ1É´&‹D؉ÂÁèˆD‹Áê‹D؈‹ÁèˆD‹‹D؈D‹Aƒù~ÔƒîƒÃ…övÿÿÿ‹Eä‹}Ø‹M܉EÔ‹Uà‹E‰¸È‰ˆÌ‰Ð‹UÔ‰ÔƒÄ<[^_]ÃÇ$ŸD¿ ¾]D‰|$‰t$è+ôvU‰åWV‰ÖSƒì\ö‰Ë}…‹‡È…ö‰E´‰E؋̉MÜ‹—ЉUà‹‡Ô‰EäŽÉ´&1É´&¼'¶‹¶D‹ÁâÁà ¶D‹Áà ¶D‹ ‰T¸‰TÈAƒù~Љ<$EȉD$ÿ—Ä1É´&¼'‹TØ‹DÈ1ЉÂÁêÁ舋ˆD‹‹TØ‹DÈ1ÐÁèˆD‹‹DÈ2D؈D‹‹D¸‰DØAƒù~¼ƒîƒÃ…öNÿÿÿ‹]Ø‹MÜ‹Uà‰]´‹Eä‹]´‰Ì‰—ЉŸÈ‰‡ÔƒÄ\[^_]ÃÇ$ŸD»¹]D‰\$‰L$èÖò´&¼'U¸ð‰åƒì‰D$Ç$èÕ,þÿÉÃvU‰å]é‡1þÿ´&U‰å‹U ÇE ‹E‰Uº]éRùÿÿfU‰å‹U ÇE ‹E‰Uº]é2ùÿÿfU‰å‹U ÇE ‹E‰Uº]éùÿÿfU1ɉåV‹uS‹] v¶‹¶D‹ÁâÁà ¶D‹Áà ¶D‹ ‰”ŽÈAƒù~Ñ[^]ö¼'U‰å‹E ‹U]éüÿÿU‰å‹E ‹U]é¡ýÿÿU‰åWVSƒìL‹U‹E ö‰EĉUÀ…‹M‹™È‰Î‰]Ø‹‰Ì‰MÜ‹–ЉUà‹†Ô‹uÀ‰Eä…öŽº´&¼'‰EÔ‹E1ÿ‰UÐUȉ]ȉMÌè×ûÿÿ‹uÄt&¶‹\½ÈG¶FÁáÁà Á¶FÁà Á¶F Á‰Ø1ȉÂÁꈉÂÁèˆFˆØÁêˆV0ȈFƒÆƒÿ~µ¿‹D½Ø@…À‰D½ØuOyðƒmÀƒEÄ‹EÀ…À~‹]Ø‹MÜ‹Uà‹Eäé`ÿÿÿ‹]Ø‹MÜ‹Uà‹Eä‹u‰žÈ‰ŽÌ‰–Љ†ÔƒÄL[^_]ÃÇ$ŸD¸7¿]D‰D$‰|$è{ðvU¸ ‰åWº}ÐSìüÿÿ‰D$‹E‰$‰Øè!÷ÿÿü1À¹ó«‰$‹U‹E èÙúÿÿ‰$¸ð‰D$1À‰D$èºïÄ[_]ô&Uº ‰åW}ÐSìüÿÿ‰T$‹Eº‰$‰Øè±öÿÿü1À¹ó«‰$‹U‹E è™ûÿÿ‰$¸ð‰D$1À‰D$èJïÄ[_]ÃU‰åW1ÿVSƒì‹E‹U‹u¶ƒÆˆEó¶RˆUòë-þEó¶Mó¶Uò¶]ò¶ˆˆ¶Â‹U ¶0G;}|ζEó‹Uˆ¶EòˆBX[^_]ÃfU‰åW‰×VSìX‹uþwuÆ@1ÉÆt&¼'ˆ ‰È1Ò÷ö¶ˆ„)èþÿÿAùÿvã1ö1Éë ¶¶Âð„)èþÿÿ¶ð¶ˆAùÿˆvÚÄ[^_]ÃÇ$|žD¹&ºŒžD‰L$‰T$èyîU¸‰åƒì‰D$Ç$è…(þÿÉÃvU‰å]é7-þÿ´&Uº‰åƒì‰T$‰]ø‰uü‰ÆÇ$èM(þÿ‰Ã¸‰D$1À‰$‰D$è¬í‰\$¸‰D$‰4$è_þÿÿ‰$¸‰D$1À‰D$è€í‰$èÀ,þÿ‹]ø‹uü‰ì]öU‰åSƒì‹]‹U Ç$‰Øè…þÿÿY‰Ø[]é[ÿÿÿt&¼'U‰åSƒì‹]‹U Ç$ ‰ØèUþÿÿ‰Ø[[]é+ÿÿÿt&¼'U‰å]ÃU‰åW‰ÇVSƒì‰Ó‹E ‹U ‹M ÂÁ‰Eð‹E ‰Uì‹U  ‰Eè‹‚‹Uð1ljø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A1ß1ljó‰øÁè‰þ‰Eà‹Uð‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A ‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A1ß1ljó‰øÁè‰þ‰Eà‹Uð‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A ‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A$‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A(1ß1ljó‰øÁè‰þ‰Eà‹Uð‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A,‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A0‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A4‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A81ß1ljó‰øÁè‰þ‰Eà‹Uð‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A<‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹U ‰Eä‹Eà<‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹AD‹Q@1Æ‹E1ß1׉0‰xƒÄ[^_]ô&U‰åW‰ÇVSƒì‰Ó‹E ‹M ‹U Á‰Eð‹E ‰Uì ‰Eè‹AD1ljú‰øÁê‰Uà‹UðÁè%ÿ‰þ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A@‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A<1ß1ljó‰øÁè‰þ‰Eà‹Uð‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A8‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A4‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A0‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A,1ß1ljó‰øÁè‰þ‰Eà‹Uð‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A(‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A$‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A ‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A1ß1ljó‰øÁè‰þ‰Eà‹Uð‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A 1ß1ljó‰øÁè‰þ‰Eà‹Uð‰øÁè%ÿ‹<‚‹Eà‹U <‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹A‹Uð1ß1Ç‰ó‰ø‰þÁè‰Eà‰øÁè%ÿ‹<‚‹U ‰Eä‹Eà<‚‰ò¶Æ‹Uì3<‚‹Uè‰ð%ÿ<‚‹E ‹1ß‹Y1Ö‹U1߉2‰zƒÄ[^_]ô&U‰åW‰ÇV1öSƒìD¿E‰Uä—‰UÜ—‰Eà‡ ‰M؉EÔ‰Uе‹µ°¯D™‰EÌ÷}à‹MЋE䉱¶ ‹EÌ‹UÐÁá@1Ù‰ ²™÷}à‹Eä¶‹EÌ‹UÐÁãƒÀ1ˉ²™‹Mä÷}à‹EжÁâ1Ú‰U¼‰°‹Ũ‰Й÷}à¶1U¼‹UЋM¼‰ ²FƒþŽtÿÿÿ1ö´&‹µ°«D‹UÜ‹M؉·‹µ°§D‰²‹µ°£D‹UÔ‰±‹µ°ŸD‰²Fþÿ~ÆÇEì]è1öÇEè‹S‰|$‹Eè‰$è‘õÿÿ‹Eè‹MЉ±‹C‰D±ƒÆƒþ~Ö1ö´&‹S‰|$‹Eè‰$è^õÿÿ‹E艷‹C‰D·ƒÆþÿ~Ö1öt&‹S‰|$‹Eè‰$è.õÿÿ‹Eè‹U܉²‹C‰D²ƒÆþÿ~Ó1ö‹S‰|$‹Eè‰$èþôÿÿ‹Eè‹M؉±‹C‰D±ƒÆþÿ~Ó1ö‹S‰|$‹Eè‰$èÎôÿÿ‹Eè‹UÔ‰²‹C‰D²ƒÆþÿ~ÓƒÄD[^_]Ãt&¼'UºP‰åƒì‰T$Ç$èþÿÉÃvU¹P‰åƒì‰L$Ç$èåþÿÉÃvU‰å]é— þÿ´&U‰å‹EÇE‹U ]ézýÿÿv¼'U‰å‹EÇE ‹U ]éZýÿÿv¼'U‰å‹M S‹]¶¶AÁâÁà ¶AÁà ¶A ‰“H¶Q¶AÁâÁà ¶AÁà ¶A ‰“L[]Ãv¼'U‰åSƒì‹]Ç$ ‹U ‰ØèÕüÿÿ1À1ɺP‰ƒHƒP‰‹L‰\$‰T$‰$èzàƒÄ[]Ãt&U‰åWVSƒì,‹E‹] ¨‰Eä…ë‹E‹¸H‹°L‹Eä…ÀŽºEè‰Eà¶¶C¶ ¶SÁà Á¶CÁà Á¶CÁà Á¶C1ÏÁà ¶CÁà ¶CÁà ‹E1Ö‰ò‰D$‹Eà‰$‰øèÉòÿÿ‹}èEè‹uì‰Eà‰øˆ‰øÁèˆC‰øÁèˆC‰øÁèˆC‰ðˆC‰ðÁèˆC‰ðÁèˆC‰ðÁèˆCƒÃƒmä‹Eä…ÀRÿÿÿ‹E‰¸H‰°LƒÄ,[^_]ÃÇ$ø¯D¸‰D$¸°D‰D$è•ß¶¼'U‰åWVSƒì,‹E‹U‹} ‰EäÂP¨‰Uà…ý‹Eà‹Mä‹L…É‹˜H‰UØŽÆUèv¼'¶‰EܶGÁà EܶGÁà EܶGÁà EܶG¶wÁà Æ¶GÁà Æ¶G‰$Áà Æ‹Eà‰ò‰D$‹EÜè)öÿÿ‹Uè‹Eì1EØ1ÓUèˆÁëˆ_Áëˆ_Áëˆ_¶E؈GÁmضE؈GÁmضE؈GÁmضE؈GƒÇƒmä‹]܉uØ‹Eä…ÀGÿÿÿ‹Uà‹E؉šH‰‚LƒÄ,[^_]ÃÇ$ø¯D¾9»°D‰t$‰\$èGÞë U‰åWVSƒì,‹E‹] ¨‰Eä…ë‹E‹¸H‹°L‹Eä…ÀŽºEè‰Eà¶¶ ¶C¶SÁáÁà Á¶CÁâÁà Á¶C Á1϶CÁà ¶CÁà ¶C ‹E1Ö‰ò‰D$‹Eà‰$‰øèIðÿÿ‹}èEè‹uì‰Eà‰øÁ舉øÁèˆC‰øÁèˆC‰øˆC‰ðÁèˆC‰ðÁèˆC‰ðÁèˆC‰ðˆCƒÃƒmä‹Eä…ÀRÿÿÿ‹E‰¸H‰°LƒÄ,[^_]ÃÇ$ø¯D¸U‰D$¸°D‰D$èݶ¼'U‰åWVSƒì,‹E‹} ¨‰Eä…ý‹E‹U‹€L‹’H‰EÜ‹Eä‰Uà…À޽Uè¶7¶G¶_ÁæÁà Æ¶GÁãÁà Æ¶G ƶGÁà öGÁà öG‰$ ËE‰Ú‰D$‰ðèÀóÿÿ‹Uè‹Eì1UàUè1EÜ‹EàÁ舋EàÁèˆG‹EàÁèˆG¶EàˆG‹EÜÁèˆG‹EÜÁèˆG‹EÜÁèˆG¶E܈GƒÇƒmä‰uà‰]Ü‹Eä…ÀFÿÿÿ‹Uà‹E‰H‹U܉LƒÄ,[^_]ÃÇ$ø¯D¹qº°D‰L$‰T$èÓÛt&¼'U‰åWVSƒì,‹E‹u ¨‰Eä…û‹E‹U‹¸L‹Eä‹’H…À‰UàŽÁUè‰UÜ‹E‹U܉D$‹Eà‰$‰úGèîÿÿ¶‹Mè¶FÁãÁà öFÁà öF ÉÈ1؉ÂÁꈉÂÁèˆFˆÈ0؈F¶^Áê¶FˆVÁã‹MìÁà öFÁà öF ÃEè‰E܉È1؉ÂÁêˆV‰ÂÁèˆFˆÈ0؈FÁêƒÿˆVƒUàƒÆƒmä‹]ä…ÛEÿÿÿ‹U‹Eà‰ºL‰‚HƒÄ,[^_]ÃÇ$ø¯D¸‰D$¸°D‰D$è•ÚU‰åWSƒì‰Ã¸‰D$C‰$è’þÿ…À‰ÂtA ‰ÇAƒøvöÂtÇz‰Èt&¼'ü‰ÁÁé1À󫉃ĉÐ[_]Ãè®Ú¶U‰å‹U‹ƒøv#‹ ‚…ÉuHt&¼'‰ƒøv H‹L‚…Étð]ô&¼'U‰åƒì‰uø‹u‰]ô»‰}ü‰\$‹@‰$èÚþÿ…Àt;‹‰ÇSƒúv¨t‰xƒÆ‰Út&ü‰ÑÁéó¥‹]ô‹uø‹}ü‰ì]ÃèþÙ¶U‰åƒì‰|$‰$‹]‹‰ßÁàPƒúvöÃt Ç{‰Âü‰ÑÁé1Àó«‰]‹$‹|$‰ì]éþÿt&U‰åSƒì‹]‹M ‹Áà9È~?…ɉÈx4ÁøPÁà)Á¸Óà‹M…Ét “X[]Ãt&÷Ð!“X[]ô&AëÇèNÙ¶U‰åƒì‰uü‹u‰]ø…ö‰ðx,Áø@èþÿÿ‰t$‰Ã¸‰D$‰$èkÿÿÿ‰Ø‹uü‹]ø‰ì]ÃFëÏv¼'U‰åWVSƒì$‰Uè‹U ‰EìÇEÔƒøë‹MÔ‹]Ç‹A9ȉMÔëJ…Ò‰Uà‰Uäxië ‹}à1Û1ö‰}Ô…ÿë;f‹EÔ‹Uè‹Mä‹}ì‹‚÷$‹MÔ‹}ËEäÖ‹UÁ‹DŠ1ÒÃÖ‰\‰ó1öÿMÔyÅ‹Eä‹U‰‚H‰Eäy¦ƒÄ$[^_]ô&¼'U‰åWVSƒìD‹M ‰Eì‹EƒùÇE䋉Eè~ ‹u‹v‰uäÇE܉Ð)Ȉ ‰EÌJÁà‰UÈ‹UI‰MÄЉEÀ¶¼'ÇEà‹EÜ…Àt‹Uì‹EÜ‹MÜ‹D‚ü‰Eà1À‰DŠü‹uÜ1ÿ9uÈt‹Eì‹|°ÇEØÿÿÿÿ‹Uè9UàsL‰}ЋMÜ‹uìÇEÔ‹މ֋Uà‰Ø÷ö‰EØ‹Eä‰Ñ÷e؉Ã1ÀEЉ։ÊUÔ9òw‚9Ø‚út&ÇE¼‹}Ä…ÿë3f‹M‹EØ÷$¹‹Mì‰Ã‹E¼‰Ö1ÒËEÜÖ‰u¼‹‘9؃U¼)ØO‰‘yÍ‹uà9u¼t9‹}Ä1Û1ö…ÿë)‹M1Ò‹¹ËEÜÖ‹Uì ‹Š1ÒÃÖ‹E쉈‰ó1öOyÕÿMØ‹E…ÀtO‹EÀ…Àˆ‹MÀÁø1ö‹]ØxÁà)Á¥ÞÓãöÁ …„‰ò Úëv‹M1Ò‹¹ÃÖ‰¹‰ó1ö‰ðG ØuæÿE܃mÀ ‹UÜ9ŨþÿÿƒÄD[^_]ÃÿMØ1Ò‹Eä)ËEèÖÁ;Mè‚ñþÿÿ1À‰ÊEÐUÔ9ò‡ßþÿÿr9؃ÕþÿÿÿMØéÍþÿÿƒÀé[ÿÿÿ‰Þ1Ûésÿÿÿ¶¿Uº‰åWVSƒì<‹]‹‰T$‰Eà‰$ènþÿ‰Eì1Òë´&‹‹Mì)Ћƒ‰‘B;Uà|í‹]ì1ö‹ë t&Fƒþ ‰Ð‰ñÓà…Àyð…ötNÇEЋ]àK‰]̃û~/» )óf‹}Љñ‹E싸‹D¸ÓâˆÙÓè ‹E쉸G9}̉}ÐÚ‹]à‰ñ‹}ìÓdŸü‹U‹M ‹‹ 9Á‰Mäs‰Eä‹]三D$‰$è¶þÿ‰Eð‹}1Ò‹)Ã9Ú‰]Ð}v‹EðÇB;UÐ|ð‹U‹1Òƒø~(‹]Ћ}ð Ÿt&¼'‹])ÐB‹ƒ‰‹ƒÁ9Ðì‹}三D$‰<$èHþÿ‰Eè‹U ‹1Ò)Ç9ú‰}Ð}t&‹MèÇ‘B;UÐ|ð‹] ‹1Òƒø~(‹}Ћ]è »t&¼'‹} )ÐB‹‡‰‹ƒÁ9Ðì‹]三D$Û‰$èÖ þÿ‰Ç‹Eä‹Uè‰<$‰D$‹Eðè/ûÿÿ1É‹Uà1À‰L$‹Mì‰D$ ‰ø‰T$‰Ú‰ $èÍûÿÿ…ö„¹‹Uà‰Ø)ÐH‰EÐCÿ;EÐ~6ÇEØ ‰Ã)uض‹EЉñ‹‡‹D‡Óâ¶MØÓè ‹EЉ‡@9ÉEÐÜ‹]ä‰ñ1À‹UìÓdßüÛ‰D$ 1À‰D$‹Eà‰$‰Ú‰D$‰øèOûÿÿKÿ‰Ø‹]à‰MÐ)Ø9È2ÇEÔ ‰Ã)uÔf‹EЉñ‹‡‹D‡üÓê¶MÔÓà ‹EЉ‡H9ÉEÐ~Ü‹uäö;uà~‹uà‰ðèøÿÿÇEÐ9uЉEÜ}3‹Uäµ÷ØÐ8´&‹MÜ‹UÐÿEЋ)ЋƒÃ9uЉ|æ‹]Ü‹ƒøv‹ƒ…ÛuHt&‹U܃ø‰v H‹L‚…ÉtíÇEЋEäÀƒøë‹MÐÇA9ȉMÐî‰<$èòþÿÇEЋ]à9]Ðëv‹}ЋEì‹UàǸG9׉}Ð|è‹Mì‰ $è½þÿÇEЋ]ä9]Ðë‹}ЋEð‹UäǸG9׉}Ð|è‹Mð‰ $è‹þÿÇEЋ]ä9]Ðë‹}ЋEè‹UäǸG9׉}Ð|è‹Mè‰ $èYþÿ‹E܃Ä<[^_]ô&¼'U‰åWVSƒìL‰Ó‰Eð‹ ‹E‹U ‰Mà‰E츉Uè‰ $‰D$èP þÿ‰Eä1Éë‹‹uä)È‹ƒ‰ŽA;Mà|í‹Eä1ÿ‹ëGƒÿ ‰Ð‰ùÓà…Àyð…ÿt`ÇEÌ‹uàN‰uăþ~A» )ûë ‹EÌ‹M䉯‹‰ùÓâ‹Mä‹DˆÙÓè ‹E䉰F9uĉuÌÕ‹uà‰ù‹EäÓd°ü‹Uð‹2;uà‹uàF‰4$¸‰D$èš þÿ‰Ã1Éë t&Ç‹A9ñ|ô‹E𹋅À~T³üf‹Eð‹ˆA‰‹Eðƒê9}í‰|$ ‹Uè‰T$‹Mà‰ò‰L$‹Eä‰$‰Øèløÿÿ…ÿ„¼‹Uà‰ð)ÐHVÿ9‰ẺUÐ~7ÇEÜ )}Üt&‹MÌ‹‹‰ùÓâ‹MÌ‹D‹¶MÜÓè ‹Ẻƒ@9EЉEÌØ1À‰ùÓd³ü‰D$ ‹Eè‰D$‹Uà‰Ø‰T$‹Mä‰ò‰ $èï÷ÿÿ‹Mà‰ò‹EÐ)Ê9‰ẺUÔ3ÇEØ )}Ø‹MÌ‹‹‰ùÓê‹MÌ‹D‹ü¶MØÓà ‹ẺƒH9EÔ‰EÌ~Ø‹}ì…ÿt.ÇEÌ‹Uì‹ …É~‰ð1Ò+EÌx‹ƒ‹MÌ‹E쉈A9‰MÌ}ãÇEÌ‹Uà9UÌët&‹MÌ‹Eä‹UàLjA9щMÌ|è‹Mä‰ $èÍ þÿÇEÌ9uÌë‹EÌǃ@9ð‰EÌ|î‰]ƒÄL[^_]éŸ þÿë U‰åƒì‰]ø‹] ‰uü‹è ôÿÿ‰Æ1À‰Ú‰D$‹E‰4$è%ýÿÿ‰ð‹]ø‹uü‰ì]Éö¼'U‰åWVSƒì<‹U‹‹4‚…ö„i‹M1ö‹E‰L$‰$è“ÿÿÿ‰EÜ‹Eº‹‰T$‰Eà‰$èGþÿ‰Eèëf‹U‹Mè‹)ð‹‚‰±F;uà|êÇEä‹Eè‹ë ÿEäƒ}ä ¶Mä‰ÐÓà…Àyë‹Eä…ÀtO‹uà1ÛNƒþ~6‹Eä¿ )Çt&¼'¶Mä‹E苘‹D˜Óâ‰ùÓè ‹E艘C9Þß¶Mä‹Eà‹UèÓd‚ü‹Mྉt$1ö‰ $è›þÿ‰Eì‹UÜ‹]à‹)Ã9Þ}v¼'‹MìDZF9Þ|ñ‹UÜ‹1öƒø~)‹Mì™ë ‹MÜ)ðF‹‰‹ƒÂ9ðì‹u້\$1Ûö‰4$è$þÿ‰4$¹‰Ç‰L$èþÿ‰Eðƒþ~‰ð´&ÇŸC9Øô‹Eàº1Û‹M ¾‰TÇü‹ƒú~@‹‘…ÀˆÜ‘‰EÐët&9Ú~%‰ñ¸Óà‹MÐ……¸NyåƒmÐC9Ú¾Û‹]ä…Û„˜‹]à‹EàKtÿ9Þ~*ÇEÐ ‹Uä)UжM䋟‹DŸÓâ¶MÐÓè ‰ŸC9Þã¶Mä1Ò‹EàÓdÇü‰ÃÛ‰T$‹Uè1ɉD$‰ø‰$‰ÚK‰L$ èTôÿÿ;]à|+‹Eä¾ )Æt&¶M䋟‹DŸüÓê‰ñÓà ‰ŸK;]à}ä‹U1Û‹è8ñÿÿ;]à‰Æ}#‹Eà ‡t&¼'‹‹ƒÁ)ØC;]à‰†|øv'‹ †…Éu Hë ‰ƒøv H‹T†…Òtð‹Eà1ÛÀƒøët&ÇŸC9Øô‰<$è, þÿ‹Eà1ÛÀƒøë ‹UðÇšC9Øñ‹Mð1Û‰ $è þÿë f‹EèǘC;]à|ð‹Uè1Û‰$èã þÿë ‹MìÇ™C;]à|ð‹Eì‰$èÅ þÿ‹U܉$èjñÿÿƒÄ<‰ð[^_]Ã9ÚŽQþÿÿ‹Eà‹MàÁà‰EØɉMÔ…öyé­‰øN‹}ð‰Eðˆ™‹EØ‹Uà‹Mðø‰T$‰Â‰ $èòÿÿ1À‹Uè1ɉD$ ‹Eà‰$‹UÔ‰D$‹Eð‰L$è²òÿÿ‹M ¸‹‰ñÓà‹M )Ú…‘tœ‰<$‹Uð‹EØЋUà‰T$‹UìèÀñÿÿ1À‹Mà‹UÔ‰D$ 1À‰D$‹Eè‰L$‰$‰øè]òÿÿN‰gÿÿÿ‹M ‹C¾9ÚTÿÿÿéwýÿÿÇ$0°D»'¹A°D‰\$‰L$èÈÉUº‰å‹Mƒ9~0‹A…Àu‰ö¼'Ç‘ÿÿÿÿB9~‹‘…ÀtíH‰‘]ô&‹AH‰‘]Ë‘H‰‘]ô&¼'U‰åWVSƒì ‹E ƒÀˆ€‰Ç»Áÿ‰øèºîÿÿ‰Æë¶ÇžC9û~ô‹] ë ‰× ÝÁÿ…ɶÀ‰Êx:ƒâà)ÑÓà D¾Kƒûÿt9‹U¶B…Û‰U‰ÚyÊS¶À‰× ÝÁÿ…ɉÊyÇQëÁ‹E ƒÀéuÿÿÿ‹ƒøv)‹†…Òu"Pÿë ‰ƒúv J‹|–…ÿtðƒÄ ‰ð[^_]öUºÿÿÿÿ‰åƒì‰}ü‹} ‰]ô‹]ƒÿ‰uø~P1À¹‰ÂÁâ¶CIyñ‰ÂƒÂxD‰ÖÁþºÿÿÿÿF9ø"‹}‰Â…ÿt‰t$‰$è¾þÿÿ‹U‹M‰3)Ê‹]ô‰Ð‹uø‹}ü‰ì]ÃfPë·t&¼'U‰åS‹]‹ÁàPÿë‰Ð‰ÑÁø‹DƒƒáÓè…ÀuJ…Òyç[B]ÃU‰åƒì‹E‰$è¿ÿÿÿ‰ÂƒÂxÉÁúBÃÉPÁúBÃt&U‰åƒì‹E‰$èÿÿÿ‰ÂƒÂxÉÁúBÃÉPÁúBÃt&U1Ò‰åS‹]‹M ‹Áà9È~ …ɉÈx%‰ÂÁú•)Á‹D“ÁáÓè¶Ð[‰Ð]öA‰ÂÁú•)Á‹D“ÁáÓè¶ÐëÖU1Ò‰åS‹]‹M ‹Áà9È~…ɉÈx‰ÂÁú‰Ð‹T“Áà)ÁÓêƒâ[‰Ð]ÃA‰ÂÁú‰Ð‹T“Áà)ÁÓêƒâëáU‰åWVSƒì ‹E ‹}‰$èÙþÿÿ‰Eð‹E ‰$è›þÿÿ‰ÂÁúˆGˆ‹uðGƒîë‰t$‹E ‰ûNG‰$èÿÿÿˆƒþÿuæ‹EðƒÄ [^_]ÃvU‰åWVS‹E‹} ‹‹9؉Æ}‰Ø…Àt$t&1É9Ø‹U‹ ‚1Ò9ð‹‡9Ñr9Ñw Huà[1À^_]Ã[¸^_]Ã[¸ÿÿÿÿ^_]Ãt&U‰åWVSƒì‹E‹] ‰$èéýÿÿ)؉ƒÂˆÁú‰ÐèBëÿÿ…À‰Çtv…ۉ؈~ÇEè Áø‹M‰EðÁà‹Uð)˾)]è‹T‘…À‰]ì‰Uä~éhÿÿÿCézÿÿÿ¶¿U‰åWVSƒì,‹E‹U ‹‹‰Eì9É]è}‰Ã¸‰D$‰$èÿýÿ‰EÜ1É9Ù}=‰Ø´&¼'‹u1Ò;‹†‹}Ü1ö‰‹} ;‹4‡‹}ÜAH9Ù‰4—|Ó‰\$‹E܉Á˜؉$‰Èè*ìÿÿ‹}è‹uìt>‰uä‹}…ÿt ‹}‹9ð|@‰Eä‹EäèáéÿÿÇEà‹0‰Ç¹…ö~'‹UÜ4ÁãDü1Ò9Î|‹‰…Òt‰MàAƒè9}æ‹U‹Eà…ÒtU¹1Û1ö;MäG‰ë‹9È| ‹1ÒÃÖ‹E9| ‹ˆ1ÒÃÖ‰‹‰ó1ö…À•À1Ò;MàŸÂ…Ðt‰MàA;Mä~½‹Mà‹u܉‰4$è§þÿƒÄ,‰ø[^_]ö¼'U1À‰åƒì‰D$‹E ‰D$‹E‰$èbþÿÿÉÃU‰åWVSƒì ‹}‰<$èœéÿÿ‹‰Æë¶I‹…Û”À1Ò…ÉŸÂ…Ðuì…É~$¸ƒûëD9Ãwø‰ŽëÇŽÿÿÿÿI…ÉôƒÄ ‰ð[^_]Ãv¼'U¸‰åƒì‰t$1ö‰$‹]ètèÿÿ‰pƒþÒ‰XƒÂÇ@ ‰‹$‹t$‰ì]ÃfU‰åW1ÿVSƒì1Û‹U‹@è8èÿÿ‰Eì‹1ÉÇEä‹u ÇEè…À~R¶¿1Òñ‹EèÓ‹U9|‰Â‹E‹1ÒÁÓ‹Uè‰þ1ÿ‹Eì‰ ‹‰Ù1Û…Àt‰UäÿEè‹Eì‹Uè9}º‹Eä‹U쉃ĉÐ[^_]ô&U‰åW1ÿV1öSƒì,‹M·E ÇEì‹ ‰Eè…ɉMäެÇ$€‹Eè‹Uì‰D$1À‰T$ ‰D$è彉E؉UÜë ‹EØ÷æ‰Ó‹U؉Á‰Ø¯×ЋUܯ։ދU¤Î‰Ë‹Mä‹EèÛ‹ЉD$1ɉL$‰$‹Uì‰T$ è…½ËMìÖ‹Uè‰t$‰L$ ‰T$‰$èg½ÿM䉯‰×‹Eä…À‰ƒÄ,·Æ[^_]ô&¼'U‰åWVSƒì‹E‹U …À‰Eð‰Uì„á‰D$Ç$]°DèSþÿ‹Eì‰$èùÿÿ‰ÂƒÂˆ³‰×Áÿ…ÿŽœ‹Uì1ö‹…)û9Þ}¶¿Ç$b°DFèþÿ9Þ|ïwÿë?‰óÁëÑû‰\$‹EìÛ‰$è?ùÿÿÇ$d°D‰ñ)ÙÁáNÓøƒà¾€L°D‰D$è»þÿƒþÿu¼‹Uð…ÒtÇEg°DƒÄ[^_]éœþÿƒÄ[^_]ÿéZÿÿÿPéEÿÿÿ¸i°Déÿÿÿ´&U‰åƒì‰]ø‹]‰uü‹èšåÿÿ‰D$‹U ‰ÆÇ$‰Øè³îÿÿ‰ð‹]ø‹uü‰ì]ô&U‰åWVSƒì ‹E‰$è æÿÿ‰Ç‹E ‰$èÿåÿÿ‰Æ¡äD‰D$‰4$èlùÿÿ…Àti´&‹è)åÿÿ‰$1ɉÉL$‰ø‰òèEîÿÿ‹ƒøv‹ƒ…ÒuH¶‰ƒøv H‹Lƒ…Étð‰<$‰÷‰Þèæÿÿ‰4$¡äD‰D$èùÿÿ…ÀuŸ‰4$èçåÿÿƒÄ ‰ø[^_]ö¼'U‰åWVSƒì,‹E ‰$èLåÿÿ‰Eð‹E‰$è>åÿÿ‰Ç¡äD‰$è/åÿÿ‰Eì¡àD‰$èåÿÿ‰EèÇEä¡àD‰D$‰<$è„øÿÿ…À„´¶¿‹è9äÿÿ‹Uð‰Ã‹è-äÿÿ‰D$‰Æ‰ú‰$‹EðèJíÿÿ‹ƒøv#‹ ƒ…ÉuHt&¼'‰ƒøv H‹Tƒ…Òtð‹Mð‰ $èåÿÿ‰}ð‹Eè‰ß‹]ì‰Eì‰D$‰\$‰4$è'ùÿÿ÷]ä‰Eè‰$èÙäÿÿ‰4$èÑäÿÿ‰<$¡àD‰D$èÐ÷ÿÿ…À…Xÿÿÿ‰<$è°äÿÿ‹Uð‰$è¥äÿÿ‹Mì‰ $èšäÿÿ‹Eä…Àx ‹EèƒÄ,[^_]Ë} »‹èYãÿÿÇEà‰Æ‹>1À…ÿëF¶9Ê“À…Ò¶Àt‰]àC9|,‹M 1Ò9|‹™‹}è1É9|‹ Ÿ)Ê)Â…À‰ž÷ÑuÇ9Ê—ÀëÅ‹Eà‹U艉$èäÿÿ‰uè‹EèƒÄ,[^_]ÃfU‰åWVSƒì,‹E‰$è\õÿÿÇEð…À‰Çt&Å»Á ,)ø …\‰È÷ë‰ÈÁøÁú)‰UðÿEðº1ÿ‰T$‹Mð‰ $è0÷ýÿ‰Eä‹U¸‰D$‹‰$è÷ýÿ‰Eà‹M‹ƒøë‹U)ø‹Mà‹‚‰¹‹G9øë‹Eð‹Uä‹MðH‰EìÆD ÿvÇEè‹E1Û1ÿ‹…À~o¶¿‹Mà‰Þ1Û1Ò‹¹ÃÖ¸ ‰D$1À‰$‰D$ ‰t$èEº‹Mà…À‰¹”À¶À‰$÷ØG!Eè¸ ‰D$1À‰D$ ‰t$è6¸‰Ã‹E98ÿMìˆØ‹Uä0‹Mìˆ ‹]è…Û„bÿÿÿ…É~)Mð‰$‹Eð‰D$‰ÐȉD$èD¼‹Uà‰$èÙúýÿ‹EäƒÄ,[^_]ÃU‰å‹MV‹u S‹]ë¶¶ÁÁéF1‹•p°D1ÁKƒûÿuå[‰È^]Ãë U‰åƒì Ç$‹E ‰D$‹E‰D$è ÿÿÿÉÃU¸‰åƒì‰D$Ç$èuõýÿÇÇ@ÉöU‰åSƒì‹]…Ût"‹‰$èúýÿlj]Y[]é÷ùýÿ´&Z[]ö¿U‰åSƒì‰Ã‰T$¸‰D$‹‰$èÿÿÿ‰ƒÄ[]ô&U‰åWVSƒì ‰Ó‰Eì‹} ÇEð…ÿt ü¹‰Æó¦tY‹EØ9؉Eèë ºðDEðƒÃèŒÿÿÿºEEðèÿÿÿ9]èvü‹u칉ßó¦tϺEëÍt&1Àƒ}ð”ÀƒÄ [^_]ÃEðºðDèBÿÿÿºEEðè5ÿÿÿë‹vU‰åWVSƒì,}wöEtÇ$p´D¿r¾µ´D‰|$‰t$èò¹‹E‹@‰Â‰Eà‹EÁè@ÑèëfÁâ9Ðwù‹M‹ …ɉM䄹9Uà‚…ƒ}8‡¿‹M ‹E‰MìÁ‹Eì‰Mè9ÁvZ‹E…Àtü‹u칋}ó¦„-‹] ‹Eì9Ãs(t&¼'ü‹u츉߉Áó¦„ÙƒÃ;]ìrãƒEì‹Mì9Mèw§1ÒƒÄ,‰Ð[^_]ËM‹Eä‰Q¹‰L$‰T$‰$è öýÿ‰Eä‹U‰éPÿÿÿ‹E»‰P‰\$‰$èóýÿëÚ‹U‹Mä‹B‰ $À‰D$¸ÿ‰D$èo¸‹E…Àt8‹E‹M¶¶@ÁâÁà ¶AÁà ¶A‹M ‹AH!‹‰EäfÇPþÿÇEð‹U ‹E‰Uì‹Mì‰Uè9ʆ1ÿÿÿ‹E‹‰Eä‹Uì‹M¶‹I¶BÁãÁà öBÁà öB‹Uä‰Mà ÉÈH!÷Zfƒøÿt4t&fƒøþtLü‹U ·À‹uì¹<Âó¦tlC‹EàH‹Uä!÷ZfƒøÿuЃEì‹Mð‹UäÿEð‹Eì9Eèf‰ Z‡sÿÿÿé—þÿÿü‹u칋}ó¦uº‹E‹M‹U ‰$‹Eì‰L$èæüÿÿ…ÀuP‹M‹ ‰Mä먋E‹M‹U ‰$‹Eì‰L$èÀüÿÿ…Àu*‹E‹‰Eäë‚‹E‹U‰D$‹Eì‰$‹U èšüÿÿ…À„þÿÿºéþÿÿ‹U‹M‹Eì‰T$‹U ‰ $èpüÿÿ…Àº…îýÿÿéçýÿÿU‰åW‰ÇV1öS‰Ó‹UJƒúÿt.t&¼'‹ öƒÃ…Éxä‰ÈÁøƒá‹‡Óèƒà ÆJƒúÿuÝ[‰ð^_]öU‰åW1ÿVSƒì‰U躾D‰EìEèÇ$è‹ÿÿÿÇ$‰Æº¿DEèèuÿÿÿ‰ÃvÇ$ ‹½ÀDº‰Eä‰ð¶MäÓà‹Mä)ʈÑÓî¶Mä Æ‰Øæÿÿÿ‰uìÓàˆÑÓ뺿D ÃãÿÿÿEè‰]èèÿÿÿ‹U‰ººÀDEèÇ$ èÿÿÿ‹M‰D¹@Gƒÿ~ƒ1Ò1À‰‘„‰€ƒÄ[^_]Ãt&¼'U‰åWVSƒì‰Ó‰Uð‹uÁë1óã‰Ú1]Áâ1Uð‹M‹UðÁê1Ê·Ú1]‰ÚÁâ1Uð‹]‹UðÁë1Óã33331]ð1U‹}ð‹]Áë1ûãÿÿ1]ð‰ÚÁâ1U‹]ð‹uÑë1óãUUUU1Uð1]‹U ÑEÑEð‹‹}‹J@‹u1ß1ÎÁljò‰ùÁêÁéƒá?ƒâ?‹¶D‹•·D‰ùÁéƒá? Ú‹¸D‰ñÁéƒá? Ú‹¹D‰ùÁéƒç?ƒá? Ú‹ºD‰ñÁéƒæ?ƒá? Ú‹»D‹ ½¼D‹<µ½D Ú Ê ú1Uð‹U ‹}ð‹Z‹JD‹uð1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰ò ÙÁêƒâ?‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù1M‹U ‹}‹u‹Z‹JH1ß1ÎÁljû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒâ? Ù‹•ºD‰òÁê Ùƒâ?‹•»Dƒç?ƒæ?‹½¼D‹<µ½D Ù Ñ ù‹U 1Mð‹Z ‹}ð‹JL‹uð1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù‹U 1M‹Z‹}‹JP‹u1ß1ÎÁljò‰ûÁêÁëƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù1Mð‹U ‹}ð‹uð‹Z‹JT1ß1ÎÁljû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù‹U 1M‹Z‹}‹JX‹u1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒâ? Ù‹•ºD‰ò ÙÁêƒâ?ƒç?‹•»Dƒæ?‹½¼D‹<µ½D Ù Ñ ù‹U 1Mð‹Z‹}ð‹J\‹uð1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù1M‹U ‹}‹u‹Z ‹J`1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù‹U 1Mð‹Z$‹}ð‹Jd‹uð1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù‹U 1M‹Z(‹}‹Jh‹u1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒâ? Ù‹•ºD‰ò ÙÁêƒç?ƒâ?‹•»Dƒæ?‹½¼D‹<µ½D Ù Ñ ù1Mð‹U ‹}ð‹uð‹Z,‹Jl1ß1ÎÁljû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù‹U 1M‹Z0‹}‹Jp‹u1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù‹U 1Mð‹Z4‹}ð‹Jt‹uð1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù1M‹U ‹}‹u‹Z8‹Jx1ß1ÎÁljû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁê Ùƒâ?‹•ºD‰òÁêƒç?ƒâ? Ù‹•»Dƒæ?‹½¼D‹<µ½D Ù Ñ ù‹U 1Mð‹Z<‹}ð‹J|‹uð1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù‹] Ñ ù1Ù‹]ðÁÁ‰MðÁÉ]‹U‰ËÑë1ÓãUUUU1Uð‹}ð1]‹]Áë1ûãÿÿ‰Ú1]ðÁâ1U‹uð‹]Áë1óã33331]ð1U‹Uð‹MÁê1Ê·Ú1]‰ÚÁâ1Uð‹U‹u‹]ð‹}ðÁë1Óã‰ÚÁâ1ó1ú‰‰X[[^_]ÃU‰åWVSƒì‰Ó‰Uð‹uÁë1óã‰Ú1]Áâ1Uð‹M‹UðÁê1Ê·Ú1]‰ÚÁâ1Uð‹]‹UðÁë1Óã33331]ð1U‹}ð‹]Áë1ûãÿÿ1]ð‰ÚÁâ1U‹]ð‹uÑë1óãUUUU1Uð1]‹U ÑEÑEð‹Z<‹}‹J|‹u1ß1ÎÁljò‰ùÁêÁéƒá?ƒâ?‹¶D‹•·D‰ùÁéƒá? Ú‹¸D‰ñÁéƒá? Ú‹¹D‰ùÁéƒç?ƒá? Ú‹ºD‰ñÁéƒæ?ƒá? Ú‹»D‹ ½¼D‹<µ½D Ú Ê ú1Uð‹U ‹}ð‹Z8‹Jx‹uð1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰ò ÙÁêƒâ?‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù1M‹U ‹}‹u‹Z4‹Jt1ß1ÎÁljû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒâ? Ù‹•ºD‰òÁê Ùƒâ?‹•»Dƒç?ƒæ?‹½¼D‹<µ½D Ù Ñ ù‹U 1Mð‹Z0‹}ð‹Jp‹uð1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù‹U 1M‹Z,‹}‹Jl‹u1ß1ÎÁljò‰ûÁêÁëƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù1Mð‹U ‹}ð‹uð‹Z(‹Jh1ß1ÎÁljû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù‹U 1M‹Z$‹}‹Jd‹u1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒâ? Ù‹•ºD‰ò ÙÁêƒâ?ƒç?‹•»Dƒæ?‹½¼D‹<µ½D Ù Ñ ù‹U 1Mð‹Z ‹}ð‹J`‹uð1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù1M‹U ‹}‹u‹Z‹J\1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù‹U 1Mð‹Z‹}ð‹JX‹uð1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù‹U 1M‹Z‹}‹JT‹u1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒâ? Ù‹•ºD‰ò ÙÁêƒç?ƒâ?‹•»Dƒæ?‹½¼D‹<µ½D Ù Ñ ù1Mð‹U ‹}ð‹uð‹Z‹JP1ß1ÎÁljû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù‹U 1M‹Z ‹}‹JL‹u1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù‹U 1Mð‹Z‹}ð‹JH‹uð1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù Ñ ù1M‹U ‹}‹u‹Z‹JD1ß1ÎÁljû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁê Ùƒâ?‹•ºD‰òÁêƒç?ƒâ? Ù‹•»Dƒæ?‹½¼D‹<µ½D Ù Ñ ù‹U 1Mð‹‹}ð‹J@‹uð1ßÁÇ1Ήû‰òÁëÁêƒã?ƒâ?‹ •·D‹¶D щúÁêƒâ?‹•¸D‰òÁêƒâ? Ù‹•¹D‰úÁêƒç?ƒâ? Ù‹•ºD‰òÁêƒæ?ƒâ? Ù‹•»D‹½¼D‹<µ½D Ù‹] Ñ ù1Ù‹]ðÁÁ‰MðÁÉ]‹U‰ËÑë1ÓãUUUU1Uð‹}ð1]‹]Áë1ûãÿÿ‰Ú1]ðÁâ1U‹uð‹]Áë1óã33331]ð1U‹Uð‹MÁê1Ê·Ú1]‰ÚÁâ1Uð‹}‹M‹]ð‹uðÁë1ûã‰ÚÁâ1Ë1ò‰X‰_[^_]ÃU‰åWVSƒì,ö‰Uä‰Ã…Ñ‹E1ÿ‹°€‹ˆ„é›v¶ƒÇ¶CÁâÁà ¶CÁà ¶C Â1Ö¶C¶SÁàÁâ ¶CÁà ¶C ‹E1щò‰D$Eè‰ $èXêÿÿ‹uè‹Mì‰ðˆKÁ舉ðÁèˆC‰ðÁèˆC‰ðˆC‰ÈÁèˆC‰ÈÁèˆC‰ÈÁèˆCƒÃ;}ä‚_ÿÿÿ‹E‰°€‰ˆ„ƒÄ,[^_]ÃÇ$ÐÀD¸a¿ßÀD‰D$‰|$èŸv¼'U‰åW‰ÇVSƒì,ö‰Uä…ÿÇEØ‹E‹U‹€€‹’„‰Eà‰UÜé²t&¶7‹U¶G¶_Áæ‰T$Áà Æ¶GÁãÁà Æ¶G Ɖò¶GÁà öGÁà öG ÃEè‰$èÏóÿÿƒEØ‹Eè‹Uì1Eà1UÜ‹Eà¶UÜÁ舋EàˆWÁèˆG‹EàÁèˆG¶Eà‰uàˆG‹EÜÁèˆG‹EÜÁèˆG‹E܉]ÜÁèˆGƒÇ‹Eä9EØ‚Gÿÿÿ‹Uà‹E‰€‹U܉„ƒÄ,[^_]ÃÇ$ÐÀD¸y‰D$¸ßÀD‰D$脞¶¿U‰åƒì‰]ô‹]‰uø‰Ö‰}ü‰Ç‰$è’ýÿÿƒˆ‰òÉ$‰øèŠþÿÿ‰]‰ò‹]ô‹uø‰ø‹}ü‰ì]ébýÿÿfU‰åWVSƒì,ö‰Uä‰Ã…3ÇEà‹E‹°€‹ˆ„‹Eä9Eàƒú‹E}舉EØ‹E‰EÜ´&¼'¶¶CÁâÁà ¶CÁà ¶C Â1Ö¶C¶SÁàÁâ ¶CÁà ¶C ‹E1щò‰D$Eè‰ $è‹çÿÿ‹EØ‹Uè‰D$‹G‰$‰øèòÿÿ‹EÜ‹Uè‰D$‹G‰$‰øè]çÿÿƒEà‹uè‹O‰ðÁ舉ðÁèˆC‰ðÁèˆC‰ðˆC‰ÈÁèˆC‰ÈÁèˆC‰ÈÁèˆC‹EäˆKƒÃ9Eà‚-ÿÿÿ‹E‰°€‰ˆ„ƒÄ,[^_]ÃÇ$ÐÀD¸›‰D$¸ßÀD‰D$èÀœ´&U‰åƒì‰]ô‹]‰}ü‰Çƒ‰uø‰Ö‰$‰øèÚüÿÿƒˆ‰ò‰$‰øè¸ûÿÿ‰]‰ò‹]ô‹uø‰ø‹}ü‰ì]é°üÿÿU‰åW‰ÇVSƒì<ö‰Uä…OÇEØ‹E‹U‹€€‹’„‰Eà‹Eä9E؉U܃‹U‹E‰UÔˆ‰Eд&¶7‹UÔ¶G¶_Áæ‰T$Áà Æ¶GÁãÁà Æ¶G Ɖò¶GÁà öGÁà öG ÃEè‰$è_ðÿÿ‹EЋUè‰D$‹Eì‰$Eèè·åÿÿ‹E‹Uè‰D$‹Eì‰$Eèè/ðÿÿƒEØ‹Uè‹Eì1Uà1EÜ‹Eà¶UàÁ舋EàˆW‹UäÁèˆG‹Eà‰uàÁèˆG‹EÜÁèˆG‹EÜÁèˆG‹EÜÁèˆG¶E܉]܈GƒÇ9UØ‚ÿÿÿ‹Eà‹U‰‚€‹E܉‚„ƒÄ<[^_]ÃÇ$ÐÀDº½¸ßÀD‰T$‰D$èäš¶¿U¹ˆ‰åƒì‰L$Ç$èåÔýÿÉÃvU¸ˆ‰åƒì‰D$Ç$èÅÔýÿÉÃvU¸ˆ‰åƒì‰D$Ç$è¥ÔýÿÉÃvU¸ˆ‰åƒì‰D$Ç$è…ÔýÿÉÃvU‰å]é7Ùýÿ´&U‰åVSƒì‹] ‹u¶S¶C¶KÁâÁà ¶CÁáÁà ¶C ¶Áà ȶKÁá ȶK‰4$ Èè-ãÿÿ¶S ¶C ¶K ÁâÁà ¶CÁáÁà ¶C ¶CÁà ȶK Áá ȶK ÈŽˆ‰ $èáâÿÿ¶S¶C¶KÁâÁà ¶CÁà ¶C ¶CÁàÁá ȶKÆÁá ȶK‰uƒÄ[ È^]éâÿÿë U‰å‹M S‹]¶¶AÁâÁà ¶AÁà ¶A ‰“€¶Q¶AÁâÁà ¶AÁà ¶A ‰“„[]Ãv¼'U‰åS‹] ¶S¶C¶KÁâÁà ¶CÁáÁà ¶C ¶Áà ȶKÁá ȶK[ È]éÕáÿÿt&U‰åƒì‰]ø‹]‰uü‹u ‰$؉t$è,þÿÿ‰u ‹uü‰]‹]ø‰ì]éþÿÿ´&U‰å‹E ‹U]éÑùÿÿU‰å‹E E˜‹U]ézûÿÿv¼'U‰å‹E ‹U]éñùÿÿU‰å‹E ‹U]é¡ûÿÿU‰åWVSƒì,‹u öE…IÇEà‹E‹U‹€€‹º„‰Eä‹E9Eàƒ‹Eˆ‰U؉EÜ´&¼'‰<$‹UEèG‰T$‹Uäèªáÿÿ‹EØ‹Uè‰D$‹Eì‰$Eèè"ìÿÿ‹EÜ‹Uè‰D$‹Eì‰$Eèèzáÿÿ¶‹Mè¶FÁãÁà öFÁà öF ÉÈ1؉ÂÁꈉÂÁèˆFˆÈ0؈FÁêˆVƒÆ‹Mì¶¶FÁãÁà öFÁà öF ÉÈ1؉ÂÁꈉÂÁèˆFˆÈÁêˆV0؈FƒÆƒÿƒUä‹UƒEà9Uà‚ÿÿÿ‹E‹U䉸„‰€ƒÄ,[^_]ÃÇ$ÐÀD¸Ù‰D$¸ßÀD‰D$è‹–vU‰å‹E ‹U]é±õÿÿU‰å‹E ‹U]é±öÿÿU‰åVµXþÿÿSì°‹]¶S¶C¶KÁâÁà ¶CÁáÁà ¶C ¶Áà ȶKÁá ȶK‰4$ ÈèGßÿÿ¶S ¶C ¶K ÁâÁà ¶CÁáÁà ¶C ¶CÁà ȶK Áá ȶK Èàþÿÿ‰ $èûÞÿÿ¶S¶C¶KÁâÁà ¶CÁà ¶C ¶ÁàÁá ȶKÁá ȶK Èhÿÿÿ‰ $è°Þÿÿ‰4$‹U‹E è²øÿÿ‰4$º˜1À‰T$‰D$èó”İ[^]ÃU‰åVµXþÿÿSì°‹]¶S¶C¶KÁâÁà ¶CÁáÁà ¶C ¶Áà ȶKÁá ȶK‰4$ Èè'Þÿÿ¶S ¶C ¶K ÁâÁà ¶CÁáÁà ¶C ¶CÁà ȶK Áá ȶK Èàþÿÿ‰ $èÛÝÿÿ¶S¶C¶KÁâÁà ¶CÁà ¶C ¶ÁàÁá ȶKÁá ȶK»˜ Èhÿÿÿ‰ $è‹Ýÿÿ‰4$‹U‹E èÍõÿÿ‰\$1ɉ4$‰L$èÓ“İ[^]ÃU‰åW½HþÿÿVS켋]‹u ¶S¶C¶KÁâÁà ¶CÁáÁà ¶C ¶Áà ȶKÁá ȶK‰<$ ÈèÝÿÿ¶S ¶C ¶K ÁâÁà ¶CÁáÁà ¶C ¶CÁà ȶK Áá ȶK ÈÐþÿÿ‰ $è·Üÿÿ¶S¶C¶KÁâÁà ¶CÁà ¶C ¶CÁàÁá ȶKÁá ȶK ÈXÿÿÿ‰ $èkÜÿÿ¶¶FÁâÁà ¶FÁà ¶F ‰•Èþÿÿ¶V¶FÁâÁà ¶FÁà ¶F1ö‰<$ ‹E‰•Ìþÿÿ‹Uèröÿÿ‰t$¸˜‰<$‰D$èe’ļ[^_]ÃfU‰åW½HþÿÿVS켋]‹u ¶S¶C¶KÁâÁà ¶CÁáÁà ¶C ¶Áà ȶKÁá ȶK‰<$ Èè“Ûÿÿ¶S ¶C ¶K ÁâÁà ¶CÁáÁà ¶C ¶CÁà ȶK Áá ȶK ÈÐþÿÿ‰ $èGÛÿÿ¶S¶C¶KÁâÁà ¶CÁà ¶C ¶CÁàÁá ȶKÁá ȶK ÈXÿÿÿ‰ $èûÚÿÿ¶¶FÁâÁà ¶FÁà ¶F ‰•Èþÿÿ¶V¶FÁâÁà ¶FÁà ¶F‰<$ ‹E‰•Ìþÿÿ‹UèDóÿÿ‰<$¸˜‰D$1À‰D$èõļ[^_]ÃfU1ɉåW1ÿVuèSƒì$1Û‰Uà1Ò‰E䶃ù‹EäÁâƒÁ¶G ƒé‰ÐÓèÀˆ3¸CÓà÷Ð!ƒû~ζV¶F¶NÁâÁà ¶FÁáÁà ¶F ¶EèÁà ȶNÁá ȶN È‹Mà‰ $èåÙÿÿƒÄ$[^_]ö¼'U‰åSì¤hÿÿÿ‹E‰Úè6ÿÿÿ‰$‹E ºè¦ïÿÿĤ[]ö¼'U‰åSì¤hÿÿÿ‹E‰Úèöþÿÿ‰$‹E ºèvðÿÿĤ[]ö¼'U‰åƒì‰]ø‹]‰uü‹u ‰$ȉt$è ÷ÿÿ‰u ‹uü‰]‹]ø‰ì]éøöÿÿ´&U‰å‹E ‹U]éïÿÿU‰å‹E Eˆ‹U]éúïÿÿU‰åSƒì‰Ã¸‰D$‹C‰$è“Éÿÿ‰C ‰$èøËÿÿ‰CÇCǃÄ[]ÃfUº‰åVSƒì‹]‰T$Ç$èpÉýÿ‰Æ‹C‰D$‹C‰$èÌÅÿÿ‰F‹C‰D$‹C ‰$è·Åÿÿ‰F‰ðèmÿÿÿƒÄ‰ð[^]Ãt&U¹‰åSƒì‰L$Ç$èÉýÿ‰Ã‹E‰$èµÿÿ‰C‹E ‰$èù´ÿÿ‰C‰ØèÿÿÿƒÄ‰Ø[]ô&U‰åSƒì‹]‹‰$è<µÿÿ‹C‰$è1µÿÿ‹C‰$è&µÿÿ‹C‰$èµÿÿ‹C ‰$èµÿÿ‹C‰$èµÿÿ‰][[]éJÍýÿv¼'U‰åWVSƒì‹U‹B‰$èyÆÿÿ‰Eðº‰T$‰$èUÈýÿ‰Æv‹U‹…À…Ò‹E …Àt‹U‹B‰$èÆÿÿ;E Á‹U»‹B‰4$‰D$è.Çÿÿ;]ð}‰ö¼'èÛQ 3C;]ð|ò‰4$‹E‹Uð‰D$‰T$è,Åÿÿ‹E‹‰$¡àD‰D$èFÇÿÿ…ÀŽnÿÿÿ‹U‹B ‰D$‹‰$è*Çÿÿ…À‰Rÿÿÿ‰4$èZÌýÿ‹U‹B‰D$‹‰D$‹B‰$èï¾ÿÿ‹U‰BƒÄ[^_]É$èÙ³ÿÿé!ÿÿÿ‹U 1Û1ÿ‰$èu´ÿÿ;] ‰Â‹EÇEì‰|.éfÿÿÿ‰\$‰ø‹UƒàCÑÿ‰D$‹‰$èà³ÿÿÿMì;] 8ÿÿÿ‹Eì…ÀuÐÇEìèáP‰ÇëÀ¶¼'U‰åƒì‹U‹B‰D$‹‰D$‹E ‰$è?¾ÿÿÉÃU‰åW‰ÇV‰ÖSƒì‰$è‹Äÿÿ‰ÂƒÂx_‰Ð‰ÓÁøˆEð‰ÐÁú ˆUòÁûºˆ]óÁøˆEñ‰T$ë‰\$‰4$èßÄÿÿˆEð¸‰D$‰<$Eð‰D$è´¤‰ØK…ÀÒƒÄ[^_]ÃPëœU‰åƒì ‰$‰Ó‰t$‰Æ‹E‰|$‹} ƒ:Ç~J‹¶¶AÁâÁà ¶AÁà ¶AƒÁ‰ ‰‹ƒê‰‹9Â|‹})‰‰t&¼'‹$‹t$‹|$‰ì]ÃU‰åMüƒì‰L$Mø‰ $èhÿÿÿ‹Uø1À…Òt€:x‰$‹Eü‰D$èûÁÿÿÉÉö¼'U¹‰åƒì‰L$‰]ø‰Ã‰uü‹‰Ö‰$èÍÁÿÿƒ‹]øƒ.‹uü‰ì]ö¼'U‰åƒì(‰]ô»‰uø‰}ü‰\$Ç$èÅýÿ‰Ã1À…Ût:EðU ‰D$Eì‰$Eè¼þÿÿ‹Eì…Àtü¿ÐÃD¹‰Æó¦t‰$èœÉýÿ1À‹]ô‹uø‹}ü‰ì]ÃU Eèÿÿÿ‰U Eèõþÿÿ‰CU Eèçþÿÿ‰CU EèÙþÿÿ‰C ‹uø‰Ø‹}ü‹]ô‰ì]ô&U‰åSƒì‹]‹‰$èܰÿÿ‹C‰$èѰÿÿ‹C‰$èÆ°ÿÿ‹C ‰$è»°ÿÿ‰]X[]éÉýÿU‰åWVSƒì‹E‹1À…Ò„ª‰$èÂÿÿÁà‰ÂƒÂ<ˆÁÁúZ ‹U‹B‰$èÞÁÿÿÁà‰ÂƒÂ<ˆÄÁúÓ‹U‹B‰$è½ÁÿÿÁà‰ÂƒÂ<ˆÇÁúÓ‹U‹B ‰$èœÁÿÿÁà‰ÂƒÂ<ˆÊÁú¹Ó‰L$‰$è˜Ãýÿ‰Eð‹Uð1À…Ò„ ‹EðfÇ0xÆ@‹UÇE싉$èHÁÿÿ‰ÂƒÂˆ‰‰ÐÁø…ÀŽõxÿë=‰û‹UÁë‹uìÑû‰\$‹ÛÿEì‰$è˜Áÿÿ‰ù‹Uð)ÙÁáOÓøƒà¶€(ÄDˆƒÿÿu¾‹Eì‹UðÇ,0x‹UƒÀ‰Eì‹B‰$èÈÀÿÿ‰ÂƒÂˆ‰ÐÁø…ÀŽkxÿë>‰û‹UÁë‹uìÑû‰\$‹BÛÿEì‰$èÁÿÿ‰ù‹Uð)ÙÁáOÓøƒà¶€(ÄDˆƒÿÿu½‹Eì‹UðÇ,0x‹UƒÀ‰Eì‹B‰$èGÀÿÿ‰ÂƒÂˆ˜‰ÐÁø…ÀŽàxÿë>‰û‹UÁë‹uìÑû‰\$‹BÛÿEì‰$è–Àÿÿ‰ù‹Uð)ÙÁáOÓøƒà¶€(ÄDˆƒÿÿu½‹Eì‹UðÇ,0x‹UƒÀ‰Eì‹B ‰$èÆ¿ÿÿ‰ÂƒÂˆ‰ÐÁø…À~\xÿë>‰û‹UÁë‹uìÑû‰\$‹B ÛÿEì‰$èÀÿÿ‰ù‹Uð)ÙÁáOÓøƒà¶€(ÄDˆƒÿÿu½‹Eì‹UðƉЃÄ[^_]øë¸éÿÿÿ¸é‹þÿÿ¸éþÿÿPKÁúZ ‹U‹B‰$è¿ÿÿÁà‰ÂƒÂ<‰<ýÿÿPKÁúÓ‹U‹B‰$èö¾ÿÿÁà‰ÂƒÂ<‰9ýÿÿPKÁúÓ‹U‹B ‰$èÒ¾ÿÿÁà‰ÂƒÂ<‰6ýÿÿPKé.ýÿÿPé÷ýÿÿPéoýÿÿPééþÿÿPé`þÿÿ¶¿U‰åWVuˆSìü‹}‰4$èæ‰4$¸ ‰D$¸9ÄD‰D$è ‹‰$èR¾ÿÿ‰ÂƒÂˆ‰Ð‰ÓÁøˆ…ÿÿÿ‰ÐÁøˆ…ÿÿÿ¸Áû‰D$Áú …ÿÿÿˆ•ÿÿÿˆÿÿÿë#‰\$‹‰$莾ÿÿˆ…ÿÿÿ¹…ÿÿÿ‰L$‰D$K‰4$范ûÿuË‹G‰$è̽ÿÿ‰ÂƒÂˆ›‰Ð‰ÓÁøˆ…ÿÿÿ‰ÐÁøˆ…ÿÿÿÁú Áûˆ•ÿÿÿ…ÿÿÿºˆÿÿÿ‰T$ë$‰\$‹G‰$è¾ÿÿˆ…ÿÿÿ¸‰D$…ÿÿÿ‰D$K‰4$èƒûÿuÊ‹G‰$èE½ÿÿ‰ÂƒÂˆ$‰Ð‰ÓÁøˆ…ÿÿÿ‰ÐÁøˆ…ÿÿÿ¸Áû‰D$Áú …ÿÿÿˆ•ÿÿÿˆÿÿÿë$‰\$‹G‰$耽ÿÿˆ…ÿÿÿ¸‰D$…ÿÿÿ‰D$K‰4$è~ƒûÿuÊ‹G ‰$è¾¼ÿÿ‰ÂƒÂˆ•‰Ð‰ÓÁøˆ…ÿÿÿ‰ÐÁøˆ…ÿÿÿ¸Áû‰D$Áú …ÿÿÿˆ•ÿÿÿˆÿÿÿë$‰\$‹G ‰$èù¼ÿÿˆ…ÿÿÿ¸‰D$…ÿÿÿ‰D$K‰4$è÷ƒûÿuʉt$…xÿÿÿ1Û‰$苵ÿÿÿ‰$è¼ÿÿ‰D$¸EÄD‰D$‰4$èÁƒ‰ö¼'‰ñ´&¼'‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁ¶„+xÿÿÿ҉ʃÚ…Û‰D$ ¸QÄDu¸SÄD‰D$¿TÄDC‰|$‰$èLƒƒû~‰ñ‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁÒ»ƒÙ)ñA‰\$‰$èm½ýÿ…À‰Ãt ‰t$‰$ècƒÄü‰Ø[^_]ÃPéßüÿÿPé]ýÿÿPécþÿÿPéÔýÿÿ´&¼'U1Ò‰åƒìx‹E‰]ô‰uø‰}ü‹…ÛtVƒ}(tpEÄU‰D$EÀ‰$E è¨öÿÿ‹uÀ…öt!ƒ}Äuü¸ÐÃD¹‰Çó¦t)v¼'1Ò´&¼'‹]ô‰Ð‹uø‹}ü‰ì]ÃE ƒm‰ö¼'UE è÷ÿÿ‰E¼UE è÷öÿÿ‰E¸‹M¼‹U¸…É”À…Ò” Ð1Ò¨u¬‹U]È‹}¸‹B‰<$‰D$èäÂÿÿ‰E´‹E‰\$‰D$‹E‰$諜‰]ÀUÄEÀÇEÄè–öÿÿ‰E ‹U‹}´‹B‰|$‰D$‹E ‰$èg¬ÿÿ‹U‰Ã‹B‰|$‹}¼‰D$‰<$èL¬ÿÿ‰E¤‹U‹‰\$‰D$‹B‰$è1³ÿÿ‰E°‹}‹‰D$‹E¤‰D$‹G ‰$è³ÿÿ‰E¬‹U¬‹‹}°‰T$‰D$‰<$èø«ÿÿ‰E¨‹U‹}¨‹B‰<$‰D$¡àD‰D$è׫ÿÿ‰Ã‹E¼‰$‰D$èÖºÿÿ…À‹U´”À¶À‰$‰Eœè°§ÿÿ‹} ‰<$襧ÿÿ‹E°‰$èš§ÿÿ‹U¬‰$è§ÿÿ‹}¨‰<$è„§ÿÿ‰$è|§ÿÿ‹E¼‰$èq§ÿÿ‹U¸‰$èf§ÿÿ‹Uœé>þÿÿ´&¼'U‰åWVSƒì,‹U‹‰$誸ÿÿ‰ÃƒÃˆ ‹U‰ÞÁþ‹B‰$茸ÿÿ‰ÂƒÂˆãÁú‰Uð‹U‹B‰$èm¸ÿÿ‰ÂƒÂˆ¼Áú‰Uì‹U‹B ‰$èN¸ÿÿ‰ÂƒÂˆ•Áú‹}칉Uè‹Uð‰L$‹UèøD‰Eä‰$è7ºýÿ‰Eà‰ÇƒÇÆÆ@Æ@Æ@Ç@ssh-‰ØÁøfÇGdsÆGs‹UàƒÇˆB ‰ØÁøˆGÁû ‰ðˆ_ˆG‰×ƒÇë´&‰t$‹U‰ûG‹‰$è<¸ÿÿˆNƒþÿuä‹EðÁøˆ‹EðÁøˆG‹EðÁøˆG¶EðˆG‹uðƒÇë‰t$‹U‰ûG‹B‰$èö·ÿÿˆNƒþÿuã‹EìÁøˆ‹EìÁøˆG‹EìÁøˆG¶EìˆG‹uìƒÇët&‰t$‹U‰ûG‹B‰$è«·ÿÿˆNƒþÿuã‹EèÁøˆ‹EèÁøˆG‹EèÁøˆG¶EèˆG‹uèƒÇë‰t$‹U‰ûG‹B ‰$èe·ÿÿˆNƒþÿuã‹Eà‹UäÐ9øu3‹E ‹U䉋EàƒÄ,[^_]ÃPécþÿÿPé<þÿÿPéþÿÿXéïýÿÿÇ$[ÄD¿S¾oÄD‰|$‰t$èh~U‰åWVSƒì‹U‹B‰$èY¶ÿÿ‰ÆƒÆˆ‚‰ó¹Áû‰L$C‰Eð‰$èR¸ýÿ‰Eì‹Uì‰ðÁø‰×ƒÇˆ‰ðÁøˆBÁþ ‰ðˆBsÿˆZë‰t$‹U‰ûNG‹B‰$è‚¶ÿÿˆƒþÿuã‹Eì‹UðÐ9øu‹E ‹Uð‰‹EìƒÄ[^_]ÃpévÿÿÿÇ$[ÄD¸k‰D$¸oÄD‰D$èž}¶U‰åWVSì¼»ÿÿÿÿ‹E‰…dÿÿÿ‹E ‰D$‹E‰$èTòÿÿ‰…TÿÿÿU…dÿÿÿèÀñÿÿ‰`ÿÿÿ‹•Tÿÿÿ‰B…`ÿÿÿU‰D$…\ÿÿÿ‰$…dÿÿÿèñÿÿƒ½`ÿÿÿtW‹•Tÿÿÿ‹‰D$‹B‰D$‹B‰$è™®ÿÿ‹½Tÿÿÿ‰Ã‹G ‰$‰D$è’¶ÿÿ…À…‰$èr£ÿÿ‹…Tÿÿÿļ[^_]Ã]ˆ‰$è•‹½Tÿÿÿ‰Ø‹èðÿÿ‹W‰Øè ðÿÿ‹W‰Ø½hÿÿÿèüïÿÿ‰$…hÿÿÿ‰D$è –ü‹µ\ÿÿÿ¹ó¦„Oÿÿÿ‹…Tÿÿÿ‰$ë‰<$èòÿÿļ1À[^_]öU¹‰åWVSƒì ‹}‰L$‹u Ç$èL¶ýÿ1Ò…À‰Ã„ž‰ò‰øèwðÿÿ‰‰ò‰øèlðÿÿ‰C‰ò‰øè`ðÿÿ‰C‰ò‰øèTðÿÿ‰C ‰ò‰øèHðÿÿ‰C‰Á‹…Àt‹S…Òt‹{…ÿt‹s …öuP´&‰$蘺ýÿ‹C‰$èºýÿ‹C‰$肺ýÿ‹C ‰$èwºýÿ‹C‰$èlºýÿ‰$èdºýÿ1ÒƒÄ ‰Ð[^_]ÅɉÚuðë°U‰åWVSƒì ‹U‹‰$躳ÿÿ‹U‰Ã‹B‰$誳ÿÿ‹UËB‰$èš³ÿÿ‹UËB ‰$芳ÿÿ‹UËB‰$èz³ÿÿ<;}~ ƒÄ ‰ø[^_]ËU¿‹‰$èV³ÿÿ‹U ƒèÁøˆ‹U‹‰$è>³ÿÿ‹U ƒèÁøˆB‹U‹‰$è%³ÿÿ‹U ƒèÁøˆB‹U‹‰$è ³ÿÿ‹U ,ˆB‹U‹‰$è÷²ÿÿpûëf‰t$‰û‹UGN‹‰$è ³ÿÿ‹U ˆƒþÿuà‹U‹B‰$è²ÿÿ‹U ƒèÁøˆ‹U‹B‰$訲ÿÿ‹U ƒèÁøˆD:‹U‹B‰$è²ÿÿ‹U ƒèÁøˆD:‹U‹B‰$èr²ÿÿ‹U ,ˆD:‹UƒÇ‹B‰$èX²ÿÿpûëv‰t$‰û‹UGN‹B‰$èj²ÿÿ‹U ˆƒþÿuß‹U‹B‰$è!²ÿÿ‹U ƒèÁøˆ‹U‹B‰$è²ÿÿ‹U ƒèÁøˆD:‹U‹B‰$èì±ÿÿ‹U ƒèÁøˆD:‹U‹B‰$èѱÿÿ‹U ,ˆD:‹UƒÇ‹B‰$è·±ÿÿpûëf‰t$‰û‹UGN‹B‰$èʱÿÿ‹U ˆƒþÿuß‹U‹B ‰$è±ÿÿ‹U ƒèÁøˆ‹U‹B ‰$èg±ÿÿ‹U ƒèÁøˆD:‹U‹B ‰$èL±ÿÿ‹U ƒèÁøˆD:‹U‹B ‰$è1±ÿÿ‹U ,ˆD:‹UƒÇ‹B ‰$è±ÿÿpûëf‰t$‰û‹UGN‹B ‰$è*±ÿÿ‹U ˆƒþÿuß‹U‹B‰$èá°ÿÿ‹U ƒèÁøˆ‹U‹B‰$èǰÿÿ‹U ƒèÁøˆD:‹U‹B‰$謰ÿÿ‹U ƒèÁøˆD:‹U‹B‰$è‘°ÿÿ‹U ,ˆD:‹UƒÇ‹B‰$èw°ÿÿpûëf‰t$‰û‹UGN‹B‰$芰ÿÿ‹U ˆƒþÿu៎ ‰ø[^_]Ãt&U‰åƒì‰]ø‹E ‰uü‰D$‹E‰$è¢ìÿÿ‰Æ‹‰$趯ÿÿ‰4$‰ÃèLíÿÿ‰Ø‹uü‹]ø‰ì]ÃU‰å…èþÿÿW¿VµÿÿÿSìl»{ÄD‰D$‹E‰D$‹E ‰$è’‰4$èPe‰|$‰\$‰4$è e‹U‹z‰<$èB¯ÿÿ‰ÂƒÂˆ’‰Ð‰ÓÁøˆ…¤þÿÿ‰ÐÁûˆ§þÿÿÁø¹ˆ…¥þÿÿÁú …¤þÿÿˆ•¦þÿÿ‰L$‰D$ë%‰\$‰<$è|¯ÿÿˆ…¤þÿÿº‰T$•¤þÿÿ‰T$‰4$èe‰ØK…À̉4$½¨þÿÿ1À‰…¤þÿÿ‰|$èzЉ4$è’d‰|$¸@‰D$‰4$èÝd‰4$¸‰D$…èþÿÿ‰D$èÂd‰|$‰4$è6Љ4$¸Ô‰D$1À‰D$èçu‰<$¸@‰D$èάÿÿ‹U‰Ã‹B‰$‰D$èz§ÿÿ‰$‰Æè°œÿÿü1À¹ó«‹U¿‹‰t$‰D$‹B‰$艧ÿÿ‹U‰Ã‹B‰$‰D$è5§ÿÿ‰… þÿÿ‰$ègœÿÿ‰|$…èþÿÿ‰$èU¬ÿÿ‹U‰Ç‹B‰4$‰D$èq¶ÿÿ‰|$‰Æ‹… þÿÿ‹U‰D$‹B‰$èc°ÿÿ‹U‰Ã‹B‰\$‰4$‰D$è  ÿÿ‰$»‰…œþÿÿèø›ÿÿ‰4$1öèî›ÿÿ‰<$èæ›ÿÿ‰\$Ç$7èf¯ýÿÆ‰ÇÆ@Æ@Æ@Ç@ssh-fÇ@dsÆ@ sÆ@ Æ@ Æ@ Æ@(t&‹… þÿÿ»)ó‰\$‰$臭ÿÿˆD7‹•œþÿÿ‰\$‰$èq­ÿÿˆD7#Fƒþ~Ç‹… þÿÿ‰$èY›ÿÿ‹•œþÿÿ‰$èK›ÿÿ‹EÇ7Äl‰ø[^_]ÃPéfýÿÿU‰å‹EÇ#EgÇ@‰«ÍïÇ@þܺ˜Ç@ vT2Ç@PÇ@XÇ@T]ô&U‰åWVSƒìl‹U‹E ‹ZX‰Ñ‰E¤‹EØ;E‰BX‹]’À¶ÀBT‹RPƒø?†°¸@‹])ЉD$‹E¤T‰$‰D$è¢s‹SP‹E¤‹M)ÐL ÀƒÀ@‰M1ɉE¤´&‹]¶T‹¶D‹ÁâÁà ¶D‹Áà ¶D‹ ‰T¨Aƒù~ЋS ‹s‹C‰Uœ‹;‹Mœ‰E ‰Â‰ð÷Ð!ò‹]¬!È‹M¨ Âú” x¤j×ÁÂ<2‹M ‰ø‰ú÷Ð!È!ò‹M´ ‹Eœ”V·ÇèÁ ú‰Uœ‹Eœ!ú‹]œ÷Ð!ð ‹E ‹E°”Ûp $‹EœÁ‰U ‹E !Ú‹] ÷Ð!ø Âò” îνÁÁ‹Mœ4‰ð‰Ú÷Ð!È!ò ‹E¸ú‹M¼”¯|õÁÂ<2‰ø‰ú÷Ð!Ø!ò ‹Eœ” *ƇGÁ ú‰Uœ‹Eœ!ú÷Ð!ð ÂÚ‹]À‹Eœ”F0¨Á‹]œ‹Eœ‰U ‹M !‹E ÷Ð!ø ‹EÄò”•FýÁÂ4 ‰ð‰Ê÷Ð!Ø!ò‹]È Âú”ؘ€iÁÂ<2‰ø‰ú÷Ð!È!ò ‹Eœ‹EÌ”¯÷D‹Á ú‰Uœ‹Eœ!ú‹]œ÷Ð!ð ÂÊ‹MЋEœ” ±[ÿÿÁ‹Mœ‰U ‹E !Ú‹]Ô÷Ð!ø Âò‹E ”¾×\‰Á‹] 4‰Â‰ð÷Ð!ò!È‹MØ Âú” "kÁ‹Mœ<2‰ø‰ú÷Ð!ò!Ø‹]Ü ÂÊ”“q˜ýÁ ú‰Uœ‰Ó‰Ð÷Ó!ø‹Mœ‰Ú!ò ЋU ЋUà„ŽCy¦ÁÀ‹UœȉE ‹M !Ð÷щÊ!ú ЋUäð„!´I‹U ÁÀ4‹Eœ!Ó!ñ!ð Ø‹]¬ø„b%öÁÀ<0‰Ð!ø‹UÀ È‹MœÈ„@³@ÀÁÀ ‰ò‹MÔø÷Ò‰Eœ!ð!ú ЋU ‹]œЄQZ^&‹MœÁÀ‰ú؉E ÷Ò!ø!Ê‹]¨ Ðð‹U „ªÇ¶éÁÀ‹] 4‹Uœ‹Eœ‹M¼÷Ò!Ú!ð ЋU ø„]/Ö‹MœÁÀ<0‹E ÷Ò!ò‹]Ð!ø Ðȉò„SD÷ÒÁÀ ø!ú‰Eœ!ð‹]œ ЋU ‹MœЋU䄿¡ØÁÀ‰ú؉E ÷Ò!Ê!ø‹M¸ Ћ] ð„ÈûÓç‹UœÁÀ4‹Eœ÷Ò‹Mà!ð!Ú Ð‹UÌø„æÍá!ÁÀ‰Ú<0÷Ò‰Ø!ò!ø ЋUœЄÖ7ÉòÁÀ ÷Òø‰Eœ!ú!ð ЋMœØ‹]´‰ú÷Ò!Ê„‡ Õô‹]œÁÀØ‹]܉E !ø‹M  ЋUÈð„íZEÁÀ‹Uœ4‹Eœ÷Ò!Ê!ð Ðø‰Ê„éã©ÁÀ÷Ò<0‰È!ò!ø ЋUœЋU°„ø£ïüÁÀ ‰òø÷Ò‰Eœ!ð!ú Ћ]œÈ‹Mĉú÷Ò„Ùog‹MœÁÀØ‹]Ø!ʉE !ø Ðð‹U „ŠL*ÁÀ‹]œ4‰Ð‹M¼1ð1Øø‹]È„B9úÿÁÀ‹Mœ<0‰ø1ð1ÐÈ„öq‡ÁÀ ø‰Eœ1ø‹]œ1ð‹MàЋUÔ„"am‹UœÁÀЋU¬‰E 1Ø1ø‹] ð„ 8åýÁÀ‹Mœ4‰Ø1ð1Èø‹M¸„D꾤ÁÀ‹Uœ<0‰ø1ð1ØЄ©ÏÞK‹UÐÁÀ ø‰Eœ1ø‹Mœ1ðØ‹]Ä„`K»ö‹]œÁÀØ‹]܉E 1È1ø‹M ð„p¼¿¾ÁÀ‹Uœ4‰È1ð1Ðø‹U¨„Æ~›(ÁÀ‹]œ<0‰ø1ð1ÈØ„ú'¡ê‹]ÀÁÀ ø‰Eœ1ø‹Uœ1ðÈ‹M´„…0ïÔ‹MœÁÀÈ‹M̉E 1Ð1ø‹U ð„ˆÁÀ‹]œ4‰Ð1ð1Øø‹]Ø„9ÐÔÙÁÀ‹Mœ<0‰ø1ð1ÐÈ„å™ÛæÁÀ ø‰Eœ1ø‹]œ1ðЋU䄸|¢ÁÀ؉E ‹Mœ‹] ‹U¨1È‹M°1øð„eV¬ÄÁÀ‹MÄ4‹Eœ÷Ð ð1Øø„D")ôÁÀ‹Uœ<0‰Ø÷Ð ø1ðЄ—ÿ*CÁÀ ø‰Eœ‹Mœ‰ð÷ЋUœ È1ø‹MœØ‹]à„§#”«ÁÀЋU¼‰E ‹] ‰ø÷Ð Ø1Èð‹M „9 “üÁÀ‹]Ø4‹Eœ‹Uœ÷Ð ð1Èø„ÃY[eÁÀ<0‰È÷Ð ø1ðЋU´„’Ì ÁÀ ø‰Eœ‹]œ‰ð÷Ð Ø1øÈ‹MЋ]œ„}ôïÿ‹MœÁÀÈ‹MȉE ‹U ‰ø÷Ð Ð1Ø‹]¬ð‹U „Ñ]„…ÁÀ‹]ä4‹Eœ÷Ð ð1Ðø„O~¨oÁÀ‹Mœ<0‰Ð÷Ð ø1ðÈ„àæ,þÁÀ ø‰Eœ‹]œ‰ð÷ЋMœ Ø1ø‹]œЋUÀ„C£ÁÀÈ‹M܉E ‹U ‰ø÷Ð Ð1Øð‹] „¡NÁÀ‹U¸4‹Eœ‹Mœ÷Ð ð1Øø„‚~S÷ÁÀ<0‰Ø÷Ð ø1ðÈ‹MÔ„5ò:½ÁÀ ø‰Eœ‹Uœ‰ð÷Ð Ð1øØ‹]°‹Uœ„»Ò×*‹]œÁÀØ‹]‰E ‹M ‰ø÷Ð È1ЋUÌðÇCP‹M ;„‘Ó†ëÁÀK4‹EœsC ƒ}?v,1ÒéP÷ÿÿ‰\$D ‹U¤‰$‰T$èüj‹MYPƒÄl[^_]ËU‰ØƒÀ‰T$‹M¤‰$‰L$èÓj‹E‰CPƒÄl[^_]Ãt&U‰åWVSƒìl‹] ‹CPƒø7ŽûÇE¤x)E¤ü‹CT}¨‹SX‹M¤4ʼnÐÁè ÆÁâ1ÀÁé‰U ó«öE¤tfǃÇöE¤tÆÆE¨€‹E¤M¨‰L$‰$‰D$èEöÿÿ¶M ‰ðÁèˆE¯‰ðÁèˆE®‰ðÁèˆE­‰ð¾ˆE¬‹E ˆM¨‰t$ÁèˆE«‹E ‰$ÁèˆEª‹E ÁèˆE©E¨‰D$èîõÿÿ1Ò¶¿¶D“‹MˆD‘·D“ˆD‘‹“ÁèˆD‘‹“ˆ‘Bƒú~ÕƒÄl[^_]ÃÇE¤8éÿÿÿU‰åSƒìt]˜‰$èNõÿÿ‰$‹E ‰D$‹E‰D$èxõÿÿ‰\$‹E‰$è©þÿÿƒÄt[]ÃvU¸\‰åƒì‰D$Ç$èµ£ýÿÉÃvU‰å]ég¨ýÿ´&Uº@‰åW¸6Vu¨Sƒì\‹}‰T$‹] ‰D$‰4$èìh1É9ù}(´&¼'¶0D)¨A9ùœÂ1Àƒù?žÀ…Âuæ‹E‰$è‹ôÿÿ‰t$¸@‰D$‹E‰$è³ôÿÿ‰4$¸@‰D$¸\‰D$èh1É9ù}v¶0D)¨A9ùœÂ1Àƒù?žÀ…Âuæ‹]‰÷ƒÃ\‰$è&ôÿÿ‰t$¸@‰D$‰$èQôÿÿü¹1Àó«ƒÄ\[^_]Ãë U¹‰åƒì‹E ‰L$‰D$‹E‰$èßþÿÿÉö¼'U‰å옉uøuˆ‰}ü‰Ç¸\‰]ô‰Ó‰D$‰|$‰4$èÒg‰\$‹E‰4$‰D$è¿óÿÿ‹M …Ét‰4$‹E‰D$‹E ‰D$è¢óÿÿ‰t$xÿÿÿ‰$èÐüÿÿ‰4$º\G\‰T$¿‰D$èsg‰|$‰\$‰4$ècóÿÿ‰t$‹E‰$è”üÿÿ‹]ô‹uø‹}ü‰ì]ô&U‰å‹MÇE‹E‹U ‰MÇE ]éÿÿÿ¶¼'U‰åSƒì$‹] ‰T$Ç$‰ÙÁéˆMè‰ÙÁéˆMé‰ÙÁéˆMê‹Mˆ]ë]è‰Ú‰L$ ‹M‰L$èÈþÿÿƒÄ$[]ÃfU‰åS‹]‹U ‹E‰] ‰M‹M‰M []ëU‰åƒì8‰}ü‹U‹} ‰]ô‹E‹]‰uøu؉T$‰ú<;‰t$‰$è]ÿÿÿü¹‹]ôó¦”À‹uø‹}ü‰ì¶À]ÃU‰åP¸Ä@è’e‰]ô‹Eü¹‰uø¾@‰Ã‰}ü‹E1ÿ‰•t¿ÿÿ•è¿ÿÿlj½h¿ÿÿ‰$‰t$‰L$‰\$ èáf‰$‰Æèf‰ò1ÀÁêþ@”À Â…W‹}…öÇðÄDŽ€½è¿ÿÿ… Fÿ…ÀŽþ¶é¿ÿÿ…Û•À1Òƒû•Â…Ð…âFþƒøŽÖ€½ê¿ÿÿ…É€½ë¿ÿÿ…¼€½ì¿ÿÿ…¯€½í¿ÿÿ…¢‰t$1Àº‰D$ ‹…t¿ÿÿ‰T$‰D$…î¿ÿÿ‰$è'*‰Á‰ÂƒÁ‰p¿ÿÿˆd¶¼)è¿ÿÿƒÂ Á牽l¿ÿÿ¶„ é¿ÿÿÁà lj½l¿ÿÿ¶„ ê¿ÿÿÁà lj½l¿ÿÿ¶„ ë¿ÿÿ‰•p¿ÿÿ ljð‰½l¿ÿÿ)Ð9øŒ¸‰D$‰ø@‰$èŸýÿ‰…d¿ÿÿ…Àt-‰|$‹•p¿ÿÿ‹d¿ÿÿ„*è¿ÿÿ‰D$‰ $èwd‹…d¿ÿÿÆ‹E ‹•l¿ÿÿ•p¿ÿÿ…Àt‹d¿ÿÿ‰ $èÜ ýÿ‹} ‰‹…t¿ÿÿ…À„O‹•d¿ÿÿ‹…t¿ÿÿ‰P ‹E…À…ª‹½t¿ÿÿ…ÿ„:…Û…¡‹½p¿ÿÿ‰ð)øƒø~J‹•p¿ÿÿ¶„*ê¿ÿÿ8„*è¿ÿÿu¶„*ë¿ÿÿ8„*é¿ÿÿ„‹M¾ÿÿÿÿ‰µh¿ÿÿÇÅDv¼'º@1À‰T$•è¿ÿÿ‰D$‰$è{c‹…h¿ÿÿ‹]ô‹uø‹}ü‰ì]ËMÇÅD량…h¿ÿÿë¸x¿ÿÿ‰$èïÿÿ‹E‰$è/c‰D$‹U‰$‰T$è<ïÿÿ‰\$Ø¿ÿÿ‰ß‰$èhøÿÿ‰$‹p¿ÿÿ‰ð‹•p¿ÿÿ)ȃÀƒàø‰D$…è¿ÿÿЉD$èÚÌÿÿü‹E¹ó«éáþÿÿ‹d¿ÿÿ‰ $è ¢ýÿé­þÿÿ‹}1À…Û•À‰…h¿ÿÿÇé ÿÿÿƒ…p¿ÿÿ‰ð‹½t¿ÿÿ‹p¿ÿÿ‹p¿ÿÿ‰|$)؉D$…è¿ÿÿȉ$è×(‰…l¿ÿÿ…ÀˆÉþÿÿ…p¿ÿÿ‰øƒÀ‰D$‹•p¿ÿÿ‰ð‹p¿ÿÿ)ЉD$…è¿ÿÿ؉$èšÿÿ‰…l¿ÿÿ…Àˆˆþÿÿ…p¿ÿÿ‰øƒÀ‰D$‹p¿ÿÿ‰ð‹•p¿ÿÿ)ȉD$…è¿ÿÿЉ$èÅ™ÿÿ‰…l¿ÿÿ…ÀˆGþÿÿ…p¿ÿÿ‰øƒÀ‰D$‹…p¿ÿÿ)Ɖt$‹µp¿ÿÿ…è¿ÿÿð‰$膙ÿÿ…Àˆþÿÿ‰<$è†0»…À‰h¿ÿÿ…óýÿÿ‹EÇ&ÅD‰<$èò21ɉh¿ÿÿéÕýÿÿt&U¸8ÅD‰åƒìx‰D$‹E‰]ô‰uø‰}üÇE ÇE¤‰$èGa…À‰Ã„—‰D$¸@‰D$E¨‰$è•a…Àu?ÇE¤;ÅD…Ût‰$è>aƒ} •À1Òƒ}•Â…Ðt‹E¤‹U‰‹E ‹]ô‹uø‹}ü‰ì]Ãü¿TÅD¹!u¨ó¦u¯Ç$E¤‹U ‰D$ ‹E‰D$1À‰D$‰Øècúÿÿ‰E ë˜ÇE¤uÅDët&U¸8ÅD‰åƒìx‰]ô‰uø‰}ü‰D$‹E‰$èu`‰Ã1À…Ût8‰\$¸@‰D$E¨‰$èÅ`…Àtü¿TÅD¹!u¨ó¦t‰$èg`1À‹]ô‹uø‹}ü‰ì]ÃE¤1Ò‰D$ 1À‰D$‹E Ç$‰D$‰Øè¼ùÿÿ‹]ô‹uø‹}ü‰ì]Ãë U1À‰å쨋U‰…tÿÿÿ‹E ‰]ô‰uø‰}üÇ1À‰…pÿÿÿ¸8ÅDljD$‹E‰$è _…À‰Ã„ô‰D$¸@‰D$E¨‰$èî_…ÀuRº;ÅD‰•tÿÿÿ…Ût‰$è“_ƒ½pÿÿÿ•À1Òƒ}•Â…Ðt ‹…tÿÿÿ‹U‰‹…pÿÿÿ‹]ô‹uø‹}ü‰ì]öü¿TÅD¹!u¨ó¦uœ‹…pÿÿÿ½xÿÿÿ¹ µxÿÿÿ‰òó«Ç$…tÿÿÿ1ÿ‰D$ ‹E‰|$‰D$‰ØèŽøÿÿ…À„_ÿÿÿ‰4$‹U‰T$è÷.‹U ‰‰4$è0¹‰pÿÿÿé?ÿÿÿ¸uÅD‰…tÿÿÿé/ÿÿÿv¼'U¸œ@‰åWVSèÐ]ƒ}¸ATE Æ…Àÿÿ‹} ‰…ð¿ÿÿ¸KEY ¹SSH ‰…ô¿ÿÿ¸FILEºPRIV‰…ø¿ÿÿ¸ FORµÀÿÿ‰…ü¿ÿÿ¸MAT ‰…Àÿÿ¸1.1 ‰…ÀÿÿÀöЉè¿ÿÿ$‰•ì¿ÿÿˆ… ÀÿÿÆ… ÀÿÿÆ… ÀÿÿÆ… ÀÿÿÆ… Àÿÿ‹G‰$è1–ÿÿÁøˆ…Àÿÿ‹G‰$è–ÿÿÁøˆ…Àÿÿ‹G‰$è –ÿÿÁøˆ…Àÿÿ‹G‰$èõ•ÿÿˆ…Àÿÿ‹G‰4$‰D$è —ÿÿÆ‹G ‰4$‰D$è—ÿÿ‹_ Æ…Û…mÆÆFÆFÆFƒÆ‰µt¿ÿÿF‰óè¢!‹•t¿ÿÿFˆè”!ˆ¶Fþˆ¶FÿˆF‹GƒÆ‰4$‰D$è³–ÿÿÆ‹G‰4$‰D$袖ÿÿÆ‹G‰4$‰D$è‘–ÿÿÆ‹G‰4$‰D$耖ÿÿÆëÆF‹½t¿ÿÿ‰ð)ø¨uî‹]…Ûthx¿ÿÿ½Ø¿ÿÿ‰$èèÿÿ‹E‰$è”\‰D$‹U‰$‰T$è¡èÿÿ‰<$‰\$èÕñÿÿ‰<$‹t¿ÿÿ‰ð)ȉD$‹…t¿ÿÿ‰D$èuÇÿÿü¹1Àó«‹Eº…ÅD‰T$‰$èO\‰Ç1À…ÿt?‰|$ •è¿ÿÿ‰ó‰$)Ó¸‰\$‰D$èl\‰<$9Ø”À¶ØèD\…À”À¶À÷Ø!ØÄœ@[^_]É$èÝ[Á舉$èÐ[ÁèˆF‰$èÂ[ÁèˆF‰$è´[ˆFƒÆ‰$è¦[‰D$‰4$‰\$è¶[‹G ‰$è‹[ÆéDþÿÿt&U‰åW‰ÇV¾'Sƒì ‰Ó´&¼'‰<$è@[‰Áƒø ”Àƒù ” Шuƒùÿtƒù:t…ötˆ NC…öÎ1ÀƒÄ [^_]É<$è[‰Á1Àƒù uçÆ¸ë݉ö¼'U‰åWVSƒì‰Eð¸ÇE耉D$Ç$€èh•ýÿÇEì‰ÇÆë ‹Eìˆ8‰uìÆ>‹Eð‰$èšZ‰Ãƒø ”Àƒû ” Шu.ƒûÿtf‹uìF;uè|ƃm耸‰D$‹Eè‰<$‰D$èÔ—ýÿ‰Ç릋Eð‰$èMZƒø ‰Ã•À1Òƒû •Â…Ðtƒûÿt‹Eð‰$‰D$è=[ƒÄ‰ø[^_]É<$è{™ýÿƒÄ1À[^_]ÃU1ɉåWVSƒì‹]f¶ˆÐ,A<‡€¾ÂƒèA‰DØAƒù~à‹U؃úÿ„µ‹]܃ûÿ„©‹Màƒùÿ„±‹u促þÿ„ªÁâƒá?Áã Áá Ú Êƒæ?‹M ò‰ÐÁèƒÿˆrƒÿ~‹E ˆPƒÄ‰ø[^_]ÃfˆÐ,a<w ¾ÂƒèGésÿÿÿˆÐ,0< v+€ú+¸>„]ÿÿÿ€ú/¸?„Oÿÿÿ€ú=u¸ÿÿÿÿé@ÿÿÿ¾ÂƒÀé5ÿÿÿ1ÀƒÄ[^_]ÉÐÁèˆAë„‹uä1Àƒþÿuäƒùÿ•À¶øGéGÿÿÿfU¹‰åWVSƒì‰EðRÁà‰Uì‰L$‰$èj“ýÿ‰Eè‹EìÇEä9EäÇEà}i‹Eðè¹ýÿÿ…À‰Çtv‰$è«X‰Æ¨•Àƒþ@ŸÂ Шup1Û9ó}'f‹Eè‹UäЉD$‰$èYþÿÿ…Àt0EäƒÃ9ó|Û‰<$è³—ýÿÿEà‹Eì9Eà|—‹E‹U䉋EèƒÄ[^_]É<$è—ýÿ‹Uè‰$è‚—ýÿƒÄ1À[^_]ËEè‰$èm—ýÿ‰<$ëá´&U¹‰åüƒì‰4$‹u‰|$¿ˆÅDó¦—Â’À8¹@ÈDt‹u¹¿ÅDó¦—Â’À8¹ðÃDu ‹4$‰È‹|$‰ì]Ã1Éëït&U1ɉåWVSì\‹U ‰þÿÿ…Òt‹E ‰$èŠW‰…þÿÿ1À1ÿ¾8ÅD‰…üýÿÿ1À‰…þÿÿ1À‰…$þÿÿ1À‰…(þÿÿ1À‰…,þÿÿ1À‰… þÿÿ‹E‰½þÿÿ‰t$‰$èPW‰…Äýÿÿ…À„]‹…ÄýÿÿU¸èœûÿÿ…À„”ü¹¿˜ÅDu¸ó¦—Â’À1ɉþÿÿ8Â…!‹…Äýÿÿ»ðÄD‰üýÿÿèØûÿÿ…À‰ÃtR‰$èºþÿÿ‰… þÿÿ…À„E‰$è–ýÿ‹…ÄýÿÿU¸è&ûÿÿ…Àt"ü¿®ÅD¹ u¸ó¦„ü¶¿‹…Äýÿÿ…Àt‹µÄýÿÿ‰4$è°V‹…(þÿÿ…Àt‹…(þÿÿ‰$è •ýÿ‹…,þÿÿ…Àt‹•,þÿÿ‰$舕ýÿ‹…$þÿÿ…Àt‹$þÿÿ‰ $èp•ýÿ‹½þÿÿ…ÿt‹µþÿÿ‰4$èX•ýÿ‹µ þÿÿ…öt‹… þÿÿ‰$è@•ýÿ‹]…Ût ‹üýÿÿ‹U‰ ‹…þÿÿÄ\[^_]ÿ¹ÅD¹u¸ó¦—Â’À¿ÏÅD‰½üýÿÿ8Â…%ÿÿÿè€Å¾‰µþÿÿé¢þÿÿ‹…Äýÿÿè…úÿÿ‰…,þÿÿ…À„÷þÿÿü¿íÅD¹ ‰Æó¦—Â’À¹‰þÿÿ¿8‰½þÿÿ…‡‹…ÄýÿÿU¸è¶ùÿÿ…À„®þÿÿü¿øÅD¹u¸ó¦…˜þÿÿ‹…Äýÿÿè úÿÿ‰…(þÿÿ…À„þÿÿ‹…ÄýÿÿU¸èqùÿÿ…À„iþÿÿü¿ÆD¹ u¸ó¦…Sþÿÿ‹…ÄýÿÿèÈùÿÿ…À‰Ã„>þÿÿ‰$è¦T‰$‰Çèü“ýÿ…4þÿÿ‰ú‰$‹…Äýÿÿè–ûÿÿ‰…þÿÿ…À„þÿÿ‹…ÄýÿÿU¸èúøÿÿ…À„òýÿÿü¿ ÆD¹u¸ó¦…Üýÿÿ‹…ÄýÿÿèQùÿÿ…À‰Ã„Çýÿÿ‰$è/T‰$‰Çè…“ýÿ…0þÿÿ‰ú‰$‹…Äýÿÿèûÿÿ‰… þÿÿ…À„‘ýÿÿ‹…ÄýÿÿU¸èƒøÿÿ…À„{ýÿÿü¿ÆD¹ u¸ó¦„|ü¿'ÆD¹ u¸ó¦…Oýÿÿ‹•þÿÿ…Ò„Aýÿÿ‹…Äýÿÿè¶øÿÿ‰…$þÿÿ…À„(ýÿÿ1À‰…þÿÿ‹…Äýÿÿ‰$èÚS‹…þÿÿ…À„Ö‹E …À„ýÿÿ‹…0þÿÿ™÷½þÿÿ…Ò…üüÿÿ(ÿÿÿ¾4ÆD}ˆ‰$èþk‰$¸‰D$¸9ÆD‰D$è$l‰$‹•þÿÿ‹M ‰T$‰L$è l‰|$‰$èÿl‰$è·k‰t$¸‰D$‰$èâk‰$‹E ‹µþÿÿ‰D$‰t$èÉk‰$Eœ‰D$èºl‰<$‹…0þÿÿ‹• þÿÿ‰D$‰T$ècÿÿ‹þÿÿ…Û„]‹ þÿÿ‹µ0þÿÿ‰Ðýÿÿ1ɉµÌýÿÿ‰Èýÿÿ‹…þÿÿ…À„ü¸@ÆD»‰Æ‰Ù½8þÿÿó¥·\ÆDµxþÿÿ‰Ëf‰¶^ÆDˆG‰4$èçj‰4$¸‰D$…8þÿÿ‰D$è k‹½þÿÿ…ÿ•Â1Àƒ} •À…Ât‰4$‹…þÿÿ‹U ‰D$‰T$èÛj‰4$½Xþÿÿ‰|$èÉk‰<$‹Ìýÿÿ…Øþÿÿ‰D$‹…Ðýÿÿ‰L$ ¹‰D$‰L$èÚpü‰Ø¹ó«‰4$º`1À‰T$‰D$è‘Q‹…Èýÿÿ…Àt,1À‹µÌýÿÿ‰D$‹…Ðýÿÿ‰t$‰$èiQ‹•Ðýÿÿ‰$è£ýÿµøþÿÿ1ÿ‰ó¶„/ØþÿÿG‰$ƒÃ‰D$¸_ÆD‰D$èPQƒÿ~Ú‰t$‹$þÿÿ‰ $èéQ…À„É‹½þÿÿ¸ÅD‰…üýÿÿ¸ E…ÿ‰…þÿÿ…}úÿÿ¾dÆD1Û‰µüýÿÿ‰þÿÿéeúÿÿ»uÅD‰üýÿÿéÍúÿÿ‹µ,þÿÿ¿oÆD¹»ó¦‰þÿÿ—Â’À1ö8‰µþÿÿ„Fûÿÿ‹…,þÿÿ‰$èÌýÿé÷ùÿÿ‰$è¿ýÿéêùÿÿ‹•Ìýÿÿ…Øþÿÿ‹Ðýÿÿ‰D$‰T$‰ $èXkéºþÿÿ‹• þÿÿ‹B0‰$è2P‹,þÿÿ‰Ã‰ $è"P‰Æ‹…(þÿÿ‰$èP‹•4þÿÿ‰Ç3‹0þÿÿøÐȺƒÀ‰T$‰…Ìýÿÿ‰$èqŠýÿ‰…Ðýÿÿ‹•Ðýÿÿ‰ØÁøˆ‰ØÁøˆB‰ØÁøˆZˆB‹ þÿÿ‹•Ðýÿÿ‹A0ƒÂ‰\$‰$‰D$è¹O‹•Ðýÿÿ‰ðÁøÚZˆB‰ðÁøˆC‰ðÁøˆC‰ðˆCB‹•,þÿÿ‰t$‰$‰T$èxO‰ø3ÁøˆB‰øZÁø‰ùˆC‰øÁøˆKˆC‹µ(þÿÿB‰|$‰$‰t$èÇ$ìE‹@E‰ð)Ð|:Àp@¸E‰D$èØS‹èEf¶ƒEJ0‚8E1Òù¯‰ÊCƒû~Þ‰èEƒú~<1À1Ò£@E¸@9øŽpÿÿÿ1ɉ|$E‰t$‰$è•==@EƒÄ [^_]Ãè²ýÿÿë½U‰åVS‹u ‹]þ¯~-1Òt&¼'¶C0‚8EBú¯~íèxýÿÿî°ëË1Òë ¶C0‚8EB9ò|ñ[^]éUýÿÿt&U¸°‰åWVSƒì ‹ èE‹} ‹])È9øD¸°1Ò)ȃø~‰Æ¶C0„8EB9Öðè ýÿÿ¡èE1Éø¸Pûÿÿ1À£èE¸°9ø~¼1Òë ¶C0‚8EB9ú|ñ‰èEƒÄ [^_]Ãt&¼'U‰åƒì‹0E…Ò~2¡0FE9E x(èqåÇ$à“¸8E‰D$¸ÐÌB‰D$èã£0FEÉö¿U‰åƒì¡0E…Àt@£0EÉÃÇ$8E¸‰D$1À‰D$èö;Ç$@ÌBèâãè-üÿÿÇ$à“¸8E¹ÐÌB‰D$‰L$èo£0FE¡0E@£0EÉö¼'U‰åÿ 0E]Ãt&U‰åƒì‹èEú¯¶‚8EB‰èEÉÃè·ûÿÿ‹èE¶‚8EB‰èEÉÃU¹‰åƒì‰]ô‰uø‹u ‰}ü‹}‰L$Ç$Xè¶uýÿ‰Ãèoûÿÿ¡èEºX‰$‰T$8E‰D$è ;ÇX‰‹]ô‹uø‹}ü‰ì]é7ûÿÿU¸ÿÿÿÿ‰åWVSƒì ‹} ‹]ƒÿŽØ‹E…À„‹E¹Çv¼'‹U‹¶CÁàЋUI‰yê‹uƒï…öu.‹M1À…Ét‹EƒÀ ‰D$‰|$‰$èArÿÿ‰Æ…ö¸ÿÿÿÿxkó)÷‹U1À…Òt‹EƒÀ‰D$‰|$‰$èrÿÿ…À‰ÆxM‹E…Àt‹U‹B‰$èˆrÿÿ…Àt4‹UFþ‰B‹E…Àt‹UC‰ó)÷ƒ}t‹U‰Ø)ÐƒÄ [^_]ÃvƒÄ ¸ÿÿÿÿ[^_]ËM1À…Ét‹EƒÀ ‰D$‰|$‰$è”qÿÿ‰Æ…ö¸ÿÿÿÿx¾ó볋]ƒÃéÿÿÿv¼'U‰åƒE]écqÿÿvU‰åWVSƒì‹M‹} ‹]‹QG1É9Â} ƒÄ‰È[^_]É|$¾‰\$)ø‰$èî9ÆÆC‹E‹P‰Ð)øHƒøë!´&è‹ýÿÿˆ„Àtô‹MF‹Q‰Ð)øH9ðä)ú‰ßÆDÿ‹U‹B‰$‰D$èéoÿÿ‰Eð‹M‹A‰D$‹A ‰D$‹Eð‰$èÊjÿÿ‰Eì‹U‹rë‰t$‰û‹MìG‰ $è­qÿÿˆNƒþÿuæ‹Eð‰$èš_ÿÿ‹Uì‰$è_ÿÿƒÄ¹‰È[^_]ÃU‰åW‰ÇV‰ÖSƒì‰$èÛpÿÿ‰ÂƒÂx[‰Ð‰ÓÁøˆEð‰ÐÁøˆEñÁû¸ˆ]óÁú ˆUòë‰\$‰4$è3qÿÿˆEð¸‰D$Eð‰D$‰<$èØ&‰ØK…ÀÒƒÄ[^_]ÃPë t&U‰åWV¾@S1Ûì\‰…Àþÿÿ‰•¼þÿÿ‰µ¬þÿÿ‰¨þÿÿt&‹•¼þÿÿ1ö1ÿ‹B‰$èK^ÿÿ‰…¸þÿÿ‰$èpÿÿ‰Ãë‰\$‹•¸þÿÿ‰ðƒàÑþO‰D$‰$èÛ^ÿÿKƒûÿt)…ÿ؃½¬þÿÿ?¿wh‹…¬þÿÿ¶´(Èþÿÿ@‰…¬þÿÿ볡äD‰D$‹…¸þÿÿ‰$èUqÿÿ…À~#‹•¼þÿÿ‹B‰D$‹…¸þÿÿ‰$è6qÿÿ…Àˆ3‹•¸þÿÿ‰$è^ÿÿé;ÿÿÿ‹…¨þÿÿ•ÿÿÿ‰$Áøˆ…Äþÿÿ‹…¨þÿÿÁøˆ…Åþÿÿ‹…¨þÿÿÁøˆ…Æþÿÿ¶…¨þÿÿˆ…Çþÿÿè#%¹ºˆÈD…ÿÿÿ‰L$‰T$‰$èc%¸•Äþÿÿ‰D$…ÿÿÿ‰T$‰$èB%‹…¼þÿÿ‹P…ÿÿÿèîýÿÿ…ÿÿÿ•Èþÿÿ‰$‰T$è–Jÿ…¨þÿÿ•ÿÿÿ‰$è¢$¸@•ÿÿÿ‰D$…Èþÿÿ‰D$‰$èá$‹•Àþÿÿ…ÿÿÿèýÿÿ…Èþÿÿ•ÿÿÿ‰D$‰$è8J1À‰…¬þÿÿéxþÿÿ‹•¼þÿÿ‹B‰D$‹B ‰D$‹…¸þÿÿ‰$èÉgÿÿ‰…´þÿÿ‹•¼þÿÿ‹B‰D$‹…¸þÿÿ‰$èØvÿÿ‰…°þÿÿ‹•¼þÿÿ‹B‹•Àþÿÿ‰D$‹…´þÿÿ‰$‰D$è}`ÿÿ‹•¼þÿÿ‰Æ‹B‰D$‹B‰4$‰D$è_gÿÿ‹•¼þÿÿ‰Ã‹B‰$‰D$‹…°þÿÿ‰D$è>`ÿÿ‰$‰Çè4\ÿÿ‰4$è,\ÿÿ‹•°þÿÿ‰$è\ÿÿ‹…´þÿÿ‰$è\ÿÿ‹•¸þÿÿ‰$è\ÿÿÄ\‰ø[^_]Ãt&U‰å‹E‹U ]éáüÿÿU‰åƒì‰]ø‹E‰uü‹P‹X ‰$è3mÿÿ‰ÂƒÂx,‰$‰ÖÁþèmÿÿ‰ÂƒÂx8Áú‹]ø‹uü‰ì…]É$P‰Öèólÿÿ‰ÂÁþƒÂyщö¼'P‹]øÁú‹uü‰ì]…öU‰åWVSƒì‹E ‹P‹@ ‰Uð‰Eì‹EfÇ0xÆ@‹UìÇEè‰$èŠlÿÿ‰ÂƒÂˆí‰ÐÁø…ÀŽÑxÿë;‰û‹EìÁë‹uèÑû‰\$ÛÿEè‰$èÜlÿÿ‰ù‹U)ÙÁáOÓøƒà¶€£ÈDˆƒÿÿuÀ‹Eè‹UÇ,0xƒÀ‰Eè‹Eð‰$èlÿÿ‰ÂƒÂxq‰ÐÁø…À~Wxÿë;‰û‹UðÁë‹uèÑû‰\$Û‰$ÿEèèilÿÿ‰ù‹U)ÙÁáOÓøƒà¶€£ÈDˆƒÿÿuÀ‹Eè‹UƃÄ[^_]ø뢸é%ÿÿÿPëŠPé ÿÿÿv¼'U‰åWVuˆSìü‰4$èÙ¾ÿÿ‹U‹B‰$è‹kÿÿXýƒûÿt9½ÿÿÿ‰\$‹MK‹A‰$èÊkÿÿˆ…ÿÿÿ¸‰D$‰|$‰4$èϾÿÿƒûÿuÍ‹U‹B ‰$è5ÁǃûO‹µ¤þÿÿ‰…¤þÿÿ~ª‹•”þÿÿ‹ þÿÿ‹œþÿÿЋU‰‹…þÿÿð‰B‹…Œþÿÿø‰B‹…ˆþÿÿ؉B ‹…˜þÿÿȉBÄl[^_]Ãv¼'U‰å‹EÇ#EgÇ@‰«ÍïÇ@þܺ˜Ç@ vT2Ç@ðáÒÃÇ@TÇ@\Ç@X]ÃU‰åWVSƒì\‹]‹u‹} ‹C\‹STð9ð‰C\’À¶ÀCX…Òt 2ƒø?Ž 2ƒø?~z‰|$¸@)ЉD$T‰$èÕæ‹ST‰ø1É)Ðt2Àx@t&¶T‹¶D‹ÁâÁà ¶D‹Áà ¶D‹ ‰T¨Aƒù~Ó‰$E¨‰D$èdüÿÿÇCT1Òƒþ?†‰t$C‰|$‰$ècæ‰sTƒÄ\[^_]Ét$D‰|$‰$èDæsTƒÄ\[^_]Éö¼'U‰åWVSƒìl‹]‹CTƒø7ŽûÇE¤x)E¤ü‹CX}¨‹S\‹M¤4ʼnÐÁè ÆÁâ1ÀÁé‰U ó«öE¤tfǃÇöE¤tÆÆE¨€‹E¤M¨‰L$¿‰$‰D$è€þÿÿ¶M ‰ðÁèˆE¨‰ðÁèˆE©‰ðÁèˆEª‰ðˆE«‹E ˆM¯‰|$ÁèˆE¬‹E ‰$ÁèˆE­‹E ÁèˆE®E¨‰D$è.þÿÿ1Ò¶¿¶D“‹M ˆ‘·D“ˆD‘‹“ÁèˆD‘‹“ˆD‘Bƒú~ÕƒÄl[^_]ÃÇE¤8éÿÿÿU‰åSƒìt]˜‰$èŽýÿÿ‰$‹E ‰D$‹E‰D$è¸ýÿÿ‰$‹E‰D$è©þÿÿƒÄt[]ÃvU¸`‰åSƒì‰D$Ç$è$ýÿ‰$‰Ãè:ýÿÿƒÄ‰Ø[]ÃfU‰å]égýÿÿ´&U‰åSƒì‹]‹E ‰$‰D$èGþÿÿ‰]ƒÄ[]éš#ýÿv¼'U¸`‰åƒì‰D$Ç$èµýÿÉÃvU‰å]ég#ýÿ´&U¹@‰åW‰×º6V‰ÆE¨Sƒì\‹]‰L$‰T$‰$èëã1É9Ù}'¶¼'¶90D)¨A9ÙœÂ1Àƒù?žÀ…Âuæ‰4$è^üÿÿ‰4$¸@‰D$E¨‰D$è†üÿÿ¸@‰D$¸\‰D$E¨‰$èã1É9Ù}v¶90D)¨A9ÙœÂ1Àƒù?žÀ…Âuæ^`}¨‰$èøûÿÿ‰$¸@‰D$E¨‰D$è üÿÿü¹1Àó«ƒÄ\[^_]ô&¼'U‰å‹EÇE‹U ]éêþÿÿv¼'U‰å‹EÇE‹U ]éÊþÿÿv¼'U‰åW‰ÇV¾`S쬉•dÿÿÿ‹U ]ˆ‰t$µhÿÿÿ‰Ðˆ•kÿÿÿÁ舅hÿÿÿ‰ÐÁ舅iÿÿÿ‰ÐÁè‰|$‰$ˆ…jÿÿÿè”â‰t$¹‰L$‰$èOûÿÿ‰$‹E‰D$‹…dÿÿÿ‰D$è6ûÿÿ‰t$‰$è*üÿÿ‰$º`G`‰T$¿‰D$è=â‰|$‰t$‰$èýúÿÿ‰$‹E‰D$èîûÿÿĬ[^_]ÃvU‰åS‹]‹U ‹E‰] ‰M‹M‰M []éýþÿÿ¶¼'U‰åƒìH‰}ü‹U‹} ‰]ô‹E‹]‰uøuȉT$‰ú<;‰t$‰$è½þÿÿü¹‹]ôó¦”À‹uø‹}ü‰ì¶À]ÃfU‰åU؃ì8‹E‰uü‹u ‰T$‹U‰]ø‹]‰T$‰ò‰$èsþÿÿ‹E؉3‹E܉D3‹Eà‰D3‹]ø‹uü‰ì]Ãt&U‰åƒìH‰}ü‹U‹} ‰]ô‹E‹]‰uøuȉT$‰ú<;‰t$‰$èþÿÿü¹ ‹]ôó¦”À‹uø‹}ü‰ì¶À]ÃfU‰åVµ8ÿÿÿSìðÿÿÿ‹E ‹U‰$‰ðè™üÿÿ‰4$‹E‰D$‹E‰D$èƒùÿÿ‰\$‰4$èwúÿÿ‰\$¸]˜‰D$‰$è_ùÿÿ‰$‹E‰D$èPúÿÿÄð[^]ÃU‰Á‰åƒì ‰$‰t$‹t$‰|$‹|$¶‰ÐÁàжQiÒжQ¹WiÒ ‰Ø÷éÁúiÒ÷)Ӊ؋$‰ì]Ãt&U‰Á‰åVSƒì‹˜€ˆU÷‹u[·D fƒøÿtZ˜@fÇAÿÿ[Àf‰tfÇDÿÿ¿”q€ƒúÿf‰f‰œq€tRf‰\A¶E÷ˆ„C%ÿ‰€X[^]÷D fƒøÿt¥˜ºÿÿÿÿf‰”A€ë•t&U1ɉåWVSì\‰…Ôþÿÿ‹1Û‰Àþÿÿ1Û‹°ø‰Äþÿÿ‰•Ðþÿÿƒþ‰…ÌþÿÿŽ˜‹U)؃øŽ)1É 9ð}0‹…Ìþÿÿȶ„òˆ„)ØþÿÿAƒù,‹…Ìþÿÿ‹°ø 9ð|Ћ•Ðþÿÿ)𶈄)ØþÿÿAƒù~Ô…ØþÿÿCèPþÿÿ¶•Øþÿÿ‰$‹…Ìþÿÿè›þÿÿ‹Ìþÿÿ‹±ø9Þhÿÿÿ1À‹½Ìþÿÿ)Þ‰…Àþÿÿ1À‰…Äþÿÿ1À‰·ø‰…¼þÿÿ‹E…ÀŽC‹} …ÿ•À1Òƒ}ŸÂ…Є™‹…Ðþÿÿ1öèÐýÿÿ‰µÈþÿÿ‹•Ìþÿÿ¿„B€‰…´þÿÿ@„kë ‹Ìþÿÿ‹‰€‰¸þÿÿ‹¸þÿÿ‹´þÿÿ)Ù‘€…҉Ј!%€ÿÿ‹¸þÿÿ¾€)Â1Û)Ö)ñ…Ûˆ·‹…Ðþÿÿ¶‰Ø)ðˆÌ‹½Ðþÿÿ¶9ÂuCAƒû~σû„‹•´þÿÿ‹ÌþÿÿR¿A‰…´þÿÿ@…^ÿÿÿ‹…Èþÿÿ…Àެ¾;u²f‹½Èþÿÿ1Û1À‰…´þÿÿ9û|é—´&C;Èþÿÿ}g…öˆ‹½Ðþÿÿ¶ >‹”Ýèþÿÿ‰ð)Ј8‹•Ðþÿÿ¶9ÁuÆ‹´þÿÿ‹„Ýèþÿÿ‹”ÝìþÿÿC‰„Íèþÿÿ‰”ÍìþÿÿA;Èþÿÿ‰´þÿÿ|t&‹…´þÿÿ…Àt‹½´þÿÿF‰½Èþÿÿ;uŒPÿÿÿ‰µìþÿÿ‹½Äþÿÿ…ÿŽ_‹…Äþÿÿ@9ÆŽ+¶…¼þÿÿ»‰D$‹…Ôþÿÿ‰$ÿP‹ìþÿÿ‹•èþÿÿ‰Äþÿÿ‹Ðþÿÿ‰•Àþÿÿ¶ ‰¼þÿÿƒ}ŽË‹…Ðþÿÿèµûÿÿ‹½Ðþÿÿ¶‰$‹…ÌþÿÿèþûÿÿéÍ‹•¸þÿÿ‰Ø‹½ÌþÿÿÚâÿ)𶔉7þÿÿv‰Ï‹…Ìþÿÿçÿ‰½°þÿÿ¶„8éþÿÿÿÿéÔýÿÿ‹Äþÿÿ…ÛŽŽ‹Äþÿÿ‹½Àþÿÿ‹…Ôþÿÿ‰L$‰|$‰$ÿP ‹Äþÿÿ1ɉÄþÿÿK…ÛŽþüÿÿƒ}5ÿÿÿ‹•Ìþÿÿ‹Ðþÿÿ‹½Ìþÿÿ‹‚ø¶ˆ”ò@‰‡øÿ…ÐþÿÿKÿM…Û¿‹E…À½üÿÿÄ\[^_]Ë•Ðþÿÿ»‹Ôþÿÿ¶‰ $‰D$ÿQé»þÿÿ‰Ù9Þ닽Ìþÿÿ‰Ê)Ú¶„òA9Έ„òâé5üÿÿ‹…Ìþÿÿ‹¸€÷)×çÿ‰½°þÿÿ¶„8é©ýÿÿv‹•Ìþÿÿ‹‚€ð%ÿ¶Œékýÿÿ‹…Èþÿÿº‰´Åèþÿÿ‰”Åìþÿÿ@ƒø‰…ÈþÿÿŽÉüÿÿéäüÿÿ‹½Äþÿÿ‹…Àþÿÿ‹•Ôþÿÿ‰|$‰D$‰$ÿR é§þÿÿ‹•ìþÿÿ»‹…èþÿÿ‰•Äþÿÿ‹•Ðþÿÿ‰…Àþÿÿ¶‰•¼þÿÿéÂýÿÿ¶¿U‰åSƒì‰Ã‹H‰ÈEƒø s‰CÓâ‹K ʃø‰S ~[‹Kë*v‹ˆ‹C@‰C‰Á‹C Áè‰Â‰C ‹Cƒè‰Cƒø~,;K|ÔA@º‰C‰T$‰D$‹‰$è·ýÿ‰‹S ‹K믃Ä[]ÃÇ$ ÒD¸r»¼ÒD‰D$‰\$è‘Ù‰ö¼'U‰å‹E¶U ‹H‹A…Àu€úw¶Â¶ÐÑDÇE‰È]éÿÿÿ¶ÒëìÇE ¶Â¶ ÑD‰È]Téüþÿÿ¶¿U‰åWVSƒì‹E‹} ‹@‰Eð‹@…À…µ‹]…ÛŽY}¾ ‹uþx)u¹ÿÿÿÿ»ë ‰Ø)ÈH~$ ‰ÂÁêÑúRÁà9°DÐD~.‰Ó‰Ø)ÈHܹ‰L$Ç$ÉÒD»¼ÒD‰\$èØ´&9°HÐD} ‰Ñ뤃î냘@ÐD·€@ÐDf=xÇ$˜¶” ÏD‹Eðèþÿÿ·Cf…Àuw¹ÿÿÿÿ»‰Ø)ÈH~$ ‰ÂÁêÑúRÁà9¸ÄÎD~‰Ó‰Ø)ÈHܾA‰t$é[ÿÿÿ´&9¸ÈÎD}D‰Ñë´Ç$˜¶HÑD‹Eðèýÿÿ·Cf…Àt‰‹S˜‰$‹Eð)Ö‰òèqýÿÿéqÿÿÿƒÄ[^_]ØÀÎD¿€ÀÎD¶Å ÑD‹EðÇ$è@ýÿÿ·Cf…À„cþÿÿ‹K˜‰ú‰$‹Eð)Êè ýÿÿéKþÿÿÇ$ÔÒD¿¾¼ÒD‰|$‰t$è5×¶¼'U‰åSƒì»‰\$Ç$è4ýÿÇ$¹ü‰Ã‰L$èýÿ…ÀtO‰1Ò¹ÿfÇDÿÿfÇDÿÿfÇÿÿƒÂIyæ1Ét&ºÿÿÿÿf‰”H€Aùö~ê1É1Ò‰ˆ€‰øÇC 0C¸ÇC €0C‰D$Ç$è§ýÿÇ@Ç@ Ç@Ç@‰CƒÄ‰Ø[]ÃU‰åSƒì‹]‹C‰$è+ýÿ‹‰$è!ýÿ‰]X[]éýÿ¶U‰å‹E‹P¸‹JÇB…Éu ‹R‰ÐƒÀ x Áø]ƒÀÃfBÁøëñ´&U‰åWVSƒì ‹E‹}‹p¸Ç‹NÇFÇF…É…,‹V…Òt#…À„êÇ$1Ò‰ðè[ûÿÿéÕ¶…À„‰<$‹U »‰\$‹Eè±õÿÿÇ$1Ò‰ðè!ûÿÿÇ$ º‰ðèûÿÿÇ$‰ðºèûúÿÿÇF‹‹E‰‹E‹V‰ƒÄ ¸[^_]ø)Ð1Ò‰$‰ðèÅúÿÿt&Ç$‰Ú‰ðè°úÿÿÇ$‰Ú‰ðòÿÿ)ßè˜úÿÿ‰$1À‹U ‰D$‹Eèõÿÿ] …ÿŽkÿÿÿÿÿÿ‰û~»ÿÿÇ$1Ò‰ðèZúÿÿ‹V…Òt“évÿÿÿÇ$‰ðºxœè;úÿÿÇF1Àé³þÿÿÇ$º‰ðèúÿÿéÍþÿÿt&U‰åWV1öSƒì,»‰Uì‰\$»‰EðÇ$èEýÿ¶M‰Eè‰ØÓà¹H‰L$¶M‰EäÓã{ÿ‰$èýÿ‹Uèƒÿ‰B‰:ëÆð1Ò‹MèfÇDðÿÿ‹A‹9‰TðF9÷}âÇEà‹E9Eàë fÿEà‹U9Uà…‹Uà‹Mì¶ ;E~â‹Mð‹Eä‹‘!Ð;E uÒ¶MÓú!ú‰ÖëQ¶‹Eè‹Uà‹X‹Eàf‰Tó‹Uì¶ ‹E¶Ñ)¶ó9Ð}ˆó‹Mè‹Eà‹Uì‹9¶ ‹]¶É¸)ÙÓàÆ9÷}±élÿÿÿ1öƒÿ|t&‹Mè‹A¶ð;UF9÷}ì‹EèƒÄ,[^_]ÃfÇDðÿÿ‹M)ʃú~º¶Mˆ ð‹Eè‹} ¶M‹X‹E‰T$ ‹UЉD$‰ðÓà ø‹Uì‰D$‹E‰$‹Eðè[þÿÿ‰Dó‹UèF‹:9÷ë¶¼'U‰åW¿VSì,‰…äúÿÿ1À‰•àúÿÿ‰…Üúÿÿt&¼'1À‰D½¨Gƒÿ~ô1ÿ;½àúÿÿ}/v¼'‹•äúÿÿ¶ÿD…¨;…Üúÿÿ~‰…ÜúÿÿG;½àúÿÿ|Û1Ò¿t&‰”½hÿÿÿ‹D½¨GÂÒƒÿ~ë1ÿ;½àúÿÿ}Q‹…äúÿÿ1Û¶4‹”µhÿÿÿB‰„µhÿÿÿ1Àƒþ‰„½èúÿÿ~1Év‰ÐɃàC ÁÑú9Þð‰Œ½èúÿÿG;½àúÿÿ|°‹•Üúÿÿ…èúÿÿƒú ~º ‰T$ ‹•àúÿÿ1ÿ‰|$1ö‰t$‰$‹•äúÿÿèýÿÿÄ,[^_]Ãt&¼'U‰åW‰Ç¸ÿÿÿÿVSƒì …ÿt[‹71À…ötS‹1Ûƒú|R‹Fë ¶C9Ú|‹LØ…ÉtóDØCè¹ÿÿÿ‹‹F9Ú}å‰$èØýÿÇF‰4$èÉýÿÇ1ÀƒÄ [^_]ËFëÔt&Uº¬‰åVµØþÿÿSì0‰T$Ç$èÊ ýÿ‰4$‰Ã¸‰D$¸‰D$è&иp‰D$¸ ‰D$…hÿÿÿ‰$èÐÇEغ ‰ðÇEÜÇEàÇEäÇEèÇEìÇEðÇEôèšýÿÿ‰¸º‰…Øþÿÿ¸¹‰…Üþÿÿ¸‰…èþÿÿ¸‰…ìþÿÿ¸‰…ðþÿÿ¸‰•äþÿÿº ‰…ôþÿÿ‰ð1ö‰àþÿÿè2ýÿÿ‰C1À‰ƒ”1À‰ƒ˜‰ØÇCÇCÇC ÇC‰³œÄ0[^]ÃU‰åSƒì‹]‹C…Àt;t Cèþÿÿv‹C …Àt;CtC èüýÿÿ¶¿‹C…Àu‰ØèâýÿÿCèÚýÿÿ‰]Y[]éÿ ýÿCèÇýÿÿ‰ØèÀýÿÿCè¸ýÿÿ‰]Y[]éÝ ýÿ¶¼'U‰åW‰ÇVSƒì‹E‰Uð‹‹2t&¼'‹‹@!Úж 9ñ ·BÓë)Îfƒøÿu‹B…ÀuÚ¸þÿÿÿZ[^_]ÃZ¸ÿÿÿÿ[^_]É‹Uð˜‰2Z[^_]öU‰åƒì‰]ø‰Ã‰uü‹€œ‰Öˆ”œ@%ÿ‰ƒœ‹ƒ¤;ƒ¨}‹“ ‰ñˆ ÿƒ¤‹]ø‹uü‰ì]ù‰ƒ¨‰L$‰D$‹ƒ ‰$èø ýÿ‰ƒ ‰Â‹ƒ¤‰ñˆ ÿƒ¤‹]ø‹uü‰ì]Ãt&U¸‰åW¿V1öSƒì‰D$Ç$èÛýÿ‹]‹U…Û‰‚ ‰º¨‰²¤Ž‹M‹™˜fƒû‰ÞžÀ1Òƒ}ŸÂ…Ðt^‹EƒÃ‰]苸”¶¿‹U ‰ñ‹]‹u¶B‰U Óà lj»”‹]èC‰ž˜‰ÞÿMƒûžÂ‰Eè1Àƒ}ŸÀ…Âu½‹U‹Bƒø wRÿ$…üÒD‹}‹U‹E‹O ˜”‰ $èüýÿÿƒøÿt:ƒøþ„ÇG ‰G‹Ÿ˜´&¼'‹u…ö%ÿÿÿ…Ûÿÿÿ‹U‹M‹]‹‚ ‰‹‚¤‰¸ƒÄ[^_]Ëš˜ëʃû~Í‹M‰È¶‘”èéýÿÿ‹u‹F<‹ž˜Á®”Hƒë‰ž˜…À‰FÖDèüýÿ‰D$‰Ã‹G‰$è›2‰]‹uø‹]ô‹}ü‰ì]é‡ýÿ´&U‰åƒì8‰uø‹u‰]ô‰Ã‰ð‰}ü‰×ˆUÙ‹SˆEÚ¸ÆEØÿ‹ ‰D$E؉$‰D$ÿQ‰t$ºHÖD‰<$‰CL‰Øè ÿÿÿ‹]ô‹uø‹}ü‰ì]ÃU‰åSƒì‰Ã‹B‹Mƒøtlƒøt{‹C …Àu@‹KH…Éu3¡pÓDƒ|ƒt|¡ÔDƒ|ƒ„¬¡TÓDƒ|ƒ„|ÇCHƒÄ[]É$1Ò1ɉT$ 1Ò‰L$‰T$è–âüÿë¤t&:ýu‘1À…É”À‰C@ë…:ý…yÿÿÿ1À…É”À‰CDéjÿÿÿ1Ò‰Tƒ¡lÓD‹\ÓD‰$‰ØèÖþÿÿédÿÿÿ1Ò‰Tƒ¡PÓD‹@ÓD‰$‰Øè¶þÿÿédÿÿÿ1É‹ÔD‰Lƒ¡ÔD‰$‰Øè–þÿÿé4ÿÿÿU‰åƒì8‰uü‹u‹U ‰]ø‹E‹N‰V‰F…Ét ¡¨ÓDƒ|†t ‹]ø‹uü‰ì]ÃÆEØÿ‰Ð]ØÆEÙúÁø¹ˆEÛþÀÆEÚ„–‹FˆD)ØA€|)×ÿ„¤‹V‰ÐÁøˆD)ØA€|)×ÿ„ˆT)ØA€|)×ÿtmÆD)ØÿAÆD)Øð‹FA‹‰L$‰\$‰$ÿR‰FL‹F‰D$‹FÇ$OÖD‰D$è‘þüÿ‰D$‰Ã‹F‰$è00‰$è(ÿüÿ‹]ø‹uü‰ì]ÃÆEÜÿ¹é\ÿÿÿÆD)ØÿAë‹ÆD)ØÿAétÿÿÿÆD)ØÿAéQÿÿÿfU‰åƒì‰]ô‰Ó‰uø‰Æ‰}ü:ûtÇ$‰Ú‰ðè¥ýÿÿ‹]ô‹uø‹}ü‰ì]ÃztT‹Kƒù'”Àƒù$” Шtȃù'¿@ÔDt¿$ÔD‹Gƒ|†vJ¿‰Ú‰|†‰ðÇ$èKýÿÿ‹]ô‹uø‹}ü‰ì]Ë@‰D$‹F‰4$‰D$è8þÿÿ;û…gÿÿÿ눋G‹W‰$‰ðèªüÿÿ‹Gë¡t&U‰åW‰×VSƒì‹u‰Eð‰$ºeÖD‰t$èÞûÿÿÇEìÀÓD‹ÀÓD…Òt}¡TÔD‰Ó‰EèëƒEì‹Uì‹…Ûtc9suî9{„9suà9{ uÛ‹C‹Mð‹T…Ò„£Jui‹Mðº‰T‹S‰È‰4$è üÿÿÇE‹Eì‹‹EðƒÄ[^_]éRüÿÿf1Òÿû”Â1Àÿý”À Ðt”ü‰u‹EðƒÄ[^_]é½ûÿÿƒÄ[^_]ËS‹Mð‹D‘ƒøtL@…Àuã‹Eð¹‰L‰ÚƒÄ[^_]éþÿÿ‹Uð¾‰t‚;ût:ÇE‰Úécÿÿÿƒøu¢‹Së‹‹Mð¿‰È‰|‘‰4$‹èBûÿÿ‹Eì‹‹Eð릃{'uÀ‹Mèƒ|Šu¶Ç$$ºû‹Eðèûÿÿ‹Eè1É‹Uð‰L‚ë”¶U¸‰åSìøþÿÿ‰D$‰\$‹E‰$èL‹E …Àu2‹E‰\$Ç$lÖD‰D$èŠûüÿ‰D$‹E‹@‰$è(-Ä[]ËE‰\$Ç$…ÖD‰D$èXûüÿ‰D$‹E‹@‰$èö,Ä[]ö¼'U‰åƒì‰]ø‹]‰uü‹u ‹S…Òu7…öt'‰t$‹C‰$è´,‰t$¸¡ÖD‰D$‹C‰$è„‹´&¼'‰×EU èÃýÿÿ…À|&~-‹U€:u¥‹] €;u3‹U€:u•‹E €8”À¶ÀƒÄ [^_]ËU B‰Æ‰E €zt,‹U몉4$)óè •‰}ðU )؉E Eè[ýÿÿƒÄ [^_]Ã1À붸ë¯Ç$ŽÚDºá¸ŸÚD‰T$‰D$è•v¼'U‰åVS‹] ‹u¶ „Ét>´&¼'€ù\t;€ù*”À€ù?” Шu3€ù[t.€ù]t)…ötˆFC¶ „ÉuÐÆ¸[^]Ãt&C¶ „ÉuÙëæ[1À^]ÃU‰åƒìè5è€<‹E‰$èÝ•t&U‰å]Ãt&¼'U‰å]Ãt&¼'U‰å]Ãt&¼'U‰åƒìh‰uø‹u‰}ü‹}‰]ô‹]‰|$ ‰t$‹E‰D$‹E ‰$è.o…Àº„Áƒø„ÈH„BÇ$öÿÿÿèÍ•‰ÃƒìEĉD$‰$豕‹Eăì‰$ƒÈ‰D$蔕ƒìEÀ1ɉD$ ºEȉL$‰T$‰D$‰$èd•‹Eăì‰$‰D$èZ•¶Mȃì„É•Â1À€ù •À…Âtz€ù tu€ùy”À€ùY” Ш…|ºv¼'‹]ô‰Ð‹uø‹}ü‰ì]á€E…À„‰\$ ¸0ÝD‰t$‰D$¡äSEƒÀ@‰$è’“1Ò‹]ô‰Ð‹uø‹}ü‰ì]ø5áD‰D$¡äSEƒÀ@‰$èg“1ÒëÓ‰|$ ‰t$‹E‰D$‹E ‰$èÙpºéoÿÿÿ¡€E…ÀtI‰t$¾°ÚD‰\$ ‰t$ë‰\$ ¸ÞD‰t$‰D$¡äSEƒÀ@‰$è“¡äSEƒÀ@‰$è “élþÿÿ‰\$ »pÛD‰t$‰\$ëÈv¼'U‰å]Ãt&¼'U‰åSƒìT‹ €E‹U ‹E…Ét*‰D$ ¡äSE»ÐáD‰T$ƒÀ@‰\$‰$舒1Ò‹]ü‰ÐÉÉD$ ¡äSE¹PáD‰L$ƒÀ@‰T$‰$è^’¡äSEƒÀ@‰$èf’Ç$öÿÿÿèš“‰ÃƒìEÔ‰D$‰$è~“‹EÔƒì‰$ƒÈ‰D$èa“ƒìEÐ1Ò‰D$ ¸‰D$E؉T$‰D$‰$è1“‹EÔƒì‰$‰D$è'“¶E؃ì‰D$¸ŠçD‰D$è¿´&U‰åƒì‹E‹…Òt ƒÀ8‰EÉéåºüÿÇ$€çD¸D‰D$¸ŠçD‰D$è´&U‰å‹E]‹@ ÃU‰å]Ãt&¼'U‰åƒìÇ$êçDèþ‰$膽üÿÉÃt&Uº‰åì(‹E ‰]ø‹]‰uüµèþÿÿ‰T$‰4$‰D$è°€‰t$¸‰$ÆEë‰D$è§€‰Ø‹uü‹]ø‰ì]‰ö¼'U‰å‹E]ô&U‰å… ƒì‰D$E‰$èÉ…À”À¶ÀÃt&¼'U1À‰å€}]”ÀÃfU‰åVuôSƒì‰t$ÇEôÇ$è¾vƒì…ÀuÇEô‹Eô¹‰L$‰$èlºüÿ‰$‰Ã‰t$èŽvƒìeø‰Ø[^]ÃfU¸”‰åƒì‰D$1À‰D$Ç$@FEè§Ç$@FE¸”£@FEèiƒìÉÃt&U‰åVSƒì ¡ÀE‹u…Àt}¡°E…ÀtX‹àDƒûÿt-‰4$èP‰D$1Ò‰T$Uô‰T$ ‰t$‰$è«€¡°Eƒì‰4$‰D$è/€¡°E‰$èjeø[^]ÃÇ$òçD¹üçD‰L$裰EëŒè€…À„vÿÿÿÇ$õÿÿÿ»‰ÀEèc€£àDƒìéRÿÿÿU¹ÿÿÿÿ‰å‹E ‹P‹E9Pr—À¶È]‰ÈÃUºÿÿÿÿ‰å‹E ‹@9Er—À¶Ð]‰ÐÃvU‰åSƒì¶E ¶]Áà É$¸°E‰D$ÿE1Òƒì…Àu 1Ò8°E”‹]ü‰ÐÉÃë U‰åƒìÇ$ èD耣àEƒì…À£ðE„ ‰$¹+èD‰L$èØƒì…À„}¡àE1Ò…À… ‰`E1Ò…À…>‰pE1Ò…À…^‰€E1Ò…À…~‰E‹ðE1À…Ò… £ E¡àE1Ò…À…׉ðFE1Ò…À…§‰ GE1Ò…À…w‰GE1Ò…À…G‰GE1Ò…À…‰àFE1Ò…À…ç‰E1Ò…À…·‰ E1Ò…À…‡‰0E1Ò…À…W‰@E1Ò…À…'‰PE1Ò…À…÷‰`E1Ò…À…ljpE1Ò…À…—‰€E1Ò…À…g‰E1Ò…À…7‰ E1Ò…À…‰°E1Ò…À…׉ÀE1Ò…À…§‰ÐE1Ò…À…w‰àE1Ò…À…G‰ðE1Ò…À…‰E1Ò…À…ç‰E1Ò…À…·‰ E1Ò…À…‡‰0E1Ò…À…W‰@E1Ò…À…,‰PE¸‰D$Ç$èYýÿÿ…À„ÁÇ$ŠCè5Òÿÿ£EÉÉ$º+èD‰T$è}‰Â¡àEƒì‰`E1Ò…À„Åýÿÿv‰$¹7èD‰L$è_}‰Â¡àEƒì‰pE1Ò…À„§ýÿÿt&‰$ºDèD‰T$è/}‰Â¡àEƒì‰€E1Ò…À„‡ýÿÿt&‰$ºPèD‰T$èÿ|ƒì‰Âégýÿÿt&Ç$1ɉL$è~üÿÿ…À…%ÿÿÿÇ$º‰T$èaüÿÿ…À…ÿÿÿÇ$]èDèm'é÷þÿÿ‰$ºzèD‰T$è—|ƒì‰Âé¹þÿÿ‰$¹ƒèD‰L$è||‰Â¡àEƒìé‰þÿÿ‰$ºˆèD‰T$è\|‰Â¡àEƒìéYþÿÿ‰$¹èD‰L$è<|‰Â¡àEƒìé)þÿÿ‰$º›èD‰T$è|‰Â¡àEƒìéùýÿÿ‰$¹ èD‰L$èü{‰Â¡àEƒìéÉýÿÿ‰$º§èD‰T$èÜ{‰Â¡àEƒìé™ýÿÿ‰$¹®èD‰L$è¼{‰Â¡àEƒìéiýÿÿ‰$º¹èD‰T$èœ{‰Â¡àEƒìé9ýÿÿ‰$¹¾èD‰L$è|{‰Â¡àEƒìé ýÿÿ‰$ºÆèD‰T$è\{‰Â¡àEƒìéÙüÿÿ‰$¹ÐèD‰L$è<{‰Â¡àEƒìé©üÿÿ‰$ºÚèD‰T$è{‰Â¡àEƒìéyüÿÿ‰$¹èèD‰L$èüz‰Â¡àEƒìéIüÿÿ‰$ºöèD‰T$èÜz‰Â¡àEƒìéüÿÿ‰$¹üèD‰L$è¼z‰Â¡àEƒìééûÿÿ‰$ºéD‰T$èœz‰Â¡àEƒìé¹ûÿÿ‰$¹éD‰L$è|z‰Â¡àEƒìé‰ûÿÿ‰$ºéD‰T$è\z‰Â¡àEƒìéYûÿÿ‰$¹éD‰L$è1À…ÒuxÉÃf‹@ 1Ò‹@‹…Éu"‹H…Éu‹H…Éux u º¶É‰ÐËP …Òu-‹H…Ét‹P;P|HÇ$tñD¸k‰D$¸©ñD‰D$è n‹B‹@Éé\þÿÿÇ$ññD¸p¹©ñD‰D$‰L$èvn‹‘‰$ÿPEƒìë˶¼'U‰å‹E‹P¸ƒút 1Àƒú•ÀƒÀ]ÃU‰åSƒì‹M‹] ‹A…À„Š‹Q …Òt1ƒøt^ƒø…“‹R‹B‰‹B ‰C‹B‰C‹B‰C ‹]üÉÃt&ƒøuò‹Q…Òt‹A;A|+Ç$tñD¸»©ñD‰D$‰\$è¶m‹B‹@‰‹]üÉË‚‰$ÿPE‰ƒìëèÇ$ òD¸€‰D$¸©ñD‰D$èxmÇ$%òD¸Š‰D$¸©ñD‰D$èZmfU‰åSƒì‹]‹C…Àt ‹pE…Òu)‹C…Àu‰]‹]üÉé¬üÿf‰$è¬üÿ‰]‹]üÉéü«üÿ‰$ÿÒƒìëÍfU‰å‹U ‹M…Ò‹A t‰Q ]Ãt&¼'U‰å]Ãt&¼'Uº`‰åVSƒì‹]‰T$Ç$èà¦üÿÇ@òD‰ÆÇ@‹E ‰F F‰$èÀ¥üÿ‰^CÇF$ÇF8ÇF(ÇF,ÇF0ÇFTÇF\ÇFXÇFLt>ÇF<¸‰D$‹F‰$è …Àt ‰FƒÄ‰ð[^]Ét$¡E‰$è_ÉÿÿëäÿGE‰$èŸõÿÿëѶ¼'U‰åWV‰ÆSƒì|‹@ƒøÿt‰$1Ò‰T$è?‹F‰$ÿ0Eƒì‹V 1À1ÿ1Û‹ ‰D$‰|$‹FP‰D$ ‹FL‰\$‰$‰D$ÿÇE¤‹FL‹@ …Àt‹@‰E¤1À‰D$¸‰D$‹E¤‰$ÿðE‰E¨ƒì ‰F@„3‹F<…À…‹~@…ÿ…Æ‹FD…À…~‹FHƒøÛ÷ÓãÿéŠfÇE¸Ç$ÿPE‰E¼ƒì·Ã‰$ÿ`Ef‰Eºƒì‹VL1Àƒz”ÀHƒàôƒÀ‰D$EȃztE¸‰D$‹E¨‰$ÿÐEƒì @u^ÿGE=@'‰ÇuK…Û„¨Cÿ¿Ø…Û„šƒ}¤…lÿÿÿü1À}ȹó«fÇEȷÉ$ÿ`Ef‰Eʃìémÿÿÿ…Àua‹FL‹P …Ò„Oƒ}¤„vfÇE¸‹B‹@‰E¼·FP‰$ÿ`Ef‰Eºƒì¿‰|$‹E¨‰$è|…À„‰‰F¿ë‰<$è’óÿÿ‰F…ÿt,‹V »‹ ‰|$‹F‰D$‹FP‰D$ ‹FL‰\$‰$‰D$ÿeô‰ø[^_]ÃÇE¬¸‰D$E¬‰D$ ¸‰D$¸ÿÿ‰D$‹E¨‰$ÿàEƒìéEþÿÿÇE°E°¹‰D$ º»‰\$‰L$‰T$‹E¨‰$ÿàEƒìéýýÿÿÇE´¸‰D$E´‰D$ ¸‰D$¸ÿÿ‰D$‹E¨‰$ÿàEƒìéµýÿÿ‹H…Ét ‹P;PŒßÇ$dòD¸{‰D$¸©ñD‰D$èÕh·FPfÇEȉ$ÿ`E‹NLƒìf‰EÊ‹A ‹P‹B‰EЋB ‰EÔ‹B‰EØ‹B‰EÜ‹A ‹P‹B‰EÌ‹B‰Eàé[þÿÿ1Àƒ}¤”ÀHƒàôƒÀ‰D$Eȃ}¤tE¸‰D$‹E¨‰$ÿÀEƒì @tSÇF$‰t$1ÿ¡E‰$è{Åÿÿeô‰ø[^_]ÃÿGE‰$‰Çè±ñÿÿéþÿÿfÇE¸‹‘‰$ÿPEƒìé»ýÿÿÿGE=3'‰Çt¥‰$è{ñÿÿéäýÿÿ¶U¹`‰åSƒì‰L$Ç$èä¡üÿÇÀòD‰ÃÇ@‹E ‰C C‰$èÄ üÿÇC ‹EÇC$ÇC8‰C<‹EÇC(ÇC,‰C@‹EÇC0ÇCT‰CD‹EÇC\ÇCX‰CH‹E ÇCÿÿÿÿ‰CP‹E‰CLv¼'‰Øè)ûÿÿ…Àt‹CL‰$èjõÿÿ…ÀuæƒÄ‰Ø[]ô&¼'U¸`‰åWVSƒìlÇE´‰D$Ç$èû üÿÇóD‰ÃÇ@‹E‰C C‰$èÛŸüÿƒ}ÇC$‹EÇC8ÇC(ÇC,‰C0ÇCTÇC\ÇCXÇCLÇE°t1Àƒ}”ÀHƒàëƒÀ‰E°1ÿ¾‰t$‰|$‹E°‰$ÿðE‰Cƒì ƒøÿ‰Æ„aÇC<E´¹‰D$ º¸ÿÿ‰L$‰T$‰D$‰4$ÿàEƒìƒ}°„BfÇE¸‹E…Àt\‹E‰$ÿ E‰E¼ƒìƒøÿtE‰$ÿ@E%ÿƒì=”À¶À‰C0·E ‰$ÿ`Ef‰Eºƒì¸ƒ}°uD¸ë=‹E…À…&Ç$ÿPE‰E¼·E ƒì‰$ÿ`Ef‰Eºƒì¸ƒ}°t¼‰D$Eȃ}°tE¸‰D$‰4$ÿÐEƒì @„‰4$¸ÿÿÿ‰D$ÿEƒì@„܉4$¸‰D$èX…À‰Ç„‰4$ÿ0E‰{‰Øƒìeô[^_]Ãt&ÿGE‰$èRîÿÿ‰Ceô‰Ø[^_]Ãt&ü1À}ȹó«fÇEÈ‹E…ÀuJ¡èD‰EСèD‰EÔ¡èD‰EØ¡èD‰EÜ·E ‰$ÿ`Ef‰Eʃì¸é ÿÿÿÇ$éÕþÿÿ¡èD‰EСèD‰EÔ¡èD‰EØ¡ èDë´‰4$ÿ0EƒìÇ$è¥íÿÿéNÿÿÿÿGE…À‰Ç„Ûþÿÿ‰4$ÿ0Eƒì‰<$è|íÿÿé%ÿÿÿ‰\$¡E‰$èÁÿÿƒ}°”Â1Àƒ}”À…„ÿþÿÿ¿‰|$‹E‰D$ ‹E‰D$‹E ‰D$‹E‰$è•üÿÿ…À„Îþÿÿ‹p…öu ‰XX‰C\é¼þÿÿ‰$èS¢üÿé¯þÿÿ´&¼'U‰åSƒì‹]‹C\…ÀuD‰\$¡E‰$èÊÿÿ1À‰D$‹C‰$è‹C‰$ÿ0E‹CLƒì…Àu‰]‹]üÉéë¡üÿ‰$è£ÿÿÿ벉$è˜õÿÿ‰]‹]üÉéÌ¡üÿ¶¿U‰åWVSƒì‹}G‰Eè´&¼'‹G8…ÀtY‰Eð‰ÂG4‰E컉\$ ‰T$‰D$‹G‰$ÿEƒì‰Ã‰$èt …Û~t‹G8…ÀtY‹Eð9ÃŒÞÇG8‹G8…Àu§‹Eè‰$è•›üÿ…ÀŽæ‹G8…ÀuEð1Û‰D$Eì‰D$‹Eè‰$è{›üÿ‹Uð‹Eìéwÿÿÿ‰\$‹Eè‰$è¡üÿéLÿÿÿŒ§1ö‰Øþ'–ÂÁè…Â…­þ3'„¡…Û”ÀþE'” ШudþF't\‰4$èNëÿÿ‰D$Ç$èŽÑÿÿ‰4$è6ëÿÿ‰D$Ç$$óDèÖ éÑþÿÿ)؉D$D4‰D$G4‰$è·a‹Eð)؉G8éªþÿÿ‰wTeô[^_]ÃÿGE‰Æþ'‰Ø–ÂÁè…„SÿÿÿÇG$eô[^_]ÃfU‰åƒì‰]ø‹E‹]‰uü‰D$‹E s‰4$‰D$踛üÿ‹C$…Àu‰u‹]ø‹uü‰ì]é0šüÿ‰$èþÿÿ‰u‹]ø‹uü‰ì]éšüÿ´&U‰åƒì‰uü‹u‰]ø‹]F‰$ès üÿƒûwC‰\$V4‹E ‰$‰D$èH`‰^8‹V$‰Ø…Òu ‹]ø‹uü‰ì]Ãf‰4$è˜ýÿÿ‹F8‹]ø‹uü‰ì]ÃÇ$'óD»¹©ñD‰\$‰L$èE`¶¼'U¸ÈP‰åè3_‰]ô‹U¸‰uø‹] ‰}ü…Òu ‹]ô‹uø‹}ü‰ì]ÉT$¸°ŠC‰D$¡E‰$èÔ¿ÿÿ‰Ç…ÿ¸tΉÞÁît6‹GL…ÀuJ…ö¸t·‰4$èZéÿÿ‹W 1Û‹‰\$ ‰t$‰D$‹G ‰$ÿR둉$è” ·Ãƒø ‡éÿ$…`óD‰4$»èéÿÿ‹W ‹‰t$‰D$‹GP‰D$ ‹GL‰\$‰D$‹G ‰$ÿë‰$è£íÿÿ…À„pÿÿÿ‰øèDóÿÿ‰Æ‹GL…Àuàé[ÿÿÿ¸€h¯ÿÿ‰…`¯ÿÿ¸€‰D$1À‰$‰D$è¦^‰\$…`¯ÿÿ‰D$‹G‰$ÿ0Eƒì ƒøÿ‰Ã„òfƒ½h¯ÿÿu ‹w0…ö…ø‹G ‹‰\$‹G ‰$ÿR…Àt ‰$ÿ0Eƒì¸éŠþÿÿ¸µè¯ÿÿ‰…\¯ÿÿ‰t$1À‰D$ ¸P‰D$‹G‰$ÿ@Eƒì…À‰ÃŒ"„ñ‹G ‹1À‰\$ ‰t$‰D$‹G ‰$ÿR!…\¯ÿÿ…Û¨‹…\¯ÿÿéþÿÿÇG$‹GLÇG …À„iÿÿÿ‰$è°ðÿÿÇGL¸éäýÿÿ¹ºPµè¯ÿÿ‰L$ ‰T$‰t$‹G‰$ÿ@Eƒì‰Ã‰$躅ێþ‹G ‹¸‰\$ ‰t$‰D$‹G ‰$ÿRéƒýÿÿÇG$w‰4$èÌ–üÿ‰Ã‹G8‰<$Ãèúÿÿ‰4$èµ–üÿ‰Á‹G8Á9Ù·þÿÿ‹G ‹‰L$‹G ‰$ÿR ¸é/ýÿÿ‹O(…ÉtÇG,¸éýÿÿ‹W<…Ò…¸‰…d¯ÿÿ1Àµè¯ÿÿ‰D$ ¸P‰D$‰t$‹G‰$ÿ@Eƒì‰Ã‰$èÚ…ÛŒ6uQ‹G 1ö1Û‹1À‰D$ ‰t$‰\$é ýÿÿ…ý»AóD‰\$Ç$è‰Ìÿÿ‰\$Ç$$óDèÙ¸étüÿÿ‹G ‹1Àƒ½d¯ÿÿ‰\$ ‰t$”ÀéÁþÿÿ‹G 1É‹‰L$ 1À‰D$1À‰D$‹G ‰$ÿR!…\¯ÿÿé þÿÿÿGE=3'‰Æ„÷ýÿÿ‰$è»åÿÿé\üÿÿ¸‰…d¯ÿÿ…d¯ÿÿ‰D$¸s@‰D$‹G‰$ÿ Eƒì éØþÿÿÿGE=ú*…ýüÿÿ¸é¾ûÿÿ‹…l¯ÿÿèŽëÿÿ…À…õüÿÿéýÿÿÿGE‰$èCåÿÿ‰ÃéóþÿÿÿGE=3'‰Æ„êüÿÿ‰$è!åÿÿéÂûÿÿ¶¿U‰åVSƒì1öë t&‹CT…Àu#F‰t$¡E‰$è÷¸ÿÿ…À‰Ãuá…ÛuÕƒÄ[^]É$èÎäÿÿ‹S ‹ 1Ò‰T$ ‹ST‰D$‰T$‹C ‰$ÿQ…Ûu£ë̉ö¼'U‰å‹U ‹E‰P]ÃfU‰å‹E]‹@Ãt&U‰å‹E]‹Ã¶U‰å‹E]‹@Ãt&U‰åSƒì‹]‹E 9C(t‰C(…Àt ÇC,‹]üÉø‰D$‹C‰$è÷ ‹C,…ÀtÙ¸¹‰D$ Eû‰L$‰D$‹C‰$ÿ@Eƒì믶U‰åSƒì1Û‰\$¡E‰$èæ·ÿÿ…Àtf‹H(…ÉtC‰\$¡E‰$èÇ·ÿÿ…ÀuãƒÄ[]úC‰T$‹@‰$èh ëζU1À‰åƒì‰D$‹EÇ¡E‰$è~·ÿÿ…Àºÿÿÿÿt‹PɉÐô&¼'U‰åƒì‹E‹‰T$B‰¡E‰$èA·ÿÿ…Àºÿÿÿÿt‹PɉÐÃU¸°ŠC‰åƒì‰D$‹E‰D$¡E‰$èM¹ÿÿ1Ò…ÀtƒÀ‰$蜒üÿ1Ò…ÀŸÂɉÐÃU1À‰åƒì‰D$‹E‰$ÿE1Òƒì…Àt·@‰$ÿpEƒì·ÐɉÐô&U¸‰åSƒì‰D$Ç$è“üÿ‰Ã¸‰D$1À‰$‰D$èsXÇäóDƒÄ‰Ø[]ÃU‰åƒì¡0E…ÀuÉÃEü‰D$Eø‰$èÝÿÿ‹Eü‰D$‹Eø‰$èû:‹Eø‰$è`—üÿÉô&¼'U‰åWVµ¨þÿÿSì|»‰\$˜ýÿÿ‹}‰$è4Zƒì‰$èÉWfÇ\*ÆD‰$‰t$è Zƒìƒøÿ‰Ãt4´&‰4$¹@‰L$ÿ׉t$‰$èÖYƒì…Àu߉$è¿Yƒìè¯Y‰…”ýÿÿº…”ýÿÿ‰T$‰$ÿ׉<$è­9èøþÿÿeô[^_]ÃU‰åƒì8‰]ø]è‰uü‹u‰$è^Yƒì¸‰D$‰$]ØÿÖ‰$Eä‰D$E܉D$è,Yƒì ¸‰$‰D$ÿÖ‹]ø‹uü‰ì]ÃU‰åW¿V¾Sƒì|]¤èåM‰E¤‰|$}¸‰$ècÿÿèÆM‰E¤‰t$u°‰$èLÿÿè§M‰E¤¹‰L$‰$]˜è0ÿÿÇ$¿è|M‰E ºƒì‰T$E ‰$è ÿÿ‰$èRMƒì¸‰$]ȉD$èëÿÿ‰$è[Xƒì¸ ‰D$‰$]¨èÌÿÿè/X‰$UÀ‰T$‰|$ ‰t$‰\$èXƒì¸ ‰D$‰$è˜ÿÿèëW‰$UÀ‰T$‰|$ ‰t$‰\$èØWƒì¸ ‰$‰D$èdÿÿeô[^_]ö¿U¸‰åSƒì$]è‰D$E‰$è2ÿÿèíV‰Eô¸‰D$Eô‰$èÿÿ‰$è^Wƒì…Àu‹]üÉÃf‰$¸‰D$èïÿÿ‹]üÉÃU¸ ôD‰åƒì‰D$Ç$ ôDèELƒì…À•ÀɶÀô&U‰åƒìX‰}ü‹E¿ ôD‰]ô‹U‰uøÇlj|$Ç$ ôDèúK‰EÔƒì…Àt[è;W‰D$¾ Ç$(ôDèF“üÿ‰D$1ɺ‰T$‰Ã1À‰t$‰L$ ‰D$Ç$ÿÿÿÿèóVƒì…À”ƒøÿ‰Ç”À Шt‹]ô¸‹uø‹}ü‰ì]Ãv‰<$1À‰D$1À‰D$ 1À‰D$¸‰D$èV‰Æ‹E ƒì‰D$‹E‰4$‰D$è2TÇEغPN€‰$èT‰]à@»J‰EÜE؉D$ 1À‰D$‰\$‹EÔ‰$èKƒì…À~[¶¹¶FÁâÁà ¶FÁà ¶F ƒÂ‰UЉL$‰$è/Žüÿ…À‰Ãt ‹UЉt$‰$‰T$è¦S‹E‹U‰‹EЉ‰4$èÙUƒì‰<$èUƒì‹]ô¸‹uø‹}ü‰ì]ÃU¹ ‰åƒìº¡äSE‰L$‰T$ƒÀ@‰D$ Ç$@ôDè€SE ‰D$‹E‰D$¡äSEƒÀ@‰$èJT¡äSEÇ$ ƒÀ@‰D$èÚS¡HE…ÀuÇ$èõ½ÿÿÉÃv‰$è8üÿ1À£HEÇ$èÕ½ÿÿÉÃvU‰åƒì¡äSEÇ$@ôDƒÀ@‰D$ ¸ ‰D$¸‰D$èàRE ‰D$‹E‰D$¡äSEƒÀ@‰$èªS¡äSEÇ$ ƒÀ@‰D$è:S¡HE…ÀuÇ$èU½ÿÿÉÃv‰$è˜~üÿ1À£HEÇ$è5½ÿÿÉÃvU‰åƒì¡äSEÇ$@ôDƒÀ@‰D$ ¸ ‰D$¸‰D$è@RE‰D$‹E ‰D$¡äSEƒÀ@‰$è S¡äSEÇ$ ƒÀ@‰D$èšR¡HE…ÀuÇ$èµ¼ÿÿÉÃv‰$èø}üÿ1À£HEÇ$蕼ÿÿÉÃvU¹‰åƒìº¡äSE‰L$‰T$ƒÀ@‰D$ Ç$NôDè QE ‰D$‹E‰D$¡äSEƒÀ@‰$èjRÇ$ ¡äSEƒÀ@‰D$èúQÇ$èR´&¼'U1À‰å]Éö¼'U‰åƒìƒ} ‹UÀƒàüƒÀ…ÒtƒÈ‰D$¡ðGE‰$è;RƒìÉÃàý‰D$¡ðGE‰$è"RƒìÉÃt&U1À‰å]Éö¼'U‰åSƒì‹M ‹U‹E…Ét<‰D$¡ÀGE‰T$‰$è—Ëÿÿ¡PGE‰$èúÎÿÿ‰Ã¡ÀGE‰$èëÎÿÿÃĉØ[]ÉD$¡PGE‰T$ëÂU¸‰åƒì‰D$¸VôD‰D$Ç$lôDèdP¶¿U‰åƒì‰]ô‹]‰uø‹u ‰}ü‹}‰\$‰t$‰<$èHZüÿƒøÿt‹]ô‹uø‹}ü‰ì]ö‰\$‰t$‰<$è@Àÿÿ‹]ô‹uø‹}ü‰ì]ÃvU¸‰åƒì‰D$Ç$èŠüÿ‹U‰‹U ‰P‹U‰P‹U‰P ‰D$ 1À‰D$¸€‰D$¡pEE‰$è†FƒìÉÉö¼'U‰åƒìƒ} À÷Ѓà?‰D$¡ HE‰D$‹E‰$ÿ GE1Òƒì @uÿGEº›ôD=B'tº¬ôDɉÐÃvU¸H‰åèCN‰uø‹u‰}ü‹} …ö‰]ôˆì‰4$èùÿÿ‹ pGE…Éu1À‹]ô‹uø‹}ü‰ì]á E‰$¡EÿP …ÀtÝ…öަ1Û9ó}‰ö¼'€<;ÿt*C9ó|õ‰t$‰|$¡ E‰$¡EÿP ‹]ô‹uø‹}ü‰ì]ÃC9ðÏ1Ò…Û‰•äïÿÿ~‰\$‰|$¡ E‰$¡EÿP ‰…äïÿÿƒÃ¶ƒÃ¶C‰T$‰D$¡ E‰$¡EÿP9óŒ%‹…äïÿÿé-ÿÿÿt&Ç$1Àèïÿÿ‰D$¸‰D$1À‰D$ ‰ð÷؉D$1À‰\$‰D$è'PÆEçƒì‰Ù´&¼'‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁÒƒÙ)Ù€¼)çïÿÿ t.‰\$»ÌôD‰\$¡äSEƒÀ@‰$èmMÇ$èA¸ÿÿé`þÿÿ‰Ùv¼'‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁÒƒÙ)Ù1Àˆ„)çïÿÿë¸ ‰D$¡ E‰$¡EÿPéþÿÿ)Þ‰t$‰D$¡ E‰$¡EÿP …äïÿÿé³þÿÿvU¸$‰åSèòK‹E …Àx[¡pGE…Àu‹]üÉá E‰$¡EÿP …Àtç¡PGE‰$èüÊÿÿ‰Ã¡ÀGE‰$èíÊÿÿ‰D$¡ E‰$¡EÿP8‹]üÉÃÇ$1Û÷؉\$¹øïÿÿ‰D$1Ò1À‰L$‰\$‰T$ ‰D$èyNÆE÷ƒì‰Ù‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁÒƒÙ)Ù€¼)÷ïÿÿ tG‰\$ ºôôD‹E;PGEtºûôD‰T$ºõD‰T$¡äSEƒÀ@‰$è´KÇ$舶ÿÿéèþÿÿ‰Ù‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁÒƒÙ)Ù1Àˆ„)÷ïÿÿé|ÿÿÿ¶U¸'‰åWVSè€Jƒäð¸èsJèÞBÇ$¸1É£€GE¸1ö£ÐGEº¸0E‰µ,Ùÿÿ1Û¿ÿÿÿÿ‰4Ùÿÿ‰0HE‰D$‰½@Ùÿÿ‰<ÙÿÿèG ýÿÇ$põD1À£0GE¡4!E£0HE¡0!E£€GE1À‰…0Ùÿÿè˜K…À‰Æt9¡D…Àt01Û´&‰t$‹ƒD‰$è&K…À„Ѓà ‹»D…ÿuÙÿMu预À…ÇÿM„~ƒE ‹E ‹¶<-uß1Àƒ}¾0E¹‰t$ ‰L$~‹U ‹B‰D$‰$èRUüÿƒøþ„Pƒø„³Ht¦ü¿õD¹‰Þó¦…§ÿM¸£€Eu‹‰ö¼'‹•0Ùÿÿ¸…Ò…Ç$0EèÑŒüÿ…À„i Ç$0E¸†õD‰D$è”J‰Ã¹0E¶¼'‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁÇ$0EÒƒ0EƒÙ)Ùé/E‰L$‰D$è´IÇ$0EèHŒüÿ…ÀtGÇ$0E¸@‰D$èJ…À‰Ãt,-0Eƒøc†ÅC‰$èÂH‰\$@‰D$Ç$0Eè]IÇ$0Eè¡aüÿ‹…,Ùÿÿ…Àt ¸£Ð+EÇ$0E¸‰õD1ö‰D$1Ûè\IÆ€0E¶0E„Àt'ˆÁ€ù •À1Ò€ù •Â…ÐtˆŽ0EFC¶‹0E„ÉuÛÆ†0E‹=`*E…ÿu€=`(Eu€=Ü+Euƒ ÐGE‹5D…öt+‹ 4!E¸D1Ò‰ö¼'9Hø„:ƒÀ ƒÂ ‹…Ûuë1ÿ‰=E‹5E…ö„ƒ½@Ùÿÿÿt ‹@Ùÿÿ‰ 0!Eè‹Éÿÿ‹ GE…Ò…#Ç$‹õD¡äSEƒÀ@‰D$ ¸‰D$¸‰D$èÓG¸eô[^_]öÇ$0E褊üÿ…À…Y ü¿¥õD¹‰Þó¦…¢€{/s„ܸ‰ó£4!E¶„É•À1Ò€ù:•…Є]€ù/„I¶¼'C¶ „É•À1Ò€ù:•…Є1€ù/uâÆC€ù:„­¿ÿÿÿÿ‰=0!E‰t$»ÿ‰\$Ç$0Eè±FÆ/!Eénüÿÿ‰$¹,‰L$è|F‰…Ùÿÿ…À„–‹D…Ò„ˆ)؉…Ùÿÿ1À‰…Ùÿÿ붃…Ùÿÿ ‹•Ùÿÿ‹‚D…ÀtY‹Ùÿÿ‹±D‰4$è%F9…ÙÿÿuÍü‹…Ùÿÿ‰ß9À‰Áó¦u¼‹•Ùÿÿ‹Ùÿÿ‹‚DC£4!E£0HE‹‚D‹@@‰…@Ùÿÿ‰$¸@‰D$èG‰…Ùÿÿ9Ø„A‹…Ùÿÿ…À„4‹Ùÿÿ‰ßqƉ4$…¨Ùÿÿ‰D$è3ýÿ¡0GE…Àu•¨Ùÿÿ‰$è̈üÿ…À…8‰t$¸ÿ‰D$Ç$0EèkEÆ/!E¡€GE£0!E…ÿ„ûÿÿ‰|$¹c‰L$Ç$ 5Eè9Eƃ5EéöúÿÿÿMƒE éêúÿÿü¿­õD¹‰Þó¦tgü¿°õD¹‰Þó¦„Ò ü¿³õD¹‰Þ󦄶 ‰\$¸ºõD‰D$¡äSEƒÀ@‰$èùD¸‰…0Ùÿÿé‚úÿÿ¶„É„ÐýÿÿéÇýÿÿ¸‰…,Ùÿÿébúÿÿ‰\$ºØõD‰T$ë±Ç$¸0E1Û‰D$ècpüÿ‰$£HEè–´ÿÿÇ$1À‰D$ 1À‰D$1À‰D$èF£ HE‹=H!Eƒì…ÿ…A‰\$¡L!E¹ E‰L$¾0E»0E‰t$ ‰D$…TÙÿÿ‰D$¡0!E‰\$Ç$‰D$¡Eÿ…À„4‰D$¡äSEºöD‰T$ƒÀ@‰$èôCé<üÿÿÇ$ öD¡äSE»+‰\$¹‰L$ƒÀ@‰D$ èåCé üÿÿC1ÿ‰ÞéÑýÿÿ‹ƒD£4!E£0HE‹ƒD‹@@£0!E£€GEéùÿÿ€~/…üÿÿs éüÿÿÇ$0E»<&¨Ùÿÿ‰\$‰L$è=CéÎýÿÿ‰$èC£0!EéLüÿÿ‰D$¸0E‰D$Ç$ 5EèýBƃðéúÿÿÇ$öÿÿÿèmDƒì‰$èREƒìƒø…œþÿÿ»é’þÿÿ±/éþÿÿ‹‚D£EéÊúÿÿ¡HE1ö1ÿ»°¼C‰D$¡ E‰$¡EÿP4‹…TÙÿÿ‰$è½üÿÇ$öÿÿÿ¸£pGEèïC£ðGEƒìÇ$õÿÿÿèÛC£@GEƒìÇ$ôÿÿÿèÇC£@HEƒì¸°GE‰D$¡ðGE‰$è¡Cƒì¸‰D$¡ðGE‰$è€Cƒì1À‰D$ 1À‰D$¸°¼C‰D$¡@GE‰$èó»ÿÿ£PGE¡@HE‰t$‰|$ ‰\$‰$èÕ»ÿÿ£ÀGEè+D£pEE1ɉDÙÿÿè C‰Æ‹•DÙÿÿ…Ò„B‰4$…PÙÿÿ»ÿÿÿÿ‰D$èâ–ÿÿ…À…•LÙÿÿ1ÿ‰$è ½ÿÿ‰…Ùÿÿ¸‹Ùÿÿ‰D$‹…LÙÿÿ‰ $@‰D$è’~üÿ‰…Ùÿÿ‹•LÙÿÿ¡ HE‹µÙÿÿ‰–B¸‰D$‰\$ ‰|$‰t$‰$è:8‰…Ùÿÿ‹…LÙÿÿƒì9…Ùÿÿ‚p„á@;…Ùÿÿ„±½Ùÿÿ…ß‹…Ùÿÿ‹µPÙÿÿ‰$èøüÿ‹…DÙÿÿ…À…à¡pGE…À…¡PGE‰$è0¿ÿÿ‰Ã¡ÀGE‰$è!¿ÿÿ…À…Ïþÿÿ¡ E‰$¡EÿP$…Àˆú‰$èf«ÿÿ1ÀéÑøÿÿ‹dÙÿÿ‹C ‰D$‹C‰D$‹C‰$ÿ‰$èküÿ¸XÙÿÿ‰D$¸€‰D$ ¸€‰D$¸ÿÿÿÿ‰D$‰ $è!7ƒì…Àu£éÿÿÿèHA‰Æ‹…Ùÿÿ‰$èüÿ‹…DÙÿÿ…À„ ÿÿÿ¡ E‰$¡EÿP‰D$¡HE‰$è ¾ÿÿ¡pGE…À„ÿþÿÿ¡ E‰$¡EÿP …À…Ýýÿÿéâþÿÿ‹•Ùÿÿ‹–‰$è~¼ÿÿéþÿÿèÄ@‹PÙÿÿ)ÃéÝýÿÿ¡ E‰$¡EÿP(…À„¦ýÿÿ1À‰D$ 1À‰D$¸`ºC‰D$¡ðGE‰$è¸ÿÿ£HE¸‰…DÙÿÿéoýÿÿHÙÿÿ1ö‰ $èXåÿÿë…HÙÿÿF‰$è‡åÿÿ@uî;µ4Ùÿÿ‰1ɉ8ÙÿÿHÙÿÿ‰ $è"åÿÿë$‹µ8ÙÿÿHÙÿÿ‹•<Ùÿÿ‰²F‰µ8Ùÿÿ‰ $è<åÿÿƒøÿu×1ö;µ8Ùÿÿ­ýÿÿ‹…<Ùÿÿ•xÙÿÿ‹<°‰T$1Ò‰T$‰<$ÿàFEƒì …ÀtFëȉ<$è¥èÿÿ‹…xÙÿÿ1Û‰$è•èÿÿëCƒûwÝ‹ÝDõD…•xÙÿÿtë‰<$‹Ý@õD·Ò·„…|ÙÿÿÁà ‰T$è+Þÿÿ!pGEëÀ‹U1ÿ1ö1À…Ò„†¶ „Étt&¼'9þ}%ˆ CF¶ „Éuð9þ}:Æ FÿMtMƒE ‹U ‹ëʼn$¹¾‰L$‰|$èìzüÿ¶ Cˆ F뻉$¾º‰T$‰|$èÇzüÿë©…ötÆDÿ£`*E1Û¹‰d*E‰ h*EéŸóÿÿ‹•<ÙÿÿƒÆ»‰µ4Ùÿÿ‰\$‰t$‰$è{züÿ‰…<ÙÿÿéHþÿÿÇ$LöDè,>Ç$ Dè >Ç$xöDè>Ç$¨öDè>Ç$ßöDèü=Ç$èöDèð=Ç$÷Dèä=Ç$H÷DèØ=Ç$l÷DèÌ=Ç$Ÿ÷DèÀ=Ç$¼÷Dè´=Ç$ì÷Dè¨=Ç$øDèœ=Ç$@øDè=Ç$løDè„=Ç$¤øDèx=Ç$ÎøDèl=Ç$ìøDè`=Ç$ùDèT=Ç$DùDèH=Ç$xùDè<=Ç$ ùDè0=Ç$ÔùDè$=Ç$úDè=Ç$0úDè =Ç$\úDè=Ç$”úDèô<Ç$¼úDèè<Ç$ÜúDèÜ<Ç$ ûDèÐ<Ç$0ûDèÄ<Ç$TûDè¸<Ç$„ûDè¬<Ç$ÀûDè <Ç$õûDè”<Ç$üDèˆ<Ç$èl<Ç$DüD¡äSE¿%‰|$¾‰t$ƒÀ@‰D$ èŠ;¸éÒúÿÿè«ÿÿë¹Ç$jüD¸ D‰D$èD<ë¢U‰åSƒì‹]‹E‰$èÛ¹ÿÿ…Û‰Á|Uu&‹@1Û‹‰\$1À‰D$ 1À‰D$‹A‰$ÿRƒÄ[]Ë@‹‰\$ ‹E ‰D$¸‰D$‹A‰$ÿRƒÄ[]Ãt&‹@‹1À‰D$ 1À‰D$¸€üD‰D$ë¨t&U‰åSƒì‹E‹] ‰$èK¹ÿÿ‹@‹‰] ‰E‹J ƒÄ[]ÿá¶U‰å‹U ‹M…Ò‹At‰Q]Ãt&¼'U‰åSƒì‹]‹C ‰$è«¶ÿÿ‹C‰$è ¶ÿÿ‹C‰$è;‹Cƒì‰$è;‰]ƒì‹]üÉé(yüÿ´&U‰å‹E‹@ ‰E]éþ´ÿÿ´&¼'U‰å]ëÚv¼'U‰å]Ãt&¼'U‰å‹U ‹E‰P]ÃfU‰å‹E]‹@Ãt&U‰å]Ãt&¼'U‰å‹E]‹@Ãt&U1À‰åWVS켋U(ƒº(…¾‰T$‹Eu؉D$‹E‰$èÙ©üÿ‰D$‰ÇÇ$äüDè§wüÿ‰D$‰ÃÇ$èE©ÿÿ‰$è=xüÿÇ$¸ ‰D$èhsüÿÇÀüD‰Ã‹E$ÇCÇEØ ‰C1À‰D$ …tÿÿÿ‰D$…pÿÿÿÇEÜÇEà‰t$‰$è4;ƒì…ÀuÇ$ýDèwüÿ‰C‰Øeô[^_]Ét$1À‰D$ …lÿÿÿ‰D$…hÿÿÿ‰$èò:ƒì…Àu3‹…pÿÿÿ‰$èÝ9‹…tÿÿÿƒì‰$èÌ9ƒìÇ$ýDèµvüÿ‰Cëš1À¾‰D$‹…lÿÿÿ‰t$1ö‰$è‘:‹…pÿÿÿ1ɺƒì ‰T$‰L$‰$èq:ÇEˆD‹…hÿÿÿƒì ÇEŒÇE‰EÀ‹…tÿÿÿÇE”ÇE´‰EÄ…xÿÿÿ‰D$$Eˆ‰D$ 1À‰D$1À‰D$¸ ‰D$¸‰D$1À‰D$ 1ÀfÇEºÇE¼ÇEȉ|$‰D$Ç$èÒ9‹…hÿÿÿƒì(‰$èÑ8‹…tÿÿÿƒì‰$èÀ8‹…lÿÿÿƒì¹@ÎC‰C‹…pÿÿÿ‰C‰L$‰t$ ‰\$‹C‰$è÷¯ÿÿ‰C1Ò¸ÐÎC‰T$ ‰\$‰D$‹C‰$èæ°ÿÿ‰C ‹E‰$èÈÉÿÿé=þÿÿU‰åSƒì‰Ã‹@…Àua‹C…ÀuI‹ƒøÿt‹S…Òu‰$è+8Çÿÿÿÿƒì‹]üÉÃt&‰$è@9‹ƒì‰$è8ÇÿÿÿÿƒìëÖ‰$èè²ÿÿÇC릉$èײÿÿÇC뎴&¼'U‰åVSƒì‹u‹E‰$èú´ÿÿ…ö‰Ã~$‰t$ 1É‹E ‰L$‰D$‹C ‰$èhåÿÿƒÄ[^]ÃtN¾@ýD‰Øè"ÿÿÿ‹C ‰$è¡ÿÿ‰t$‹C ‰$è¦ÿÿ‰t$¾aýD‰t$‹C ‰$èãÿÿƒÄ1À[^]ô&¾dýDë°‰ö¼'U‰åƒì‰uü‹E‹u ‰]ø‰$èV´ÿÿ…ö‰Ãx‰p‹]ø‹uü‰ì]Ãvè›þÿÿ‹C ‰$è ÿÿ¸ŒýD‰D$‹C ‰$è|¥ÿÿ¸ŒýD‰D$¸aýD‰D$‹C ‰$èÿâÿÿ‹]ø‹uü‰ì]Ãt&U‰åWV‰ÆEÈSƒìl‰U¤‰D$‰$è³7ƒì…À„ȶUжEÑ€â߀Ê€â3 $ˆUЋUˆEÑ‹‚À‰ẺD$Ç$«ýDèAsüÿ‰D$‰Ã‹F ‰$èà¤ÿÿ‰$èØsüÿ‹U‹‚ĈEÚ‰D$Ç$ÄýDè süÿ‰D$‰Ã‹F ‰$諤ÿÿ‰$è£süÿ‹U‹‚ȃø„Aƒø„ºàýDeô‰Ð[^_]ô&ƒøuåÆEÜ¿þDéÆEÛ¿þDt&‰|$Ç$þDèrüÿ‰D$‰Ã‹F ‰$è/¤ÿÿ‰$è'süÿ‹U‹‚Ѓø„Ž<ƒø„ƒø„t¶¼'‰|$Ç$-þDè0rüÿ‰D$‰Ã‹F ‰$èÏ£ÿÿ‰$èÇrüÿEȉD$‹U¤‰$è-6ƒì…ÀºLþD„$ÿÿÿÇE¨E¨ÇE¬ÇE°ÇE´ÇE¸‰D$‹E¤‰$èà5ƒì…ÀºlþD„ßþÿÿeô1Ò‰Ð[^_]Ãt&ÆEÜ¿þD‰|$Ç$”þDè‡qüÿ‰D$‰Ã‹F ‰$è&£ÿÿ‰$èrüÿ‹U‹‚̃ø‡¼þÿÿÿ$…ÜþDÆEÜ¿­þDë³€MÑ¿¯þDéüþÿÿ¶EÑ¿¸þD€MÐ$Ï ˆEÑéãþÿÿ…À…Ûþÿÿ¿ÀþDéÑþÿÿÆEÛ¿ÃþDécþÿÿÆEÛ¿ÈþDéUþÿÿÆEÛ¿ÍþDéGþÿÿÆEÛ¿ÀþDé9þÿÿ¶EпÑþD$Ï (ˆEÐé„þÿÿt&U¸‰åWVSƒì,‰D$Ç$è’lüÿÇÿÿÿÿ‰ÆÇ@Ç@Ç@Ç@‹E ‰0‹E‰F ‹EÇ$ðþDÀ‰Eð‰D$èXpüÿ‰D$‹F ‰$èù¡ÿÿ¸\‰D$‹Eð‰$è1…Àº ÿD„€‰T$‹Eð1ÿÇ$ ÿD‰D$èpüÿ‰|$‰Ã1À‰D$¸@¹À‰D$¸‰D$1À‰L$‰D$ ‰$èò3ƒì‰Ç‰$è}püÿƒÿÿ¸ÿDt‹E‰ú‰$‰ðèüÿÿ…Àteô[^_]ú*ÿDévÿÿÿ‰>º¸ÀÓC‰T$ ‰t$‰D$‰<$èþªÿÿ‰F¸‰D$ ¸ ÓC‰t$‰D$‰<$èÍ©ÿÿ‰F‹Eð‰$è_müÿ‹U‰‹F ‰$èžÿÿ1Àë‹t&¼'U‰åSƒì‹]‰ØèÏùÿÿ‰$èdžÿÿ‰]Z[]é¼oüÿ¶¿U‰å‹U ‹E‰U‹]éLûÿÿ¶¿U1À‰åSƒì‹]‹S…Òu ƒÄ[]ô&‹E‰D$‹E ‰$‰D$èJ«ÿÿ‰CƒÄ[]ÃU‰å‹E]‹@Ãt&U‰å]Ãt&¼'U‰åSƒì‹]‹C;E ‹…Àu‹]üÉÃv‰$è2ÇC‹C ƒìÇE /ÿD‹]ü‰EÉéèŸÿÿ´&U‰åSƒì‹]‹…À•À1Òƒ} ”Â…Ðu‹]üÉøHÿD‰D$‹C ‰$詟ÿÿ‹‰$èÿ1ƒì¹`ÙC‰\$‰L$Ç$èãƒÿÿ‰CÇC‹]üÉÃt&U¸tÿD‰å]öU¸‰å]öU¸‰å]öU‰å‹E‹@…Àu]ÉE]éG­ÿÿ´&U1À‰å]Éö¼'U‰å]Ãt&¼'U‰å]Ãt&¼'U‰å‹E]ƒ8ÿ•À¶ÀH%€Hô&U1À‰å]ÃU‰åW1ÿV‰Æ¶S‰Ó„É„}‰ö¼'€ù ”À€ù\” Шu.€ù*t)€ù?t$€ù%t€ù~€ùt€ù.”À1Ò…ÿ”Â…Ðt@t&Æ%C¶Àè¶À¶€ÿDˆC¶ƒà¶€ÿDˆCF¿¶„ÉuŒÆ[^_]È ëæU‰åWVSƒì‹]‹} …ÛÇ„”€;„‹‰$¾è-‰t$D@‰$èhüÿ‰Â‰Æ‰ØèÿÿÿÇ$€Eð¹ ÿD‰D$‰L$è^$ƒì …ÀuJ‰t$Eì‰D$‹Eð‰$èA$‰Ã‹Eðƒì ‰$è)$ƒì…ÛuF‰4$èzlüÿ‹Eìeô[^_]ûÄÿDékÿÿÿ‰4$è]lüÿÇ$ØÿDº ÿD‰T$è˜küÿ‰1Àeô[^_]Ét$¸ ÿD‰D$Ç$ Eèsküÿ‰‰4$èlüÿ1ÀëÑt&U‰åƒì(‰uü‹u‰]ø‹]…öt2‰$è¢,‰\$@‰D$¸‰D$ 1À‰D$‹E ‰4$‰D$èc#ƒì‹]ø‹uü‰ì]ô&¼'U‰åƒì‹U…Òt1‰$¸‰D$E‰D$¸‰D$ 1À‰D$‹E ‰D$è #ƒìÉÃU‰åƒì‹E‰$èÿ"ƒìÉÃv¼'U‰åVSƒì ‹]…Ûti€;td‰$èä+D@º‰T$‰$è_füÿ‰Â‰Æ‰ØèTýÿÿÇ$€Eô‰D$¸ ÿD‰D$èˆ"ƒì …Àt!ÇEð‰4$èâjüÿ‹Eðeø[^]ûÄÿD땉t$Eð‰D$‹Eô‰$èJ"ƒì …ÀtÇEð‹Eô‰$èA"ƒì‰4$è–jüÿ‹Eðeø[^]ö¿U‰åSƒì$‹U‹E‹]…Ò‰Eøt6‰\$Eø1ɉD$Eô‰D$ ‹E ‰L$‰$‰D$èÊ!ƒì…Àuƒ}ô‰Øt1À‹]üÉö¿U‰åƒì(ÇEü‹U…ÒttÆ,FGÿMÌy‡Æ‹U‰T$‹}ä‰<$èw#…À…dþÿÿ‰<$¾1Ûèˆ"‰|$@‰D$‰t$ ‰\$‹Eà‰D$‹Eð‰$èMƒìé*þÿÿ1ÒI„Åýÿÿt&eôº‰Ð[^_]ÃAé/ÿÿÿ‰ö¼'U‰åƒì(‰uø‹u‰]ô‹]‰}ü‰4$è"‰$‰Çè "ºD@‰T$‰$è\üÿ‰\$‰Ç‰ò‹E ‰$‰øè,üÿÿÇ$€Eð‰D$¸\E‰D$è¸ƒì …Àt‰<$èaüÿ‹]ô‹uø‹}ü‰ì]Ãt&‹E¾1Û‰$èŽ!@‰D$‹E‰t$ ‰\$‰|$‰D$‹Eð‰$èS‹Eðƒì‰$èMƒì‰<$è¢`üÿ‹]ô‹uø‹}ü‰ì]Ãt&U‰Á‰åSƒì$…Ò‹]t`‰ $1Àƒú‰D$•¶ÂH%€‰D$¶ÂƒÀ‰D$1À‰D$ ¶Â@‰D$¶ÂH%À-€‰D$è›#‰ƒì‹]üÉ@•À¶ÀÃf‰$è"Çÿÿÿÿ1À‹]üÉÃt&¼'U1Ò‰åW¹½¸ýÿÿV‰ÆSì\Èýÿÿ·‹E‰L$‰T$f‰…Èýÿÿ…Êýÿÿ‰$ès Ç$€¸‰…Àýÿÿ…Äýÿÿ‰D$¸E‰D$è!ƒì …À„¸‹  EE…É„.¡€EE…À„ˉ\$1É1Ò‰L$ ¹‰T$‰L$Ç$ÿЃì…Àx8‰$èêÇ\PUTºTY.R‰T‰òfÇDNDÆD ‰Ø‰<$è‚þÿÿ…À…,‰\$1À¹‰D$ 1À‰D$‰L$Ç$ÿ€EEƒì…Àx=‰$è…Ç\PUTºTY.R‰T‰òfÇDNDÆD ‰Ø‰<$èþÿÿ…À…Çt&‰\$¹‰L$Ç$¸Eè"ºƒì )‰T$‰D$Ç$ÂEèö!ƒì …Àt4‰$èÇ\PUTºTY.R‰T‰òfÇDNDÆD ‰Ø‰<$èŸýÿÿ…ÀuM‰$¹‰L$è*!ƒì‰$è¿Ç\PUTºTY.R‰T‰òfÇDNDÆD ‰Ø‰<$èWýÿÿ…Àºÿÿÿÿt‹•¸ýÿÿeô‰Ð[^_]É\$…Àýÿÿ¿ËE‰D$…¼ýÿÿ‰D$ 1À‰D$‹…Äýÿÿ‰|$‰$è!ƒì…À„~Æ…Èýÿÿ‹…Äýÿÿ½¸ýÿÿ‰$èƒì€½Èýÿÿ„Ýýÿÿ‰<$‰ò‰ØèÇüÿÿ…À…qÿÿÿéÄýÿÿÇ$ØEèæ£EEƒì…À„¶ýÿÿ‰$ºäE‰T$è½£€EEƒìéýÿÿƒ½¼ýÿÿ…uÿÿÿéwÿÿÿ´&¼'U¸‰åWVSì<èÚüÿÿƒøÿ‰ÃtX½äûÿÿµèûÿÿët&‹…äûÿÿ…Àt0‰D$‰4$ÿU‰|$ 1À‰D$¸‰D$‰t$‰$轃ì…ÀuƉ$èÖƒìeô[^_]ÃvU¸‰åSƒì$è_üÿÿƒøÿ‰Ãt1‰$1À‰D$Eø‰D$ ‹E ‰D$‹E‰D$è]ƒì‰$肃ì‹]üÉÃfU‰åVµèþÿÿSì0‰Ãë‰t$‰$èƒì‰t$¸‰D$ 1À‰D$‰$èYƒì…Àu;‰t$…äþÿÿ‰D$‰$èTƒì …Àu²‹…äþÿÿè’ÿÿÿ‹…äþÿÿ‰$èDƒìë”eø[^]ô&U1À‰åVµäþÿÿSì0èxûÿÿ‰t$¸E‰D$Ç$€èïƒì …Àt(‰t$¸õE‰D$Ç$€èÏƒì …ÀtHeø[^]Ë…äþÿÿèÿÿÿ‹…äþÿÿ‰$è·ƒì¸õE‰t$‰D$Ç$€è‹ƒì …Àu¼t&¸ E»‰D$‹…äþÿÿ‰$èTƒì…èþÿÿ1ɉD$‹…äþÿÿ‰\$ ‰L$‰$è'‰Ã‹…äþÿÿƒì‰$è<ƒì…Û„Yÿÿÿ‰t$ºE‰T$Ç$€èƒì …À…5ÿÿÿ¸E‰D$‹…äþÿÿ‰$èÖ‹…äþÿÿƒì‰$èåƒìéÿÿÿU‰åEèSƒìT‹]‰$è³·Eôƒì1ɉE¸·Eò‰E¼·Eð‰EÀ·Eî‰EÄ·EêH‰EÈ‹Eèf=kv ·Àˆ”øÿÿ·Uì‹E¸‰‹E¼‰C‹EÀ‰C‹EĉC ‹EȉK‰S‰C‰ØÇCÿÿÿÿÇC ‹]üÉÂUº‰åƒì‰4$‰|$‹} ‹M‹9wr&üƒÇq¹ó¦—Â’À(¾ҋ4$‰Ð‹|$‰ì]Ë4$ºÿÿÿÿ‹|$‰ì‰Ð]ô&U¸”‰åWVSƒì\‹]‰D$Ç$è_Tüÿƒû‰Æ„ƒû…$»¹‰˜€1Û‰ˆˆv1ÀƒûtèÞþÿˆ3Cƒû~ëÇ$ðîCèÿoÿÿ‰†‹E 1Û}¨‰D$‹†€‹…XE‰D$‹E‰$èaÆE¨‹–ˆ…Ò~_v‰ù´&¼'‹ƒÁÿþþþ÷Ð!Â €€té÷€€uÁêƒÁ¶3ÒƒÙC‰ $‰D$¸dE‰D$è9žˆ¤‰|$‹E‰D$‹E‰$èÞƒÄ\‰ð[^_]ø1Û‰†€¸‰†ˆèÝþÿˆ3Cƒû~ò1ÀéÿÿÿÇ$iE¿L¾}E‰|$‰t$èá‰ö¼'U‰åSƒì‹]‹ƒ…Àt0ë‰$è¢Wüÿ‹ƒ‰$1Ò‰T$è.ÿÿ…Àuà‹ƒ‰$èoÿÿ‰]ƒÄ[]éoWüÿë U1Ò‰åƒì¹@‹E‰„Œ‰ˆŒ‰T$ P@„‰D$‹E ‰T$‰$èÏ–ÿÿÉö¼'U‰å]Ãt&¼'U‰åƒì‰]ø‹]‰uü…Ût-‹‰$ÿP‰Æ‹@…Àu,‰4$èÔVüÿ‹‰]‹uü‹]ø‹H‰ì]ÿá‹]ø‹uü‰ì]ö‰$è¨Vüÿ‹F‰$èVüÿ‰4$è•Vüÿ‹‰]‹uü‹]ø‹H‰ì]ÿáfU‰åSƒì‹]‹CD‰$èûRýÿ‹CH‰$è`ÿÿÿY¸[]ô&U‰åSƒì‹E‹]‰D$‹E‰D$‹CD‰$èÍPýÿ…À~ÇC4‹CH»‹‰\$‰$ÿRƒÄ¸[]ÃvU‰å‹E‹@D‰E]éž?ýÿ´&¼'U¸‰E‰åSƒì‹]‰D$‰$è]€<t‰$¸‹E‰D$èF€<uƒÄ1À[]ÃD‰EƒÄ[]é/ë U‰åƒì‰]ø‹E‰uü…Àt€8u8è#•ÿÿ…À‰Æt¶„ÒuÇ$EèªRüÿ¶‰Æ€ú:‰ðt‹]ø‹uü‰ì]Ãt&‰$ë܉t$1À‰D$Ç$àçDèÕQüÿ‰4$‰Ãè Uüÿ‰Ø‹uü‹]ø‰ì]Ãë U‰åWV¾‰ESìÜ‹] ‰$èTÿÿÿ‰$‰Ã‰t$è^…À‰Æ„11À‰…Lÿÿÿ€<…šƒþ‡!‰t$…hÿÿÿ¿¤E‰\$‰$èF‰$1Àˆ„.hÿÿÿµhÿÿÿèoTüÿü¹ó¦…ñ‹•Lÿÿÿ…Tÿÿÿ‰D$‰$èY¼ÿÿ‰Ç1À‰…PÿÿÿÇ$¸L1Û‰D$èhOüÿÇE‰Æ1ÒÇ@‹E¹ÇF0‰F‹EÇFÇF8‰FD‹E ÇF4‰T$ ‹•Pÿÿÿ‰D$ 1À‰D$‹…Tÿÿÿ‰\$‰L$‰T$‰t$‰D$‰<$è1nüÿ‹U‰‰FH‹‹‰$ÿR …À‰Ã„œ‰4$èSüÿ‰ØÄÜ[^_]þéÕþÿÿ¶‹…Lÿÿÿ‹U p‰…Pÿÿÿ1À‰D$…Tÿÿÿ‰D$‹…Pÿÿÿ‰T$ •hÿÿÿ‰$‰D$èmüÿ‰$‰ÇèV¹ÿÿ…À‰Ã„Ýþÿÿ‰<$èÔ¦ÿÿë…fD3‰$褉…LÿÿÿéOþÿÿ‹E…ÀtA…dÿÿÿ•Xÿÿÿ‰D$…`ÿÿÿ‰D$…\ÿÿÿ‰D$ ¸©E‰D$‹E‰T$‰$èƒøtDÇF<ÇF@ÿÿÿÿ‹U‹‹‰$‰t$ÿR1ÀéÿÿÿÇ$µE¹%º}E‰L$‰T$è…‹•Xÿÿÿ‹…\ÿÿÿÁâÁà ‹…`ÿÿÿÁà ‹…dÿÿÿ ‹E‰V<‰F@ë˜t&¼'U‰åSƒì‹]…Ût&‹‰$ÿP‹Ç@4‹@8‰$…À•À¶À‰D$ÿRƒÄ[]öU‰åƒì‰]ø‹]‰uü‹u …ÛtJ‹‰$ÿP1É‹‰p8‹@4…Àt‰]¹‹]ø‰M ‹uü‹J‰ì]ÿá…öuã‰M ‹uü‹J‰]‹]ø‰ì]ÿáv‹]ø‹uü‰ì]öU1Ò‰åWVS켋u…ö„7‹U‹‰$ÿP‹]…Û‰…TÿÿÿŽ8‹Xƒû 2CÿM‰Ã‹Tÿÿÿ‹u ‰A¶F‰u ˆD ‹M…ÉŽƒû C~Ñ‹…Tÿÿÿ‹P…Ò…¤¶P€úB„ЋTÿÿÿ¶C ¶K Áà‹µTÿÿÿ Á€úB‰N „³‹½Tÿÿÿ¶G ¶W Áà ‹…Tÿÿÿ¿‰P(A‹Tÿÿÿƒàü‰A$Bƒàü‰A,¸‰D$‹A$@‰$èÀKüÿ‹Tÿÿÿ‰C‰|$‹C,‰$è¨Küÿ‰C‹µTÿÿÿ‹^‹u…öŽF‹½Tÿÿÿ‹W$B 9Ã}@ÿM‰Ú‹…TÿÿÿC‹H‰XÊ‹M ¶A‰M ˆBô‹}…ÿŽè‹Tÿÿÿ‹S$‹[B 9Ã|Á‹u…öŽù‹µTÿÿÿ‹N,D 9Ã}Ct&ÿM‰Ù‹½TÿÿÿC)Ñ‹W‰_‹] ¶C‰] ˆD ô‹]…ÛŽs‹W$‹O,‹_D 9Ã|ÂD 1Ò9ÃŒd‹…Tÿÿÿ‹H0…É…/‰Á‹P ‹@Æ‹Y<‹y‹A‹q@‰]¤‹Ÿ€‰}œ‹Q‹I(‰E˜‹XE‰M”‰u ‰D$‰$èÅ…À¹ÀE…ÇK„T‹Eœƒ¸€„*‹•Tÿÿÿ1À‰…pÿÿÿ‹R‹š„‰•lÿÿÿ‹XE‰$艅hÿÿÿK„‹Tÿÿÿ€yB„ɶ•hÿÿÿ‹TÿÿÿˆQ ‹…hÿÿÿÁøˆA ¶pÿÿÿˆY ‹…pÿÿÿÁøˆA ‹u¸ ‹‰D$‹…Tÿÿÿ‰4$ƒÀ‰D$ÿR‹½hÿÿÿ…ÿ…‹pÿÿÿ…É…Ä‹TÿÿÿÇC0‹u‹}‹‰|$‹U ‰4$‰T$ÿP‰Â‰ö¼'ļ‰Ð[^_]öH ¶@ Ááé1ýÿÿ‹½Tÿÿÿ‹_1Òƒû îüÿÿļ‰Ð[^_]ÃÇ$èî‹Uˆ¹èE)‰Й1Ð)Ð=°eÇ$¸ ‰D$èùHüÿ‹Mˆ‰Ã‰‹G‰C·G f‰C‹uœ‹†…À„ʉ\$‹}œ‹‡‰$èÞkÿÿ9Ø„]‰$ènMüÿ¹E‰L$Ç$:Eè©Lüÿ‰…|ÿÿÿ‰$èû ‰…tÿÿÿºƒÀ ‰T$‰$èqHüÿ‰…xÿÿÿ‹µtÿÿÿƶtÿÿÿƒÆƒæüˆX‹½Tÿÿÿ‹•xÿÿÿ‹G‰B€B„‹xÿÿÿ‰ðÁøˆC‰ðÁø ˆC‹xÿÿÿ1À‰t$‰D$ƒÃ‰$è} ‹½tÿÿÿ‰|$‹…|ÿÿÿ‰$‰D$èy F‰D$‹•xÿÿÿ‰T$‹Tÿÿÿ‹AD‰$è'Gýÿ‹Tÿÿÿ‹CD‰$èIýÿ‹u‰4$èkõÿÿ‹½xÿÿÿ‰<$è]Lüÿ‹…|ÿÿÿ‰$èOLüÿļ1Ò‰Ð[^_]˽Tÿÿÿ‹_‹W$‹O,éŠüÿÿ‹…Tÿÿÿ‹X‹P$éüÿÿ¶V ¶F ÁâéNûÿÿ‹½Tÿÿÿ‹W$éüûÿÿ‹µTÿÿÿ‹N,éMüÿÿƒ}”¹PE…wþÿÿƒ} ÿ¹|E„hþÿÿºƒÀ ‰T$‹U˜‰$‰T$èv|þÿü‹uœ¹‹}˜ó¦—Â’À8¹¸E…,þÿÿ‹E˜‹M˜¶P¶@ ÁâÁà ¶A Áà ¶A ¹¸E Â;U¤…ùýÿÿ‹]˜¶C ¶S Áà Ð;E …àýÿÿ¶sÁæ‰uˆ¶CÁà Ɖuˆ¶CÁà Ɖuˆ¶C Ƹ‰uˆë´&@ƒøýÿÿ‹}˜€<8tí¹¸EéŠýÿÿv‹xÿÿÿ‰ò‰ðÁúÁø ˆAˆQéõýÿÿ‹]”¹àE9Ÿˆ…Xýÿÿü‰þ‹}˜‰Ù9Ûó¦—Â’À8¹ E…9ýÿÿétûÿÿ‹]‹•pÿÿÿ‹‰T$U¨‰T$‰$ÿP÷pÿÿÿº¼E‹ƒ¥pÿÿÿ‹pÿÿÿ‰T$‰$‰L$ÿPéóûÿÿ‹½hÿÿÿ»¼E‹‰|$‹Tÿÿÿ‹A‹€„‰4$‹…XE‰D$ÿR‰ø‹÷؉\$ƒà‰D$‰4$ÿRé˜ûÿÿ‹…hÿÿÿÁøˆA ¶hÿÿÿˆY ‹…pÿÿÿÁøˆA ¶…pÿÿÿé8ûÿÿ‹lÿÿÿ‹Œƒø@‡‰…pÿÿÿ‹•lÿÿÿ]¨‰dÿÿÿ‰ÃƒÂ@ƒøv&ö…dÿÿÿt‹µlÿÿÿ}¬ƒë‹F@‰òƒÂD‰½dÿÿÿ‰E¨ü‰Ù‹½dÿÿÿÁé‰ÖöÃ󥉽dÿÿÿ‰òt·ƒÂf‰ƒÇ‰½dÿÿÿöÄgúÿÿ¶‹•dÿÿÿˆéWúÿÿÇ$4E¸í‰D$¸}E‰D$è1 1À‰D$‹Uœ‹‚‰$èÂgÿÿ…À‰ÃtN‹Eˆ‹3)ð=°†Ñùÿÿ1ɉL$‹Mœ‹‰$èspÿÿ‰$èËHüÿë°Ç$]E¸¦‰D$¸}E‰D$ëÇ$sE¸¯¿}E‰D$‰|$érÿÿÿÿ%´REÿ%ÄREÿ%ÀREÿ%ÌREÿ%ÈREÿ%ÐREÿ%¸REÿ%¼REÿ%ÈTEÿ%ÐTEÿ%ÄTEÿ%ÀTEÿ%ÌTEÿ%àTEÿ%¼TEÿ%ØTEÿ%ÔTEÿ%ÜTEU‰åƒì¡pDƒ8tÿ‹pDB‹R£pD…ÒuéÉô&U‰åSƒì¡` Dƒøÿt)…À‰Ãt‰ö¼'ÿ` DKuöÇ$DèÊüÿY[]Ã1Àƒ=d Dë @‹…d D…Ûuôë¾¶¼'U¡ÀEE‰å…Àt]Ãf]¸£ÀEEëƒU¹@E‰åë¶‹Q‹ƒÁ‚@ù@Erê]ÃU‰åSœœX‰Ã5 PœX1Ø© „À1À¢…À„´¸¢öÆ…§‰Ð%€f…Àtƒ ÐEE÷€tƒ ÐEE÷Âtƒ ÐEE÷Âtƒ ÐEEâtƒ ÐEE öÁtƒ ÐEE@öÅ t ÐEE€¸€¢=€v,¸€¢¡ÐEE‰ÁÉâ@t £ÐEE¶[]à ÐEEéMÿÿÿ[‰ ÐEE]ÃU‰åÛã]ÃU¡`HE‰å]‹Hÿá‰öUºB‰åS·Àƒìd‰T$U¨1Û‰T$‰$ÿ SEº¹ƒì …Àuë=ÉJx€|*¨Auô ËÉJyòƒ;Tu‰Ø‹]üÉÃÇ$¤Eº÷¸ÔE‰T$‰D$è£Ç$E»ñ¹ÔE‰\$‰L$è…¶¼'U‰åWVS켋=`HE…ÿteô[^_]ÃÇE˜AAAA¡€E}˜ÇEœAAAAÇE AAAA‰E¸¡„EÇE¤AAAAÇE¨AAAA‰E¼¡ˆEÇE¬AAAAÇE°AAAA‰EÀ¡ŒEÇE´AAAA‰EÄ¡E‰EÈ¡”E‰EÌ¡˜E‰EСœE‰EÔ· Ef‰E؉<$ÿSE·Àƒì…À…qÇ$TèÉ…À‰Ã„‰$1ɾT‰L$‰t$è0ÇC8 D¹ÇC€D¡ðEEÇT‹ôEEÇC(‰C¡€D‰S‹„D‰C¡FEÇC,ÿÿÿÿ‰S ‰C0¡ˆD‹ŒD‰C4¡FE‰S8‹FE‰C<¡ FEÇCDÿÿÿÿ‰S@‰CH‹”D¡D‰SPº‰CL‰Ø!ȃøÀ$ ÉAˆ„*HÿÿÿJyç¡€E‰…hÿÿÿ¡„E‰…lÿÿÿ¡ˆE‰…pÿÿÿ¡ŒE‰…tÿÿÿ¡E‰…xÿÿÿ¡”E‰…|ÿÿÿ¡˜E‰E€¡œE‰E„· Ef‰Eˆ…Hÿÿÿ‰$ÿÜRE·ðƒì…öuB1Ò…Òu‰$èc‰<$ÿSEƒì·Àè/ýÿÿ‰Ã‰`HEC£PHEC£pHEeô[^_]Éðèýÿÿ9؉òu±ë±è£U‰åƒì8‰uø‹U‹u‰}ü‹E‹} ‰]ô…Ò‰ÃÇEàÇEä‰U܉u؉}ÌuH9ø†°‰ð‰ú÷ó‰UØMè…É„lÇEä‹E؉Eà‹Uà‹Mä‹]ô‰Uè‹uø‰Ð‰Mì‹}ü‰ì]‰ÊÉö‹MÌ9MÜv‰uà‰Mä‹Eà‹Uä‹]ô‰Eè‹uø‹}ü‰Uì‰ì]ýE܃ð‰EÐua‹EÜ9EÌ—À9]Ø“ Шt‹MÌ‹UØ)ÚM܉U؉MÌEè…À„Ü‹UØ‹M̉Uà뜅Àu ¸1Ò÷ó‰Ã‹EÌ‹UÜ÷ó‰UÌ‹EØ÷óé2ÿÿÿ¶Mи ‹UЋuÌ)ЋU܉EÔ‰ØÓâ¶MÔÓè ¶MЉUÜ‹UÌ‹EØÓã¶MÔÓê¶MÐÓæ¶MÔÓè Æ¶MЉủð÷u܉UÌÓeØ÷ã;Ủ։Çw”À1Ò;}Ø—Â…Ðt)ßuÜMè…Ét.¶MÔ‹UÌ‹EØ)øò‰UÌÓâ¶MЉEØÓè ‰Uà‹EÌÓè‰Eäé¡þÿÿ‹Eè‹Uì‹]ô‹uø‹}ü‰ì]ÃU‰åƒì‰]ô‹U‹M‰uø‹E…Ò‰}ü‹] ‰Æ‰Mðu,9ØvZ‰È‰Ú÷ö‰ÁÇEì‹Uì‰È‹]ô‹uø‹}ü‰ì]ô&ÇEì1É9Úwڽƒð‰EèuM9Ó¹—À9uð“ Шu²1Éë®…Àu ¸1É1Ò÷ñ‰Æ‰Ø1Ò÷ö‰Eì‹]ô‹Eð‹}ü÷ö‹Uì‰Á‹uø‰ì‰È]ËEè¹ )Á‰Mä¶Mè‰ðÓâ¶Mä‰×‰ÚÓè Ç‹Eð¶MèÓæ¶MäÓê¶MèÓã¶MäÓè öMè‰Ø÷÷‰ÓÓeð‰Á÷æ9Ú‰Æw”À1Ò;uð—…ЄÿÿÿIé ÿÿÿQ‰áƒÁ=réƒ -ëé)Áƒ ‰à‰Ì‹‹@ÿàÿ%¼SEÿ%¸SEÿ%ØSEÿ%àSEÿ%ÐSEÿ%dTEÿ%ÔSEÿ%ôSEÿ%ÈSEÿ%TEÿ%TEÿ%pTEÿ%„TEÿ%LTEÿ%ŒTEÿ%TEÿ%DTEÿ%hTEÿ%èSEÿ%¨TEÿ% TEÿ% TEÿ%€TEÿ%TEÿ%4TEÿ%ÜSEÿ%0TEÿ%\TEÿ%: èDE@VC XCYC`YC`ZC€HCpZC \C0\Cà\CP\C\CÀ\CÐ\C`\C]CPuTTY-Local: Mar 16 2009 19:57:05Unidentified build, Mar 16 2009 19:57:05ÿÿÿÿ ×C°ØCàØCÙC@ÙCPÙC°ÙC ÚC0ÚC ÚC@ÚCpÚC€ÚCÚCPÚCÀÚCÿÿÿÿ@p DÿÿÿÿÿÿÿÿÿÿÿÿsshtelnetrloginrawserialPuTTY$ Doption "%s" not available in this tool-load-ssh-telnet-rlogin-raw-v-l-L-R-D-nc-mrout of space for port forwardings-P-pwthe -pw option can only be used with the SSH protocol-agent-pagent-pageant-noagent-nopagent-nopageant-A-a-X-x-t-T-N-C-1-2-i-4-ipv4-6-ipv6-nc expects argument of form 'host:port'unable to open command file "%s"Proxy error: Server chose CHAP of other than HMAC-MD5 but we didn't offer it!Proxy error: SOCKS proxy refused CHAP authenticationProxy error: SOCKS proxy wants a different CHAP versionProxy error: SOCKS proxy won't negotiate CHAP with usProxy error: Server chose CHAP authentication but we didn't offer it!<%02X>  ^R r%Y%H%M%S%m%dí7@ñ6@ñ6@ñ6@Ò7@ñ6@ñ6@ñ6@ñ6@¤7@ñ6@ñ6@ñ6@ñ6@ñ6@ñ6@’7@ñ6@ñ6@ñ6@ñ6@€7@ctx->lgfp../logging.cIncomingOutgoing%s packet type %d / 0x%02x (%s) s (%d byte%s omitted) %08x%*s %02x%s raw data Event Log: %s %s ASCIIrawSSH packetsSSH raw dataunknownDisabled writingAppendingWriting new%s session log (%s mode) to file: %sabwb%Y.%m.%d %H:%M:%S=~=~=~=~=~=~=~=~=~=~=~= PuTTY log %s =~=~=~=~=~=~=~=~=~=~=~= ctx->state != L_OPENINGTA@`A@`A@`A@mA@`A@hA@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@`A@TA@`A@`A@`A@mA@`A@hA@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/tmp != NULL../misc.cch->buffersize >= lench->head != NULL %c%02.2x%*s%s %p: %d (0x%x) bytes: forwarding%d.%d.%d.%d0N@ T@°N@@N@0N@ T@°N@@N@0N@ T@°N@@N@ U@ÐZ@ðZ@ [@p[@à[@\@0\@P\@`]@]@°]@ ^@°^@ð^@Proxy error: Unknown proxy methodProxy error: Unable to resolve proxy host nameProxy error: unexpected proxy errorCONNECT %s:%i HTTP/1.1 Host: %s:%i %s:%s HTTP/%i.%i %nProxy error: HTTP response was absentProxy error: %s../proxy.clen > 0Proxy error: Error while communicating with proxyProxy error: SOCKS version 4 does not support IPv6Proxy error: SOCKS proxy responded with unexpected reply code versiontype == ADDRTYPE_NAMEProxy error: SOCKS server wanted IDENTD on clientProxy error: Username and IDENTD on client don't agreeProxy error: Unexpected proxy errorProxy error: SOCKS proxy returned unexpected versionProxy error: SOCKS password subnegotiation contained wrong version numberProxy error: SOCKS proxy returned wrong version numberProxy error: We don't support GSSAPI authenticationProxy error: SOCKS proxy refused password authenticationProxy error: Server chose username/password authentication but we didn't offer it!Proxy error: SOCKS proxy did not accept our authenticationProxy error: SOCKS proxy returned unrecognised address formatUnrecognised SOCKS error code %dív@*x@Êw@¾y@„y@Cy@y@Òx@x@hostport%iuserpassproxyhostproxyport%dConnecting to %s port %dFailed to connect to %s: %s%s‡@°‡@ ˆ@pˆ@ (IPv4) (IPv6)Looking up host "%s"%sConnecting to %s port %dFailed to connect to %s: %s%sP‹@ð‹@@ @ (IPv4) (IPv6)Looking up host "%s"%s/INTRQUITERASEKILLEOFEOLEOL2STARTSTOPSUSPDSUSPREPRINTWERASELNEXTFLUSHSWTCHSTATUSDISCARDIGNPARPARMRKINPCKISTRIPINLCRIGNCRICRNLIUCLCIXONIXANYIXOFFIMAXBELISIGICANONXCASEECHOECHOEECHOKECHONLNOFLSHTOSTOPIEXTENECHOCTLECHOKEPENDINOPOSTOLCUCONLCROCRNLONOCRONLRETCS7CS8PARENBPARODDð,Dõ,Dú,D-D-D -D -D-D-D-D"-D(-D0-D7-D=-DC-DI-DP-DX-D_-Df-Dl-Ds-Dy-D-D…-D‹-D-D–-Dœ-D¤-D©-D°-D¶-D»-DÁ-DÇ-DÎ-DÕ-DÜ-Dã-Dë-Dò-Dù-Dÿ-D.D .D.D.D.D".D&.D-.Ddh-gex-sha1dh-group14-sha1dh-group1-sha1WARN(/D4/DD/DS/Daesblowfish3desarcfourdes/D”/D/DS/D¢/Dª/D,mapping[i].v < 32../settings.cPresentHostNameLogFileNameLogTypeLogFileClashLogFlushSSHLogOmitPasswordsSSHLogOmitDatarawProtocolPortNumberCloseOnExitWarnOnClosePingIntervalTCPKeepalivesPingIntervalSecsTCPNoDelayTerminalTypeTerminalSpeedTerminalModesAddressFamilyProxyExcludeListProxyHostProxyDNSProxyPortProxyLocalhostProxyMethodTryAgentAgentFwdProxyUsernameProxyPasswordProxyTelnetCommandEnvironmentUserNameLocalUserNameNoPTYCompressionSshNoShellSshProtChangeUsernameCipherKEXRekeyTimeRekeyBytesSshNoAuthAuthTISAuthKISSH2DESPublicKeyFileNoApplicationKeysNoApplicationCursorsRemoteCommandRFCEnvironPassiveTelnetBackspaceIsDeleteRXVTHomeEndLinuxFunctionKeysApplicationKeypadNetHackKeypadNoMouseReportingNoRemoteResizeNoAltScreenNoRemoteWinTitleRemoteQTitleActionNoDBackspaceNoRemoteCharsetApplicationCursorKeysLocalEditAnswerbackAltF4AltSpaceAltOnlyComposeKeyCtrlAltKeysTelnetKeyTelnetRetLocalEchoBeepIndAlwaysOnTopFullScreenOnAltEnterHideMousePtrSunkenEdgeWindowBorderCurTypeBlinkCurBeepBellWaveFileDisableArabicShapingDisableBidiBellOverloadBellOverloadNBellOverloadTBellOverloadSScrollbackLinesDECOriginModeAutoWrapModeLFImpliesCRWinNameAlwaysWinTitleTermWidthTermHeightFontTryPaletteANSIColourFontQualityFontVTModeUseSystemColoursXterm256ColourBoldAsColourColour%d%d,%d,%dMouseOverrideRawCNPPasteRTFMouseIsXtermRectSelectWordness%d%s%dLineCodePageScrollOnKeyScrollOnDispCJKAmbigWideUTF8OverridePrinterCapsLockCyrScrollBarScrollBarFullScreenRemotePortAcceptAllEraseToScrollbackLockSizeBCEBlinkTextX11ForwardX11DisplayX11AuthTypeLocalPortAcceptAllBugIgnore1PortForwardingsBugPlainPW1BugRSA1BugHMAC2BugDeriveKey2BugRSAPad2BugPKSessID2LoginShellBugRekey2ScrollbarOnLeftStampUtmpBoldFontWideFontWideBoldFontSerialStopHalfbitsSerialParitySerialFlowControlShadowBoldShadowBoldOffsetSerialLineSerialSpeedSerialDataBits187,187,187255,255,2550,0,085,85,850,255,0187,0,0255,85,850,187,085,255,85187,187,0255,255,850,0,18785,85,255187,0,187255,85,2550,187,18785,255,255è7Dô7D8D8D8D8D8D8D8D8D)8D18D;8DE8DP8DX8Db8Dl8Dw8D8Dè7Dô7D0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,00,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,11,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,21,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,11,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,12,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2è8D(9Dh9D¨9Dè9Dè9D(:D(:Ddefaultxterm38400,38400%s%s=A,proxyconnect %host %port\nBugDHGEx2dh-group14-sha1,dh-group1-sha1,WARN,dh-gex-sha1dh-gex-sha1,dh-group14-sha1,dh-group1-sha1,WARN1GNoRemoteQTitlePuTTYBuggyMACProxyTypeProxySOCKSVersionDefault Settingsnone;DðÐ@Ñ@Ñ@ðÐ@Ñ@Ñ@ Ñ@INTRQUITERASEKILLEOFEOLEOL2STARTSTOPSUSPDSUSPREPRINTWERASELNEXTFLUSHSWTCHSTATUSDISCARDIGNPARPARMRKINPCKISTRIPINLCRIGNCRICRNLIUCLCIXONIXANYIXOFFIMAXBELISIGICANONXCASEECHOECHOEECHOKECHONLNOFLSHTOSTOPIEXTENECHOCTLECHOKEPENDINOPOSTOLCUCONLCROCRNLONOCRONLRETCS7CS8PARENBPARODDÔ;DÙ;DÞ;Dä;Dé;Dí;Dñ;Dö;Dü;D channels, &i, ssh_channelfind)../ssh.cpkt->bodyÀÝ@ÁÞ@¬Þ@ŽÞ@zÞ@,Þ@Þ@ Þ@×Ý@padding <= 255ssh->queueingpkt->savedpos < pkt->lengthssh-rsaIncorrect CRC received on packet%sExtremely large packet length from server suggests data stream corruptionNetwork attack (CRC compensation) detected!Zlib decompression encountered invalid dataIncoming packet was garbled on decryptionIncorrect MAC received on packetConnecting to %s port %dFailed to connect to %s: %sServer unexpectedly closed network connectionServer closed network connectionssh->v1_throttle_count >= 0qh != NULLssh->packet_dispatch[qh->msg1] == ssh_queueing_handlerssh->packet_dispatch[qh->msg2] == ssh_queueing_handlerpktin->type == qh->msg1 || pktin->type == qh->msg2ssh->packet_dispatch[ssh->qhead->msg1] == NULLssh->packet_dispatch[ssh->qhead->msg2] == NULLssh->packet_dispatch[qh->msg1] == NULLssh->packet_dispatch[qh->msg2] == NULLRemote port forwarding from %s refusedRemote port forwarding from %s enabledrpf == pfIncoming terminal data packet was badly formedReceived X11 connect requestRejected X11 connect requestOpening X11 forward connection succeededOpened X11 forward channelOpening X11 forward connection failedReceived remote port open request for %s:%dPort open failed: %sRejected remote port open request for %s:%dForwarded port opened successfullyForwarded connection refused by serverhalf-open_CONFIRMATIONReceived CHANNEL_CLOSE%s for %s channel %d nonexistentForwarded X11 connection terminatedForwarded port closedc->u.x11.s != NULLc->u.pfd.s != NULLRemote debug message: %.*sServer sent disconnect message: "%.*s"expected key exchange reply packet from serverDoing Diffie-Hellman group exchangeexpected key exchange packet from serverInitiating key re-exchange (%s)Using Diffie-Hellman with standard group "%s"Doing Diffie-Hellman key exchange with hash %sUnexpected data from server while waiting for user host key responseUnexpected data from server while waiting for user response,expected new-keys packet from serverexpected key exchange group packet from serverInitialised %.200s client->server MAC algorithmInitialised %.200s client->server encryptionServer bug prevents key re-exchange (%s)key-exchange algorithmServer initiated key re-exchangeUser aborted at cipher warningunable to read mp-ints from incoming group packetclient-to-server cipherunable to parse key exchange reply packetUser aborted at kex warningserver-to-client cipherUser aborted at host key verificationInitialised %.200s server->client encryptionInitialised %.200s server->client MAC algorithm(null)Couldn't agree a key exchange algorithm (available: %s)Host key fingerprint is:Initialised %s compressionServer's host key did not match the signature suppliedCouldn't agree a client-to-server cipher (available: %s)Initialised %s decompressionCouldn't agree a server-to-client cipher (available: %s)ssh->v2_session_id_len <= sizeof(ssh->v2_session_id)sizeof(keyspace) >= ssh->kex->hash->hlen * SSH2_MKKEY_ITERS(ssh->cscipher->keylen+7) / 8 <= ssh->kex->hash->hlen * SSH2_MKKEY_ITERSssh->csmac->len <= ssh->kex->hash->hlen * SSH2_MKKEY_ITERSssh->cscipher->blksize <= ssh->kex->hash->hlen * SSH2_MKKEY_ITERSssh->kex->hash->hlen <= sizeof(s->exchange_hash)(ssh->sccipher->keylen+7) / 8 <= ssh->kex->hash->hlen * SSH2_MKKEY_ITERSssh->scmac->len <= ssh->kex->hash->hlen * SSH2_MKKEY_ITERSssh->sccipher->blksize <= ssh->kex->hash->hlen * SSH2_MKKEY_ITERSlAHA5AA–AáAtoo much data sentcancel-tcpip-forward0.0.0.0127.0.0.1:localremotedynamic%s port forwarding from %s%s%d%s to %s:%dCancelling %sSSH-1 cannot handle remote source address spec "%s"; ignoringService lookup failed for source port "%s"Service lookup failed for destination port "%s")(%s%s%s%s%d%s%s:%s%s%d%sDuplicate remote port forwarding to %s:%d failed: IPv4 IPv6 Local %sport %s SOCKS dynamic forwarding%s%sLocal %sport %s forwarding to %s%s%sRequesting remote port %s forward to %stcpip-forwardwindow-changeDisconnected: %sDisconnectedenServer sent command exit status %dPublic key packet not receivedPageant failed to answer challengeKey refusedEncryption not successfully enabledAuthentication successfulReceived RSA challengeBizarre response to RSA authentication responsePageant key #%d matches configured key fileTrying Pageant key #%dPageant has %d SSH-1 keysPageant key list packet was truncatedTrying public key "%s"Wrong passphrase. SSH key passphrasePassphrase for key "%.100s": Server refused our public key. Bizarre response to offer of public keyTIS authentication declinedUnexpected data from server while waiting for agent responseServer's RSA challenge was badly formattedConfigured key file not in PageantSent passwordCryptoCard authentication declinedCryptoCard authentication refused. Trying to enable encryption...Initialised %s encryptionInstalling CRC compensation attack detectorPageant's response not acceptedFailed to authenticate with our public key. Unable to authenticatecipherReceived public keysFailed to read SSH-1 public keys from public key packetSending length-padded passwordPageant is running. Requesting keys.SSH password%.90s@%.90s's password: Sending Pageant's responseSSH-1 public key packet stopped before random cookieRequested CryptoCard authenticationPageant's response acceptedRequested TIS authenticationTrying public key authentication. Received CryptoCard challengeSSH CryptoCard authentication%.*s Using CryptoCard authentication.%s%sSent username "%s" Using Blowfish encryptionNo passphrase required. No reply received from PageantCouldn't load private key from (). SSH-1 public key encryptions failed due to bad formattingSending password with camouflage packetsSending unpadded passwordCryptoCard challenge packet was badly formedNo username providedReading private key file "%.150s"Unable to use this key file (%s)Unable to use key file "%.150s" (%s) Successfully started encryptionSSH login namelogin as: Strange packet received, type %dReceived TIS challengeSSH TIS authenticationUsing TIS authentication.%s%sAuthenticated using RSA key "" from agent TIS authentication refused. Authentication refusedrsaUsing 3DES encryptionTIS challenge packet was badly formedEncrypted session keyServer violates SSH-1 protocol by not supporting 3DES encryptionUsing single-DES encryptionResponse: Access denied SSH-1 public keys were badly formattedUnable to load private key (%s)Unable to load private key file "%.150s" (%s) single-DESBlowfish3DESAES not supported in SSH-1, skipping0 && "unexpected return from loadrsakey()"pwlen >= bottom && pwlen <= topNo supported ciphers foundbreakat user requestSent EOF messageABRTsignalSent signal SIG%sHUPALRMFPEILLUnable to send BREAK signal in SSH-1INTPIPESEGVTERMUSR1USR2Allocated pty (ospeed %dbps, ispeed %dbps)X11 forwarding enabledStarted sessionRequesting X11 forwardingStrange packet received: type %dProtocol confusionStarted compressionInitialised zlib (RFC1950) compressionInitialised zlib (RFC1950) decompression%d,%dRequesting agent forwardingAgent forwarding enabledX11 forwarding refusedServer refused to compress Agent forwarding refusedServer refused to allocate pty Server version: %s2.01.99SSH-2.0-%s We claim version: %.*sUsing SSH protocol version %d1.5SSH-%s-%s SSH protocol version 2 required by user but not provided by serverDigiSSH_2.0OpenSSH_2.[0-4]*OpenSSH_2.5.[0-3]*Sun_SSH_1.0Sun_SSH_1.0.1WeOnlyDo-*We believe remote version has SSH-2 rekey bugOpenSSH_2.[0-2]*We believe remote version has SSH-2 public-key-session-ID bugOpenSSH_2.[5-9]*OpenSSH_3.[0-2]*We believe remote version has SSH-2 RSA padding bug* VShell2.0.0*2.0.10*We believe remote version has SSH-2 key-derivation bug2.1.0*2.0.*2.2.0*2.3.0*2.1 *We believe remote version has SSH-2 HMAC bugCisco-1.25We believe remote version can't handle SSH-1 RSA authenticationOSU_1.4alpha3We believe remote version needs a plain SSH-1 password1.2.181.2.191.2.201.2.211.2.22OSU_1.5alpha4We believe remote version has SSH-1 ignore bugSSH protocol version 1 required by user but not provided by server*str == '-'*str == 'H'*str == 'S'Received CHANNEL_CLOSE for %s channel %d All channels closedAdministratively prohibitedConnect failedUnknown channel typeResource shortagejjD€jDœjD«jDÀjDForwarded connection refused by server: %s [%.*s]exit-statusexit-signal %d (core dumped)Server exited on signal%s%s%sReceived channel request for nonexistent channel %d ("%.*s") "%.*s"Unsupported channel type requestedRejected channel open: %sx11Received X11 connect request from %s:%dX11 forwarding is not enabledforwarded-tcpipReceived remote port %d open request from %s:%dAttempting to forward remote port to %s:%dPort open failedauth-agent@openssh.comAgent forwarding is not enabledRemote port is not recognisedUnable to open an X11 connectionssh-connectionOffered public keypublickeySSH server authenticationUsing keyboard-interactive authentication.%s%.*sServer refused to open a sessionStrange packet received during authentication: type %dServer refused to open a direct-tcpip channelUnexpected response to agent forwarding request: packet type %dpasswordSSH server: %.*sUnexpected response to pty request: packet type %dNo supported authentication methods availableAccess grantedsessionenvSent %d environment variablesAll environment variables refusedServer refused to set environment variables execStarted a shell/commandServer's channel confirmation cited wrong channelssh-userauthServer refused service requestOpening direct-tcpip channel to %s:%d in place of sessiondirect-tcpipkeyboard-interactiveServer refused to start a shell/commandUnexpected response to X11 forwarding request: packet type %dServer refused public keypty-reqUsing username "%s". Opened channel for sessionServer requested password changeServer rejected new passwordNew SSH passwordCurrent password (blank for previously entered password): Enter new password: Confirm new password: Passwords do not match Sent new passwordUnexpected response to shell/command request: packet type %dx11-reqFurther authentication required Further authentication requiredOffer of public key acceptedWrong passphrase Unable to load private key () Access deniedOpened direct-tcpip channelRequesting OpenSSH-style agent forwardingauth-agent-req@openssh.comshellsubsystemUnexpected response to environment request: packet type %dPrimary command failed; attempting fallbackKeyboard-interactive authentication refusedAuthenticating with public key "" Server refused our key %d environment variables refusedServer refused to set all environment variables All environment variables successfully setp == sigdata_lenPageant has %d SSH-2 keysReceived disconnect message (%s)Disconnection message text: %n%.*sServer sent disconnect message type %d (%s): "%s"Received disconnect message (unknown type %d)timeouttoo much data receivedö@ ÷@Ð~A°ù@ (IPv4) (IPv6)Looking up host "%s"%scompression setting changedcipher settings changeddata limit loweredtimeout shortenedIGNORE messageX'Ýq¹¾¶Oáð­ˆÉf¬ }´:ÎcJßå‚1—`3QbES±àwd»„®kþ ù”+pXhHýE”‡lÞR·ø{«#ÓsrâKãWf*«U²(ë/µ†š{ÅÓ¥70ò‡(#²¥¿ºjí\‚Š+ϧ’´yóðòN¡âieÍôÚÕ¾Ñb4ÄŠþ¦4S.¢ Uó2ኤuëö 9ìƒ@ªï`^Ÿq½Qn>ùŠ!–=ÝÝ®>MF½æ‘µTq]ÄoÔ`ÿP$û˜Ö—齉ÌC@gwžÙ°½B舋‰ç8[yÛîÈ¡G ||éBøÉ„ ƒ†€2Hí+¬plNrZýûÿV8…=Õ®6'9- dÙh!¦\›ÑT[$:.6 ±g “çW´Ò–îž‘›€OÅÀa¢ ÜZiKwâ º“Àå* Äh8,4$Â_@£rü %â(‹I<ÿA• 9q¨Þ³ Øœä´dÁV{a„ËÕp¶2Ht\lÐBW¸ôQP§A~Seä':–^«;ËkñEú¬«XãK“0 Uúv­öm̈‘võ%LåOü×*Å×Ë5&€Dbµ£±ÞIZº%gêE˜þ]áÀ/ÃuLðF£—ÓkÆùç_’•œm¿ëzR•ÚY¾Ô-ƒtXÓ!àI)iÉŽDÈÂuj‰ŽôxyX™k>¹'Ýqá¾¶Oˆð­ Éf¬Î}´:ßcJå‚1Q—`3SbEd±àwk»„®þ ù”+HpXhEýÞ”‡l{R·øs«#ÓKrâãWUf*«ë²(µ/Âņš{7Ó¥(0ò‡¿#²¥ºjí\‚ÏŠ+y§’´óðòiN¡âÚeÍôÕ¾4Ñb¦ÄŠþ.4Só¢ UŠ2áö¤uëƒ 9ì`@ªïq^Ÿn½Q!>ùŠÝ–=>Ý®æMF½T‘µÄq]oÔP`ÿ˜$û½Ö—é@‰ÌCÙgwžè°½B‰ˆ‹ç8[ÈyÛî|¡G B|鄸ɀ ƒ†+2Hí¬pZlNrýûÿ…V8®=Õ-6'9 dÙ\h!¦[›ÑT6$:. ±gW“çî´Ò–›ž‘À€OÅÜa¢ wZiK“â º Àå*"Ä$8,4£Â_@rÃâ¼ %<(‹I ÿA•¨9q Þ³´ØœäVdÁË{a„2Õp¶lHt\¸ÐBW§ôQPeA~S¤Ã^':–k«;ËEñXú¬«ãK“ú0 Umv­öv̈‘Lõ%×åOüË*Å×D5&€£bµZ±ÞIº%gêE˜Àþ]áu/ÃðL—F£ùÓkÆ_眒•zm¿ëYR•Úƒ¾Ô-!tXÓiàI)ÈÉŽD‰ÂujyŽôx>X™kq¹'ÝOá¾¶­ˆð¬ Éf:Î}´Jßc1å‚3Q—`SbEwd±à®k»„ þ+ù”hHpXýElÞ”‡ø{R·Ós«#KrâãW«Uf*(ë²µ/{ņš7Ó¥‡(0ò¥¿#²jº‚í\ÏŠ+´y§’òóðâiN¡ôÚe;Õb4Ñþ¦ÄŠS.4Uó¢ áŠ2ëö¤uìƒ 9ï`@ªŸq^n½QŠ!>ùÝ–=>Ý®½æMFT‘µ]ÄqÔoP`ÿû˜$é½Ö—C@‰ÌžÙgwBè°½‹‰ˆ[ç8îÈyÛ |¡GB|鄸Ɇ€ ƒí+2Hp¬rZlNÿýû8…VÕ®=9-6'Ù d¦\h!T[›Ñ.6$:g ±çW“–î´Ò‘›žÅÀ€O Üa¢KwZiº“â * Àåà"4$8,@£Â_Ãr%â¼ I<(‹• ÿA¨9q³ Þä´ØœÁVd„Ë{a¶2Õp\lHtW¸ÐBP§ôQSeA~ä–^':Ëk«;ñE«Xú¬“ãKUú0 ömv­‘v̈%Lõü×åO×Ë*Å€D5&£bµIZ±Þgº%˜êEáÀþ]u/ÃðL£—FÆùÓkç_•œ’ëzm¿ÚYR•-ƒ¾ÔÓ!tX)iàIDÈÉŽj‰ÂuxyŽôk>X™Ýq¹'¶Oá¾­ˆðf¬ É´:Î}Jßc‚1å`3Q—ESbàwd±„®k» þ”+ùXhHpýE‡lÞ”·ø{R#Ós«âKrWã*«Uf(ë²µ/š{ņ¥7Óò‡(0²¥¿#ºj\‚í+ÏŠ’´y§ðòó¡âiNÍôÚeÕ¾b4ÑŠþ¦ÄS.4 Uó¢2áŠuëö¤9ìƒ ªï`@Ÿq^Qn½ùŠ!>=Ý–®>ÝF½æMµT‘]ÄqoÔÿP`$û˜—é½ÖÌC@‰wžÙg½Bè°ˆ‹‰8[çÛîÈyG |¡éB|É„øƒ†€ Hí+2¬pNrZlûÿýV8…Õ®='9-6dÙ !¦\hÑT[›:.6$±g çW“Ò–î´ž‘›OÅÀ€¢ ÜaiKwZ º“âå* ÀCà"< ­Ç‹ò¹¨¶-È©…ñWLu¯»Ý™îý`£Ÿ&÷¼õr\Å;fD4~û[v)C‹ÜÆ#Ëhüí¶cñä¸ÊÜ1×…cB@"— Æ„}$J…ø=»Ò2ù®m¡)ÇK/žó0²ÜìR† ÐãÁwl³+™¹p©úH”"déGÄŒü¨?ð Ø,}Vï3"ÇNI‡ÁÑ8Ùþ¢ÊŒ6 Ô˜Ïõ¦(Þz¥&Ž·Ú¤¿­?ä:, ’xP›Ì_jbF~TÂöè¸Ø^÷9.õ¯Ã‚¾€]Ÿ|“Ði©-Õo³%Ï;™¬È§}ncœè{»;Û x&ÍôYn·šì¨šOƒen•æ~æÿªϼ!æèïÙ›çºÎ6oJÔ ŸêÖ|°)¯²¤11#?*0”¥ÆÀf¢57¼Nt¦Ê‚ü°Ðàا3J˜ñ÷ÚìAPÍ/ö‘ÖMvM°ïCTMªÌß–äãµÑžˆjL¸,ÁQeFê^]5Œst‡ú.A ûZg³RÒÛ’3VéGÖmŒaךz ¡7ŽøY‰<ëî'©Î5Éa·íåá<±GzYßÒœ?sòUyο7ÇsêÍ÷S[ªý_o=߆ÛDxó¯Ê>Äh¹,4$8_@£Ârà %⼋I<(A• ÿq¨9Þ³ œä´ØÁVda„Ë{p¶2Õt\lHBW¸Ðc|w{òkoÅ0g+þ׫vÊ‚É}úYGð­Ô¢¯œ¤rÀ·ý“&6?÷Ì4¥åñqØ1Ç#Öš€âë'²u ƒ,nZ R;Ö³)ã/„SÑí ü±[j˾9JLXÏÐïªûCM3…EùP<Ÿ¨Q£@’8õ¼¶Ú!ÿóÒÍ ì_—Dħ~=d]s`OÜ"*ˆFî¸Þ^ Ûà2: I$\ÂÓ¬b‘•äyçÈ7mÕN©lVôêez®ºx%.¦´ÆèÝtK½‹Šp>µfHöa5W¹†Ážáø˜iÙŽ”›‡éÎU(ߌ¡‰ ¿æBhA™-°T»R jÕ06¥8¿@£žó×û|ã9‚›/ÿ‡4ŽCDÄÞéËT{”2¦Â#=îL• BúÃN.¡f(Ù$²v[¢Im‹Ñ%røöd†h˜Ô¤\Ì]e¶’lpHPýí¹Ú^FW§„Ø«Œ¼Ó ÷äX¸³EÐ,Ê?Á¯½Šk:‘AOgÜê—òÏÎð´æs–¬t"ç­5…âù7èußnGñq)ʼno·bª¾üV>KÆÒy šÛÀþxÍZôݨ3ˆÇ1±Y'€ì_`Q©µJ -åzŸ“Éœï à;M®*õ°Èë»<ƒS™a+~ºwÖ&áicU! }Æ¥ccø„||î™wwö{{ÿ òòÖ½kkÞ±oo‘TÅÅ`P00ΩggV}++çþþµb××Mæ««ìšvvEÊÊ‚‚‰@ÉÉú‡}}ïúú²ëYYŽÉGGû ððAì­­³gÔÔ_ý¢¢E꯯#¿œœS÷¤¤ä–rr›[ÀÀu··áýý=®““Lj&&lZ66~A??õ÷÷ƒOÌÌh\44Qô¥¥Ñ4ååùññâ“qq«sØØbS11*? •RÇÇFe##^ÃÃ0(7¡–– /µšš $6›€€ß=ââÍ&ëëNi''Ͳ²êŸuu žƒƒXt,,4.6-ܲnn´îZZ[û  ¤öRRvM;;·aÖÖ}γ³R{))Ý>ãã^q//—„„¦õSS¹hÑÑÁ,íí@` ãüüyȱ±¶í[[Ô¾jjFËËgÙ¾¾rK99”ÞJJ˜ÔLL°èXX…JÏÏ»kÐÐÅ*ïïO媪íûû†ÅCCš×MMfU33”……ŠÏEEéùùþ ðPPxD<<%ºŸŸK㨨¢óQQ]þ££€À@@Š?­’’!¼pH88ñõõcß¼¼wÁ¶¶¯uÚÚBc!! 0åÿÿýóó¿mÒÒLÍÍ &5Ã/ìì¾á__5¢——ˆÌDD.9“WÄÄUò§§ü‚~~zG==Ȭddºç]]2+æ•ssÀ ``˜žÑOO£ÜÜDf""T~**;« ƒˆˆŒÊFFÇ)îîkÓ¸¸(<§yÞÞ¼â^^ ­vÛÛÛ;ààdV22tN:: ’ÛII Hl$$¸ä\\Ÿ]½nÓÓCשּׁĦbb9¨‘‘1¤••Ó7ääò‹yyÕ2çç‹CÈÈnY77Ú·mmŒ±dÕÕœÒNNIà©©Ø´ll¬úVVóôôÏ%êêʯeeôŽzzGé®®oÕººðˆxxJo%%\r..8$Wñ¦¦sÇ´´—QÆÆË#èè¡|ÝÝèœtt>!–ÝKKaܽ½ †‹‹…ŠŠàpp|B>>qĵµÌªffØHH÷öö£aaj_55®ùWWiй¹‘††™XÁÁ:''¹žžÙ8ááëøø+³˜˜"3Ò»ii©pÙÙ‰ŽŽ3§””-¶››<"’‡‡É éé‡IÎΪÿUUPx((¥zßߌŒYø¡¡ €‰‰ eÚ¿¿×1ææ„ÆBBиhh‚ÃAA)°™™Zw--{˰°¨üTTmÖ»»,:cÆ¥c|ø„|wî™w{ö{òÿ òkÖ½koÞ±oÅ‘TÅ0`P0gΩg+V}+þçþ×µb׫Mæ«vìšvÊEÊ‚‚ɉ@É}ú‡}úïúY²ëYGŽÉGðû ð­Aì­Ô³gÔ¢_ý¢¯Eꯜ#¿œ¤S÷¤rä–rÀ›[À·u·ýáý“=®“&Lj&6lZ6?~A?÷õ÷̃OÌ4h\4¥Qô¥åÑ4åñùñqâ“qØ«sØ1bS1*? Ç•RÇ#Fe#Ã^Ã0(–7¡– š/µš $6€›€âß=âëÍ&ë'Ni'²ͲuêŸu  ƒžƒ,Xt,4.6-nܲnZ´îZ [û R¤öR;vM;Ö·aÖ³}γ)R{)ãÝ>ã/^q/„—„S¦õSѹhÑíÁ,í @` üãü±yȱ[¶í[jÔ¾jËF˾gÙ¾9rK9J”ÞJL˜ÔLX°èXÏ…JÏлkÐïÅ*ïªOåªûíûC†ÅCMš×M3fU3…”…EŠÏEùéùþP ðP!K–ÝK½aܽ‹ †‹Š…Špàp>|B>µqĵf̪fHØHö÷öa£a5j_5W®ùW¹i醑†Á™XÁ:'ž'¹žáÙ8áøëø˜+³˜"3iÒ»iÙ©pÙŽ‰Ž”3§”›-¶›<"‡’‡éÉ é·IÎUªÿU(Px(ߥzߌŒ¡Yø¡‰ €‰  ¿eÚ¿æ×1æB„ÆBhиhA‚ÃA™)°™-Zw-°{˰T¨üT»mÖ»,:ccÆ¥||ø„wwî™{{öòòÿ kkÖ½ooÞ±ÅÅ‘T00`PggΩ++V}þþç××µb««MævvìšÊÊE‚‚Éɉ@}}ú‡úúïYY²ëGGŽÉððû ­­AìÔÔ³g¢¢_ý¯¯Eꜜ#¿¤¤S÷rrä–ÀÀ›[··uÂýýá““=®&&Lj66lZ??~A÷÷õÌ̃O44h\¥¥QôååÑ4ññùqqâ“ØØ«s11bS*? ÇÇ•R##FeÃÃ^0(––7¡ šš/µ $6€€›ââß=ëëÍ&''Ni²²ÍuuêŸ ƒƒž,,Xt4.6-nnܲZZ´î  [ûRR¤ö;;vMÖÖ·a³³}Î))R{ããÝ>//^q„„—SS¦õÑѹhííÁ, @`üüã±±yÈ[[¶íjjÔ¾ËËF¾¾gÙ99rKJJ”ÞLL˜ÔXX°èÏÏ…JÐлkïïÅ*ªªOåûûíCC†ÅMMš×33fU……”EEŠÏùùéþPP ð<!KK–ݽ½aÜ‹‹ †ŠŠ…ppà>>|BµµqÄff̪HHØöö÷aa£55j_WW®ù¹¹iІ†‘ÁÁ™X:'žž'¹ááÙ8øøë˜˜+³"3iiÒ»ÙÙ©pŽŽ‰””3§››-¶<"‡‡’ééÉ Î·IUUªÿ((PxßߥzŒŒ¡¡Yø‰‰ € ¿¿eÚææ×1BB„ÆhhиAA‚Ù™)°--Zw°°{ËTT¨ü»»mÖ,:¥ccÆ„||ø™wwî{{ö òòÿ½kkÖ±ooÞTÅÅ‘P00`©ggÎ}++Vþþçb×׵櫫MšvvìEÊÊ‚‚@Éɉ‡}}úúúïëYY²ÉGGŽ ððûì­­AgÔÔ³ý¢¢_꯯E¿œœ#÷¤¤S–rrä[ÀÀ›Â··uýýᮓ“=j&&LZ66lA??~÷÷õOÌ̃\44hô¥¥Q4ååÑññù“qqâsØØ«S11b?* RÇÇ•e##F^ÃÃ(0¡––7 µšš/ 6$›€€=ââß&ëëÍi''NͲ²Ÿuuê žƒƒt,,X.4-6²nnÜîZZ´û  [öRR¤M;;vaÖַγ³}{))R>ããÝq//^—„„õSS¦hÑѹ,ííÁ` @üüãȱ±yí[[¶¾jjÔFËËÙ¾¾gK99rÞJJ”ÔLL˜èXX°JÏÏ…kÐл*ïïÅ媪OûûíÅCC†×MMšU33f”……ÏEEŠùùéþðPP D<ÝKK–ܽ½a†‹‹ …ŠŠppàB>>|ĵµqªffÌØHHöö÷£aaÂ_55jùWW®Ð¹¹i‘††XÁÁ™':¹žž'8ááÙøøë³˜˜+3"»iiÒpÙÙ©‰ŽŽ§””3¶››-"<’‡‡ ééÉIηÿUUªx((PzßߥŒŒø¡¡Y€‰‰  Ú¿¿e1ææ×ÆBB„¸hhÐÃAA‚°™™)w--Z˰°{üTT¨Ö»»m:,keylen == 16 || keylen == 24 || keylen == 32../sshaes.cblocklen == 16 || blocklen == 24 || blocklen == 32(len & 15) == 0¸DðDPžDarcfour256Arcfour-2560BPB@BBBBÀDËDarcfour128Arcfour-1280BPB@BàBBBžD€'žDkeybytes <= 256../ssharcf.c¸žDPŸDðžDblowfish-cbcBlowfish-128 CBC°'Bð'B@(B(Bp+B ,BÀžD€ÍžDblowfish-ctrBlowfish-256 SDCTR°'Bð'B@(B (Bà-Bà-BŸD)ŸDÐ'Bð'B (Bð(B *BÍžD7Î9:ÏõúÓ7w«-ÅZžg°\B7£O@'‚Ó¾›¼™ŽÕs¿~-Ö{ÄÇkŒ·E¡!¾±n²´n6j/«HWyn”¼Òv£ÆÈÂIeîøS}ÞF sÕÆMÐLÛ»9)PFº©è&•¬ã^¾ðÕú¡šQ-jâŒïc"¸Â‰Àö.$Cª¥¤ÐòœºaÀƒMjé›PåÖ[dºù¢&(á::§†•©KébUïÓï/ÇÚ÷R÷io?Y úw©ä€†°‡­æ ›“å>;Zýé—×4žÙ·ð,Q‹+:¬Õ–}¦}Ö>ÏÑ(-}|Ï%Ÿ›¸ò­r´ÖZLõˆZq¬)àæ¥àý¬°G›ú“íÄÓèÌW;()fÕø(.y‘_xU`uíD–÷Œ^ÓãÔmºmôˆ%a¡½ðdžëâW<ì'—*:©›m?õ!cûfœõóÜ&(Ù3uõýU±‚4V»<ºŠwQ(øÙ ÂgQÌ«_’­ÌQèMŽÜ08bX7‘ù “ÂzêÎ{>ûdÎ!Q2¾Ow~㶨F=)ÃiSÞH€æd®¢$²mÝý-…if! Fš³ÝÀEdÏÞlX®È Ý÷¾[@XÒÌ»ã´k~j¢ÝEÿY:D 5>ÕÍ´¼¨Îêr»„dú®fGo<¿cä›Òž]/Tw®pcNö tW[çqrø]}S¯Ë@@Ìâ´NjFÒ4„¯(°á:˜•´Ÿ¸H n΂;?o‚« 5Kø'r'±`aÜ?“ç+y:»½%E4á9ˆ KyÎQ·É2/ɺ ~ÈàöÑǼÃÏǪè¡I‡š½OÔËÞÚÐ8Ú Õ*Ã9g6‘Æ|1ùO+±à·Yž÷:»õCÿÕòœEÙ',"—¿*üæqü‘%”›a“åú뜶ÎYd¨ÂѨº^Á¶ jãePÒB¤Ënìà;Û˜¾ ˜Ldéx22•Ÿß’Óà+4 Óòq‰At Œ4£K q¾ÅØ2vß5ß./™›Go æñãTÚL周ÚÏybÎo~>Íf±,ýÅÒ„™"ûöWó#õ#v2¦15¨“ÍÌVbð¬µëuZ—6nÌsÒˆ’b–ÞÐI¹PLVÆq½ÇÆæ z2ÐáEš{òÃýSªÉ¨bâ¿%»öÒ½5iq"²|Ï˶+œvÍÀ>SÓã@`½«8ð­G%œ 8ºvÎF÷Å¡¯w``u NþË…Øèаùªz~ªùL\ÂHŒŠûäjÃùáëÖiøÔ Þ\¦-% ?ŸæÂ2aN·[âwÎãßWærÃ:hZ=é÷@”&Lö4)i”÷ A÷Ôv.kô¼h¢Ôq$Ôjô 3·Ô·C¯aP.ö9FE$—tO!@ˆ‹¿ü•M¯‘µ–ÓÝôpE/ fì ¼¿…—½Ðm¬…Ë1³'ë–A9ýUæG%Úš Ê«%xP(ô)SÚ†, ûm¶ébÜhiHפÀhî¡'¢þ?OŒ­‡èàŒµ¶Öôz|Ϊì_7Ó™£xÎB*k@5žþ ¹…óÙ«×9î‹N;÷úÉVmK1f£&²—ãêtún:2C[Ý÷çAhû xÊNõ û—³þجV@E'•Hº::SU‡ƒ ·©kþK•–мg¨UXš¡c)©Ì3Ûá™VJ*¦ù%1?~ô^|1)èøýp/'\»€ã,(HÁ•"mÆä?ÁH܆ÇîÉùA¤yG@nˆ]ëQ_2ÑÀ›ÕÁ¼òd5A4x{%`œ*`£èøßlc´ž2áÑOf¯ÑÊà•#ká’>3b $;"¹¾î¢²…™ ºæŒ rÞ(÷¢-ExÐý”·•b}dðõÌço£ITúH}‡'ýÃ>óAcG tÿ.™«no:7ýøô`ܨøÝë¡Lá™ knÛU{Æ7,gm;Ôe'èÐÜÇ )ñ£ÿÌ’9µ íiûŸ{fœ}ÛÎ Ï‘ £^Ùˆ/»$­[Q¿y”{ëÖ;v³.97yYÌ—â&€-1.ô§­Bh;+jÆÌLuñ.x7BjçQ’·æ»¡PcûKkúíÊؽ%=ÉÃáâYBD† nì Ù*ê«ÕNg¯d_¨†Úˆé¿¾þÃädW€¼†À÷ðø{x`M``FƒýѰ8ö®EwÌü6×3kBƒq«ð‡A€°_^<¾W w$®è½™BFUa.X¿ôXN¢ýÝò8ïtô½‰‡ÃùfSt޳ÈUòu´¹ÙüFa&ëz„ß‹yj„â•_‘ŽYnFpW´ ‘UÕŒLÞÉᬠ¹Ð‚»Hb¨ž©tu¶· ܩࡠ-f3F2ÄZ茾ð % ™Jþn=¹ߤ¥ ò†¡iñh(ƒÚ·Üþ9W›Îâ¡RÍO^Púƒ§Äµ 'Ðæ 'ŒøšA†?wL`õ¨a(zðà†õÀªX`b}Ü0מæcê8#”ÝÂS4ÂÂVî˻޶¼¡}üëvYÎ äoˆ|K= r9$|’|_rㆹMr´[Áü¸žÓxUTíµ¥üÓ|=ØÄ­M^ïPøæa±Ù…¢<QlçÇÕoÄNáVο*67ÈÆÝ42š×‚c’Žúgà`@épzKD)³µ. uÛ#&ݦn­}ß§I¸`îœf²íqŒªìÿšilRdVឱ¥6)L u@Y >:䚘T?eB[ÖäkÖ?÷™œÒ¡õ0èïæ8-MÁ]%ð† ÝL&ëp„Æé‚c^Ì?kh Éïº>—<¡pjk„5h†â RSœ·7Pª„>\®ÞìD}ޏòW7Ú:° Pððÿ³õ ®²tµÇÈìAu¤™Í8â/ê;¡»€21³>8‹TN¹mO Bo¿ ö¸,y|—$r°yV¯‰¯¼wšÞ“Ù®‹³.?ÏÜrU$qk.æÝP‡Í„ŸGXzÚt¼šŸ¼Œ}Ké:ìzìú…ÛfC cÒÃdÄGïÙ27;CݺÂ$CM¡QÄe*”PÝä:žøßqUN1Öw¬›_ñV5kÇ£×;< ¥$Yíæòúûñ—,¿ºžn<pEㆱoéê ^†³*>Zçwú=N¹Üe)ç™Ö‰>€%ÈfRxÉL.j³œºÆxêâ”S<ü¥ô- §N÷ò=+6&9`y§#R¶÷nþ­ëfÃê•E¼ãƒÈ{¦Ñ7±(ÿŒïÝ2Ã¥Zl¾…!Xe˜«h¥Îî;•/Û­}ï*„/n[(¶!pa)uGÝìŸa0¨Ì–½aëþ4Ïcª\sµ9¢pL žžÕު˼†Ìî§,b`«\«œn„󲯋dÊð½¹i# P»Ze2Zh@³´*<Õéž1÷¸!À T›™ _‡~™÷•¨}=bšˆ7øw-ã—_“íh)ˆ5ÖæÇ¡ßÞ–™ºXx¥„õWcr"ÿÛ–FÂë ³ÍT0.SäHÙ(1¼mïòëXêÿÆ4aí(þs<|îÙJ]ã·dè]Bà> ¶âîEꫪ£OlÛÐOËúBôBǵ»jï;Oe!ÍAžyØÇM…†jGKäPb=ò¡bÏF&[ ƒˆü£¶ÇÁÃ$’tËi Š„G…²’V¿[ H­t±b‚#*BXêõU >ô­ap?#’ðr3A~“ñì_ÖÛ;"lY7Þ|`tî˧ò…@n2w΄€¦žPøUØïè5—Ùaª§i©Â Åü«ZÜÊ €.zDž„4EÃgÕýÉžÓÛsÛ͈UyÚ_g@Cgãe4ÄÅØ8>qžø(= ÿmñç!>J=°+Ÿãæ÷­ƒÛ¦ 1Ѭµß˜Ûrý/·ßÐí¯á¸–~&jE|º™,ñG™¡$÷l‘³âòüŽ…Ø iciNWq£þX¤~=“ôt• X¶ŽrXÍ‹qîJ‚¤T{µYZÂ9Õ0œ`ò*#°ÑÅð…`(yAÊï8Û¸°ÜyŽ:`‹žl>аÁw×'K1½Ú/¯x`\`Uó%U攫Uªb˜HW@ècj9ÊU¶«*4\Ì´ÎèA¯†T¡“ér|î³*¼oc]Å©+ö1t>\Γ‡›3ºÖ¯\Ï$lS2zw†•(˜H;¯¹Kkè¿Ä“!(fÌ Øa‘©!û`¬|H2€ì]]]„ï±u…é#&܈eë>‰#Ŭ–Óóom9Bôƒ‚D . „¤JðÈi^›žBhÆ!šléöaœ gðˆÓ«Ò Qjh/TØ(§–£3Q«l ïnä;zPð;º˜*û~eñ¡v¯9>YÊfˆC‚†îŒ´ŸoEÃ¥„}¾^‹;Øuoàs Á…ŸD@¦jÁVbªÓNw?6rßþ=›B$×Ð7H ÐÓêÛ›ÀñIÉrS{™€ØyÔ%÷ÞèöPþã;Ly¶½àl—ºÀ¶O©ÁÄ`Ÿ@ž\^c$j¯oûhµSl>ë²9oìR;Qüm,•0›DEÌ ½^¯Ðã¾ýJ3Þ(f³K.W¨ËÀtÈE9_ ÒÛûÓ¹½ÀyU 2`Æ¡Öyr,@þ%ŸgÌ£ûøé¥Žø"2Ûßu<kaýÈP/«R­úµ=2`‡#ýH{1S‚ß>»W\ž ŒoÊ.V‡Ûißö¨BÕÃÿ~(Æ2g¬sUOŒ°'[iÈXÊ»]£ÿá ð¸˜=ú¸ƒ!ýlµüJ[ÓÑ-yäSšeEø¶¼IŽÒ—ûKÚòÝá3~ˤAûbèÆäÎÚÊ ïLw6þž~дñ+MÚÛ•˜‘®qŽ­ê Õ“kÐÑŽÐà%ǯ/[<Ž·”uŽûâöd+ò¸ˆˆð  ^­OÃh‘ñÏÑ­Á¨³"//w¾þ-uê¡‹Ì åètoµÖó¬™â‰ÎàO¨´·àý;Ä|Ù¨­Òf¢_w•€sÌ“w!e ­æ†úµwõBTÇÏ5û ¯Íë ‰>{ÓAÖI~®-%^³q »h"¯à¸W›6d$¹ ð‘cUª¦ßY‰CÁxSZÙ¢[} Źåv&ƒ©Ï•bhÈAJsNÊ-G³J©{RQ)Sš?WÖ䯛¼v¤`+tæµoºéWkì–òÙ *!ec¶¶ù¹ç.4ÿdV…Å]-°S¡Ÿ©™Gºj…nˆj?$Ó£….ŠDsp"8 ¤Ð1Ÿ)˜ú.‰lNìæ!(EwÐ8ÏfT¾l é4·)¬ÀÝP|ɵՄ? GµÙÕ’ûy‰(len & 7) == 0../sshblowf.cmod[mod[0]] != 0../sshbn.c0123456789ABCDEF%s0x-%c –0w,aîºQ ™Ämôjp5¥c飕dž2ˆÛ¤¸ÜyéÕàˆÙÒ—+L¶ ½|±~-¸ç‘¿d·ò °jHq¹óÞA¾„}ÔÚëäÝmQµÔôÇ…ÓƒV˜lÀ¨kdzùbýìÉeŠO\Ùlcc=úõ È n;^iLäA`Õrqg¢Ñäjm ¨Zjz Ïäÿ “'® ±ž}D“ðÒ£‡hòþÂi]Wb÷Ëge€q6lçknvÔþà+Ó‰ZzÚÌJÝgoß¹ùùホC¾·Õް`è£ÖÖ~“Ñ¡ÄÂØ8RòßOñg»ÑgW¼¦Ýµ?K6²HÚ+ ØL ¯öJ6`zAÃï`ßUßg¨ïŽn1y¾iFŒ³a˃f¼ Òo%6âhR•w ÌG »¹"/&U¾;ºÅ( ½²’Z´+j³\§ÿ×Â1Ïе‹žÙ,®Þ[°Âd›&òc윣ju “m© œ?6ë…grW‚J¿•z¸â®+±{8¶ ›ŽÒ’ ¾Õå·ïÜ|!ßÛ ÔÒÓ†BâÔñø³ÝhnƒÚ;[&¹öáw°owG·æZˆpjÿÊ;f\ ÿžei®bøÓÿkaEÏlxâ  îÒ ×TƒN³9a&g§÷`ÐMGiIÛwn>JjÑ®ÜZÖÙf ß@ð;Ø7S®¼©Åž»ÞϲGéÿµ0ò½½ŠÂºÊ0“³S¦£´$6к“×Í)WÞT¿gÙ#.zf³¸JaÄh]”+o*7¾ ´¡Ž ÃßZï-!(len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) || len % SSH_BLOCKSIZE != 0)../sshcrcda.csingle-DES CBC0oBPoByBÐyBàyBдDtriple-DES inner-CBCðnBPoBqBPqB`qBü´D8µDµDPµDdes-cbc@ssh.comoBPoB`pBÀpB sB0sB@µD8дDdes-cbcoBPoB`pBÀpB sB0sB|µD8дDĵDP¶DðµD3des-cbctriple-DES CBCÐnBPoB`pB`oB€qBqB̵D¨ÕµD3des-ctrtriple-DES SDCTRÐnBPoB`pB`oB qB qB¶D¨%¶D €€€€€ € € €€ € €€€€€€€ €€  €€€€ €€  €€ €€€€ € € € €€€€€€€€€ €€ € €€ €€€ €  €€ € €€€ €€ € €€€ € €€ €€€ € € €€€€ € €€€ € €€ €€ € € €€€€ € € €€ €€€ € € € € € €€ € € €€€ € €B@@@BB@@@@BBB@BBB@B@@B@BBBB@B@@@ @ @@@ @ @@ @@ @@@ @@ @@@ @@@@ @ @ @@@@ @@@@@ @ @ @@@@ @@ @@ @ @@ @@@ @@@@ @ @@ @@@@@ @@ @@                             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'/7?&.6> %-5=  !)19 "*2: #+3;$,4<1$;7ÿÿÿÿÿÿÿÿ%)08"4ÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿ.+ÿÿÿÿÿÿÿÿ9 -6'2ÿÿÿÿÿÿÿÿ,5!(/:ÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿ (len & 7) == 0../sshdes.cøÀDhÁD$ÁDdiffie-hellman-group-exchange-sha1ÁDHÎDdiffie-hellman-group-exchange-sha256@ÁD(ÉDŒÁD´ÁDdiffie-hellman-group14-sha1group14ÁD¬ÁDðÁDÐÁDHÎDÿÿÿÿÿÿÿÿÉÚ¢!hÂ4ÄÆb‹€ÜÑ)NŠgÌt ¾¦;›"QJyŽ4ÝÍ:C0+ mò_7Oá5mmQÂEä…µvb^~ÆôLBé¦7ík ÿ\¶ô·íî8kûZ‰Ÿ¥®Ÿ$|KæI(fQìä[=Â|¸¡c¿˜ÚH6UÓši?¨ý$Ï_ƒe]#Ü£­–bóV …R»žÕ)p––mg 5NJ¼˜ñtlÊ!|2^F.6Î;ãžw,†›'ƒ¢ì¢µÅ]ðoLRÉÞ+Ëö•X9•I|ê•jåÒ&˜úrŽZЬªhÿÿÿÿÿÿÿÿøÂD ÃDdiffie-hellman-group1-sha1group1üÂDÃDPÃDÐÁD€HÎDÿÿÿÿÿÿÿÿÉÚ¢!hÂ4ÄÆb‹€ÜÑ)NŠgÌt ¾¦;›"QJyŽ4ÝÍ:C0+ mò_7Oá5mmQÂEä…µvb^~ÆôLBé¦7ík ÿ\¶ô·íî8kûZ‰Ÿ¥®Ÿ$|KæI(fQìæSÿÿÿÿÿÿÿÿssh-dssdss~BPBBðˆB@‹BŒB`B@ŽBБB ƒB°†B’BÐÃDØÃD0123456789abcdefssh-dssssh-dss %d :%s%02xp == blob + bloblen../sshdss.cDSA deterministic k generatorhmac-md5HMAC-MD5 B  B0¡B ¢BÀ¢B°ÄD¹ÄDfile format errorwrong passphraseerror reading filersa_verify failedrbnot an SSH-1 RSA fileSSH PRIVATE KEY FILE FORMAT 1.1 can't open filewbssh-rsassh-dssPuTTY-User-Key-File-2EncryptionPuTTY-User-Key-File-1not a PuTTY SSH-2 private keyaes256-cbcCommentPublic-LinesPrivate-LinesPrivate-MACPrivate-Hashputty-private-key-file-mac-key%02xMAC failednonecreatekey failedwPublic-Lines: %d PuTTY-User-Key-File-2: %s Encryption: %s Comment: %s Private-Lines: %d Private-MAC: priv_encrypted_len - priv_blob_len < 20../sshpubk.crPuTTY-User-Key-File----- BEGIN SSH2 ENCRYPTED PRIVAT-----BEGIN INTERNAL ERRORssh.com SSH-2 private keyunable to open filenot a private keySSH-1 private keyPuTTY SSH-2 private keyOpenSSH SSH-2 private keybÉBiÉBpÉBwÉB~ÉBWÉBssh-rsarsa2ðÛB ÜBÀÜBÝBpÞBàBáB âBpæBÀæB`éBëB ÈD(ÈD0!0 +RSA deterministic blinding0123456789abcdef%d :%s%02xp == blob + bloblen../sshrsa.cssh-rsassh-rsa %d 1 <= nbytes - 20 - ASN1_LENSHA-2560÷B`÷Bp÷B ÉD˜/ŠB‘D7qÏûÀµ¥Ûµé[ÂV9ññY¤‚?’Õ^«˜ªØ[ƒ¾…1$Ã} Ut]¾rþ±Þ€§Ü›tñ›ÁÁi›ä†G¾ïÆÁÌ¡ $o,é-ª„tJÜ©°\ÚˆùvRQ>˜mÆ1¨È'°ÇY¿ó àÆG‘§ÕQcÊg))… ·'8!.üm,M 8STs e» jv.ÉÂ…,r’¡è¿¢Kf¨p‹K£QlÇè’Ñ$™Ö…5ôp jÁ¤l7LwH'µ¼°4³ 9JªØNOÊœ[óo.hî‚toc¥xxȄnjúÿ¾ëlP¤÷£ù¾òxqÆgæ jɼó…®g»;§Ê„rón<+ø”þ:õO¥ñ6_RQт歌h›l>+«Ùƒk½AûÍà[y!~˜/ŠB"®(בD7qÍeï#ÏûÀµ/;Mì¥Ûµé¼Û‰[ÂV98µHóññY椂?’›O¯Õ^«mÚ˜ªØB£[ƒ¾opE¾…1$Œ²äNÃ} Uâ´ÿÕt]¾ro‰{òþ±Þ€±–;§Ü›5Ç%tñ›Á”&iÏÁi›äÒJñž†G¾ïã%O8ÆÁµÕŒ‹Ì¡ $eœ¬wo,é-u+Yª„tJƒä¦nÜ©°\ÔûA½ÚˆùvµSƒRQ>˜«ßfîmÆ1¨2´-È'°?!û˜ÇY¿äï¾ó àÆÂ¨=G‘§Õ%§ “QcÊo‚àg))pn … ·'ü/ÒF8!.&É&\üm,Mí*ÄZ 8Sß³•Ts eÞc¯‹» jv¨²w<.ÉÂæ®íG…,r’;5‚¡è¿¢dñLKf¨0B¼p‹K‘—øÐ£QlÇ0¾Tè’ÑRïÖ$™Ö©eU…5ô* qWp j¸Ñ»2Á¤ÈÐÒ¸l7S«AQLwH'™ëŽßµ¼°4¨H›á³ 9cZÉÅJªØNËŠAãOÊœ[sãcwóo.h£¸²Öî‚tü²ï]oc¥x`/CxÈ„r«ð¡ÇŒì9dúÿ¾(c#ëlP¤é½‚Þ÷£ù¾yƲòxqÆ+SrãÎ>'Êœa&êǸ†ÑÂÀ!Ö}ÚêëàÍO}õxÑnîªgðºorÅ}c ¦˜È¢˜?® ù¾5 qGõwÛ(„}#{«Ê2“$Ç@ ¾ž<¼¾ÉÄgCL œ¾ÔÅL¶B>Ëœ)Y*~eü«oË_ìúÖ:ŒDlXGJhmac-sha1-96bug-compatible HMAC-SHA1-96%C %CP&CÐ'C (CÍD ÍDhmac-sha1bug-compatible HMAC-SHA1%C %CP&CP'C€'C`ÍDjÍDHMAC-SHA1-96%C %C0&CÐ'C (CÍD ÀÍDHMAC-SHA1%C %C0&CP'C€'C`ÍDÎDSHA-1$CÀ$CÐ$C@ÎDzlibzlib (RFC1950)`ÎD€2CP3CÀ3Cà8C0:CÐ;C€3CeÎD    !0 1@ A` a€ÀÁ€           0 0@ @` `€       "#*+23:;BCRSbcrs‚ƒ¢£ÂÃâã€@À  `àPÐ0°pðˆHÈ(¨hè˜XØ8¸xø„DÄ$¤dä”TÔ4´tô ŒLÌ,¬lìœ\Ü<¼|ü‚BÂ"¢bâ’RÒ2²rò ŠJÊ*ªjêšZÚ:ºzú†FÆ&¦fæ–VÖ6¶vöŽNÎ.®nîž^Þ>¾~þAÁ!¡aá‘QÑ1±qñ ‰IÉ)©ié™YÙ9¹yù…EÅ%¥eå•UÕ5µuõ MÍ-­mí]Ý=½}ýƒCÃ#£cã“SÓ3³só ‹KË+«kë›[Û;»{û‡GÇ'§gç—W×7·w÷OÏ/¯oïŸ_ß?¿ÿout->noutbits + nbits <= 32../sshzlib.cj - i >= 2!out->comp_disabled     hACAC•@Cù?C¡?C%?C½>Cl>C¥WILLWONTDODONT%s: %s %sclientclient: SB NAWS %d,%dserverConnecting to %s port %dFailed to connect to %s: %s%sserver: SB TTYPE server: SB TSPEED server: SB %s SENDserver: SB TSPEED SENDclient: SB TSPEED IS %sserver: SB TTYPE SENDclient: SB TTYPE IS %s USER=client: SB %s IS %s%s%s%sMCÝNC`OC®NC‰OCmOCzOCuNC6NCMCLC°LC MC0VC (IPv4) (IPv6)Looking up host "%s"%sÿÿ ˆ[C‘[Cš[Cß[Cè[Cñ[CÒZC[C [C[C[C[C"[C”ZC([CÆZCS[CAre You ThereBreakSynchErase CharacterErase LineGo AheadNo OperationAbort ProcessAbort OutputInterrupt ProcessSuspend ProcessEnd Of RecordEnd Of FileDØDRØDXØD^ØDnØDyØD‚ØDØDØDªØD ¼ØD ÌØD ÚØD !relation == REL234_LT || relation == REL234_GT../tree234.cexpected ']' to close character classcharacter range was not terminated (']' just after '-')INTERNAL ERROR: unrecognised wildcard error number'' occurred at end of string (expected another character)*wildcard == '*'../wildcard.cThe server's host key is not cached in the registry. You have no guarantee that the server is the computer you think it is. The server's %s key fingerprint is: %s Connection abandoned. The server's host key is not cached in the registry. You have no guarantee that the server is the computer you think it is. The server's %s key fingerprint is: %s If you trust this host, enter "y" to add the key to PuTTY's cache and carry on connecting. If you want to carry on connecting just once, without adding the key to the cache, enter "n". If you do not trust this host, press Return to abandon the connection. Store key in cache? (y/n) WARNING - POTENTIAL SECURITY BREACH! The server's host key does not match the one PuTTY has cached in the registry. This means that either the server administrator has changed the host key, or you have actually connected to another computer pretending to be the server. The new %s key fingerprint is: %s Connection abandoned. WARNING - POTENTIAL SECURITY BREACH! The server's host key does not match the one PuTTY has cached in the registry. This means that either the server administrator has changed the host key, or you have actually connected to another computer pretending to be the server. The new %s key fingerprint is: %s If you were expecting this change and trust the new key, enter "y" to update PuTTY's cache and continue connecting. If you want to carry on connecting but without updating the cache, enter "n". If you want to abandon the connection completely, press Return to cancel. Pressing Return is the ONLY guaranteed safe choice. Update cached key? (y/n, Return cancels connection) Connection abandoned. The first %s supported by the server is %s, which is below the configured warning threshold. Continue with connection? (y/n) The first %s supported by the server is %s, which is below the configured warning threshold. Connection abandoned. Connection abandoned. The session log file "%.*s" already exists. You can overwrite it with a new session log, append your session log to the end of it, or disable session logging for this session. Enter "y" to wipe the file, "n" to append to it, or just press Return to disable logging. Wipe the log file? (y/n, Return cancels logging) The session log file "%.*s" already exists. Logging will not be enabled. You are loading an SSH-2 private key which has an old version of the file format. This means your key file is not fully tamperproof. Future versions of PuTTY may stop supporting this private key format, so we recommend you convert your key to the new format. Once the key is loaded into PuTTYgen, you can perform this conversion simply by saving it again. These are the fingerprints of the PuTTY PGP Master Keys. They can be used to establish a trust path from this executable to another one. See the manual for more information. (Note: these fingerprints have nothing to do with SSH!) PuTTY Master Key (RSA), 1024-bit: 8F 15 97 DA 25 30 AB 0D 88 D1 92 54 11 CF 0C 4C PuTTY Master Key (DSA), 1024-bit: 313C 3E76 4B74 C2C5 F2AE 83A8 4F5E 6DF5 6A93 B34E Cannot get standard input/output handles FontLogFileNameSerialLineCOM1h->output../windows/winhandl.ch && !h->u.g.moribundhandles_by_evtomain!h->outputlocalhostDISPLAYdebug.logwWS2_32.DLLgetaddrinfofreeaddrinfogetnameinfogai_strerrorUnable to initialise WinSockWSAIoctlrecvacceptioctlsocketsendlistensocketsetsockoptbindconnectinet_ntoainet_addrgetservbynamegethostbynamentohshtonshtonlntohlclosesocketWSACleanupWSAStartupWSAEnumNetworkEventsWSAGetLastErrorselectWSAEventSelectWSAAsyncSelectWSAAddressToStringAwship6.dllWSOCK32.DLLUnable to load any WinSock libraryUnknown network errorNetwork error: Graceful shutdown in progressNetwork error: Too many processesNetwork error: No route to hostNetwork error: Host is downNetwork error: Connection refusedNetwork error: Connection timed outNetwork error: Cannot send after socket shutdownNetwork error: Socket is not connectedNetwork error: Socket is already connectedNetwork error: No buffer space availableNetwork error: Connection reset by peerNetwork error: Software caused connection abortNetwork error: Network dropped connection on resetNetwork error: Network is unreachableNetwork error: Network is downNetwork error: Cannot assign requested addressNetwork error: Address already in useNetwork error: Address family not supported by protocol familyNetwork error: Protocol family not supportedNetwork error: Operation not supportedNetwork error: Socket type not supportedNetwork error: Protocol not supportedNetwork error: Bad protocol optionNetwork error: Protocol wrong type for socketNetwork error: Message too longNetwork error: Destination address requiredNetwork error: Socket operation on non-socketNetwork error: Operation already in progressNetwork error: Operation now in progressNetwork error: Resource temporarily unavailableNetwork error: Too many open filesNetwork error: Invalid argumentNetwork error: Bad addressNetwork error: Permission deniedNetwork error: Interrupted function callL”CW“CW“CW“CW“CW“CW“CW“CW“CE”C>”CW“CW“CW“CW“CW“CW“CW“C7”CW“C0”CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“C)”C"”C”C”C ”C”Cÿ“Cø“Cñ“Cê“Cã“CÜ“CÕ“CΓCÇ“CÀ“C¹“C²“C«“C¤“C“C–“C“Cˆ“CW“C“Cz“CW“CW“Cs“Cl“CW“Ce“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“CW“C^“CNetwork is downHost does not existHost not foundgethostbyname: unknown errorIPv6addr->addresses && addr->curraddr < addr->naddresses../windows/winnet.clocalhostUnable to get list of local IP addressesaddr->family == AF_UNSPECaddr->family != AF_UNSPECFALSE œCP¦C€¨Cà¨CÀœC ®C°®Cà®CЮCsock->addr->addresses && sock->addr->curraddr < sock->addr->naddresses œCP¦C€¨Cà¨CÀœC ®C°®Cà®CЮC œCP¦C€¨Cà¨CÀœC ®C°®Cà®CЮC%slen <= sizeof(s->oobdata)Internal networking trouble«Cf¬C¬C«C±«C«C«C«CzªC«C«C«C«C«C«C«C«C«C«C«C«C«C«C«C«C«C«C«C«C«C«C«C «Cunix sockets not supported on this platformPageantPageantRequest%08xFATAL ERROR: plink: ../windows/winplink.c!"Unexpected call to from_backend_untrusted()"Network is downWSAEventSelect(): unknown errorUnable to read from standard input: %s outputerrorUnable to write to standard %s: %s  PLINK_PROTOCOL-batch :Plink requires WinSock 2 telnet:-s-V-pgpfpplink: unknown option "%s" plink: option "%s" requires an argument Unable to open connection: %sInternal fault: Unsupported protocol found PuTTY Link: command-line connection utilityUsage: plink [options] [user@]host [command] ("host" can also be a PuTTY saved session name)Options: -V print version information and exit -pgpfp print PGP key fingerprints and exit -v show verbose messages -load sessname Load settings from saved session -ssh -telnet -rlogin -raw force use of a particular protocol -P port connect to specified port -l user connect with specified username -batch disable all interactive promptsThe following options only apply to SSH connections: -pw passw login with specified password -D [listen-IP:]listen-port Dynamic SOCKS-based port forwarding -L [listen-IP:]listen-port:host:port Forward local port to remote address -R [listen-IP:]listen-port:host:port Forward remote port to local address -X -x enable / disable X11 forwarding -A -a enable / disable agent forwarding -t -T enable / disable pty allocation -1 -2 force use of particular protocol version -4 -6 force use of IPv4 or IPv6 -C enable compression -i key private key file for authentication -noagent disable use of Pageant -agent enable use of Pageant -m file read remote command(s) from file -s remote command is an SSH subsystem (SSH-2 only) -N don't start a shell/command (SSH-2 only) -nc host:port open tunnel in place of session (SSH-2 only)Remote process exit code unavailable plink: %s Read error from local proxy commandÏC ÏCpÏCÏC ÏC°ÏCÀÏCÐÏCàÏCStarting local proxy command: %sUnable to create pipes for proxy commandError reading from serial device%sEnd of file reading from serial deviceError writing to serial deviceConfiguring baud rate %dConfiguring %d data bitsInvalid number of stop bits (need 1, 1.5 or 2)2spaceConfiguring %s parityConfiguring %s flow controlUnable to configure serial portUnable to configure serial timeouts1.5Configuring %s data bits1XON/XOFFRTS/CTSnomarkevenoddDSR/DTRùÖCëÖCÝÖCÏÖC3ÕCOpening serial device %s%s%sUnable to open serial port\\.\Finished serial breakStarting serial break at user requestBreaknÿD!0123456789ABCDEFSoftware\SimonTatham\PuTTY\SessionsDefault SettingsUnable to create registry key HKEY_CURRENT_USER\%sUnable to create registry key HKEY_CURRENT_USER\%s\%sIsBoldCharSetHeight%d:Software\SimonTatham\PuTTY\SshHostKeysrsa:/Software\SimonTatham\PuTTYHOMEDRIVEHOMEPATHRandSeedFileSHELL32.DLLSHGetFolderPathASoftware\SimonTathamPuTTYSoftwareSimonTathamMIT-MAGIC-COOKIE-1XDM-AUTHORIZATION-10E1EDE%02xproto_id == X11_XDM../x11fwd.c:.:0€ñCòC@òCòCunix%d.%d.%d.%dn != 0wrong authentication protocol attemptedXDM-AUTHORIZATION-1 time stamp was too far outXDM-AUTHORIZATION-1 data replayedPuTTY X11 proxy: %sXDM-AUTHORIZATION-1 data was wrong lengthcannot do XDM-AUTHORIZATION-1 without remote address dataXDM-AUTHORIZATION-1 data failed checkMIT-MAGIC-COOKIE-1 data was wrong lengthMIT-MAGIC-COOKIE-1 data did not matchpr->auth->reallen <= lenof(realauthdata)auth->xdmseen != NULLseen != NULL-LIBGCCW32-EH-3-SJLJ-GTHR-MINGW32w32_sharedptr->size == sizeof(W32_EH_SHARED)../../gcc-3.4.5/gcc/config/i386/w32-shared-ptr.cGetAtomNameA (atom, s, sizeof(s)) != 0|P`\´R¤PD]ÜR€Q\]¸SQT^ÈS„Rˆ^¼TèTøTUU&U4UBUVUhUtU„U–U¤U´UÂUØUæUøUVV"V.V@VPVbVpV€VV¢V¶VÌVàVöVWW.W>WTWfWxWˆW˜W²WÄWÔWäWüWX"X2XLXXXhXxXŠXœX¨XÀXÞXðXYYY*Y:YJYZYhYzY„YŽY–Y¢Y¬Y¶YÂYÐYØYâYêYòYüYZZZZ(Z0Z8Z@ZHZRZ\ZfZpZzZ„ZŽZ˜Z Z¨Z²Z¼ZÆZÐZÚZäZîZøZ[[["[,[6[@[J[T[^[f[p[z[†[”[¢[¶[Æ[Ü[î[ \\0\èTøTUU&U4UBUVUhUtU„U–U¤U´UÂUØUæUøUVV"V.V@VPVbVpV€VV¢V¶VÌVàVöVWW.W>WTWfWxWˆW˜W²WÄWÔWäWüWX"X2XLXXXhXxXŠXœX¨XÀXÞXðXYYY*Y:YJYZYhYzY„YŽY–Y¢Y¬Y¶YÂYÐYØYâYêYòYüYZZZZ(Z0Z8Z@ZHZRZ\ZfZpZzZ„ZŽZ˜Z Z¨Z²Z¼ZÆZÐZÚZäZîZøZ[[["[,[6[@[J[T[^[f[p[z[†[”[¢[¶[Æ[Ü[î[ \\0\õGetUserNameA‚RegCloseKey…RegCreateKeyA‰RegDeleteKeyARegEnumKeyAœRegOpenKeyA§RegQueryValueExA²RegSetValueExAAddAtomA AllocConsole#ClearCommBreak&CloseHandle@CreateEventADCreateFileAECreateFileMappingATCreatePipeUCreateProcessA[CreateThreadœExitProcess°FindAtomA²FindClose¶FindFirstFileA¿FindNextFileAÑFormatMessageAÖFreeLibraryÝGetAtomNameAëGetCommStateGetConsoleModeGetCurrentProcessGetCurrentProcessIdGetCurrentThreadGetCurrentThreadId/GetEnvironmentVariableA<GetFileTypeEGetLastErrorFGetLocalTime`GetOverlappedResultlGetProcAddressuGetProcessTimes„GetStdHandle‘GetSystemTime’GetSystemTimeAdjustment¦GetThreadTimes§GetTickCount±GetVersionExA»GetWindowsDirectoryAÌGlobalMemoryStatus LoadLibraryA"MapViewOfFileUQueryPerformanceCounterhReadFileŒSetCommBreakSetCommStateSetCommTimeouts¥SetConsoleModeºSetEventÆSetHandleInformationãSetUnhandledExceptionFilterUnmapViewOfFile*WaitForSingleObject;WriteFileR_stricmpU_strnicmp'__getmainargs0__mb_cur_max<__p__environ>__p__fmodeP__set_app_typeo_asserty_cexité_iobë_isctype^_onexitg_pctype„_setmode½_vsnprintfabortatexitatoi*exit-fclose0fflush1fgetc3fgets8fopen9fprintf:fputc;fputs>fread?freeGfwriteKgetenvrmallocvmemchrxmemcpyymemmovezmemsetprintf‚puts…qsortˆrealloc‰removesignal“sprintf–sscanf˜strchr™strcmp›strcpyœstrcspnžstrftimeŸstrlen strncat¢strncpy¤strrchr¥strspn¨strtok©strtolªstrtoul±time´tolower¸ungetcºvfprintfÑFindWindowAßGetCaptureðGetClipboardOwneröGetCursorPosGetForegroundWindow5GetQueueStatus»MsgWaitForMultipleObjectsÍPeekMessageAÒPostThreadMessageA÷SendMessageAPPPPPPPPADVAPI32.DLLPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPKERNEL32.dll(P(Pmsvcrt.dll true mlterm-3.8.9/win32/setup-msys.bat010075500017600000144000000006121356600661000153210ustar kenusers@echo off rem 'set /p' is effective in Windows2000 or later. set /p MSYS_DIR="Where MSYS is installed[c:\MSYS\1.0]" if "%MSYS_DIR%" == "" set MSYS_DIR=c:\MSYS\1.0 echo set HOME=%MSYS_DIR%\home\%USERNAME%> mlterm.bat echo set PATH=%MSYS_DIR%\bin;%%PATH%%>> mlterm.bat echo set CYGWIN=tty>> mlterm.bat echo start mlterm -S sample -e /bin/sh --login -i>> mlterm.bat echo exit>> mlterm.bat mlterm-3.8.9/doc004075500017600000144000000000001356600661000122255ustar kenusersmlterm-3.8.9/doc/en004075500017600000144000000000001356600661000126275ustar kenusersmlterm-3.8.9/doc/en/README.beos010064400017600000144000000013771356600661000145220ustar kenuserscomment -*- mode: text; tab-width:2; indent-tabs-mode:nil -*- BeOS (Haiku) support * Tested environment Haiku R1 Beta1 * Build ./configure --with-gui=beos ... make sudo make install * Configuration Edit main, font, key and color files in ~/.mlterm/ See files in http://bitbucket.org/arakiken/mlterm/src/tip/etc/ (Font Configuration) Format of font,vfont,tfont is as follows. [font family]( Bold Italic [font size]:[percentage]) Unlike aafont for cairo and xft, it is not necessary to escape '-' character by '\' in [font family] string. aafont, vaafont, taafont files are not used. * Start mlterm * Caution o -L/--ls, -u/--onlyucsfont and --boxdraw options are enabled by default. o It is impossible to disable -s/--mdi option. mlterm-3.8.9/doc/en/ControlSequences010064400017600000144000000644131356600661000161320ustar kenuserscomment -*- mode: text; tab-width:2; indent-tabs-mode:nil -*- List of escape/control sequences which mlterm supports. O: Support, -: Not support MNEMONIC SEQUENCE https://vt100.net/docs/vt520-rm/ek-vt520-rm.pdf O CBT (Cursor Backward Tabulation) CSI Pn Z O CHA (Cursor Horizontal Absolute) CSI Pn G O CHT (Cursor Horizontal Forward Tabulation) CSI Pn I O CNL (Cursor Next Line) CSI Pn E O CPL (Cursor Previous Line) CSI Pn F O CPR (Cursor Position Report) CSI 6 n - CRM (Show Control Character Mode) CSI 3 [hl] O CUB (Cursor Backward) CSI Pn D O CUD (Cursor Down) CSI Pn B O CUF (Cursor Forward) CSI Pn C O CUP (Cursor Position) CSI Pl;Pc H O CUU (Cursor Up) CSI Pn A O DA1 (Primary Device Attributes) CSI c O DA2 (Secondary Device Attributes) CSI > c O DA3 (Tertiary Device Attributes) CSI = c O DCH (Delete Character) CSI Pn P - DECAAM (Set/Reset Auto Answerback Mode) CSI ? 100 [hl] O DECAC (Assign Color) CSI Ps1;Ps2;Ps3 , l O DECALN (Screen Alignment Pattern) ESC # 8 O DECANM (ANSI Mode) CSI ? 2 [hl] - DECARM (Autorepeat Mode) CSI ? 8 [hl] - DECARR (Select Auto Repeat Rate) CSI Ps - p - DECARSM (Set/Reset Auto Resize Mode) CSI ? 98 [hl] O DECATC (Alternate Text Color) CSI Ps1;Ps2;Ps3 , } - DECATCBM (Set/Reset Alternate Text Color Blink Mode) CSI ? 115 [hl] - DECATCUM (Set/Reset Alternate Text Color Underline Mode) CSI ? 114 [hl] - DECAUPSS (Assigning User-Preferred Supplemental Sets) DCS Pn ! u Dscs ST O DECAWM (Autowrap Mode) CSI ? 7 [hl] O DECBI (Back Index) ESC 6 O DECBBSM (Bold and Blink Style Mode) CSI ? 116 [hl] O DECBKM (Backarrow Key Mode) CSI ? 67 [hl] - DECCANSM (Conceal Answerback Message Mode) CSI ? 101 [hl] - DECCAPSLK (Caps Lock Mode) CSI ? 109 [hl] O DECCARA (Change Attributes in Rectangular Area) CSI Pt;Pl;Pb;Pr;Ps1;...;Psn $ r - DECCKD (Copy Key Default) DCS " z D...D ST O DECCKM (Cursor Keys Mode) CSI ? 1 [hl] O DECCKSR (Memory Checksum Report) CSI ? 63;Pid n DCS Pid ! ~ D...D ST O DECCOLM (Select 80 or 132 Columns per Page) CSI ? 3 [hl] O DECCRA (Copy Rectangular Area) CSI Pts;Pls;Pbs;Prs;Pps;Ptd;Pld;Ppd $ v - DECCRTSM (Set/Reset CRT Save Mode) CSI ? 97 [hl] - DECCRTST (CRT Saver Timing) CSI Ps - q O DECCTR (Color Table Request) CSI 2;Pu $ u O DECDC (Delete Column) CSI Pn ' ~ O DECDHL (Double-WidthDouble-Height Line) ESC # [34] O DECDLD (Dynamically Redefinable Character Sets) DCS Pfn;Pcn;Pe;Pcmw;Pss;Pt;Pcmh;Pcss f Dscs Sxbp1;...;Sxbpn ST O DECDMAC (Define Macro) DCS Pid;Pdt;Pen ! z D...D ST - DECDLDA (Down Line Load Allocation) CSI Ps , z O DECDWL (Double-WidthSingle-Height Line) ESC # 6 O DECECM (Erase Color Mode) CSI ? 117 [hl] - DECEKBD (Extended Keyboard Report) APC : ppp mm ST - DECELF (Enable Local Functions) CSI Pf1;Pc1;...;Pfn;Pcn + q O DECERA (Erase Rectangular Area) CSI Pt;Pl;Pb;Pr $ z - DECES (Enable Session) CSI & x - DECESKM (Enable Secondary Keyboard Language Mode) CSI ? 104 [hl] O DECFI (Forward Index) ESC 9 O DECFRA (Fill Rectangular Area) CSI Pch;Pt;Pl;Pb;Pr $ x - DECFWM (Set/Reset Framed Windows Mode) CSI ? 111 [hl] - DECHDPXM (Set/Reset Half-Duplex Mode) CSI ? 103 [hl] - DECHEBM (Hebrew/N-A Keyboard Mapping) CSI ? 35 [hl] - DECHEM (Hebrew Encoding Mode) CSI ? 36 [hl] - DECHWUM (Host Wake-Up Mode (CRT and Energy Saver)) CSI ? 113 [hl] O DECIC (Insert Column) CSI Pn ' } O DECID (Identify Device) ESC Z O DECINVM (Invoke Macro) CSI Pid * z - DECIPEM (Enter/Return from IBM ProPrinter Emulation Mode) CSI ? 58 [hl] - DECKBD (Keyboard Language Selection) CSI Ps1;Ps2 SP } - DECKBUM (Typewriter or Data Processing Keys) CSI ? 68 [hl] O DECKLHIM (Keyboard LED's Host Indicator Mode) CSI ? 110 [hl] O DECKPAM (Keypad Application Mode) ESC = - DECKPM (Key Position Mode) CSI ? 81 [hl] O DECKPNM (Keypad Numeric Mode) ESC > - DECLANS (Load Answerback Message) DCS Ps v D...D ST - DECLBAN (Load Banner Message) DCS Ps r D...D ST - DECLFKC (Local Function Key Control) CSI Pk1;Pf1;...;Kpn;Pfn * } - DECLL (Load LEDs) CSI Ps q O DECLRMM (Left Right Margin Mode) CSI ? 69 [hl] - DECLTOD (Load Time of Day) CSI Ps1;Ps2 , p - DECMCM (Set/Reset Modem Control Mode) CSI ? 99 [hl] - DECNAKB (Greek/N-A Keyboard Mapping) CSI ? 57 [hl] O DECNCSM (Set/Reset No Clearing Screen On Column Change) CSI ? 95 [hl] O DECNKM (Numeric Keypad Mode) CSI ? 66 [hl] - DECNRCM (National Replacement Character Set Mode) CSI ? 42 [hl] - DECNULM (Set/Reset Ignoring Null Mode) CSI ? 102 [hl] - DECNUMLK (Num Lock Mode) CSI ? 108 [hl] O DECOM (Origin Mode) CSI ? 6 [hl] - DECOSCNM (Set/Reset Overscan Mode) CSI ? 106 [hl] - DECPAK (Program Alphanumeric Key) DCS " y D...D ST - DECPCCM (Page Cursor-Coupling Mode) CSI ? 64 [hl] - DECPCTERM (Enter/Exit PCTerm or Scancode Mode) CSI ? Ps1;Ps2 r - DECPEX (Printer Extent Mode) CSI ? 19 [hl] - DECPFF (Print Form Feed Mode) CSI ? 18 [hl] - DECPFK (Program Function Key) DCS " x D...D ST - DECPKA (Program Key Action) CSI Ps + z - DECPS (Play Sound) CSI Pv;Pd;Pn , ~ O DECRARA (Reverse Attributes in Rectangular Area) CSI Pt;Pl;Pb;Pr;Ps1;...;Psn $ t O DECRC (Restore Cursor) ESC 8 - DECRLCM (Right-to-Left Copy) CSI ? 96 [hl] - DECRLM (Cursor Right to Left Mode) CSI ? 34 [hl] O DECRQCRA (Request Checksum of Rectangular Area) CSI Pid;Pp;Pt;Pl;Pb;Pr * y O DECRQDE (Request Displayed Extent) CSI " v - DECRQKD (Request Key Definition) CSI Ps1;Ps2 , w - DECRQKT (Key Type Inquiry) CSI Ps , u O DECRQM (Request Mode Host To Terminal) (ANSI) CSI Pa $ p (DEC) CSI ? Pd $ p - DECRQPKFM (Program Key Free Memory Inquiry) CSI + x O DECRQPSR (Request Presentation State Report) CSI Ps $ w O DECRQSS (Request Selection or Setting) DCS $ q D...D ST O DECRQTSR (Request Terminal State Report) CSI Ps $ u - DECRQUPSS (User-Preferred Supplemental Set) CSI & u O DECRSPS (Restore Presentation State) DCS Ps $ t D...D ST - DECRSTS (Restore Terminal State) DCS Ps $ p D...D ST O DECSACE (Select Attribute Change Extent) CSI Ps * x O DECSASD (Select Active Status Display) CSI Ps $ } O DECSC (Save Cursor) ESC 7 O DECSCA (Select Character Protection Attribute) CSI Ps " q - DECSCL (Select Conformance Level) (L1) CSI 61 " p (L4) CSI 6 n ; Pn " p - DECSCLM (Scrolling Mode) CSI ? 4 [hl] O DECSCNM (Screen ModeLight or Dark Screen) CSI ? 5 [hl] - DECSCP (Select Communication Port) CSI Ps1;Ps2 * u O DECSCPP (Select 80 or 132 Columns per Page) CSI Ps $ | - DECSCS (Select Communication Speed) CSI Ps1;Ps2 * r O DECSCUSR (Set Cursor Style) CSI Ps SP q - DECSDDT (Select Disconnect Delay Time) CSI Ps $ q - DECSDPT (Select Digital Printed Data Type) CSI Ps ) p O DECSED (Selective Erase in Display) CSI ? Ps J O DECSEL (Selective Erase in Line) CSI ? Ps K - DECSEST (Energy Saver Timing) CSI Ps - r O DECSERA (Selective Erase Rectangular Area) CSI Pt;Pl;Pb;Pr $ { - DECSFC (Select Flow Control) CSI Ps1;Ps2;Ps3;Ps4 * s - DECSIN (Set Icon Name) OSC 2 L; ST - DECSKCV (Set Key Click Volume) CSI Ps SP r - DECSLCK (Set Lock Key Style) CSI Ps SP v O DECSLPP (Set Lines Per Page) CSI Pn t O DECSLRM (Set Left and Right Margins) CSI Pl;Pr s - DECSMBV (Set Margin Bell Volume) CSI Ps SP u - DECSMKR (Select Modifier Key Reporting) CSI Pm1;Pf1;...;Pmn;Pfn + r O DECSNLS (Set Lines Per Screen) CSI Pn * | - DECSPMA (Session Page Memory Allocation) CSI Pn1;Pn2;Pn3;Pn4; ' x - DECSPP (Set Port Parameter) CSI Ps1;Ps2;Ps3;Ps4 + w - DECSPPCS (Select ProPrinter Character Set) CSI Pn * p - DECSPRTT (Select Printer Type) CSI Ps $ s O DECSR (Secure Reset) CSI Pr + p - DECSSCLS (Set Scroll Speed) CSI Ps SP p O DECSSDT (Select Status Display (LineType)) CSI Ps $ ~ - DECSSL (Select Set-Up Language) CSI Ps p O DECST8C (Set Tab at Every Columns) CSI ? 5 W O DECSTBM (Set Top and Bottom Margins) CSI Pt;Pb r O DECSTGLT (Select Color Look-Up Table) CSI Pn ) { O DECSTR (Soft Terminal Reset) CSI ! p - DECSTUI (Setting Terminal Unit ID) DCS ! { D...D ST - DECSTRL (Set Transmit Rate Limit) CSI Ps1;Ps2 " u - DECSWBV (Set Warning Bell Volume) CSI Ps SP t O DECSWL (Single-Width, Single-Height Line) ESC # 5 - DECSZS (Select Zero Symbol) CSI Ps , { - DECSWT (Set Window Title) OSC 2 1; ST O DECTCEM (Text Cursor Enable Mode) CSI ? 25 [hl] - DECTID (Select Terminal ID) CSI Ps , q - DECTME (Terminal Mode Emulation) CSI Ps SP ~ - DECTST (Invoke Confidence Test) CSI 4;Ps;...;Ps y - DECUDK (User Defined Keys) DCS Ps1;Ps2;Ps3 | D...D ST - DECUS (Update Session) CSI PS , y - DECVCCM (Vertical Cursor-Coupling Mode) CSI ? 61 [hl] - DECXRLM (Transmit Rate Limiting) CSI ? 73 [hl] O DL (Delete Line) CSI Pn M O DSR (Cursor Position Report (CPR)) CSI 6 n O DSR (Data Integrity Report) CSI ? 75 n O DSR (Extended Cursor Position Report (DECXCPR)) CSI ? 6 n O DSR (Keyboard) CSI ? 26 n O DSR (Locator) CSI ? 53 n or CSI ? 55 n O DSR (Locator Exist) CSI ? 56 n O DSR (Macro Space Report) CSI ? 62 n O DSR (Memory Checksum (DECCKSR)) CSI ? 63;Pid n DCS Pid ! ~ D...D ST O DSR (Multiple Session) CSI ? 83 n O DSR (Operating Status) CSI 5 n O DSR (Printer Port) CSI ? 15 n O DSR (User-Defined Keys (VT Level Only)) CSI ? 25 n O ECH (Erase Character) CSI Pn X O ED (Erase in Display) CSI Ps J O EL (Erase in Line) CSI Ps K O HPA (Horizontal Position Absolute) CSI Pn ` O HPR (Horizontal Position Relative) CSI Pn a O HTS (Horizontal Tab Set) ESC H O HVP (Horizontal and Vertical Position) CSI Pl;Pc f O ICH (Insert Character) CSI Pn @ O IL (Insert Line) CSI Pn L O IND (Index) ESC D O IRM (Insert/Replace Mode) CSI 4 [hl] O KAM (Keyboard Action Mode) CSI 2 [hl] O LNM (Line Feed/New Line Mode) CSI 20 [hl] O MC (Media Copy) (ANSI) CSI Pn i (DEC) CSI ? Pn i O NEL (Next Line) ESC E O NP (Next Page) CSI Pn U O PP (Preceding Page) CSI Pn V O PPA (Page Position Absolute) CSI Pn SP P O PPB (Page Position Backward) CSI Pn SP R O PPR (Page Position Relative) CSI Pn SP Q O RIS (Reset to Initial State) ESC c - S7C1T (Send CControl Character to the Host) ESC SP F - S8C1T (Send CControl Character to the Host) ESC SP G O SD (Pan Up) CSI Pn T O SGR (Select Graphic Rendition) CSI Ps;Ps;... m O SRM (Local Echo: Send/Receive Mode) CSI 12 [hl] O SU (Pan Down) CSI Pn S O TBC (Tab Clear) CSI Ps g O VPA (Vertical Line Position Absolute) CSI Pn d O VPR (Vertical Position Relative) CSI Pn e --- SCO Console Emulation - SCODFK (Define Function Key) ESC Q Fn string - SCODPCC (Display PC Characters) ESC xx (xx = hex value) O SCOSC CSI s O SCORC CSI u https://vt100.net/docs/vt510-rm/contents.html - DECSRFR (Select Refresh Rate) CSI Ps " t ftp://ftp.invisible-island.net/shuford/terminal/dec_vt_mouse.html https://www.vt100.net/docs/vt3xx-gp/contents.html O DECEFR (Enable Filter Rectangle) CSI Pt;Pl;Pb;Pr ' w O DECELR (Enable Locator Reports) CSI Pn;Ps ' z O DECREGIS DCS Pn p D...D ST O DECRQLP (Request Locator Position) CSI ' | O DECSIXEL DCS Pn1;Pn2;Pn3;Pn4 q D...D ST O DECSDM (Sixel Scrolling) CSI ? 80 [hl] O DECSLE (Select Locator Events) CSI Pn ' { https://vt100.net/docs/vt100-ug/chapter3.html O DECREQTPARM (Request Terminal Parameters) CSI Pn x https://vt100.net/emu/ctrlfunc_dec.html O DECCAHT (Clear All Horizontal Tabs) ESC 2 - DECCAVT (Clear All Vertical Tabs) ESC 4 - DECHTS (Horizontal Tab Set) ESC 1 - DECVTS (Vertical Tab Set) ESC 3 - DECSHTS (Set Horizontal Tabulation Stops) CSI Pn u - DECSVTS (Set Vertical Tabulation Stops) CSI Pn v ftp://ftp.invisible-island.net/shuford/terminal/ansi_dec_controls_news.txt O WYSTCURM (Wyse Steady Cursor Mode) CSI 33 [hl] O WYULCURM (Wyse Underline Cursor Mode) CSI 34 [hl] https://www.vt100.net/docs/vt220-rm/table4-11.html O CUP (Cursor Up) ESC A O BPH (Cursor Down) ESC B - ESA (Exit Graphics Mode) ESC G O MCP (Direct Cursor Address) ESC Y y x O NBH (Cursor Right) ESC C O V5EX (Exiting ANSI(VT52) Mode) ESC < - SCI (Identify) ESC Z - SSA (Enter Graphics Mode) ESC F O (Cursor Left) ESC D O (Cursor to Home Position) ESC H O (Reverse Line Feed) ESC I O (Erase to end of screen) ESC J O (Erase to end of line) ESC K - (Enter Alternate Keypad Mode) ESC = - (Exit Alternate Keypad Mode) ESC > - (Enter Auto Print Mode) ESC ^ - (Exit Auto Print Mode) ESC _ - (Enter Printer Contoller Mode) ESC W - (Exit Printer COntroller Mode) ESC X - (Print Screen) ESC ] - (Print cursor line) ESC V http://invisible-island.net/xterm/ctlseqs/ctlseqs.txt O XTALTSCRN (Use Alternate Screen Buffer) CSI ? 47 [hl] O XTALTS47 (Use Alternate Screen Buffer) CSI ? 1047 [hl] O XTALTS48 (Save cursor as in DECSC) CSI ? 1048 [hl] O XTEXTSCRN (Save cursor as in DECSC and use Alternate Screen Buffer) CSI ? 1049 [hl] O XTBRACKET (Set bracketed paste mode) CSI ? 2004 [hl] O XTMDKEY CSI > Pn;Ps m O XTMDKYD CSI > Pn n O XTMSEANY (Use All Motion Mouse Tracking) CSI ? 1003 [hl] O XTMSEBTN (Use Cell Motion Mouse Tracking) CSI ? 1002 [hl] O XTMSERXVT (Enable urxvt Mouse Mode) CSI ? 1015 [hl] O XTMSESGR (Enable SGR Mouse Mode) CSI ? 1006 [hl] O XTMSEUTF (Enable UTF-8 Mouse Mode) CSI ? 1005 [hl] O XTMSEWIN (Send FocusIn/FocusOut events) CSI ? 1004 [hl] O XTMSEX11 (Send Mouse X & Y on button press and release) CSI ? 1000 [hl] O (Scroll to bottom on tty output (rxvt)) CSI ? 1010 [hl] X (Scroll to bottom on key press (rxvt)) CSI ? 1011 [hl] O (Interpret "meta" key (set eighth bit of keyboard input)) CSI ? 1034 [hl] O (Send ESC when Meta modifiers a key) CSI ? 1036 [hl] O XTHDPT (Set resource value pointerMode) CSI > Pn p O XTREST (Restore DEC Private Mode Values) CSI ? Pn r O XTSAVE (Save DEC Private Mode Values) CSI ? Pn s O XTSMTT (Set one or more features of the title modes) CSI > Pn t O XTRMTT (Reset one or more features of the title modes to the default value) CSI > Pn T O XTWOP (Window manipulation) CSI Pn;P1;P2 t - XTSTCAP (Set Termcap/Terminfo Data) DCS + p D...D ST O XTRQCAP (Request Termcap/Terminfo String) DCS + q D...D ST - XTCOLREG CSI ? Pi;Pa;Pv S - XTMSEX10 (X10 xterm mouse protocol) CSI ? 9 [hl] - XTCBLINK (Start Blinking Cursor (att610)) CSI ? 12 [hl] O (Allow 80 -> 132 Mode) CSI ? 40 [hl] - (more(1) fix) CSI ? 41 [hl] - (Reverse-wraparound Mode) CSI ? 45 [hl] - (Use Hilite Mouse Tracking) CSI ? 1001 [hl] O (Enable Urgency window manager hint) CSI ? 1042 [hl] O (Change Icon Name and Window Title) OSC 0;Pt ST O (Change Icon Name) OSC 1;Pt ST O (Change Window Title) OSC 2;Pt ST - (Set X property on top-level window) OSC 3;Pt ST O (Change Color Number c to the color spec) OSC 4;c;spec ST O (Change Special Color Number c to the color spec) OSC 5;c;spec - (Enable/disable Special Color Number c) OSC 6;c;f OSC 106;c;f O (Change VT100 text foreground color) OSC 10;Pt ST O (Change VT100 text background color) OSC 11;Pt ST O (Change text cursor color) OSC 12;Pt ST - (Change mouse foreground color) OSC 13;Pt ST - (Change mouse background color) OSC 14;Pt ST - (Change Tektronix foreground color) OSC 15;Pt ST - (Change Tektronix background color) OSC 16;Pt ST - (Change highlight background color) OSC 17;Pt ST - (Change Tektronix cursor color) OSC 18;Pt ST - (Change highlight foreground color) OSC 19;Pt ST - (Change Log File) OSC 46;Pt ST - (Set Font) OSC 50;Pt ST O (Manipulate Selection Data) OSC 52;Pt ST O (Reset Color Number c) OSC 104;c ST O (Reset Special Color Number c) OSC 105;c ST - (Reset VT100 text foreground color) OSC 110;Pt ST - (Reset VT100 text background color) OSC 111;Pt ST - (Reset text cursor color) OSC 112;Pt ST - (Reset mouse foreground color) OSC 113;Pt ST - (Reset mouse background color) OSC 114;Pt ST - (Reset Tektronix foreground color) OSC 115;Pt ST - (Reset Tektronix background color) OSC 116;Pt ST - (Reset highlight color) OSC 117;Pt ST - (Reset Tektronix cursor color) OSC 118;Pt ST - (Reset highlight foreground color) OSC 119;Pt ST https://www.ecma-international.org/publications/standards/Ecma-048.htm O CTC (Cursor Tabulation Control) CSI Pn W - DAQ (Define Area Qualification) CSI Pn o - EA (Erase in Area) CSI Pn O - EF (Erase in Field) CSI Pn N - EPA (End of Guarded Area) ESC W - FNT (Font Selection) CSI Pn SP D O HPB (Character Position Backward) CSI Pn j O HTJ (Character Tabulation with Justification) ESC I - PLD (Partial Line Forward) ESC K - PLU (Partial Line Backward) ESC L O REP (Repeat) CSI Pn b O RI (Reverse Line Feed) ESC M O SL (Scroll Left) CSI Pn SP @ - SPA (Start of Guarded Area) ESC V O SR (Scroll Right) CSI Pn SP A O VPB (Line Position Backward) CSI Pn k - VTS (Line Tabulation Set) ESC J https://ttssh2.osdn.jp/manual/ja/about/ctrlseq.html O TTIMERS CSI < r O TTIMEST CSI < Pn t O TTIMESV CSI < s https://github.com/mintty/mintty/wiki/CtrlSeqs O (Application Escape Mode) CSI ? 7727 [hl] - CSI ? 7700/7728/7730/7766/7767/7783/7786/7787/7796/ http://nanno.dip.jp/softlib/man/rlogin/ctrlcode.html - C25LCT CSI = Pn S O RLAMBCHM CSI ? 8428 [hl] - RLBFAT CSI Pn p - RLCURCOL CSI < Pn ! q - RLIMGCP CSI < Pn ! i - RLSCD CSI Pn v O (Sixel scrolling leaves cursor to right of graphic) CSI ? 8452 [hl] - CSI ? 8400/8401/8402/8403/8405/8406/8435/8437/8440/8441/8442/8443/8448/8449/8450/8451/8453/8455/8456/8457/8458 [hl] https://www.iterm2.com/documentation-escape-codes.html O OSC 1337;Pt ST O DRCSMMv1 CSI ? 8800 [hl] O TNREPTAMB CSI ? 8840 n O OSC 20;Pt ST O OSC 5379/5380/5381/5383;Pt ST * References http://bjh21.me.uk/all-escapes/all-escapes.txt mlterm-3.8.9/doc/en/FAQ010064400017600000144000000005431356600661000132370ustar kenuserscomment -*- mode: text; tab-width:2; indent-tabs-mode:nil -*- Frequently Asked Questions [Q1] I cannot copy&paste UTF-8 characters into the command-line. [A1] If you use bash, add the following two lines to your ~/.inputrc. set convert-meta off set output-meta on If you use tcsh, all you have to do is set dspmbyte=utf8 (Thanks to Nadim Shaikli) mlterm-3.8.9/doc/en/PLATFORMS.old010064400017600000144000000235311356600661000147560ustar kenuserscomment -*- mode: text -*- comment $Id$ supported platforms (mlterm-2.9.3 pre/cvs-1.922) * tested by Seiichi SATO NetBSD 2.0.2 (x86) configure options: --with-tools= Note: compilation succeeded, but I don't know whether it works or not. Solaris 9 (Sparc) configure options: --with-tools= Note: compilation succeeded, but I don't know whether it works or not. MS Windows XP/Cygwin-1.5.19 with x-org 6.8.2.0-1 (x86) configure options: --with-type-engines=xcore,xft --with-scrollbars=sample,extra --with-imagelib=gdk-pixbuf --with-tools=mlclient,mlconfig,mlterm-menu,mlcc supported platforms (mlterm-2.9.2 pre/cvs-1.865) * tested by Seiichi SATO Solaris 8 (x86), gcc-3.4.2 configure options: --with-type-engines=xcore --with-tools=mlclient,mlcc --with-scrollbars=sample,extra MS Windows NT 4.0/Cygwin-1.5.12 with x-org 6.8.1.0-3 (x86) configure options: --with-type-engines=xcore,xft --with-scrollbars=sample,extra --with-imagelib=gdk-pixbuf --with-tools=mlclient,mlconfig,mlterm-menu,mlcc Note: It seems that Cygwin/X has libXrender.la. You can get it at: OpenBSD 3.5, gcc-2.95.3 (x86) configure options: --with-tools=mlclient,mlcc --with-scrollbars=sample --with-type-engines=xcore --enable-utmp supported platforms (mlterm-2.9.2 pre/cvs-1.838) * tested by Seiichi SATO HP-UX 11.11 (PA-RISC), CC=/usr/bin/cc configure options: --with-type-engines=xcore --with-tools=mlclient,mlcc Note: "mlterm --help" and mlcc seem to work, but I don't know whether mletrm itself works or not. supported platforms (mlterm-2.9.1 pre/cvs-1.787) * tested by MURASE, Masaki san Mac OS X 10.3.6 (PowerPC G4), Apple's cc based on gcc 3.3 20030304, gtk+-1.2.10-27, uim-0.4.5, anthy-5500 configure options: --with-type-engines=xcore --with-imagelib=imlib --with-tools=mlclient,mlconfig,mlterm-menu,mlcc --enable-uim --enable-shared supported platforms (mlterm-2.9.1 pre/cvs-1.784) * tested by Seiichi SATO Fedora Core 2 (x86) configure options: --with-type-engines=xft,xcore --with-tools=mlclient,mlconfig,mlterm-menu,mlcc --with-imagelib=imlib --with-scrollbars=sample,extra,pixmap_engine --enable-iiimf --enable-m17nlib supported platforms (mlterm-2.9.1 pre/cvs-1.783) * tested by Seiichi SATO HP-UX 11.11 (PA-RISC), gcc-3.4.1 configure options: --with-type-engines=xcore --with-tools=mlclient,mlcc Note: "mlterm --help" and mlcc seem to work, but I don't know whether mletrm itself works or not. supported platforms (mlterm-2.9.1 pre/cvs-1.778) * tested by Seiichi SATO MS Windows NT 4.0/Cygwin-1.5.12 with x-org 6.8.1.0-3 (x86) configure options: --with-type-engines=xft,xcore --with-scrollbars=sample,extra --with-tools=mlclient,mlconfig,mlterm-menu,mlcc Solaris 8 (x86), gcc-3.4.2 configure options: --with-type-engines=xcore --with-tools=mlclient,mlcc --with-scrollbars=sample,extra --enable-utmp Notes: - Using XIM with multiple displays is unstable on Xsun. - configure scripts could not find libiiimcf, (Solaris 8 doesn't have it?) - utmp support is unstable yet. OpenBSD 3.5, gcc-2.95.3 (x86) configure options: --with-tools=mlclient,mlconfig,mlterm-menu,mlcc --with-scrollbars=sample,extra,pixmap_engine --with-type-engines=xcore,xft --with-imagelib=gdk-pixbuf --enable-utmp Mac OS X 10.1 Server (PowerPC G4), Apple's cc based on gcc 2.95.2, GTK+-1.2.10 configure options: --with-type-engines=xcore --with-tools=mlclient,mlconfig,mlterm-menu,mlcc --with-scrollbars=sample,extra --with-imagelib=imlib $ chmod 755 script/* {mkf,kiklib}/script/* $ MISSING=`pwd`/script/missing install_sh=`pwd`/script/install-sh \ ./configure .. supported platforms (mlterm-2.9.0 post/cvs-1.758) * tested by Seiichi SATO Red Hat Linux 7.3 (x86), gcc-2.96 20000731, early xft without fontconfig configure options: --with-type-engines=xcore,xft --with-tools=mlclient,mlconfig supported platforms (mlterm-2.8.0 post/cvs-1.744) * tested by Seiichi SATO FreeBSD 4.10-BETA (x86), gcc-2.95.4 20020320 configure options: --with-type-engines=xcore --with-tools=mlclient,mlcc --with-scrollbars=sample,extra supported platforms (mlterm-2.8.0 post/cvs-1.740) * tested by Seiichi SATO HP-UX 11.11 (PA-RISC), gcc-3.4.1 configure options: --with-type-engines=xcore --with-tools=mlclient,mlcc Notes: compilation succeeded, but I don't know whether it works or not. HP-UX 11.11 (PA-RISC), CC="cc -Dinline=" configure options: --with-type-engines=xcore --with-tools=mlclient,mlcc Notes: - "mlterm --help" and mlcc seem to work, but I don't know whether mletrm itself works or not. - CC="cc -Dinline= " is a quick and durty hack! gcc is recomended now. SuSE Linux 8 ES (x86_64), gcc-3.2.2, gtk+-1.2.10 configure options: --with-type-engines=xcore --with-tools=mlclient,mlconfig,mlterm-menu,mlcc --with-scrollbars=sample,extra Solaris 8 (x86), gcc-3.4.2 configure options: --with-type-engines=xcore --with-tools=mlclient,mlcc --with-scrollbars=sample,extra Notes: - Using XIM with multiple displays is unstable on Xsun. - configure scripts could not find libiiimcf, (Solaris 8 doesn't have it?) Solaris 9 (Sparc), gcc-3.3.2 configure options: --with-type-engines=xcore --with-tools=mlclient,mlcc --with-scrollbars=sample,extra Note: compilation succeeded, but I don't know whether it works or not. Solaris 9 (x86) Sun ONE Studio 8 C compiler (CC="cc -Dinline="), gtk+-2.1.0 configure options: --with-type-engines=xcore --with-tools=mlclient,mlconfig,mlterm-menu,mlcc --with-scrollbars=sample,extra Notes: - "mlterm --help" seems to work, but I don't know whether mletrm itself works or not. - CC="cc -Dinline= " is a quick and durty hack! gcc is recomended now. Mac OS X 10.2 Server (PowerPC G4), gcc version 3.3 20030304 configure options: --with-type-engines=xcore --with-tools=mlclient,mlcc --with-scrollbars=sample,extra supported platforms (mlterm-2.8.0 post/cvs-1.738) * tested by Seiichi SATO NetBSD 1.6.2 (x86) configure options: --with-type-engines=xcore --with-tools=mlcc Notes: compilation succeeded, but I don't know whether it works or not. Solaris 9 (Sparc) configure options: --with-type-engines=xcore --with-tools=mlcc Notes: compilation succeeded, but I don't know whether it works or not. supported platforms (mlterm-2.8.0 post/cvs-1.735) * tested by Seiichi SATO Fedora Core 2 (x86) configure options: --with-type-engines=xft,xcore --with-tools=mlclient,mlconfig,mlterm-menu,mlcc --enable-iiimf supported platforms (mlterm-2.8.0 post/cvs-1.732) * tested by Seiichi SATO Debian GNU/Linux Sid, GNU libc 2.3.2, gcc-3.3.5 (x86) configure options: --enable-fribidi --enable-ind --with-tools=mlclient,mlconfig,mlterm-menu,mlcc,mlterm-zoom --with-scrollbars=sample,extra,pixmap_engine --with-imagelib=gdk-pixbuf2 --with-type-engines=xft,xcore --enable-optimize-redrawing --enable-uim --enable-iiimf --enable-m17nlib --enable-utmp OpenBSD 3.5, gcc-2.95.3 (x86) configure options: --with-tools=mlclient,mlconfig,mlterm-menu,mlcc --with-scrollbars=sample,extra --with-type-engines=xcore MS Windows 98/Cygwin-1.5.11 with x-org 6.8.1.0-3 (x86) configure options: --with-type-engines=xft,xcore --with-scrollbars=sample,extra --with-tools=mlclient,mlconfig,mlcc SuSE LINUX 9.1 (x86) configure options: --with-type-engines=xcore,xft --with-tools=mlclient,mlconfig --with-scrollbars=sample,extra,pixmap_engine supported platforms (mlterm-2.2.0pl1) * tested by Okazaki Tetsurou san cygwin-1.3.9-1 with Cygwin/XFree86 4.2.0 cygwin-1.3.9-1 with Cygwin/XFree86 4.1.0 supported platforms (mlterm-2.1.0) * tested by Araki Ken NetBSD 1.5Y current HP-UX 10.20 (CC="cc -Ae") ([notice] kinput2 doesn't work) supported platforms (mlterm-2.0.0) * tested by Araki Ken NetBSD 1.5Y current HP-UX 10.20 (CC="cc -Ae") * tested by Sakamoto Hironori san FreeBSD 3.3R RedHat Linux 7.1 Solaris 2.6 (SunOS 5.6) (CC=cc) HP-UX 10.20 (CC="cc -Ae") EWS4800 (UX/4800 R11.7) + X11R6 (CC=/usr/abiccs/bin/cc) EWS4800 (UX/4800 R13.5, 64bit) (CC=/usr/ccs64/bin/cc) * tested by Daichi Goto san FreeBSd 4.4R * tested by Kiyoshi Nisizawa san(1.9.47) Kondara MNU/Linux 1.2, i586 Kondara MNU/Linux 2.0, i586 * tested by Tomohiro Kubota san(1.9.47) Debian GNU/Linux Sid, GNU libc 2.2.4 mlterm-3.8.9/doc/en/PROTOCOL010064400017600000144000000273671356600661000141060ustar kenuserscomment -*- mode: text; tab-width:2; indent-tabs-mode:nil -*- mlterm configuration protocol version 20191122 * Protocol exec = "\x1b]5379;" "\x07" set = "\x1b]5379" ( ";" ( "/dev/..." ":" ) "=" )* "\x07" get(pty) = "\x1b]5380;" ( ";") ( "/dev/..." ":" ) "\x07" get(GUI menu) = "\x1b]5381;" ( "/dev/..." ":" ) "\x07" set&save = "\x1b]5383;" ( ";" ( "/dev/..." ":" ) "=" )* "\x07" set font = "\x1b]5379;" ":" "=" "\x07" get(pty) = "\x1b]5380;" ( ";") ":" "\x07" get(GUI menu) = "\x1b]5381;" ":" "\x07" set&save = "\x1b]5383;" ";" ":" "=" "\x07" set color = "\x1b]5379;color:" "=" "\x07" get(pty) = "\x1b]5380;" ( ";color:") "\x07" get(GUI menu) = "\x1b]5381;color:" "\x07" set&save = "\x1b]5383;" ";color:" "=" "\x07" return value = "#" "=" "\x0a" | "#error\x0a" | "#forbidden\x0a" exec command = paste (*) | select_pty | next_pty | prev_pty | full_reset | open_pty | close_pty () | open_screen | vsplit_screen (|%) | hsplit_screen (|%) | next_screen | prev_screen | vresize_screen (+|-||%) | hresize_screen (+|-||%) | close_screen | snapshot ("") ("") | gen_proto_challenge | mlclient "" "" | mlclientx "" "" | search_prev | search_next | update_all | mlconfig | set_shortcut = (*) | autoscroll | zmodem_start | scp "(local:|remote:)" "(local:|remote:)" "()" set key = encoding | fg_color | bg_color | tabsize | logsize | fontsize | fade_ratio | mod_meta_key | mod_meta_mode | bel_mode | type_engine | use_anti_alias | use_variable_column_width | use_combining | use_transbg | use_ctl | bidi_mode | bidi_separators | receive_string_via_ucs | input_method | locale | wall_picture | brightness | gamma | contrast | line_space | letter_space | geometry | screen_width_ratio | vertical_mode | scrollbar_mode | static_backscroll_mode | use_multi_column_char | col_size_of_width_a | scrollbar_view_name | sb_fg_color | sb_bg_color | use_dynamic_comb | cursor_fg_color | cursor_bg_color | bd_color | ul_color | bl_color | rv_color | it_color | co_color | use_bold_font | use_italic_font | hide_underline | icon_path | logging_vt_seq | vt_seq_format | logging_msg | word_separators | use_clipboard | auto_restart | use_alt_buffer | use_ansi_colors | exit_backscroll_by_pty | only_use_unicode_font | not_use_unicode_font | unicode_noconv_areas | unicode_full_width_areas | unicode_half_width_areas | box_drawing_font | use_urgent_bell | allow_osc52 (*) | allow_scp (*) | auto_detect_encodings | use_auto_detect | use_extended_scroll_shortcut | use_ot_layout | ot_script | ot_features | regard_uri_as_word | vt_color_mode | console_encoding | console_sixel_colors | borderless | underline_offset | baseline_offset | trim_trailing_newline_in_pasting | use_vertical_cursor | click_interval | emoji_path | use_local_echo | local_echo_wait | send_file get key = encoding | is_auto_encoding | fg_color | bg_color | tabsize | logsize | fontsize | fade_ratio | mod_meta_key | mod_meta_mode | bel_mode | type_engine | use_anti_alias | use_variable_column_width | use_combining | use_transbg | use_ctl | bidi_mode | bidi_separators | receive_string_via_ucs | input_method | locale | wall_picture | pwd | brightness | gamma | contrast | line_space | letter_space | screen_width_ratio | screen_height_ratio | vertical_mode | scrollbar_mode | static_backscroll_mode | use_multi_column_char | col_size_of_width_a | scrollbar_view_name | sb_fg_color | sb_bg_color | use_dynamic_comb | rows | cols | cursor_fg_color | cursor_bg_color | bd_color | ul_color | bl_color | rv_color | it_color | co_color | use_bold_font | use_italic_font | hide_underline | pty_list | pty_name | use_clipboard | use_alt_buffer | use_ansi_colors | icon_path | logging_vt_seq | vt_seq_format | word_separators | gui | allow_osc52 | allow_scp | only_use_unicode_font | not_use_unicode_font | unicode_noconv_areas | unicode_full_width_areas | unicode_half_width_areas | box_drawing_font | auto_detect_encodings | use_auto_detect | use_ot_layout | ot_script | ot_features | regard_uri_as_word | borderless | use_aafont | underline_offset | baseline_offset | trim_trailing_newline_in_pasting | fontconfig | use_vertical_cursor | click_interval | emoji_path | use_local_echo | local_echo_wait | send_file | receive_directory (*): Works in "proto:xxxx" in ~/.mlterm/key. value = challenge = font filename = font | aafont | vfont | tfont | vaafont | taafont font key = see man/mlterm.1 or "USASCII" font value = see man/mlterm.1 fontsize = color key = see man/mlterm.1 color value = see man/mlterm.1 * Values for each key allow_osc52 = true | false | switch allow_scp = true | false | switch auto_restart = true | false | switch | auto_detect_encodings = (,)* baseline_offset = bidi_separators = * bd_color = | bl_color = | bel_mode = none | sound | visual bg_color = | box_drawing_font = unicode | decsp | noconv brightness = click_interval = cols = col_size_of_width_a = 1 | 2 | switch contrast = co_colors = | console_encoding = | auto console_sixel_colors = 16 | 256 | full cursor_bg_color = | cursor_fg_color = | emoji_path = | encoding = | auto fade_ratio = fg_color = | fontsize = | larger | smaller gamma = hide_underline = true | false | switch icon_path = input_method = ":" ... it_color = | line_space = locale = local_echo_wait = logsize = mod_meta_key = none | mod1 | mod2 | mod3 | mod4 | meta | alt | super | hyper mod_meta_mode = none | esc | 8bit not_use_unicode_font = true | false | switch only_use_unicode_font = true | false | switch ot_script =