-------------------- namespace printer -- Utility to make printing easier -------------------- export constant version = "4.12.0" -- EXPORTS: -- functions callbacks -- printer:PrintFile() printer:print_file -- printer:PrintText() printer:print_text -- This version handles most common printing needs, but it will not yet respect -- 'marked up' a.k.a. 'rich' text, i.e. text with colors and styles as produced -- by GTK3's TextView widget. It just prints them as plain text. -- -- However, it DOES print text marked up with GTK's HTML subset, so you can use -- , , , , ... etc. in your printouts! This includes various -- imbedded font styles and colors. -- -- More documentation is found in ~/documentation/printing.html include GtkEngine.e include GtkCairo.e include std/datetime.e if not equal(version,gtk:version) then Error(,,"GtkPrinter version mismatch","should be version " & gtk:version) end if -- The following exported variables can be modified before calling the -- print routine: public object header = "[1]\n" -- default is just the page title public object subheader = "[1] page [5]\n\n" -- format for headers on pg.2 ... n -- default subheader (above) prints page title and pg #; public object footer = "\nPrinted by EuGTK [8] on [9]'s computer" -- default footer (above) prints date and user name; -- Info ID's for use in header and footer; -- 1 = page title (for first page) -- 2 = sub title (for subsequent pages - leave null to use page title (1) on all pgs) -- 3 = file name -- 4 = short name (file name w/o path) -- 5 = current page number -- 6 = n_pages printed e.g. pg 1 of n -- 7 = n_copies requested -- 8 = today's date in date_format -- 9 = user name --10 = user's real name --11 = font name used for this print job --12 = file length in bytes --13 = file timestamp --14 = exported filename, if any export integer n_pages = 0, -- number of pages to print (0=all) n_copies = 1, collate = FALSE, duplex = 0, number_up = 1, number_up_layout = 1, units = GTK_UNIT_INCH, use_line_numbers = TRUE, use_color = TRUE, -- print eu comments in red if true lines_per_page = 60, wrap_at = 0, track_status = TRUE, show_progress = TRUE, -- enable the built-in progressbar embed_page_setup = TRUE, orientation = 0, order = 0, confirm = FALSE, sourcecode = TRUE, plaintext = FALSE, use_full_page = FALSE, -- ignore margins has_selection = FALSE, support_selection = FALSE, quality = GTK_PRINT_QUALITY_DRAFT, action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, auto_lpp = TRUE export atom scale = 100, top_margin = 0.25, -- in inch units left_margin = 0.25, right_margin = 0.25, bottom_margin = 0.25, parent = 0, signal_status_changed = call_back(routine_id("show_status")), signal_begin_print = call_back(routine_id("begin_print")), signal_draw_page = call_back(routine_id("draw_page")), signal_end_print = call_back(routine_id("end_print")), signal_request_page_setup = 0, signal_done = 0, signal_ready = 0, signal_got_page_size = 0 export object name = 0, font = "Ubuntu Mono 8", jobname = 0, settings_file = 0, setup_file = 0, export_file = 0, page_ranges = 0, page_set = GTK_PAGE_SET_ALL, custom_tab_hook = 0, custom_tab_label = 0, custom_tab_func = 0 ifdef WINDOWS then font = "Courier New 16" end ifdef export object line_number_format = "[:4] []\n", -- controls line # format AND code line! paper_name = "na_letter", -- 8.5x11.0" tabs = " ", -- replace tab chars with 8 spaces file_name = 0, short_name = 0, page_title = 0, sub_title = 0 export atom progress = create(GtkProgressBar), settings = create(GtkPrintSettings) -- use date and time formats in std/datetime.e; export sequence date_format = "%A, %B %d %Y %l:%M %p" sequence user ifdef WINDOWS then user = "User" elsedef user = proper(getenv("USER")) end ifdef -- for local use; atom fontdesc integer filesize = 0 object timestamp = 0 sequence text sequence today = datetime:format(datetime:now(),date_format) export procedure reset() n_pages = 0 n_copies = 1 collate = FALSE duplex = 0 number_up = 1 number_up_layout = 1 units = GTK_UNIT_INCH use_line_numbers = TRUE use_color = TRUE lines_per_page = 60 wrap_at = 0 track_status = TRUE show_progress = TRUE embed_page_setup = TRUE orientation = 0 order = 0 confirm = FALSE sourcecode = TRUE plaintext = FALSE use_full_page = FALSE has_selection = FALSE support_selection = FALSE quality = GTK_PRINT_QUALITY_DRAFT action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG auto_lpp = TRUE scale = 100 top_margin = 0.25 left_margin = 0.25 right_margin = 0.25 bottom_margin = 0.25 parent = 0 name = 0 paper_name = "na_letter" font = "Ubuntu Mono 8" jobname = 0 settings_file = 0 setup_file = 0 export_file = 0 page_ranges = 0 page_set = GTK_PAGE_SET_ALL custom_tab_hook = 0 custom_tab_label = 0 custom_tab_func = 0 end procedure ------------------------------------------------------------------------ export function PrintFile(object f=0, object x=0) ------------------------------------------------------------------------ if string(f) and string(x) then page_title = f file_name = canonical_path(x) timestamp = file_timestamp(file_name) filesize = file_length(file_name) short_name = filebase(file_name) text = read_file(file_name) setup_printer() return 1 end if if string(f) and atom(x) and x = 0 then f = canonical_path(f) file_name = f timestamp = file_timestamp(f) filesize = file_length(f) short_name = filebase(f) page_title = filename(f) text = read_file(f) setup_printer() return 1 end if if string(f) and atom(x) and x < 100 then page_title = f short_name = f file_name = f text = read_file(x) setup_printer() return 1 end if if atom(f) and atom(x) and x < 101 then if atom(file_name) then file_name = "" end if if atom(short_name) then short_name = "" end if if atom(page_title) then page_title = "" end if text = read_file(x) setup_printer() return 1 end if if atom(f) and atom(x) then x = unpack(x) x = canonical_path(x) file_name = x short_name = filebase(x) page_title = filename(x) text = read_file(x) setup_printer() return 1 end if return 1 end function export constant print_file = call_back(routine_id("PrintFile")) ------------------------------------------------------------------------ export function PrintText(object f=0, object x=0) ------------------------------------------------------------------------ if string(f) and string(x) then page_title = f text = x setup_printer() return 1 end if if atom(f) and string(x) then setup_printer() text = x return 1 end if if atom(f) and atom(x) then if atom(page_title) and page_title = 0 then page_title = "" end if text = unpack(x) setup_printer() return 1 end if return 0 end function export constant print_text = call_back(routine_id("PrintText")) integer status_code sequence status_string ----------------------------------------------- export function show_status(atom op) ----------------------------------------------- atom fn1 = define_func("gtk_print_operation_get_status",{P},I), fn2 = define_func("gtk_print_operation_get_status_string",{P},S) status_code = c_func(fn1,{op}) status_string = peek_string(c_func(fn2,{op})) ifdef PRINT then display("Status [] []",{status_code,status_string}) end ifdef if show_progress then set(progress,"text",status_string) end if ifdef DELAY then sleep(0.15) end ifdef return 1 end function ------------------------------------------------------ export function begin_print(atom op, atom context) ------------------------------------------------------ ifdef PRINT then display("Begin printing [] pages ",length(text)) end ifdef fontdesc = create(PangoFontDescription,font) if auto_lpp then atom setup = get(op,"default page setup") atom pght = get(setup,"page height",GTK_UNIT_POINTS) --display("Page height [] pt.",pght) pght -= length(header) pght -= length(footer) atom fs = get(fontdesc,"size") / 1024 --display("Font size []",fs) fs = fs * (96/72) integer lpp = 1 while ((fs*lpp)) < pght do lpp += 1 --display("Text height [] lpp []",{(fs*lpp),lpp}) end while --display("New LPP []",lpp-1) lines_per_page = lpp end if text = process_text(text) set(op,"n pages",n_pages) -- important, as a new value for n_pages is computed -- based on the length of the file being read, unless a set number -- has been provided from the calling program. if show_progress then -- turn on the progress dialog in the calling program show_all(progress) end if return 1 end function ---------------------------------------------------------------------------- export function draw_page(atom op, atom context, integer pg, atom data) ---------------------------------------------------------------------------- atom fn6 = define_func("gtk_print_context_get_cairo_context",{P},P) atom cr = c_func(fn6,{context}) atom pl = create(PangoCairoLayout,cr) set(pl,"font description",fontdesc) pg += 1 if pg > length(text) then set(progress,"text","Printing complete") return 0 end if if show_progress then set(progress,"text",sprintf("Printing page %d",pg)) set(progress,"fraction",pg/n_pages) end if ifdef DELAY then sleep(0.25) end ifdef object details = { page_title,sub_title,file_name,short_name, pg,n_pages,n_copies, today,user,real_name,font,filesize,timestamp,export_file } object page if atom(header) then header = "[1] page [5] of [6]\n\n" end if if pg = 1 or atom(subheader) then page = text:format(header,details) & flatten(text[pg]) & text:format(footer,details) else page = text:format(subheader,details) & flatten(text[pg]) & text:format(footer,details) end if if plaintext then set(pl,"text",page,length(page)) else set(pl,"markup",page,length(page)) end if set(pl,"update layout",cr) set(pl,"show layout",cr) ifdef PRINT then printf(1,"Page %d\n",pg) end ifdef return 1 end function ------------------------------------------------------------------------ function process_text(object txt) ------------------------------------------------------------------------ txt = split(txt,'\n') integer comment, n object a,b object test for i = 1 to length(txt) do -- replace chars which will confuse markup txt[i] = join(split(txt[i],'&'),"&") txt[i] = join(split(txt[i],"&amp;"),"&") if sourcecode then txt[i] = join(split(txt[i],'<'),"<") txt[i] = join(split(txt[i],'>'),">") end if if use_color then if match("--",txt[i]) then -- a comment; txt[i] = split(txt[i],"--") txt[i] = txt[i][1] & "-- " & txt[i][2] & "" end if end if if use_line_numbers then txt[i] = text:format(line_number_format,{i,txt[i]}) else txt[i] &= '\n' end if end for txt = breakup(txt,lines_per_page) if n_pages = 0 then -- no selection n_pages = length(txt) end if return txt end function ------------------------------------------------------------------------ export function end_print() ------------------------------------------------------------------------ status_string = "Printing complete" ifdef PRINT then display(status_string) end ifdef return 1 end function --------------------------------------------------------------- export function setup_printer() --------------------------------------------------------------- atom _size = create(GtkPaperSize,paper_name) atom err = allocate(16) err = 0 object results = 0 atom fn7 = define_func("gtk_print_operation_run",{P,I,P,P},I) atom fn8 = define_func("gtk_print_run_page_setup_dialog",{P,P,P},P) set(settings,"paper size",_size,units) set(settings,"n copies",n_copies) set(settings,"collate",collate) set(settings,"duplex",duplex) set(settings,"reverse",order) set(settings,"scale",scale) set(settings,"quality",quality) set(settings,"number up",number_up) set(settings,"number up layout",number_up_layout) if string(name) then set(settings,"printer",name) end if atom setup = create(GtkPageSetup) set(setup,"paper size",_size) set(setup,"orientation",orientation) set(setup,"left margin",left_margin,units) set(setup,"right margin",right_margin,units) set(setup,"top margin",top_margin,units) set(setup,"bottom margin",bottom_margin,units) atom printop = create(GtkPrintOperation) set(printop,"print settings",settings) set(printop,"default page setup",setup) set(printop,"show progress",show_progress) set(printop,"track print status",track_status) set(printop,"embed page setup",embed_page_setup) set(printop,"support selection",support_selection) set(printop,"has selection",has_selection) set(printop,"use full page",use_full_page) if action = GTK_PRINT_OPERATION_ACTION_EXPORT then export_file = canonical_path(export_file) set(printop,"export filename",export_file) end if if string(jobname) then set(printop,"job name",jobname) end if if custom_tab_hook != 0 then set(printop,"custom tab label",custom_tab_label) connect(printop,"create-custom-widget",custom_tab_func,printop) connect(printop,"custom-widget-apply",custom_tab_hook) end if connect(printop,"status-changed",signal_status_changed) connect(printop,"begin-print",signal_begin_print) connect(printop,"draw-page",signal_draw_page) connect(printop,"end-print",signal_end_print) connect(printop,"request-page-setup",signal_request_page_setup) connect(printop,"done",signal_done) connect(printop,"ready",signal_ready) connect(printop,"got-page-size",signal_got_page_size) display(get(settings,"printer lpi")) c_func(fn7,{printop,action,parent,err}) -- start the print process; if string(setup_file) and file_exists(canonical_path(setup_file)) then get(setup,"to file",canonical_path(setup_file)) end if object jobname = get(printop,"job name") if confirm then if action = GTK_PRINT_OPERATION_ACTION_EXPORT then if Question(0,"PDF Written", sprintf("%s\nFolder: %s", {filename(export_file),pathname(export_file)}), sprintf("%s\nStatus: %d\n%s\nClick Yes to view",{jobname,status_code,status_string}) ,,,"printer") then show_uri(export_file) end if else Info(0,"Print Job",jobname, sprintf("Status: %d %s",{status_code,status_string}) ,,"printer") end if end if page_title = 0 n_pages = 0 n_copies = 1 action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG return 1 end function header = "[1]\n\n" ----------------------------- -- copyright 2015 Irv Mullins -----------------------------