Author Topic: Miscellaneous snippets  (Read 3890 times)

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8435
  • Assembler is fun ;-)
    • MasmBasic
Deleting selected elements from a string array
« Reply #15 on: December 18, 2017, 08:28:38 AM »
A little exercise in deleting elements from a string array:

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  void NanoTimer()              ; start the timer
  Recall "TestFile.txt", b$()   ;
  PrintLine NanoTimer$(), " for loading the file into the b$() text array"
  void NanoTimer()              ; start the timer
  xor ecx, ecx
  .Repeat
        If_ Instr_(b$(ecx), "devil", 5) Then <mcs Delete b$(ecx) : dec ecx>
        inc ecx
  .Until ecx>=b$(?)
  Inkey NanoTimer$(), " for deleting the devil. Save the file (y)?"
  If_ eax=="y" Then Store "NoDevil.txt", b$()
EndOfCode


Result on an i5:
Code: [Select]
3458 µs for loading the file into the b$() text array
4954 µs for deleting the devil. Save the file (y)?


The required text file is here - unzip to the folder where the attached exe sits.

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8435
  • Assembler is fun ;-)
    • MasmBasic
Deleting selected elements from a text file
« Reply #16 on: December 19, 2017, 10:00:07 PM »
Same as above, but not line-based. Words are removed with Replace$():

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  void NanoTimer()              ; start the timer
  Let esi=FileRead$("TestFile.txt")
  PrintLine NanoTimer$(), " for loading the file"
  void NanoTimer()              ; start the timer
  Let esi=Replace$(esi, "devil", 0, 5)         ; mode 5: case-insensitive, full word, i.e. devils & devilish still there ;-)
  Inkey NanoTimer$(), " for deleting the devil. Save & see the file (y)?"
  If_ eax=="y" Then <mcs FileWrite "NoDevil.txt", esi : ShEx "NoDevil.txt">
EndOfCode


Code: [Select]
2392 µs for loading the file
6269 µs for deleting the devil. Save & see the file (y)?

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8435
  • Assembler is fun ;-)
    • MasmBasic
Mirror$() for UTF-8 strings
« Reply #17 on: December 24, 2017, 05:21:24 AM »
Work in progress, looks fine so far:

include \masm32\MasmBasic\MasmBasic.inc         ; download
include uMirror$.inc
  SetGlobals a$="Enter text here"
  SetGlobals r$="Введите текст здесь"         ; "Enter text here" in Russian
  SetGlobals cm$, c$="在這裡輸入文字", c4$="<see attached source>"        ; "Enter text here" and some 4-byte encoded string in Chinese
  Init
  PrintLine uMirror$(a$)
  PrintLine uMirror$(r$)
  Let cm$=uMirror$(c$)
  uMsgBox 0, cm$, c$, MB_OK
 EndOfCode


Code: [Select]
ereh txet retnE
ьседз тскет етидевВ

P.S.: For the first time, I see the SMF software (or the browser??) choke over a UTF-8 string, see the red part above. It works fine in RichMasm, see attached *.asc source. This is a rare type of UTF-8 using 4-byte encoding.

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8435
  • Assembler is fun ;-)
    • MasmBasic
ClearFileCache for timings and benchmarks involving disk I/O
« Reply #18 on: December 24, 2017, 11:07:08 PM »
Just learned a new trick from deltarho[1859] - clear the file cache for better testing:

include \masm32\MasmBasic\MasmBasic.inc         ; download

ClearFileCache MACRO fname
  push ecx
  ClearLastError
  invoke CreateFile, repargA(f$), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN or FILE_FLAG_NO_BUFFERING, 0
  invoke CloseHandle, eax
  pop ecx
ENDM

  SetGlobals f$
  Init
  PrintLine "with file caching, ", Cpu$(), ":"  ; OPT_Arg1 C:\Masm32\MasmBasic\AscUser\FatFile.txt
  Let f$=CL$()
  PrintLine "Reading ", f$
  .if !Exist(f$)
        Let f$="\Masm32\include\Windows.inc"
        MsgBox 0, Cat$("Commandline empty or invalid - using this file now:"+CrLf$+f$), "Hi", MB_OK
  .endif
  For_ ecx=0 To 9
        NanoTimer()
        Recall f$, L$()                                                 ; file to array L$()
        Print Str$("%i strings, ", eax), NanoTimer$()
        NanoTimer()
        Let esi=FileRead$(f$)                                           ; file to buffer esi
        PrintLine Str$("\t%i bytes, ", LastFileSize), NanoTimer$()
  Next
  PrintLine CrLf$, "no caching:"
  For_ ecx=0 To 9

        ClearFileCache f$
        NanoTimer()
        Recall f$, L$()
        Print Str$("%i strings, ", eax), NanoTimer$()

        ClearFileCache f$
        NanoTimer()
        Let esi=FileRead$(f$)
        PrintLine Str$("\t%i bytes, ", LastFileSize), NanoTimer$()
  Next
  Inkey "--- hit any key ---"
EndOfCode


The results are pretty clear - upper half uses the cache, lower half doesn't:
Code: [Select]
with file caching, Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz:
Reading C:\Masm32\MasmBasic\AscUser\FatFile.txt
3038300 strings, 294 ms 404739200 bytes, 209 ms
3038300 strings, 354 ms 404739200 bytes, 237 ms
3038300 strings, 337 ms 404739200 bytes, 231 ms
3038300 strings, 346 ms 404739200 bytes, 229 ms
3038300 strings, 328 ms 404739200 bytes, 235 ms
3038300 strings, 332 ms 404739200 bytes, 229 ms
3038300 strings, 339 ms 404739200 bytes, 236 ms
3038300 strings, 337 ms 404739200 bytes, 238 ms
3038300 strings, 339 ms 404739200 bytes, 237 ms
3038300 strings, 334 ms 404739200 bytes, 239 ms

no caching:
3038300 strings, 4999 ms        404739200 bytes, 4903 ms
3038300 strings, 4998 ms        404739200 bytes, 4938 ms
3038300 strings, 5011 ms        404739200 bytes, 5061 ms
3038300 strings, 5010 ms        404739200 bytes, 4919 ms
3038300 strings, 5002 ms        404739200 bytes, 4897 ms
3038300 strings, 5003 ms        404739200 bytes, 4903 ms
3038300 strings, 5025 ms        404739200 bytes, 4923 ms
3038300 strings, 5016 ms        404739200 bytes, 4921 ms
3038300 strings, 4994 ms        404739200 bytes, 4906 ms
3038300 strings, 5038 ms        404739200 bytes, 4904 ms

Project attached. You can drag any plain text or Unicode file over the exe, but note that on Win7-64, for example, HeapAlloc begins to choke at around 900MB. If you haven't used the file for a while, the very first line will show a higher time - it needs to be cached...

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8435
  • Assembler is fun ;-)
    • MasmBasic
Spreadsheet editor
« Reply #19 on: December 28, 2017, 04:15:40 AM »
Work in progress, an extension of this post.

Fearless and José put me on the right track, see Select a single cell in a listview. So here is the proof that it is indeed possible to use a listview control as a replacement for Excel :icon_mrgreen:

You may have to click two or three times on a cell to select it. Hitting Return does not work. Saving the edits works, provided that you selected another cell before; the resulting temp file will open with your user-defined *.tab viewer, Excel or LibreOffice, whatever. Note that both Excel and OpenCalc are too dumb to recognise that it's a UTF-8 coded *.tab file. RichMasm shows it correctly, though.

The control is Unicode-aware, as you can see in cell R3C1 ;)

P.S.: There is a little mystery about the order of the header columns. I swear it's not my fault.

fearless

  • Member
  • ***
  • Posts: 312
    • LetTheLightIn
Re: Miscellaneous snippets
« Reply #20 on: December 28, 2017, 05:25:03 AM »
return in the listview or return in the editbox doesnt work?

Might be possible to get NM_RETURN and handle last known cell (row,col) to "edit" with the editbox placement. Or maybe some handling of WM_CHAR / WM_KEYDOWN directly in a subclass of listview parent, or NM_RETURN in that subclass. Might require IsDialogMessage in messageloop and handle want all keys or want return thing from dlg message thing (forget exact name of the msg event)
fearless

CM690II Case, HX1000 PSU, Asus Z97, Intel i7-4790K, Seidon 120v Cooler, 16GB DDR3, MSI GTX 980TI

www.LetTheLight.in  My Github  Twitter

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8435
  • Assembler is fun ;-)
    • MasmBasic
Re: Miscellaneous snippets
« Reply #21 on: December 28, 2017, 06:49:10 AM »
Slow down, man :P

Seriously: I will check what is available. Just discovered a very old article: Easy Navigation Through an Editable List Posted by Lee Nowotny on June 19th, 1999 - just a bit over 18 years ago. Good to see that I'm not the first one to attack this. Fortunately I have a nice tool called deb:
Code: [Select]
Event Message
  inc msgCount
  deb 4, "main WndProc", chg:msgCount

With another one for the listview subproc, you can wade through tons of stuff like this:
Code: [Select]
main WndProc    810     WM_NOTIFY: -121
SubListview     811     WM_NOTIFY: -121
main WndProc    813     WM_PARENTNOTIFY
SubListview     817     WM_MOUSEACTIVATE
SubListview     819     WM_LBUTTONDOWN
main WndProc    821     WM_MOUSEACTIVATE
main WndProc    823     WM_NOTIFY: NM_TOOLTIPSCREATED
main WndProc    825     WM_KILLFOCUS
SubListview     826     WM_CAPTURECHANGED
SubListview     827     WM_IME_SETCONTEXT
main WndProc    829     WM_IME_SETCONTEXT
SubListview     832     WM_SETFOCUS
main WndProc    874     WM_NOTIFY: -121
main WndProc    881     WM_NOTIFY: -121
main WndProc    888     WM_NOTIFY: -121
main WndProc    895     WM_NOTIFY: -121
main WndProc    902     WM_NOTIFY: -121
main WndProc    909     WM_NOTIFY: -121
main WndProc    911     WM_NOTIFY: -121
main WndProc    913     WM_NCACTIVATE
main WndProc    915     WM_GETTEXT
main WndProc    917     WM_ACTIVATE
SubListview     918     WM_CAPTURECHANGED
main WndProc    920     WM_ACTIVATEAPP
SubListview     921     WM_KILLFOCUS

I will need SubListview     5030    WM_LBUTTONDOWN, the built-in activation is too clumsy. And there are many more interesting messages to exploit...

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8435
  • Assembler is fun ;-)
    • MasmBasic
Table control
« Reply #22 on: December 29, 2017, 10:40:18 AM »
Playtime :P

The main features are implemented: Loading, editing, navigation and saving. Let me know if it works on your machine.

There will be two ways to create it:

  if 0
       Recall "FatTable.tab", some$(), tab
        GuiControl MyData, "table", y500, h500, some$()
  else
       GuiControl MyData, "table", y500, h500, "FatTable.tab"
  endif


The first one assumes that you have already a two-dimensional array, so you pass it as some$().
The second one simply passed a filename.

Confused source, exe and two other files attached. Extract to a folder and launch the exe.

HSE

  • Member
  • ****
  • Posts: 676
  • <AMD>< 7-32>
Re: Miscellaneous snippets
« Reply #23 on: December 29, 2017, 10:56:12 AM »
Working JJ :t

Still don't work ESC nor Ctrl-Z  :biggrin:

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8435
  • Assembler is fun ;-)
    • MasmBasic
Floating point comparisons
« Reply #24 on: December 29, 2017, 11:08:45 AM »
Still don't work ESC nor Ctrl-Z  :biggrin:

Thanks - it's work in progress and needs a lot of cleanup.

Another topic, floating point comparisons:

include \masm32\MasmBasic\MasmBasic.inc
  SetGlobals REAL10 MyPI=3.141592653589793238, hiPI=3.141592653589793239, loPI=3.141592653589793237
  SetGlobals REAL10 MyPI30=3.141592653589793238e30, hiPI30=3.141592653589793239e30, loPI30=3.141592653589793237e30
  SetGlobals REAL10 MyPIm30=3.141592653589793238e-30, hiPIm30=3.141592653589793239e-30, loPIm30=3.141592653589793237e-30
  Init
  PrintLine Str$("\nPI=%Jf", MyPI), " - top precision:"
  Fcmp hiPI, PI, top
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "hiPi is greater"
  .else
        PrintLine "hiPi is lesser"
  .endif
  Fcmp loPI, PI, top
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "loPi is greater"
  .else
        PrintLine "loPi is lesser"
  .endif

  PrintLine "---- high precision:"
  Fcmp hiPI, PI, hi
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "hiPi is greater"
  .else
        PrintLine "hiPi is lesser"
  .endif

  Fcmp loPI, MyPI, hi
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "loPi is greater"
  .else
        PrintLine "loPi is lesser"
  .endif

  PrintLine Str$("\nPI30=%Jf", MyPI30), " - top precision:"

  Fcmp hiPI30, MyPI30, top
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "hiPi is greater"
  .else
        PrintLine "hiPi is lesser"
  .endif
  Fcmp loPI30, MyPI30, top
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "loPi is greater"
  .else
        PrintLine "loPi is lesser"
  .endif

  PrintLine "---- high precision:"
  Fcmp hiPI30, MyPI30, hi
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "hiPi is greater"
  .else
        PrintLine "hiPi is lesser"
  .endif
  Fcmp loPI30, MyPI30, hi
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "loPi is greater"
  .else
        PrintLine "loPi is lesser"
  .endif

  PrintLine Str$("\nPI-30=%Jf", MyPIm30), " - top precision:"

  Fcmp hiPIm30, MyPIm30, top
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "hiPi is greater"
  .else
        PrintLine "hiPi is lesser"
  .endif
  Fcmp loPIm30, MyPIm30, top
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "loPi is greater"
  .else
        PrintLine "loPi is lesser"
  .endif

  PrintLine "---- high precision:"
  Fcmp hiPIm30, MyPIm30, hi
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "hiPi is greater"
  .else
        PrintLine "hiPi is lesser"
  .endif
  Fcmp loPIm30, MyPIm30, hi
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "loPi is greater"
  .else
        PrintLine "loPi is lesser"
  .endif

  Inkey
EndOfCode


Output (as expected):
Code: [Select]
PI=3.141592653589793238 - top precision:
hiPi is greater
loPi is lesser
---- high precision:
they are equal
they are equal

PI30=3.141592653589793238e+30 - top precision:
hiPi is greater
loPi is lesser
---- high precision:
they are equal
they are equal

PI-30=3.141592653589793238e-30 - top precision:
hiPi is greater
loPi is lesser
---- high precision:
they are equal
they are equal

LiaoMi

  • Member
  • **
  • Posts: 235
Re: Miscellaneous snippets
« Reply #25 on: December 29, 2017, 11:34:53 AM »
Theoretically, if the source code is a template like in Delphi, then it's time to start writing a good decompiler for a MasmBasic  :P

Code: [Select]
PI=3.141592653589793238 - top precision:
hiPi is greater
loPi is lesser
---- high precision:
they are equal
they are equal

PI30=3.141592653589793238e+30 - top precision:
hiPi is greater
loPi is lesser
---- high precision:
they are equal
they are equal

PI-30=3.141592653589793238e-30 - top precision:
hiPi is greater
loPi is lesser
---- high precision:
they are equal
they are equal

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8435
  • Assembler is fun ;-)
    • MasmBasic
Get size of a file over 4 GB
« Reply #26 on: January 05, 2018, 07:15:54 AM »
For syntax and options, see Lof()

include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  .if !Exist("GigaTest.txt")
        Inkey "Are you sure you want to create a 4 GB file in ", CurDir$(), "(y)?", CrLf$
        .if eax=="y"
                ClearLastError
                Open "O", #1, "GigaTest.txt"
                .if eax==INVALID_HANDLE_VALUE
                                Print "Open:  ", Err$()
                .else
                                ClearLastError
                                Let edi=FileRead$("\Masm32\include\Windows.inc")+FileRead$("\Masm32\include\WinExtra.inc")
                                PrintLine Str$("Len=%i bytes\n", Len(edi))      ; 2045966 bytes
                                Print "Read:  ", Err$()
                                ClearLastError
                                For_ ecx=0 To 2500      ; 2501*2045966=5116960966
                                       PrintLine #1, edi
                                Next
                                Print "Write: ", Err$()
                                Close
                .endif
        .endif
  .endif
  Inkey Str$("Filesize = %u bytes", edx::Lof("GigaTest.txt")), Str$(" = %3f GB", edx::Lof("GigaTest.txt")/(1 shl 30))
EndOfCode


Output: Filesize = 5116965968 bytes = 4.77 GB

HSE

  • Member
  • ****
  • Posts: 676
  • <AMD>< 7-32>
Re: Miscellaneous snippets
« Reply #27 on: January 12, 2018, 12:10:41 AM »
Hi JJ!

I extract part of the program. Still not working very well, but the main features are there (I think).

Regards

LATER: New file. I forget a little problem if first column is activated.

A lot later: New file. I forget something else.
« Last Edit: January 13, 2018, 11:18:22 AM by HSE »

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8435
  • Assembler is fun ;-)
    • MasmBasic
Re: Miscellaneous snippets
« Reply #28 on: January 12, 2018, 01:24:04 AM »
Very nice work :t

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8435
  • Assembler is fun ;-)
    • MasmBasic
Send mail with attachments
« Reply #29 on: March 12, 2018, 08:55:41 PM »
Drag files over the exe and tell me how your mail client reacts. I've tested it on Win7-64 and Win10 Home with Thunderbird.

include \masm32\MasmBasic\MasmBasic.inc         ; download
mapiMsg         MapiMessage <>

  Init
  Dll "Mapi32"
  Declare MAPISendMail, 5

  mov edi, offset mapiMsg
  Mapi equ [edi.MapiMessage]
  mov Mapi.ulReserved, CP_UTF8   ; does not work *)
  mov Mapi.lpszSubject, Chr$("Greetings from Masm")
  mov Mapi.lpszNoteText, cfm$("Hi folks,\nNever was sending mails easier!\nSincerely,\njj2007")
  GetFiles CL                           ; get a list of files from the commandline
  mov Mapi.nFileCount, eax
  xchg eax, ecx
  Dim MapiFiles(ecx) As MapiFileDesc
  or MapiFiles(ecx, nPosition), -1
  For_ ecx=0 To ecx-1
        push Files$(ecx)
        lea eax, MapiFiles(ecx, lpszPathName)
        pop [eax]
  Next
  lea eax, MapiFiles(0, ulReserved)
  mov Mapi.lpFiles, eax
  .if MAPISendMail(0, 0, addr mapiMsg, MAPI_DIALOG, 0)
        MsgBox 0, Str$("Mapi error %i", eax), "An error occurred:", MB_OK
  .endif
EndOfCode



Project attached. Note that there is a blank line before the "Hi folks"; in theory, the nPosition member of the MapiFileDesc structure could influence that, but according to this post on ExpertExchange, "It appears that MapiSendMail does not perform as Microsoft has stated in their documentation" 8)

*) MapiMessage structure:

Quote
ulReserved

    Reserved; must be zero or CP_UTF8. If CP_UTF8, the following are UTF-8 instead of ANSI strings: lpszSubject, lpszNoteText, lpszMessageType, lpszDateReceived, lpszConversationID.

And this is simply not true, Redmond - see https://stackoverflow.com/questions/9943314/windows-mapi-unicode-issue  :icon_redface: