int main (int argc, char **argv) { FILE *fp; int quiet = 0; int show_offset = 0; int opt; int i; char *filename; const char *encoding; while ((opt = getopt(argc, argv, "oqh")) != -1) { switch (opt) { case 'o': show_offset = 1; break; case 'q': quiet = 1; break; case 'h': show_usage(); return 0; default: fprintf(stderr, "Unknown option -%c", opt); show_usage(); return 1; } } if (optind == argc) { fprintf(stderr, "No files specified.\n"); show_usage(); return 1; } for (i = optind; i < argc; i++) { filename = argv[i]; fp = fopen(filename, "rb"); if (fp == NULL) { fprintf(stderr, "Can't open file '%s' for reading.\n", filename); } else { if (!quiet) printf("%s: ", filename); encoding = detect_encoding(fp); printf("%s", encoding); if (show_offset && strcmp("UNKNOWN", encoding) == 0) printf(" near offset %ld (0x%lX)", (long)ftell(fp), (long)ftell(fp)); printf("\n"); fclose(fp); } } return 0; }
encoding_type detect_buffer_encoding(const buffer * const b) { line_desc *ld = (line_desc *)b->line_desc_list.head, *next; encoding_type encoding = ENC_ASCII, e; while(next = (line_desc *)ld->ld_node.next) { e = detect_encoding(ld->line, ld->line_len); if (e != ENC_ASCII) { if (encoding == ENC_ASCII) encoding = e; if (e == ENC_8_BIT) encoding = ENC_8_BIT; } ld = next; } return encoding; }
static HRESULT read_xml(const WCHAR *name, WCHAR **xml) { HANDLE hfile; DWORD size, attrs; char *src; int cp; attrs = GetFileAttributesW(name); if (attrs == INVALID_FILE_ATTRIBUTES) return HRESULT_FROM_WIN32(GetLastError()); if (attrs & FILE_ATTRIBUTE_DIRECTORY) return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); hfile = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); if (hfile == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError()); size = GetFileSize(hfile, NULL); src = heap_alloc(size + 2); if (!src) { CloseHandle(hfile); return E_OUTOFMEMORY; } src[size] = 0; src[size + 1] = 0; ReadFile(hfile, src, size, &size, NULL); CloseHandle(hfile); cp = detect_encoding(src, size); if (cp < 0) { *xml = (WCHAR *)src; return S_OK; } if (cp == CP_UTF8 && size >= sizeof(bom_utf8) && !memcmp(src, bom_utf8, sizeof(bom_utf8))) src += sizeof(bom_utf8); size = MultiByteToWideChar(cp, 0, src, -1, NULL, 0); *xml = heap_alloc(size * sizeof(WCHAR)); if (!*xml) return E_OUTOFMEMORY; MultiByteToWideChar(cp, 0, src, -1, *xml, size); return S_OK; }
static HRESULT read_xml(const WCHAR *name, WCHAR **xml) { HANDLE hfile; DWORD size; char *src; int cp; hfile = CreateFileW(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); if (hfile == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError()); size = GetFileSize(hfile, NULL); src = heap_alloc(size + 2); if (!src) { CloseHandle(hfile); return E_OUTOFMEMORY; } src[size] = 0; src[size + 1] = 0; ReadFile(hfile, src, size, &size, NULL); CloseHandle(hfile); cp = detect_encoding(src, size); if (cp < 0) { *xml = (WCHAR *)src; return S_OK; } size = MultiByteToWideChar(cp, 0, src, -1, NULL, 0); *xml = heap_alloc(size * sizeof(WCHAR)); if (!*xml) return E_OUTOFMEMORY; MultiByteToWideChar(cp, 0, src, -1, *xml, size); return S_OK; }
void set_stream_encoding(char_stream * const cs, const encoding_type source) { cs->encoding = detect_encoding(cs->stream, cs->len); if (source == ENC_8_BIT && cs->encoding == ENC_UTF8) cs->encoding = ENC_8_BIT; }
char *request(const char *prompt, const char * const default_string, const bool alpha_allowed, const int completion_type, const bool prefer_utf8) { set_attr(0); input_buffer[pos = len = offset = 0] = 0; encoding = ENC_ASCII; x = start_x = print_prompt(prompt); init_history(); if (default_string) { strncpy(input_buffer, default_string, MAX_INPUT_LINE_LEN); len = strlen(input_buffer); encoding = detect_encoding(input_buffer, len); input_refresh(); } bool first_char_typed = true, last_char_completion = false, selection = false; while(true) { assert(input_buffer[len] == 0); move_cursor(ne_lines - 1, x); int c; input_class ic; do c = get_key_code(); while((ic = CHAR_CLASS(c)) == IGNORE); /* ISO 10646 characters *above 256* can be added only to UTF-8 lines, or ASCII lines (making them, of course, UTF-8). */ if (ic == ALPHA && c > 0xFF && encoding != ENC_ASCII && encoding != ENC_UTF8) ic = INVALID; if (ic != TAB) last_char_completion = false; if (ic == TAB && !completion_type) ic = ALPHA; switch(ic) { case INVALID: alert(); break; case ALPHA: if (first_char_typed) { input_buffer[len = 0] = 0; clear_to_eol(); } if (encoding == ENC_ASCII && c > 0x7F) encoding = prefer_utf8 || c > 0xFF ? ENC_UTF8 : ENC_8_BIT; int c_len = encoding == ENC_UTF8 ? utf8seqlen(c) : 1; int c_width = output_width(c); assert(c_len > 0); if (len <= MAX_INPUT_LINE_LEN - c_len && (alpha_allowed || (c < 0x100 && isxdigit(c)) || c=='X' || c=='x')) { memmove(&input_buffer[pos + c_len], &input_buffer[pos], len - pos + 1); if (c_len == 1) input_buffer[pos] = c; else utf8str(c, &input_buffer[pos]); len += c_len; move_cursor(ne_lines - 1, x); if (x < ne_columns - c_width) { if (pos == len - c_len) output_char(c, 0, encoding); else if (char_ins_del_ok) insert_char(c, 0, encoding); else input_refresh(); } input_move_right(true); } break; case RETURN: selection = true; break; case TAB: if (completion_type == COMPLETE_FILE || completion_type == COMPLETE_SYNTAX) { bool quoted = false; char *prefix, *completion, *p; if (len && input_buffer[len - 1] == '"') { input_buffer[len - 1] = 0; if (prefix = strrchr(input_buffer, '"')) { quoted = true; prefix++; } else input_buffer[len - 1] = '"'; } if (!quoted) { prefix = strrchr(input_buffer, ' '); if (prefix) prefix++; else prefix = input_buffer; } if (last_char_completion || completion_type == COMPLETE_SYNTAX) { if (completion_type == COMPLETE_FILE ) completion = p = request_files(prefix, true); else completion = p = request_syntax(prefix, true); reset_window(); if (completion) { if (*completion) selection = true; else completion++; } } else { if (completion_type == COMPLETE_FILE ) completion = p = complete_filename(prefix); else completion = p = request_syntax(prefix, true); last_char_completion = true; if (!completion) alert(); } if (completion && (prefix - input_buffer) + strlen(completion) + 1 < MAX_INPUT_LINE_LEN) { const encoding_type completion_encoding = detect_encoding(completion, strlen(completion)); if (encoding == ENC_ASCII || completion_encoding == ENC_ASCII || encoding == completion_encoding) { strcpy(prefix, completion); if (quoted) strcat(prefix, "\""); len = strlen(input_buffer); pos = offset = 0; x = start_x; if (encoding == ENC_ASCII) encoding = completion_encoding; input_move_to_eol(); if (quoted) input_move_left(false); input_refresh(); } else alert(); } else if (quoted) strcat(prefix, "\""); free(p); } break; case COMMAND: if (c < 0) c = -c - 1; const int a = parse_command_line(key_binding[c], NULL, NULL, false); if (a >= 0) { switch(a) { case LINEUP_A: case LINEDOWN_A: case MOVESOF_A: case MOVEEOF_A: case PAGEUP_A: case PAGEDOWN_A: case NEXTPAGE_A: case PREVPAGE_A: if (history_buff) { switch(a) { case LINEUP_A: line_up(history_buff); break; case LINEDOWN_A: line_down(history_buff); break; case MOVESOF_A: move_to_sof(history_buff); break; case MOVEEOF_A: move_to_bof(history_buff); break; case PAGEUP_A: case PREVPAGE_A: prev_page(history_buff); break; case PAGEDOWN_A: case NEXTPAGE_A: next_page(history_buff); break; } /* In some cases, the default displayed on the command line will be the same as the first history item. In that case we skip it. */ if (first_char_typed == true && a == LINEUP_A && history_buff->cur_line_desc->line && !strncmp(history_buff->cur_line_desc->line, input_buffer, history_buff->cur_line_desc->line_len)) line_up(history_buff); if (history_buff->cur_line_desc->line) { strncpy(input_buffer, history_buff->cur_line_desc->line, min(history_buff->cur_line_desc->line_len,MAX_INPUT_LINE_LEN)); input_buffer[min(history_buff->cur_line_desc->line_len,MAX_INPUT_LINE_LEN)] = 0; len = strlen(input_buffer); encoding = detect_encoding(input_buffer, len); } else { input_buffer[len = 0] = 0; encoding = ENC_ASCII; } x = start_x; pos = 0; offset = 0; input_refresh(); } break; case MOVELEFT_A: input_move_left(true); break; case MOVERIGHT_A: input_move_right(true); break; case BACKSPACE_A: if (pos == 0) break; input_move_left(true); case DELETECHAR_A: if (len > 0 && pos < len) { int c_len = encoding == ENC_UTF8 ? utf8len(input_buffer[pos]) : 1; int c_width = get_char_width(&input_buffer[pos], encoding); memmove(&input_buffer[pos], &input_buffer[pos + c_len], len - pos - c_len + 1); len -= c_len; if (input_buffer_is_ascii()) encoding = ENC_ASCII; if (char_ins_del_ok) { int i, j; move_cursor(ne_lines - 1, x); delete_chars(c_width); for(i = x, j = pos; j < len && i + get_char_width(&input_buffer[j], encoding) < ne_columns - c_width; i += get_char_width(&input_buffer[j], encoding), j = next_pos(input_buffer, j, encoding)); if (j < len) { move_cursor(ne_lines - 1, i); while(j < len && i + get_char_width(&input_buffer[j], encoding) < ne_columns) { output_char(get_char(&input_buffer[j], encoding), 0, encoding); i += get_char_width(&input_buffer[j], encoding); j = next_pos(input_buffer, j, encoding); } } } else input_refresh(); } break; case DELETELINE_A: move_cursor(ne_lines - 1, start_x); clear_to_eol(); input_buffer[len = pos = offset = 0] = 0; encoding = ENC_ASCII; x = start_x; break; case DELETEEOL_A: input_buffer[len = pos] = 0; clear_to_eol(); if (input_buffer_is_ascii()) encoding = ENC_ASCII; break; case MOVEINCUP_A: if (x != start_x) { pos = offset; x = start_x; break; } case MOVESOL_A: input_move_to_sol(); break; case MOVEINCDOWN_A: { int i, j; for(i = x, j = pos; j < len && i + get_char_width(&input_buffer[j], encoding) < ne_columns; i += get_char_width(&input_buffer[j], encoding), j = next_pos(input_buffer, j, encoding)); if (j != pos && j < len) { pos = j; x = i; break; } } case MOVEEOL_A: input_move_to_eol(); break; case TOGGLESEOL_A: case TOGGLESEOF_A: if (pos != 0) input_move_to_sol(); else input_move_to_eol(); break; case PREVWORD_A: input_prev_word(); break; case NEXTWORD_A: input_next_word(); break; case REFRESH_A: input_refresh(); break; case PASTE_A: input_paste(); break; case AUTOCOMPLETE_A: input_autocomplete(); break; case ESCAPE_A: return NULL; default: break; } } break; default: break; } if (selection) { const line_desc * const last = (line_desc *)history_buff->line_desc_list.tail_pred->prev; assert(input_buffer[len] == 0); if (history_buff->num_lines == 0 || len != last->line_len || strncmp(input_buffer, last->line, last->line_len)) add_to_history(input_buffer); return input_buffer; } first_char_typed = false; } }
static void input_autocomplete(void) { int dx = 0, prefix_pos = pos; char *p; /* find a usable prefix */ if (prefix_pos && prefix_pos <= len) { prefix_pos = prev_pos(input_buffer, prefix_pos, encoding); dx--; while (prefix_pos && ne_isword(get_char(&input_buffer[prefix_pos], encoding), encoding)) { dx--; prefix_pos = prev_pos(input_buffer, prefix_pos, encoding); } if (! ne_isword(get_char(&input_buffer[prefix_pos], encoding), encoding)) { dx++; prefix_pos = next_pos(input_buffer, prefix_pos, encoding); } p = malloc(pos - prefix_pos + 1); if (!p) { alert(); /* OUT_OF_MEMORY */ return; } strncpy(p, &input_buffer[prefix_pos], pos - prefix_pos); } else p = malloc(1); /* no prefix left of the cursor; we'll give an empty one. */ p[pos - prefix_pos] = 0; int ac_err; if (p = autocomplete(p, NULL, true, &ac_err)) { encoding_type ac_encoding = detect_encoding(p, strlen(p)); if (ac_encoding != ENC_ASCII && encoding != ENC_ASCII && ac_encoding != encoding) { free(p); alert(); } else { encoding = ac_encoding; if (prefix_pos < pos) { memmove(&input_buffer[prefix_pos], &input_buffer[pos], len - pos + 1); len -= pos - prefix_pos; pos = prefix_pos; } int ac_len = strlen(p); if (ac_len + len >= MAX_INPUT_LINE_LEN) ac_len = MAX_INPUT_LINE_LEN - len; memmove(&input_buffer[pos + ac_len], &input_buffer[pos], len - pos + 1); memmove(&input_buffer[pos], p, ac_len); len += ac_len; while (ac_len > 0) { const int cw = get_char_width(&input_buffer[pos],encoding); pos = next_pos(input_buffer, pos, encoding); ac_len -= cw; dx++; } free(p); x += dx; if (x >= ne_columns) { dx = x - ne_columns + 1; while (dx--) { offset = next_pos(input_buffer, offset, encoding); } x = ne_columns - 1; } } } if (ac_err == AUTOCOMPLETE_COMPLETED || ac_err == AUTOCOMPLETE_CANCELLED) { do_action(cur_buffer, REFRESH_A, 0, NULL); refresh_window(cur_buffer); set_attr(0); print_prompt(NULL); } input_refresh(); }