source: trunk/SL/GUI_TK/asciiprint.cxx

Last change on this file was 19612, checked in by westram, 11 days ago
  • insert module purposes.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.4 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : asciiprint.cxx                                     //
4//   Purpose   : show/print ASCII text                              //
5//                                                                  //
6//   Institute of Microbiology (Technical University Munich)        //
7//   http://www.arb-home.de/                                        //
8//                                                                  //
9// ================================================================ //
10
11#include "asciiprint.hxx"
12
13#include <aw_window.hxx>
14#include <aw_root.hxx>
15#include <aw_question.hxx>
16#include <aw_awar.hxx>
17#include <aw_msg.hxx>
18#include <arbdbt.h>
19
20#define AWAR_APRINT               "tmp/aprint/"
21#define AWAR_APRINT_TITLE         AWAR_APRINT "title"
22#define AWAR_APRINT_TEXT          AWAR_APRINT "text"
23#define AWAR_APRINT_PAPER_SIZE    AWAR_APRINT "paper_size"
24#define AWAR_APRINT_MAGNIFICATION AWAR_APRINT "magnification"
25#define AWAR_APRINT_SX            AWAR_APRINT "source_columns"
26#define AWAR_APRINT_SY            AWAR_APRINT "source_rows"
27#define AWAR_APRINT_DX            AWAR_APRINT "dest_cols"
28#define AWAR_APRINT_DY            AWAR_APRINT "dest_rows"
29#define AWAR_APRINT_ORIENTATION   AWAR_APRINT "orientation"
30#define AWAR_APRINT_PAGES         AWAR_APRINT "pages"
31#define AWAR_APRINT_PRINTTO       AWAR_APRINT "printto"
32#define AWAR_APRINT_PRINTER       AWAR_APRINT "printer"
33#define AWAR_APRINT_FILE          AWAR_APRINT "file"
34
35
36enum AWT_asciiprint_orientation {
37    AWT_APRINT_ORIENTATION_PORTRAIT,
38    AWT_APRINT_ORIENTATION_LANDSCAPE,
39    AWT_APRINT_ORIENTATION_DOUBLE_PORTRAIT
40};
41
42
43enum AWT_asciiprint_paper_size {
44    AWT_APRINT_PAPERSIZE_A4,
45    AWT_APRINT_PAPERSIZE_US
46};
47
48enum AWT_asciiprint_destination {
49    AWT_APRINT_DEST_PRINTER,
50    AWT_APRINT_DEST_FILE_PS,
51    AWT_APRINT_DEST_FILE_ASCII,
52    AWT_APRINT_DEST_PREVIEW
53};
54
55static double awt_aps_get_xy_ratio(AW_root *awr) {
56    // AWT_asciiprint_paper_size psize = (AWT_asciiprint_paper_size)awr->awar(AWAR_APRINT_PAPER_SIZE)->read_int();
57    AWT_asciiprint_orientation ori = AWT_asciiprint_orientation(awr->awar(AWAR_APRINT_ORIENTATION)->read_int());
58    double res = 1.0;
59    switch (ori) {
60        case AWT_APRINT_ORIENTATION_PORTRAIT:
61            res = 112.0/90.0;
62            break;
63        case AWT_APRINT_ORIENTATION_LANDSCAPE:
64            res = 112.0/50.0;
65            break;
66        case AWT_APRINT_ORIENTATION_DOUBLE_PORTRAIT:
67            res = 103.0/90.0;
68            break;
69    }
70    return res;
71}
72
73static int awt_aps_get_default_lines_per_page(AW_root *awr) {
74    AWT_asciiprint_orientation ori = AWT_asciiprint_orientation(awr->awar(AWAR_APRINT_ORIENTATION)->read_int());
75    switch (ori) {
76        case AWT_APRINT_ORIENTATION_PORTRAIT:
77            return 80;
78        case AWT_APRINT_ORIENTATION_LANDSCAPE:
79            return 60;
80        case AWT_APRINT_ORIENTATION_DOUBLE_PORTRAIT:
81            return 80;
82    }
83    return -1;
84}
85
86
87static void awt_aps_calc_pages_needed(AW_root *awr) {
88    int mag = awr->awar(AWAR_APRINT_MAGNIFICATION)->read_int();
89    if (mag < 25) {
90        awr->awar(AWAR_APRINT_MAGNIFICATION)->write_int(mag*2);
91        return;
92    }
93    if (mag > 250) {
94        awr->awar(AWAR_APRINT_MAGNIFICATION)->write_int(250);
95        return;
96    }
97
98    int x = awr->awar(AWAR_APRINT_SX)->read_int() * mag / 100;
99    int y = awr->awar(AWAR_APRINT_SY)->read_int() * mag / 100;
100    int default_lpp = awt_aps_get_default_lines_per_page(awr);
101    double xy_ratio = awt_aps_get_xy_ratio(awr);
102    int default_cpp = int(default_lpp * xy_ratio);
103
104    awr->awar(AWAR_APRINT_DX)->write_float(float(x)/default_cpp);
105    awr->awar(AWAR_APRINT_DY)->write_float(float(y)/default_lpp);
106    x += default_cpp-1;
107    y += default_lpp-1;
108    x /= default_cpp;
109    y /= default_lpp;
110
111    awr->awar(AWAR_APRINT_PAGES)->write_int(x* y);
112}
113
114
115static void awt_aps_set_magnification_to_fit_xpage(AW_root *awr) {
116    int x = awr->awar(AWAR_APRINT_SX)->read_int();
117
118    int dx = int(awr->awar(AWAR_APRINT_DX)->read_float()+.5);
119    if (dx < 1) dx = 1;
120    if (dx > 99) dx = 99;
121
122    int default_lpp = awt_aps_get_default_lines_per_page(awr);
123    double xy_ratio = awt_aps_get_xy_ratio(awr);
124    int default_cpp = int(default_lpp * xy_ratio);
125    int mag = 100 * default_cpp * dx / x;
126    awr->awar(AWAR_APRINT_MAGNIFICATION)->write_int(mag);
127    awt_aps_calc_pages_needed(awr);
128}
129
130static void awt_aps_set_magnification_to_fit_ypage(AW_root *awr) {
131    int y = awr->awar(AWAR_APRINT_SY)->read_int();
132
133    int dy = int(awr->awar(AWAR_APRINT_DY)->read_float()+.5);
134    if (dy < 1) dy = 1;
135    if (dy > 99) dy = 99;
136
137    int default_lpp = awt_aps_get_default_lines_per_page(awr);
138    int mag = 100 * default_lpp * dy / y;
139    awr->awar(AWAR_APRINT_MAGNIFICATION)->write_int(mag);
140    awt_aps_calc_pages_needed(awr);
141}
142
143static void awt_aps_set_magnification_to_fit_xpage(AW_window *aww) {
144    awt_aps_set_magnification_to_fit_xpage(aww->get_root());
145}
146static void awt_aps_set_magnification_to_fit_ypage(AW_window *aww) {
147    awt_aps_set_magnification_to_fit_ypage(aww->get_root());
148}
149static void awt_aps_text_changed(AW_root *awr) {
150    char *text = awr->awar(AWAR_APRINT_TEXT)->read_string();
151    {
152        char *rtext = GBS_replace_tabs_by_spaces(text);
153        delete text;
154        text = rtext;
155    }
156    int maxx, y;
157    maxx = 1; y = 0;
158    char *s;
159    char *ns;
160    for (s = text; s; s=ns) {
161        ns = strchr(s, '\n');
162        if (ns) {
163            ns[0] = 0;
164            ns++;
165        }
166        int slen = strlen(s);
167        if (slen > maxx) {
168            maxx = slen;
169        }
170        y++;
171    }
172    if (!y) y++;
173    awr->awar(AWAR_APRINT_SX)->write_int(maxx);
174    awr->awar(AWAR_APRINT_SY)->write_int(y);
175    delete text;
176    awt_aps_set_magnification_to_fit_xpage(awr);
177}
178
179static void write_file(const char *filename, const char *file) {
180    fprintf(stderr, "Printing to ASCII file '%s'\n", filename);
181    FILE *f = fopen(filename, "r");
182    if (f) {
183        fclose(f);
184        if (aw_question("overwrite_file", GBS_global_string("File '%s' already exist", filename), "Overwrite,Cancel")) {
185            return;
186        }
187    }
188    f = fopen(filename, "w");
189    if (!f) {
190        aw_message(GBS_global_string("Cannot write to '%s'", filename));
191        return;
192    }
193    fprintf(f, "%s", file);
194    fclose(f);
195}
196
197static char *printFile(AW_root *awr) {
198    const char *home = GB_getenv("HOME");
199    const char *name = awr->awar(AWAR_APRINT_FILE)->read_char_pntr();
200    return GBS_global_string_copy("%s/%s", home, name);
201}
202
203static void awt_aps_go(AW_window *aww) {
204    AW_root *awr  = aww->get_root();
205    char    *text = awr->awar(AWAR_APRINT_TEXT)->read_string();
206
207    freeset(text, GBS_replace_tabs_by_spaces(text));
208
209    AWT_asciiprint_destination dest = (AWT_asciiprint_destination)awr->awar(AWAR_APRINT_PRINTTO)->read_int();
210    if (dest == AWT_APRINT_DEST_FILE_ASCII) {
211        char *file = printFile(awr);
212        write_file(file, text);
213        free(file);
214    }
215    else {
216        char *tmp_file;
217        FILE *tmpf;
218        {
219            char *name = GB_unique_filename("arb_aprint", "txt");
220            tmpf = GB_fopen_tempfile(name, "wt", &tmp_file);
221            free(name);
222        }
223
224        GB_ERROR error = NULp;
225        if (!tmpf) {
226            error = GBS_global_string("awt_aps_go: %s", GB_await_error());
227        }
228        else {
229            char *y_begin = text;
230            int last_y = 0;
231
232            double xy_ratio = awt_aps_get_xy_ratio(awr);
233            int    mag      = awr->awar(AWAR_APRINT_MAGNIFICATION)->read_int();
234
235            int default_lpp = awt_aps_get_default_lines_per_page(awr);
236            int default_cpp = int(default_lpp * xy_ratio);
237            default_cpp     = default_cpp * 100 / mag;
238            default_lpp     = default_lpp * 100 / mag;
239
240            int text_width  = awr->awar(AWAR_APRINT_SX)->read_int();
241            int text_height = awr->awar(AWAR_APRINT_SY)->read_int();
242
243            int x;
244            int y;
245
246            for (y = 0; y < text_height; y += default_lpp) {
247                while (last_y < y) {
248                    last_y ++;
249                    y_begin = strchr(y_begin, '\n');
250                    if (!y_begin) break;
251                    y_begin++;
252                }
253                if (!y_begin) break;
254
255                for (x = 0; x < text_width; x += default_cpp) {
256                    char *line = y_begin;
257                    int i;
258                    for (i=0; i<default_lpp; i++) {
259                        if (line) {
260                            char *next_line = strchr(line, '\n');
261                            int line_length;
262                            if (next_line) {
263                                line_length = next_line - line; // exclusive '\n'
264                                next_line ++;
265                            }
266                            else {
267                                line_length = strlen(line);
268                            }
269                            if (line_length > x + default_cpp) {
270                                line_length = x + default_cpp;
271                            }
272                            if (line_length > x) {
273                                fwrite(line + x, sizeof(char), line_length - x, tmpf);
274                            }
275                            line = next_line;
276                        }
277                        fprintf(tmpf, "\n");
278                    }
279                }
280            }
281            fclose(tmpf);
282
283            char *a2ps_call = NULp;
284            {
285                AWT_asciiprint_orientation ori = AWT_asciiprint_orientation(awr->awar(AWAR_APRINT_ORIENTATION)->read_int());
286                const char *oristring = "";
287                switch (ori) {
288                    case AWT_APRINT_ORIENTATION_PORTRAIT:
289                        oristring = "-p -1 ";
290                        break;
291                    case AWT_APRINT_ORIENTATION_LANDSCAPE:
292                        oristring = "-l -1 ";
293                        break;
294                    case AWT_APRINT_ORIENTATION_DOUBLE_PORTRAIT:
295                        oristring = "-p -2 ";
296                        break;
297                }
298                const char *header          = awr->awar(AWAR_APRINT_TITLE)->read_char_pntr();
299                char       *quotedHeaderArg = GBK_singlequote(GBS_global_string("-H%s", header));
300                a2ps_call                   = GBS_global_string_copy("arb_a2ps -ns -nP %s %s -l%i %s",
301                                                                     quotedHeaderArg, oristring, default_lpp, tmp_file);
302                free(quotedHeaderArg);
303            }
304
305            const char *scall = NULp;
306            switch (dest) {
307                case AWT_APRINT_DEST_PRINTER: {
308                    char *printer = awr->awar(AWAR_APRINT_PRINTER)->read_string();
309                    scall = GBS_global_string("%s |%s; rm -f %s", a2ps_call, printer, tmp_file);
310                    free(printer);
311                    break;
312                }
313                case AWT_APRINT_DEST_FILE_PS: {
314                    char *file       = printFile(awr);
315                    char *quotedFile = GBK_singlequote(file);
316                    fprintf(stderr, "Printing to PS file %s\n", quotedFile);
317                    scall            = GBS_global_string("%s >%s;rm -f %s", a2ps_call, quotedFile, tmp_file);
318                    free(quotedFile);
319                    free(file);
320                    break;
321                }
322                case AWT_APRINT_DEST_PREVIEW: {
323                    char *tmp_file2;
324                    {
325                        char *name_only;
326                        GB_split_full_path(tmp_file, NULp, NULp, &name_only, NULp);
327                        tmp_file2 = GB_create_tempfile(GBS_global_string("%s.ps", name_only));
328                        free(name_only);
329                    }
330
331                    if (!tmp_file2) error = GB_await_error();
332                    else {
333                        scall = GBS_global_string("%s >%s;(%s %s;rm -f %s %s)&",
334                                                  a2ps_call, tmp_file2,
335                                                  GB_getenvARB_GS(), tmp_file2,
336                                                  tmp_file, tmp_file2);
337                        free(tmp_file2);
338                    }
339                    break;
340                }
341                default:
342                    arb_assert(0);
343                    break;
344            }
345
346            if (scall) error = GBK_system(scall);
347            free(a2ps_call);
348        }
349        if (error) aw_message(error);
350        free(tmp_file);
351    }
352    free(text);
353}
354
355static void cutExt(char *name, const char *removeExt) {
356    char *found = strstr(name, removeExt);
357    if (found && strcmp(found, removeExt) == 0) {
358        found[0] = 0;
359    }
360}
361static char *correct_extension(const char *name, const char *newExt) {
362    char *noExt = ARB_strdup(name);
363    cutExt(noExt, ".ps");
364    cutExt(noExt, ".txt");
365
366    char *result = ARB_alloc<char>(strlen(noExt)+strlen(newExt)+1);
367    strcpy(result, noExt);
368    strcat(result, newExt);
369    if (strcmp(name, result) == 0) freenull(result);
370
371    free(noExt);
372    return result;
373}
374
375static void aps_correct_filename(AW_root *aw_root) {
376    int type = aw_root->awar(AWAR_APRINT_PRINTTO)->read_int();
377    if (type == AWT_APRINT_DEST_FILE_PS || type == AWT_APRINT_DEST_FILE_ASCII) {
378        AW_awar    *awar_name = aw_root->awar(AWAR_APRINT_FILE);
379        const char *name      = awar_name->read_char_pntr();
380        char       *new_name  = NULp;
381
382        if (type == AWT_APRINT_DEST_FILE_PS) {
383            new_name = correct_extension(name, ".ps");
384        }
385        else {
386            arb_assert((type == AWT_APRINT_DEST_FILE_ASCII));
387            new_name = correct_extension(name, ".txt");
388        }
389        if (new_name) {
390            awar_name->write_string(new_name);
391            free(new_name);
392        }
393    }
394}
395
396void AWT_create_ascii_print_window(AW_root *awr, const char *text_to_print, const char *title) {
397    static AW_window_simple *aws = NULp;
398
399    awr->awar_string(AWAR_APRINT_TEXT)->write_string(text_to_print);
400    if (title) {
401        awr->awar_string(AWAR_APRINT_TITLE)->write_string(title);
402    }
403    if (aws) {
404        awr->awar_float(AWAR_APRINT_DX)->write_float(1.0);
405    }
406    else {
407        aws = new AW_window_simple;
408        aws->init(awr, "PRINT", "PRINT");
409        aws->load_xfig("awt/ascii_print.fig");
410        awr->awar_string(AWAR_APRINT_TITLE);
411        awr->awar_string(AWAR_APRINT_TEXT)                                  ->add_callback(awt_aps_text_changed);
412
413        awr->awar_int(AWAR_APRINT_PAPER_SIZE, (int)AWT_APRINT_PAPERSIZE_A4) ->add_callback(awt_aps_set_magnification_to_fit_xpage);
414        awr->awar_int(AWAR_APRINT_MAGNIFICATION, 100)                       ->add_callback(awt_aps_calc_pages_needed);
415        awr->awar_int(AWAR_APRINT_PAGES, 1);
416        awr->awar_int(AWAR_APRINT_SX, 1);
417        awr->awar_int(AWAR_APRINT_SY, 1);
418
419        awr->awar_float(AWAR_APRINT_DX, 1.0);
420        awr->awar_float(AWAR_APRINT_DY, 1.0);
421
422        awr->awar_string(AWAR_APRINT_FILE, "print.ps")->add_callback(aps_correct_filename);
423
424        awr->awar_int(AWAR_APRINT_ORIENTATION, (int)AWT_APRINT_ORIENTATION_PORTRAIT)->add_callback(awt_aps_set_magnification_to_fit_xpage);
425        awr->awar_int(AWAR_APRINT_PRINTTO, int(AWT_APRINT_DEST_PRINTER))->add_callback(aps_correct_filename);
426        aps_correct_filename(awr);
427
428        {
429            char *print_command;
430            if (getenv("PRINTER")) {
431                print_command = GBS_eval_env("lpr -h -P$(PRINTER)");
432            }
433            else {
434                print_command = ARB_strdup("lpr -h");
435            }
436
437            awr->awar_string(AWAR_APRINT_PRINTER, print_command);
438            free(print_command);
439        }
440
441        awt_aps_text_changed(awr);
442
443        aws->at("close");
444        aws->callback(AW_POPDOWN);
445        aws->create_button("CLOSE", "CLOSE");
446
447        aws->at("help");
448        aws->callback(makeHelpCallback("asciiprint.hlp"));
449        aws->create_button("HELP", "HELP");
450
451        aws->at("go");
452        aws->callback(awt_aps_go);
453        aws->create_button("PRINT", "PRINT");
454
455        aws->at("title");
456        aws->create_input_field(AWAR_APRINT_TITLE);
457
458        aws->at("text");
459        aws->create_text_field(AWAR_APRINT_TEXT);
460
461        aws->button_length(5);
462        aws->at("rows");
463        aws->create_button(NULp, AWAR_APRINT_SY);
464
465        aws->at("columns");
466        aws->create_button(NULp, AWAR_APRINT_SX);
467
468        aws->at("magnification");
469        aws->create_input_field(AWAR_APRINT_MAGNIFICATION, 4);
470
471        aws->at("paper_size");
472        {
473            aws->create_toggle_field(AWAR_APRINT_PAPER_SIZE, AW_HORIZONTAL);
474            aws->insert_toggle("A4", "A", int(AWT_APRINT_PAPERSIZE_A4));
475            aws->insert_toggle("US", "U", int(AWT_APRINT_PAPERSIZE_US));
476            aws->update_toggle_field();
477        }
478
479        aws->at("orientation");
480        {
481            aws->create_toggle_field(AWAR_APRINT_ORIENTATION, AW_HORIZONTAL);
482            aws->insert_toggle("#print/portrait.xpm", "P", int(AWT_APRINT_ORIENTATION_PORTRAIT));
483            aws->insert_toggle("#print/landscape.xpm", "P", int(AWT_APRINT_ORIENTATION_LANDSCAPE));
484            aws->update_toggle_field();
485        }
486
487
488        aws->at("pages");
489        aws->create_button(NULp, AWAR_APRINT_PAGES);
490
491        aws->at("dcol");
492        aws->callback(awt_aps_set_magnification_to_fit_xpage); // @@@ used as INPUTFIELD_CB (see #559)
493        aws->create_input_field(AWAR_APRINT_DX, 4);
494
495        aws->at("drows");
496        aws->callback(awt_aps_set_magnification_to_fit_ypage); // @@@ used as INPUTFIELD_CB (see #559)
497        aws->create_input_field(AWAR_APRINT_DY, 4);
498
499
500        aws->at("printto");
501        aws->create_toggle_field(AWAR_APRINT_PRINTTO);
502        aws->insert_toggle("Printer", "P", int(AWT_APRINT_DEST_PRINTER));
503        aws->insert_toggle("File (Postscript)", "F", int(AWT_APRINT_DEST_FILE_PS));
504        aws->insert_toggle("File (ASCII)", "A", int(AWT_APRINT_DEST_FILE_ASCII));
505        aws->insert_toggle("Preview", "V", int(AWT_APRINT_DEST_PREVIEW));
506        aws->update_toggle_field();
507
508        aws->at("printer");
509        aws->create_input_field(AWAR_APRINT_PRINTER, 16);
510
511        aws->at("filename");
512        aws->create_input_field(AWAR_APRINT_FILE, 16);
513    }
514    aws->activate();
515}
516
517
518void AWT_show_file(AW_root *awr, const char *filename) {
519    char *text = GB_read_file(filename);
520    if (!text) {
521        aw_message(GB_await_error());
522    }
523    else {
524        AWT_create_ascii_print_window(awr, text, filename);
525        free(text);
526    }
527}
Note: See TracBrowser for help on using the repository browser.