📄 nmrtf.c
字号:
return status; } else { /* parsing a hex encoded character */ if (ctx->ris != NMRTF_STATE_HEX) return NMRTF_ASSERTION; hex_byte = hex_byte << 4; if (isdigit(ch)) hex_byte += (char) ch - '0'; else { if (islower(ch)) { if (ch < 'a' || ch > 'f') return NMRTF_INVALID_HEX; hex_byte += (char) ch - 'a' + 10; } else { if (ch < 'A' || ch > 'F') return NMRTF_INVALID_HEX; hex_byte += (char) ch - 'A' + 10; } } hex_count--; if (hex_count == 0) { if ((status = rtf_dispatch_char(ctx, hex_byte)) != NMRTF_OK) return status; hex_count = 2; hex_byte = 0; ctx->ris = NMRTF_STATE_NORMAL; } } break; } } } if (ctx->depth < 0) return NMRTF_STACK_OVERFLOW; if (ctx->depth > 0) return NMRTF_UNMATCHED_BRACE; return NMRTF_OK;}/* * Push the current state onto stack */static intrtf_push_state(NMRtfContext *ctx){ NMRtfStateSave *save = g_new0(NMRtfStateSave, 1); save->chp = ctx->chp; save->rds = ctx->rds; save->ris = ctx->ris; ctx->saved = g_slist_prepend(ctx->saved, save); ctx->ris = NMRTF_STATE_NORMAL; (ctx->depth)++; return NMRTF_OK;}/* * Restore the state at the top of the stack */static intrtf_pop_state(NMRtfContext *ctx){ NMRtfStateSave *save_old; GSList *link_old; if (ctx->saved == NULL) return NMRTF_STACK_UNDERFLOW; save_old = ctx->saved->data; ctx->chp = save_old->chp; ctx->rds = save_old->rds; ctx->ris = save_old->ris; (ctx->depth)--; g_free(save_old); link_old = ctx->saved; ctx->saved = g_slist_remove_link(ctx->saved, link_old); g_slist_free_1(link_old); return NMRTF_OK;}/* * Step 2: * Get a control word (and its associated value) and * dispatch the control. */static intrtf_parse_keyword(NMRtfContext *ctx){ int status = NMRTF_OK; guchar ch; gboolean param_set = FALSE; gboolean is_neg = FALSE; int param = 0; char keyword[30]; char parameter[20]; int i; keyword[0] = '\0'; parameter[0] = '\0'; if ((status = rtf_get_char(ctx, &ch)) != NMRTF_OK) return status; if (!isalpha(ch)) { /* a control symbol; no delimiter. */ keyword[0] = (char) ch; keyword[1] = '\0'; return rtf_dispatch_control(ctx, keyword, 0, param_set); } /* parse keyword */ for (i = 0; isalpha(ch) && (i < sizeof(keyword) - 1); rtf_get_char(ctx, &ch)) { keyword[i] = (char) ch; i++; } keyword[i] = '\0'; /* check for '-' indicated a negative parameter value */ if (ch == '-') { is_neg = TRUE; if ((status = rtf_get_char(ctx, &ch)) != NMRTF_OK) return status; } /* check for numerical param */ if (isdigit(ch)) { param_set = TRUE; for (i = 0; isdigit(ch) && (i < sizeof(parameter) - 1); rtf_get_char(ctx, &ch)) { parameter[i] = (char) ch; i++; } parameter[i] = '\0'; ctx->param = param = atoi(parameter); if (is_neg) ctx->param = param = -param; } /* space after control is optional, put character back if it is not a space */ if (ch != ' ') rtf_unget_char(ctx, ch); return rtf_dispatch_control(ctx, keyword, param, param_set);}/* * Route the character to the appropriate destination */static intrtf_dispatch_char(NMRtfContext *ctx, guchar ch){ if (ctx->ris == NMRTF_STATE_BIN && --(ctx->bytes_to_skip) <= 0) ctx->ris = NMRTF_STATE_NORMAL; switch (ctx->rds) { case NMRTF_STATE_SKIP: return NMRTF_OK; case NMRTF_STATE_NORMAL: return rtf_print_char(ctx, ch); case NMRTF_STATE_FONTTABLE: if (ch == ';') { rtf_add_font_entry(ctx, ctx->chp.font_idx, ctx->ansi->str, ctx->chp.font_charset); g_string_truncate(ctx->ansi, 0); } else { return rtf_print_char(ctx, ch); } return NMRTF_OK; default: return NMRTF_OK; }}/* Handle a unicode character */static intrtf_dispatch_unicode_char(NMRtfContext *ctx, gunichar ch){ switch (ctx->rds) { case NMRTF_STATE_SKIP: return NMRTF_OK; case NMRTF_STATE_NORMAL: case NMRTF_STATE_FONTTABLE: return rtf_print_unicode_char(ctx, ch); default: return NMRTF_OK; }}/* * Output a character */static intrtf_print_char(NMRtfContext *ctx, guchar ch){ ctx->ansi = g_string_append_c(ctx->ansi, ch); return NMRTF_OK;}/* * Output a unicode character */static intrtf_print_unicode_char(NMRtfContext *ctx, gunichar ch){ char buf[7]; int num; /* convert and flush the ansi buffer to the utf8 buffer */ rtf_flush_data(ctx); /* convert the unicode character to utf8 and add directly to the output buffer */ num = g_unichar_to_utf8((gunichar) ch, buf); buf[num] = 0; purple_debug_info("novell", "converted unichar 0x%X to utf8 char %s\n", ch, buf); ctx->output = g_string_append(ctx->output, buf); return NMRTF_OK;}/* * Flush the output text */static intrtf_flush_data(NMRtfContext *ctx){ int status = NMRTF_OK; char *conv_data = NULL; const char *enc = NULL; GError *gerror = NULL; if (ctx->rds == NMRTF_STATE_NORMAL && ctx->ansi->len > 0) { enc = get_current_encoding(ctx); conv_data = g_convert(ctx->ansi->str, ctx->ansi->len, "UTF-8", enc, NULL, NULL, &gerror); if (conv_data) { ctx->output = g_string_append(ctx->output, conv_data); g_free(conv_data); ctx->ansi = g_string_truncate(ctx->ansi, 0); } else { status = NMRTF_CONVERT_ERROR; purple_debug_info("novell", "failed to convert data! error code = %d msg = %s\n", gerror->code, gerror->message); g_free(gerror); } } return status;}/* * Handle a property change */static intrtf_apply_property(NMRtfContext *ctx, NMRtfProperty prop, int val){ if (ctx->rds == NMRTF_STATE_SKIP) /* If we're skipping text, */ return NMRTF_OK; /* don't do anything. */ /* Need to flush any temporary data before a property change*/ rtf_flush_data(ctx); switch (prop) { case NMRTF_PROP_FONT_IDX: ctx->chp.font_idx = val; break; case NMRTF_PROP_FONT_CHARSET: ctx->chp.font_charset = val; break; default: return NMRTF_BAD_TABLE; } return NMRTF_OK;}/* * Step 3. * Search the table for keyword and evaluate it appropriately. * * Inputs: * keyword: The RTF control to evaluate. * param: The parameter of the RTF control. * param_set: TRUE if the control had a parameter; (that is, if param is valid) * FALSE if it did not. */static intrtf_dispatch_control(NMRtfContext *ctx, char *keyword, int param, gboolean param_set){ int idx; for (idx = 0; idx < table_size; idx++) { if (strcmp(keyword, rtf_symbols[idx].keyword) == 0) break; } if (idx == table_size) { if (ctx->skip_unknown) ctx->rds = NMRTF_STATE_SKIP; ctx->skip_unknown = FALSE; return NMRTF_OK; } /* found it! use kwd_type and action to determine what to do with it. */ ctx->skip_unknown = FALSE; switch (rtf_symbols[idx].kwd_type) { case NMRTF_KWD_PROP: if (rtf_symbols[idx].pass_default || !param_set) param = rtf_symbols[idx].default_val; return rtf_apply_property(ctx, rtf_symbols[idx].action, param); case NMRTF_KWD_CHAR: return rtf_dispatch_char(ctx, rtf_symbols[idx].action); case NMRTF_KWD_DEST: return rtf_change_destination(ctx, rtf_symbols[idx].action); case NMRTF_KWD_SPEC: return rtf_dispatch_special(ctx, rtf_symbols[idx].action); default: return NMRTF_BAD_TABLE; } return NMRTF_BAD_TABLE;}/* * Change to the destination specified. */static intrtf_change_destination(NMRtfContext *ctx, NMRtfDestinationType type){ /* if we're skipping text, don't do anything */ if (ctx->rds == NMRTF_STATE_SKIP) return NMRTF_OK; switch (type) { case NMRTF_DEST_FONTTABLE: ctx->rds = NMRTF_STATE_FONTTABLE; g_string_truncate(ctx->ansi, 0); break; default: ctx->rds = NMRTF_STATE_SKIP; /* when in doubt, skip it... */ break; } return NMRTF_OK;}/* * Dispatch an RTF control that needs special processing */static intrtf_dispatch_special(NMRtfContext *ctx, NMRtfSpecialKwd type){ int status = NMRTF_OK; guchar ch; if (ctx->rds == NMRTF_STATE_SKIP && type != NMRTF_SPECIAL_BIN) /* if we're skipping, and it's not */ return NMRTF_OK; /* the \bin keyword, ignore it. */ switch (type) { case NMRTF_SPECIAL_BIN: ctx->ris = NMRTF_STATE_BIN; ctx->bytes_to_skip = ctx->param; break; case NMRTF_SPECIAL_SKIP: ctx->skip_unknown = TRUE; break; case NMRTF_SPECIAL_HEX: ctx->ris = NMRTF_STATE_HEX; break; case NMRTF_SPECIAL_UNICODE: purple_debug_info("novell", "parsing unichar\n"); status = rtf_dispatch_unicode_char(ctx, ctx->param); /* Skip next char */ if (status == NMRTF_OK) status = rtf_get_char(ctx, &ch); break; default: status = NMRTF_BAD_TABLE; break; } return status;}/* * Get the next character from the input stream */static intrtf_get_char(NMRtfContext *ctx, guchar *ch){ if (ctx->nextch >= 0) { *ch = ctx->nextch; ctx->nextch = -1; } else { *ch = *(ctx->input); ctx->input++; } if (*ch) return NMRTF_OK; else return NMRTF_EOF;}/* * Move a character back into the input stream */static intrtf_unget_char(NMRtfContext *ctx, guchar ch){ ctx->nextch = ch; return NMRTF_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -