2
* Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2004, 2005, 2007 by Paul
4
* Permission to use, copy, modify, and distribute this software and its
5
* documentation for any purpose and without fee is hereby granted,
6
* provided that the above copyright notice appear in all copies and that
7
* both that copyright notice and this permission notice appear in
8
* supporting documentation.
10
* x3270, c3270, s3270 and tcl3270 are distributed in the hope that they will
11
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file LICENSE
2
* Copyright (c) 1994-2009, Paul Mattes.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are met:
7
* * Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* * Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
12
* * Neither the names of Paul Mattes nor the names of his contributors
13
* may be used to endorse or promote products derived from this software
14
* without specific prior written permission.
16
* THIS SOFTWARE IS PROVIDED BY PAUL MATTES "AS IS" AND ANY EXPRESS OR IMPLIED
17
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19
* EVENT SHALL PAUL MATTES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
111
if (color >= COLOR_NEUTRAL_BLACK && color <= COLOR_WHITE)
134
if (color >= HOST_COLOR_NEUTRAL_BLACK && color <= HOST_COLOR_WHITE)
112
135
return html_color_map[color];
140
/* Convert a caption string to UTF-8 RTF. */
142
rtf_caption(const char *caption)
147
char *result = Malloc(1);
156
u = multibyte_to_unicode(caption, strlen(caption), &consumed,
161
sprintf(uubuf, "\\u%u?", u);
163
nmb = unicode_to_multibyte(u, mb, sizeof(mb));
167
sprintf(uubuf, "\\%c", mb[0]);
168
else if (mb[0] == '-')
169
sprintf(uubuf, "\\_");
170
else if (mb[0] == ' ')
171
sprintf(uubuf, "\\~");
177
result = Realloc(result, rlen + strlen(uubuf));
178
strcat(result, uubuf);
179
rlen += strlen(uubuf);
186
/* Convert a caption string to UTF-8 HTML. */
188
html_caption(const char *caption)
193
char *result = Malloc(1);
201
u = multibyte_to_unicode(caption, strlen(caption), &consumed,
207
result = Realloc(result, rlen + 4);
208
strcat(result, "<");
212
result = Realloc(result, rlen + 4);
213
strcat(result, ">");
217
result = Realloc(result, rlen + 5);
218
strcat(result, "&");
222
nu8 = unicode_to_utf8(u, u8buf);
223
result = Realloc(result, rlen + nu8);
224
memcpy(result + rlen - 1, u8buf, nu8);
226
result[rlen - 1] = '\0';
119
235
* Print the ASCIIfied contents of the screen onto a stream.
120
236
* Returns True if anything printed, False otherwise.
122
* If 'use_html' is True, then HTML is generated, which preserves colors, but
123
* little else (for now).
238
* 'ptype' can specify:
239
* P_TEXT: Ordinary text
241
* P_RTF: Windows rich text
243
* 'opts' is an OR of:
244
* FPS_EVEN_IF_EMPTY Create a file even if the screen is clear
245
* FPS_MODIFIED_ITALIC Print modified fields in italic
246
* font-style:normal|italic
126
fprint_screen(FILE *f, Boolean even_if_empty, Boolean use_html)
249
fprint_screen(FILE *f, ptype_t ptype, unsigned opts, char *caption)
132
255
Boolean any = False;
133
256
int fa_addr = find_field_attribute(0);
134
257
unsigned char fa = ea_buf[fa_addr].fa;
135
int fa_color, current_color;
258
int fa_fg, current_fg;
259
int fa_bg, current_bg;
136
260
Bool fa_high, current_high;
139
even_if_empty = True;
261
Bool fa_ital, current_ital;
262
Bool mi = ((opts & FPS_MODIFIED_ITALIC)) != 0;
263
char *xcaption = NULL;
265
if (caption != NULL) {
266
char *ts = strstr(caption, "%T%");
269
time_t t = time(NULL);
270
struct tm *tm = localtime(&t);
272
xcaption = Malloc(strlen(caption) + 1 - 3 + 19);
273
strncpy(xcaption, caption, ts - caption);
274
sprintf(xcaption + (ts - caption),
275
"%04d-%02d-%02d %02d:%02d:%02d",
282
strcat(xcaption, ts + 3);
284
xcaption = NewString(caption);
288
if (ptype != P_TEXT) {
289
opts |= FPS_EVEN_IF_EMPTY;
142
292
if (ea_buf[fa_addr].fg)
143
fa_color = ea_buf[fa_addr].fg & 0x0f;
145
fa_color = color_from_fa(fa);
146
current_color = fa_color;
293
fa_fg = ea_buf[fa_addr].fg & 0x0f;
295
fa_fg = color_from_fa(fa);
298
if (ea_buf[fa_addr].bg)
299
fa_bg = ea_buf[fa_addr].bg & 0x0f;
301
fa_bg = HOST_COLOR_BLACK;
148
304
if (ea_buf[fa_addr].gr & GR_INTENSIFY)
151
307
fa_high = FA_IS_HIGH(fa);
152
308
current_high = fa_high;
309
fa_ital = mi && FA_IS_MODIFIED(fa);
310
current_ital = fa_ital;
312
if (ptype == P_RTF) {
313
char *pt_font = get_resource(ResPrintTextFont);
314
char *pt_size = get_resource(ResPrintTextSize);
318
pt_font = "Courier New";
321
pt_nsize = atoi(pt_size);
325
fprintf(f, "{\\rtf1\\ansi\\ansicpg%u\\deff0\\deflang1033{\\fonttbl{\\f0\\fmodern\\fprq1\\fcharset0 %s;}}\n"
326
"\\viewkind4\\uc1\\pard\\f0\\fs%d ",
327
#if defined(_WIN32) /*[*/
330
1252, /* the number doesn't matter */
332
pt_font, pt_nsize * 2);
333
if (xcaption != NULL) {
334
char *hcaption = rtf_caption(xcaption);
336
fprintf(f, "%s\\par\\par\n", hcaption);
343
if (ptype == P_HTML) {
344
char *hcaption = NULL;
346
/* Make the caption HTML-safe. */
347
if (xcaption != NULL)
348
hcaption = html_caption(xcaption);
350
/* Print the preamble. */
351
fprintf(f, "<html>\n"
353
" <meta http-equiv=\"Content-Type\" "
354
"content=\"text/html; charset=UTF-8\">\n"
358
fprintf(f, "<p>%s</p>\n", hcaption);
359
fprintf(f, " <table border=0>"
360
"<tr bgcolor=black><td>"
361
"<pre><span style=\"color:%s;"
365
html_color(current_fg),
366
html_color(current_bg),
367
current_high? "bold": "normal",
368
current_ital? "italic": "normal");
369
if (hcaption != NULL)
373
if (ptype == P_TEXT) {
374
if (xcaption != NULL)
375
fprintf(f, "%s\n\n", xcaption);
154
378
for (i = 0; i < ROWS*COLS; i++) {
155
#if defined(X3270_DBCS) /*[*/
157
Boolean is_dbcs = False;
160
384
if (i && !(i % COLS)) {
386
(void) fputc('\n', f);
164
391
if (ea_buf[i].fa) {
166
393
fa = ea_buf[i].fa;
167
394
if (ea_buf[i].fg)
168
fa_color = ea_buf[i].fg & 0x0f;
170
fa_color = color_from_fa(fa);
395
fa_fg = ea_buf[i].fg & 0x0f;
397
fa_fg = color_from_fa(fa);
399
fa_bg = ea_buf[i].bg & 0x0f;
401
fa_bg = HOST_COLOR_BLACK;
171
402
if (ea_buf[i].gr & GR_INTENSIFY)
174
405
fa_high = FA_IS_HIGH(fa);
406
fa_ital = mi && FA_IS_MODIFIED(fa);
178
#if defined(X3270_DBCS) /*[*/
180
/* XXX: DBCS/html interactions are not done */
408
if (FA_IS_ZERO(fa)) {
409
#if defined(X3270_DBCS) /*[*/
410
if (ctlr_dbcs_state(i) == DBCS_LEFT)
416
/* Convert EBCDIC to Unicode. */
417
#if defined(X3270_DBCS) /*[*/
181
418
switch (ctlr_dbcs_state(i)) {
184
c = ebc2asc[ea_buf[i].cc];
421
uc = ebcdic_to_unicode(ea_buf[i].cc,
422
ea_buf[i].cs, EUO_NONE);
187
dbcs_to_mb(ea_buf[i].cc, ea_buf[i + 1].cc, mb);
427
uc = ebcdic_to_unicode(
428
(ea_buf[i].cc << 8) |
435
/* skip altogether, we took care of it above */
198
c = ebc2asc[ea_buf[i].cc];
442
uc = ebcdic_to_unicode(ea_buf[i].cc, ea_buf[i].cs,
449
/* Translate to a type-specific format and write it out. */
450
if (uc == ' ' && ptype != P_HTML)
452
#if defined(X3270_DBCS) /*[*/
453
else if (uc == 0x3000) {
204
464
(void) fputc('\n', f);
208
(void) fputc(' ', f);
471
(void) fputc(' ', f);
474
if (ptype == P_RTF) {
477
if (ea_buf[i].gr & GR_INTENSIFY)
481
if (high != current_high) {
489
if (ptype == P_HTML) {
490
int fg_color, bg_color;
215
493
if (ea_buf[i].fg)
216
color = ea_buf[i].fg & 0x0f;
219
if (color != current_color) {
221
fprintf(f, "</font><font color=%s>",
223
current_color = color;
494
fg_color = ea_buf[i].fg & 0x0f;
498
bg_color = ea_buf[i].bg & 0x0f;
501
if (ea_buf[i].gr & GR_REVERSE) {
509
if (i == cursor_addr) {
510
fg_color = (bg_color == HOST_COLOR_RED)?
511
HOST_COLOR_BLACK: bg_color;
512
bg_color = HOST_COLOR_RED;
225
514
if (ea_buf[i].gr & GR_INTENSIFY)
229
if (high != current_high) {
519
if (fg_color != current_fg ||
520
bg_color != current_bg ||
521
high != current_high ||
522
fa_ital != current_ital) {
529
html_color(fg_color),
530
html_color(bg_color),
531
high? "bold": "normal",
532
fa_ital? "italic": "normal");
533
current_fg = fg_color;
534
current_bg = bg_color;
536
current_ital = fa_ital;
540
if (ptype == P_RTF) {
542
fprintf(f, "\\u%ld?", uc);
544
nmb = unicode_to_multibyte(uc,
551
else if (mb[0] == '-')
553
else if (mb[0] == ' ')
558
} else if (ptype == P_HTML) {
566
nmb = unicode_to_utf8(uc, mb);
570
for (k = 0; k < nmb; k++) {
239
fprintf(f, "<html>\n"
241
" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n"
245
"<tr bgcolor=black><td>"
246
"<pre><font color=%s>%s",
248
html_color(current_color),
249
current_high? "<b>": "");
253
#if defined(X3270_DBCS) /*[*/
576
nmb = unicode_to_multibyte(uc,
255
578
(void) fputs(mb, f);
261
if (use_html && c == '<')
264
(void) fputs(utf8_expand(c), f);
269
if (!any && !even_if_empty)
583
if (xcaption != NULL)
587
(void) fputc('\n', f);
590
if (!any && !(opts & FPS_EVEN_IF_EMPTY) && ptype == P_TEXT)
272
(void) fputc('\n', f);
596
(void) fputc('\n', f);
275
if (use_html && any) {
276
fprintf(f, "%s</font></pre></td></tr>\n"
599
if (ptype == P_RTF) {
600
fprintf(f, "\n}\n%c", 0);
602
if (ptype == P_HTML) {
603
fprintf(f, "%s</span></pre></td></tr>\n"
749
#if defined(_WIN32) /*[*/
751
* A Windows version of something like mkstemp(). Creates a temporary
752
* file in $TEMP, returning its path and an open file descriptor.
755
win_mkstemp(char **path, ptype_t ptype)
765
*path = xs_buffer("%s\\x3h%u.%s", s, getpid(),
766
(ptype == P_RTF)? "rtf": "txt");
767
fd = open(*path, O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
778
#define PROGRAMFILES "%ProgramFiles%"
785
static char *wp = NULL;
791
/* Get the shell print command for RTF files. */
792
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
793
"Software\\Classes\\rtffile\\shell\\print\\command",
796
&key) != ERROR_SUCCESS) {
800
if (RegQueryValueEx(key,
805
&dlen) != ERROR_SUCCESS) {
811
if (data[0] == '"') {
815
/* The first token is quoted; that's the path. */
816
strcpy(data2, data + 1);
817
q2 = strchr(data2, '"');
823
} else if ((slash = strchr(data, '/')) != NULL) {
826
if (*(slash - 1) == ' ')
830
if (!strncasecmp(data, PROGRAMFILES, strlen(PROGRAMFILES))) {
831
char *pf = getenv("PROGRAMFILES");
833
/* Substitute %ProgramFiles%. */
837
wp = xs_buffer("%s\\%s", pf, data + strlen(PROGRAMFILES));
839
wp = NewString(data);
841
if (GetShortPathName(wp, data, sizeof(data)) != 0) {
843
wp = NewString(data);
413
849
/* Print or save the contents of the screen as text. */
415
PrintText_action(Widget w unused, XEvent *event, String *params,
851
PrintText_action(Widget w _is_unused, XEvent *event, String *params,
416
852
Cardinal *num_params)
419
855
char *filter = CN;
420
856
Boolean secure = appres.secure;
421
Boolean use_html = False;
857
ptype_t ptype = P_TEXT;
422
858
Boolean use_file = False;
423
859
Boolean use_string = False;
860
char *temp_name = NULL;
861
unsigned opts = FPS_EVEN_IF_EMPTY;
862
char *caption = NULL;
425
864
action_debug(PrintText_action, event, params, num_params);