mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-02 12:02:47 -05:00
First draft of Unicode support in pterm. It's pretty complete: it
does UTF-8 copy and paste (falling back to normal strings if necessary), it understands X font encodings and translates things accordingly so that if you have a Unicode font you can ask for virtually any single-byte encoding and get it (Mac-Roman pterm, anyone?), and so on. There's work left to be done (wide fonts for CJK spring to mind), but I reckon this is a pretty good start. [originally from svn r2395]
This commit is contained in:
91
charset/fromucs.c
Normal file
91
charset/fromucs.c
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* fromucs.c - convert Unicode to other character sets.
|
||||
*/
|
||||
|
||||
#include "charset.h"
|
||||
#include "internal.h"
|
||||
|
||||
struct charset_emit_param {
|
||||
char *output;
|
||||
int outlen;
|
||||
const char *errstr;
|
||||
int errlen;
|
||||
int stopped;
|
||||
};
|
||||
|
||||
static void charset_emit(void *ctx, long int output)
|
||||
{
|
||||
struct charset_emit_param *param = (struct charset_emit_param *)ctx;
|
||||
char outval;
|
||||
char const *p;
|
||||
int outlen;
|
||||
|
||||
if (output == ERROR) {
|
||||
p = param->errstr;
|
||||
outlen = param->errlen;
|
||||
} else {
|
||||
outval = output;
|
||||
p = &outval;
|
||||
outlen = 1;
|
||||
}
|
||||
|
||||
if (param->outlen >= outlen) {
|
||||
while (outlen > 0) {
|
||||
*param->output++ = *p++;
|
||||
param->outlen--;
|
||||
outlen--;
|
||||
}
|
||||
} else {
|
||||
param->stopped = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int charset_from_unicode(wchar_t **input, int *inlen, char *output, int outlen,
|
||||
int charset, charset_state *state,
|
||||
const char *errstr, int errlen)
|
||||
{
|
||||
charset_spec const *spec = charset_find_spec(charset);
|
||||
charset_state localstate;
|
||||
struct charset_emit_param param;
|
||||
|
||||
param.output = output;
|
||||
param.outlen = outlen;
|
||||
param.stopped = 0;
|
||||
|
||||
/*
|
||||
* charset_emit will expect a valid errstr.
|
||||
*/
|
||||
if (!errstr) {
|
||||
/* *shrug* this is good enough, and consistent across all SBCS... */
|
||||
param.errstr = ".";
|
||||
param.errlen = 1;
|
||||
}
|
||||
param.errstr = errstr;
|
||||
param.errlen = errlen;
|
||||
|
||||
if (!state) {
|
||||
localstate.s0 = 0;
|
||||
} else {
|
||||
localstate = *state; /* structure copy */
|
||||
}
|
||||
state = &localstate;
|
||||
|
||||
while (*inlen > 0) {
|
||||
int lenbefore = param.output - output;
|
||||
spec->write(spec, **input, &localstate, charset_emit, ¶m);
|
||||
if (param.stopped) {
|
||||
/*
|
||||
* The emit function has _tried_ to output some
|
||||
* characters, but ran up against the end of the
|
||||
* buffer. Leave immediately, and return what happened
|
||||
* _before_ attempting to process this character.
|
||||
*/
|
||||
return lenbefore;
|
||||
}
|
||||
if (state)
|
||||
*state = localstate; /* structure copy */
|
||||
(*input)++;
|
||||
(*inlen)--;
|
||||
}
|
||||
return param.output - output;
|
||||
}
|
Reference in New Issue
Block a user