To print a pdf on btPrint using osprint.p (adecomm.pl) - openedge

I am trying to print a pdf from my application using this osprint.p option, I am able to use the printer option of saving pdf but the pdf is not in a readable format This is how it looks. any idea what I am doing wrong. Also, is there any option to set a default printer through this along with other options like the number of copies, collate, etc, without triggering MSW Print Setup dialog box I want to programmatically send these options?. With the below 4th parameters I am able to do the orientation and the paper size but don't how to set others.
/* RUN ShellExecuteA (0,"print":u,cUserFile,"default_Printer","",1,OUTPUT tInt). */
/* Using ShellExecute I won't be able to set orientation or any other options */
RUN adecomm/_osPrint.p (INPUT wWin,
INPUT cUserFile,
INPUT 3,
INPUT 1 + IF fc-orient-portrait = 1 THEN 0 ELSE 2 + i-papersize + 160 + 512,
INPUT 0,
INPUT 0,
OUTPUT vResult).
IF vResult THEN DO:
OS-DELETE VALUE(cUserFile).
END.
For reference, I am using this article from Chris:
https://www.progresstalk.com/threads/printing-on-ladscape-mode.48/
along with this one: https://knowledgebase.progress.com/articles/Knowledge/18776
Thanks Ahead.

_osprint.p cannot be used to print PDF files. As the file header (https://github.com/consultingwerk/ADE-Sourcecode/blob/master/src/adecomm/_osprint.p) says it's purpose is to send a text-file to a printer.
The easiest to print a PDF file is to use the ShellExecuteA API, e.g.:
PROCEDURE ShellExecuteA EXTERNAL "shell32":U:
DEFINE INPUT PARAMETER HWND AS LONG .
DEFINE INPUT PARAMETER lpOperation AS CHARACTER .
DEFINE INPUT PARAMETER lpFile AS CHARACTER .
DEFINE INPUT PARAMETER lpParameters AS CHARACTER .
DEFINE INPUT PARAMETER lpDirectory AS CHARACTER .
DEFINE INPUT PARAMETER nShowCmd AS LONG .
DEFINE RETURN PARAMETER hInstance AS LONG .
END PROCEDURE .
DEFINE VARIABLE hInstance AS INTEGER NO-UNDO.
RUN ShellExecuteA (0,
"print",
"c:\temp\oe-122-pdfs\start.pdf",
"",
"",
3,
OUTPUT hInstance) .
See https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecutea for options.
If you have some experience with OpenEdge GUI for .NET it should be straight forward to translate the answer that mentions the Google Pdfium library to ABL:
How can I send a file document to the printer and have it print?

Related

Time taken to run a loop (Progress 4GL)

I wrote a query which contains multiple for each statements. The query is taking more than 20 minutes to fetch the data. Is there a way to check what time each loop started and ended. (How much time does each loop takes to execute and also the total time taken to complete the program).
You could do as you ask (just follow JensD's suggestsions) but you would likely be better served to use the profiler. You can easily add profiling for a code snippet:
assign
profiler:enabled = yes
profiler:description = "description of this test"
profiler:profiling = yes
profiler:file-name = "filename.prf"
.
/* this is deliberately awful code that should take a long time to run */
for each orderline no-lock:
for each order no-lock:
for each customer no-lock:
if customer.custNum = order.custNum and orderLine.orderNum = orderLine.orderNum then
. /* do something */
end.
end.
end.
/* end of test snippet */
assign
profiler:enabled = no
profiler:profiling = no
.
profiler:write-data().
You can then load that prf file into an analysis tool. The specifics depend on your development environment - if you are using an up to date version of PSDOE there is a Profiler analyzer included, if not you might want to download ProTop
https://demo.wss.com/download.php and use the simple report included in lib/zprof_topx.p.
Ultimately what you are going to discover is that one or more of your FOR EACH statements is almost certainly using a WHERE clause that is a poor match for your available indexes.
To fix that you will need to determine which indexes are actually being selected and review the index selection rules. Some excellent material on that topic can be found here: http://pugchallenge.org/downloads2019/303_FindingData.pdf
If you don't want to go to the trouble of reading that then you should at least take a look at the actual index selection as shown by:
compile program.p xref program.xref
Do the selected indexes match your expectation? Did WHOLE-INDEX (aka "table scan") show up?
Using ETIME you can initiate a counter of milliseconds. It could be called once or several times to tell how much time has passed since reset.
ETIME(TRUE).
/*
Loop is here but instead I'll insert a small pause.
*/
PAUSE 0.5.
MESSAGE "This took" ETIME "milliseconds" VIEW-AS ALERT-BOX.
Milliseconds might not be useful when dealing with several minutes. Then you can use TIME to keep track of seconds but you need to handle start time yourself then.
DEFINE VARIABLE iStart AS INTEGER NO-UNDO.
iStart = TIME.
/*
Loop is here but instead I'll insert a slightly longer pause.
*/
PAUSE 2.
MESSAGE "This took" TIME - iStart "seconds" VIEW-AS ALERT-BOX.
If you want to keep track of several times then it might be better to output to a log file instead of using a MESSAGE-box that will stop execution until it's clicked.
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DEFINE STREAM str.
OUTPUT STREAM str TO c:\temp\timing.txt.
ETIME(TRUE).
/*
Fake loop
*/
DO i = 1 TO 20:
PAUSE 0.1.
PUT STREAM str UNFORMATTED "Timing no " i " " ETIME "ms" SKIP.
END.
OUTPUT CLOSE.

Assembly code . = 60^. in low.s file of UNIX V6 source code

The source code of UNIX V6 is available and there is a book on it by J.Lions. From the book I know that " . " symbol means current location. I do not understand the next:
"*An assignment statement of the form
identifier = expression
associates a value and type with the identifier. In the example
. = 60^.
the operator ’^’ delivers the value of the first
operand and the type of the second operand
(in this case, “location”);*"
The statement can be found in file low.s (0526). What does it mean? Does it actually change PC register value and behaves as a jump instruction? I know it is old code, but I want to understand it. Thank you.
In the 6th edition assembler, . is the location counter, an offset from the beginning of a segment (text, data, or bss). When the assembler starts processing a file, . in each segment is 0, and is incremented either by assignment to . or by the presence of data or instruction statements.
The statement . = 60^. means to take the value 60 (in octal), cast it to the type of the location counter (in this case, type data), and assign it to the location counter. You'll see several statements like this in low.s in the area where interrupt vectors are set up.
When the link editor combines multiple object files together, their text, data, and bss sections are concatenated (except for COMMON data, which gets allocated just once) and any references (such as labels) to instructions or data will be relocated appropriately.
Building the Unix kernel requires an extra step to make sure data meant to be in low memory get loaded at the proper address. After low.s and the rest of the Unix kernel object files have been linked together, sysfix is run to make the data section have a load address of 0, and to relocate all data references appropriately. So that . = 60^. statement has effectively set the location counter to physical address 60.

Jupyter Notebook different ways to display out

There seems to be 3 ways to display output in Jupyter:
By using print
By using display
By just writing the variable name
What is the exact difference, especially between number 2 and 3?
I haven't used display, but it looks like it provides a lot of controls. print, of course, is the standard Python function, with its own possible parameters.
But lets look at a simple numpy array in Ipython console session:
Simply giving the name - the default out:
In [164]: arr
Out[164]: array(['a', 'bcd', 'ef'], dtype='<U3')
This is the same as the repr output for this object:
In [165]: repr(arr)
Out[165]: "array(['a', 'bcd', 'ef'], dtype='<U3')"
In [166]: print(repr(arr))
array(['a', 'bcd', 'ef'], dtype='<U3')
Looks like the default display is the same:
In [167]: display(arr)
array(['a', 'bcd', 'ef'], dtype='<U3')
print on the other hand shows, as a default, the str of the object:
In [168]: str(arr)
Out[168]: "['a' 'bcd' 'ef']"
In [169]: print(arr)
['a' 'bcd' 'ef']
So at least for a simple case like this the key difference is between the repr and str of the object. Another difference is which actions produce an Out, and which don't. Out[164] is an array. Out[165] (and 168) are strings. print and display display, but don't put anything on the Out list (in other words they return None).
display can return a 'display' object, but I won't get into that here. You can read the docs as well as I can.

Dictionary suggestions in autopopup

I use Vim for many years now but I still don't know how to type text with autopopup dictionary suggestions enabled (like in notepad++ or google android keyboard) without pushing any shortcut key.
These are my options in vimrc:
set completeopt=longest,menuone
set omnifunc=syntaxcomplete#Complete
In short what I want is:
1) Only dictionary suggestion in autopopup while typing.
2) Only buffer words suggestion in supertab (using tab key)
(but..without the buffer names included)
How can I obtain this?
If you are using Linux you can set the existing english dictionary to /usr/share/dict/american-english or just set your own file:
:set dictionary+=/usr/share/dict/american-english
and as the shortcut for dictionary completion in insert mode is CTRL-X CTRL-K you need to add these settings:
:set noshowmode
:set completeopt+=noinsert
:autocmd CursorHoldI * call feedkeys("\<c-x>\<c-k>")
:set updatetime=500
You can restrict the Supertab plugin to popup only the buffer words by calling SuperTabSetDefaultCompletionType function (which is actually the default one):
:call SuperTabSetDefaultCompletionType("<c-x><c-n>")
But you still need to press CTRL-X before TAB.
Disable the NeoComplete plugin
:NeoCompleteDisable
:help ins-completion
(...)
Completion can be done for:
1. Whole lines i_CTRL-X_CTRL-L
2. keywords in the current file i_CTRL-X_CTRL-N
3. keywords in 'dictionary' i_CTRL-X_CTRL-K
4. keywords in 'thesaurus', thesaurus-style i_CTRL-X_CTRL-T
5. keywords in the current and included files i_CTRL-X_CTRL-I
6. tags i_CTRL-X_CTRL-]
7. file names i_CTRL-X_CTRL-F
8. definitions or macros i_CTRL-X_CTRL-D
9. Vim command-line i_CTRL-X_CTRL-V
10. User defined completion i_CTRL-X_CTRL-U
11. omni completion i_CTRL-X_CTRL-O
12. Spelling suggestions i_CTRL-X_s
13. keywords in 'complete' i_CTRL-N
Edit:
This is related to comments below this answer: It is a tiny script PopUpDict.vim (it can be improved) that I coded which pop up automatically the matched words in dictionary after typing 3 characters and which give you the ability to pop up the matched buffer keywords after typing ctrl-x tab: (newer version of vim >= 7.4)
set dictionary+=/usr/share/dict/american-english
set completeopt+=noinsert
set cmdheight=2
call SuperTabSetDefaultCompletionType("<c-x><c-n>")
NeoCompleteDisable
augroup Main
autocmd!
autocmd InsertCharPre * call <SID>PopUpDict()
augroup END
let s:count=0
function! s:PopUpDict()
let AsciiCode=char2nr(v:char)
if (AsciiCode <=# 122 && AsciiCode >=# 97) || (AsciiCode <=# 90 && AsciiCode >=# 65)
let s:count+=1
if s:count >=# 3
call feedkeys("\<c-x>\<c-k>")
endif
else
let s:count=0
endif
endfunction
Demo

Assigning unlisted shortcut keys / key binding

As one of the millions of people around the world I do not have an "anglo-saxon" keyboard and frustratingly I don't have {} on my keyboard (i have è ° à and other useful stuff for italian). How hassly for programming is that!!!!!
So I'd like to assign a key binding to curly brackets but they are not listed in the preferences->general->keys.
Is it possible? Have I missed it?
To confirm, you'd like to press one key and instead get a curly brace? You could so that using commands. The example below approximates what the editor would normally do by inserting a {} and placing the cursor in the middle.
1) Create a new Ruble via File > New Ruby project > Go to next page for "templates" and select a Ruble template
2) Edit the commands/commands.rb file and insert the following (adjusting as appropriate)
require 'ruble'
command 'Insert Right Brace' do |cmd|
cmd.key_binding = 'q' # change this for a new key binding
cmd.scope = 'source'
cmd.output = :insert_as_snippet
cmd.input = :selection
cmd.invoke do |context|
print '{${0}}' # snippet to surround the cursor with braces
end
end

Resources