Author Topic: Miscellaneous snippets  (Read 7238 times)

FORTRANS

  • Member
  • *****
  • Posts: 1025
Re: Miscellaneous snippets
« Reply #60 on: July 20, 2018, 04:42:33 AM »
Hi Jochen,

   Okay, how about:

Upper left  Resize
Top         Resize
Upper right Resize
Right       Crop
Lower right Crop
Bottom      Crop
Lower left  Resize
Left        Resize
Cropped to maximize, Resize
Maximum to restore, Resize


   More useful I hope?  Or am I still missing things as usual?

Regards,

Steve N.

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8776
  • Assembler is fun ;-)
    • MasmBasic
Re: Miscellaneous snippets
« Reply #61 on: July 20, 2018, 04:53:05 AM »
Your analysis is absolutely correct: XP behaves like that. Those resizing attempts that actually move the window trigger the resizing of the image. All others don't. But I would have to dig deep into the code to find a workaround, and I am not sure if XP is important enough to justify that effort :icon_mrgreen:

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8776
  • Assembler is fun ;-)
    • MasmBasic
Len, wLen, uLen
« Reply #62 on: July 20, 2018, 12:17:04 PM »
include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  Let esi="Нажмите на эту кнопку"              ; "Click on this button" in Russian
  Print Str$("Len(esi)=\t%i\n", Len(esi))      ; treated as Ansi
  Print Str$("uLen(esi)=\t%i\n", uLen(esi))    ; treated as Utf8
  Print Str$("wLen(esi)=\t%i\n", wLen(wRec$(esi)))     ; treated as Unicode (wRec$: convert Utf8 to wide string)
  Print
  Let esi="在這裡輸入文字"                       ; "Enter text here" in Chinese
  Print Str$("Len(esi)=\t%i\n", Len(esi))      ; treated as Ansi
  Print Str$("uLen(esi)=\t%i\n", uLen(esi))    ; treated as Utf8
  Print Str$("wLen(esi)=\t%i\n", wLen(wRec$(esi)))     ; treated as Unicode
EndOfCode


Code: [Select]
Len(esi)=       39
uLen(esi)=      21
wLen(esi)=      21

Len(esi)=       21
uLen(esi)=      7
wLen(esi)=      7

Note that the uLen macro does not check whether the string is valid Utf8 (credits to PaulSquires). Example:

  Let esi="Click on this button"+Chr$(169)      ; Ansi with one extra character
  .if rv(MultiByteToWideChar, CP_UTF8, MB_ERR_INVALID_CHARS, esi, Len(esi), NULL, 0) == 0
        PrintLine "[", esi, "] is not a valid Utf8 string"
  .else
        Print "[", esi, "]", Str$("has %i bytes and is a valid Utf8 string\n", eax)
  .endif


Code: [Select]
[Click on this button©] is not a valid Utf8 string
Len(esi)=       21
uLen(esi)=      21
wLen(esi)=      21

Full project attached.

Antariy

  • Member
  • ****
  • Posts: 544
Re: Miscellaneous snippets
« Reply #63 on: July 21, 2018, 06:53:12 AM »
Hi Jochen

You wondered why strlen for UTF8 should be different proc than regular (single-byte encodings like ASCII/ANSI/ISO/etc) strlen.
Now probably you can review that thread just for fun :biggrin:

http://masm32.com/board/index.php?topic=2369.msg24543#msg24543

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8776
  • Assembler is fun ;-)
    • MasmBasic
Utf8 macros
« Reply #64 on: July 21, 2018, 07:12:05 AM »
Welcome back, my friend! Yes, that thread was interesting - almost 5 years ago. Time flies. In the meantime, I had forgotten that exchange of views, but MasmBasic does have some dedicated macros, like uLen, uLeft$ and uMid$...

Antariy

  • Member
  • ****
  • Posts: 544
Re: Miscellaneous snippets
« Reply #65 on: July 21, 2018, 07:21:32 AM »
Welcome back, my friend! Yes, that thread was interesting - almost 5 years ago. Time flies. In the meantime, I had forgotten that exchange of views, but MasmBasic does have some dedicated macros, like uLen, uLeft$ and uMid$...

Yes, that was purpose of that thread and algo research (making utf8 chars walking faster if possible)... strlen is the simplest usage of that implementation, but more important are string-manipulation functions like basic-like ones you mentioned :biggreen: It is harder to Mid$ something from the random dataflow of utf8 string than from other - fixed-width (length/size) - encodings like ASCII/ANSI/UTF16/32/etc are.

Antariy

  • Member
  • ****
  • Posts: 544
Re: Miscellaneous snippets
« Reply #66 on: July 21, 2018, 07:25:44 AM »
So, you implemented those in your MB project, very cool and nice :T :t

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8776
  • Assembler is fun ;-)
    • MasmBasic
Re: Miscellaneous snippets
« Reply #67 on: July 21, 2018, 07:52:21 AM »
I rolled my own, actually. Your code is too complex for my old brain. But we could organise a speed test ;-)
Code: [Select]
uLen MACRO arg
  push esi
  push edx
  ifdifi <esi>, <arg>
mov esi, repargA(arg)
  endif
  xor edx, edx
  .While 1
lodsb
.Break .if !al
inc edx
.if al>=10000000b ; 128
inc esi
.if al>=11100000b
inc esi
.if al>=11110000b
inc esi
.if al>=11111000b
    inc esi
.endif
.endif
.endif
.endif
  .Endw
  xchg eax, edx
  pop edx
  pop esi
  EXITM <eax>
ENDM

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8776
  • Assembler is fun ;-)
    • MasmBasic
MRU: Most Recently Used
« Reply #68 on: July 25, 2018, 09:30:58 AM »
Attached a little demo project; I'd like to get some feedback on the behaviour of the MRU menu. The archive has source code (*.asc), but it won't build with the current MasmBasic version.

I am testing three macros:
- SetMru "somefile.ini": reads recently used files from disk and adds them to the menu
- AddMru SomeFile$: adds opened or saved filename to the menu
- MenuText$(): returns the full file path in response to a menu event

Finally,

Event Close
  StoreUtf8 Cat$(MbExeFolder$+"\EditorDemo.ini"), Mru$(), 8     ; write up to 8 strings to file


... serves to store the MRU list to disk. Note that only a few functions of the toolbar are actually implemented - use at your own risk, test it with non-important files 8)

This is work in progress, grateful for feedback, especially also from people using non-Latin alphabets.

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8776
  • Assembler is fun ;-)
    • MasmBasic
Input$
« Reply #69 on: July 31, 2018, 10:11:23 AM »
include \masm32\MasmBasic\MasmBasic.inc         ; download
  SetGlobals MyString
  Init
  PrintLine "You can hit keys as you like, but when the countdown approaches zero, you should stop"
  For_ ecx=1000 To 0 Step -1
        Print At(0, 3) Str$(ecx), "   "
        Delay 2
  Next
  Let MyString=Input$("Your hobby: ", "Basic programming (this string is editable)", flush)
  MsgBox 0, MyString, "The string:", MB_OK or MB_SETFOREGROUND
EndOfCode

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8776
  • Assembler is fun ;-)
    • MasmBasic
Creating and erasing a numerical array
« Reply #70 on: August 02, 2018, 06:32:53 PM »
include \masm32\MasmBasic\MasmBasic.inc         ; download
  Init
  N=500000000                           ; 500 Mio
  PrintCpu 0
  For_ outerloop=0 To 5

        NanoTimer()
        Dim MyBytes(N) As BYTE
        PrintLine "allocating took ", NanoTimer$()
       
        NanoTimer()
        For_ ecx=0 To N-1
                mov MyBytes(ecx), cl
        Next
        PrintLine "filling took ", NanoTimer$()
       
        NanoTimer()
        % Erase MyBytes()
        PrintLine "erasing took ", NanoTimer$(), CrLf$
  Next
  Inkey
EndOfCode


Code: [Select]
Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
allocating took 13 µs
filling took 1228 ms
erasing took 40 ms

allocating took 24 µs
filling took 1229 ms
erasing took 40 ms

allocating took 22 µs
filling took 1228 ms
erasing took 38 ms

allocating took 23 µs
filling took 1227 ms
erasing took 37 ms

allocating took 23 µs
filling took 1229 ms
erasing took 38 ms

allocating took 18 µs
filling took 1232 ms
erasing took 40 ms

Writing the bytes to file costs an extra 7-9 seconds:

        NanoTimer()
        Open "O", #1, "MyBytes.dat"
        Store #1, MyBytes()
        Close
        PrintLine "writing took ", NanoTimer$()

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8776
  • Assembler is fun ;-)
    • MasmBasic
Converting a *.csv file to a fixed size file
« Reply #71 on: August 12, 2018, 10:26:55 AM »
Usage: Drag a csv file over the attached exe. The required fixed size is calculated automatically, see results below.

include \masm32\MasmBasic\MasmBasic.inc         ; download
  SetGlobals f$, records, maxcol, record$, endreached   ; see FB thread: CSV to fixlength data files
  Init
  NanoTimer()
  Dim MxLen() As DWORD          ; OxPT_Arg1 J:\Masm32\MasmBasic\BugTests\TableControl\FatTable.csv
  Dim fix$()
  Let f$=CL$()
  .if !Exist(f$)
        GetFiles *.csv
        SortFiles
        Let f$=Files$(0)
  .endif
  Recall f$, L$(), csv
  mov records, eax
  For_ ct=0 To eax-1
        For_ ecx=0 To 99
                xchg Len(L$(ct, ecx)), eax
                .if eax>MxLen(ecx)
                                mov MxLen(ecx), eax
                                Print "*"
                .endif
       Next
  Next
  Print CrLf$, "Length of records: "
  For_ ecx=0 To 127
        mov eax, MxLen(ecx)
        .Break .if !eax
        add esi, eax
        Print Str$(eax), " "    ; record length
  Next
  mov maxcol, ecx
  lea esi, [esi+ecx+1]
  Print Str$("\nLen of full record=%i", esi), Str$(", %i columns", maxcol)
  Let edi=Space$(esi)
ComposeString MACRO maxcol
  mov ecx, maxcol
  Clr endreached
  .Repeat
        lodsb
        .if !al
                inc endreached
        .endif
        .if endreached || !al || !ecx
                mov al, 32
        .endif
        stosb
        dec ecx
  .Until Sign?
ENDM
  For_ ct=0 To records-1
        push edi
        mov esi, L$(ct, 0)
        ComposeString MxLen(0)
        For_ col=1 To maxcol-1
                mov esi, L$(ct, col)
                ComposeString MxLen(col)
       Next
        xor eax, eax
        stosb
        pop edi
        Let fix$(ct)=edi
  Next
  .if Instr_(f$, ".csv", 1)
        mov [eax], Mirror$(".fix")
        PrintLine CrLf$, "Storing to ", f$
        Store f$, fix$()
  .endif
  Inkey "Converting ", f$, " took ", NanoTimer$()
EndOfCode


For a 19MB csv database, the whole process takes about 2 seconds, but the resulting file gets bloated to >100MB:
Code: [Select]
Length of records: 11 646 348 13 141 82 20 4 10 20 4 10 28 4 10 20 4 10 25 4 10 25 4 11 25 4 11 25 4 11 25 4 11 25 4 11 25 4 10 27 4 11 26 4
 11 28 4 11 27 4 11 23 4 11 23 4 15 23 4 15 23 4 15 23 4 15 25 4 15 23 4 15 23 4 11 22 4 10 12 4 6 9 4 4 9 4 4 9 4 4 9 4
Len of full record=2376, 92 columns
Storing to C:\Masm32\MasmBasic\BugTests\TableControl\FatTable.fix
Converting C:\Masm32\MasmBasic\BugTests\TableControl\FatTable.fix took 2367 ms

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8776
  • Assembler is fun ;-)
    • MasmBasic
Subclassing a RichEdit control (dual 64-/32-bit code)
« Reply #72 on: August 12, 2018, 10:16:52 PM »
Numbers only in a RichEdit control (full project attached):
Code: [Select]
SubEdit proc <cb> uses rbx hWnd, uMsg, wParam, lParam ; <cb> indicates that it is a callback function
  mov ebx, wParam ; default: process wParam
  cmp uMsg, WM_CHAR
  jne @F
  cmp wParam, "9"
  jle @F
  Print Str$("char %i not allowed\n", ebx)
  xor ebx, ebx ; don't process
@@: jinvoke CallWindowProc, PreviousWndProc, hWnd, uMsg, ebx, lParam
  ret
SubEdit endp

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8776
  • Assembler is fun ;-)
    • MasmBasic
The console isn't completely dead yet
« Reply #73 on: August 14, 2018, 09:31:20 AM »


Full project attached (the exe includes the fake database). Use cursor up/down to scroll among the records, hit Escape to quit.

Here is the source (50 lines of code):

include \masm32\MasmBasic\MasmBasic.inc         ; symbols
include NewAtMacro.inc
  SetGlobals TopRecord
  Init
  invoke ShowWindow, rv(GetConsoleWindow), SW_MAXIMIZE
  StringToArray 100, d$(), tab
  ConsoleColor cDarkGray, cBlack
  Print 0                               ; override codepage setting
  $Data 11C #, 91C LastName, O1C FirstName, Z1C Street, s1C City, 6+1A ProdCode, A+1A UnitPrice
  Read Header$()       ; create a string array
  invoke SetConsoleOutputCP, 437        ; we need that codepage for the graphic characters
  Print ConvertCp$(ResFile$(101), CP_UTF16, 437)        ; resource 101 (boxes.txt) is Unicode and needs to be converted
  invoke SetConsoleOutputCP, 1252      ; Windows default
  For_ ecx=0 To Header$(?)-1
        xchg Header$(ecx), esi
        Print At(#esi) esi      ; the new At() macro has some goodies... it can set xy and colours based on the start of the string
  Next
  Print At(0, 20) "Use cursor up/down to scroll, Escape to quit"                ; override codepage setting
  .While 1
        m2m ecx, 3              ; start displaying data in row 3
        For_ ct=TopRecord To TopRecord+6
                mov esi, Cat$(Chr$("1", ecx+48, "F ")+Str$("%______i", ct))     ; right-aligned record number
                Print At(#esi) Left$(esi, 19)
                mov esi, Cat$(Chr$("9", ecx+48, "F ")+d$(ct, 0)+String$(20, " "))
                Print At(#esi) Left$(esi, 19)
                mov esi, Cat$(Chr$("O", ecx+48, "F ")+d$(ct, 1)+String$(10, " "))
                Print At(#esi) Left$(esi, 10)
                mov esi, Cat$(Chr$("Z", ecx+48, "E ")+d$(ct, 2)+String$(20, " "))
                Print At(#esi) Left$(esi, 18)
                mov esi, Cat$(Chr$("s", ecx+48, "E ")+d$(ct, 3)+String$(10, " "))
                Print At(#esi) Left$(esi, 10)
                mov esi, Cat$(Chr$("6+", ecx+48, "F9 ")+d$(ct, 4)+String$(10, " "))
                Print At(#esi) Left$(esi, 10)
                mov esi, Cat$(Chr$("A+", ecx+48, "C ")+d$(ct, 5)+String$(9, " "))
                Print At(#esi) Left$(esi, 9)
                add ecx, 2      ; next data two rows down
       Next
        Inkey
        .Break .if eax==VK_ESCAPE
        mov edx, TopRecord
        .if eax==VK_UP
                dec edx
        .elseif eax==VK_DOWN
                inc edx
        .endif
        mov TopRecord, Max(0, edx)
        sub d$(?), 7                   
        mov TopRecord, Min(eax, TopRecord)
  .Endw
EndOfCode
« Last Edit: August 14, 2018, 10:45:22 AM by jj2007 »

jj2007

  • Moderator
  • Member
  • *****
  • Posts: 8776
  • Assembler is fun ;-)
    • MasmBasic
The console isn't completely dead yet (part II)
« Reply #74 on: August 15, 2018, 05:44:43 PM »
How does it work?

mov esi, Cat$(Chr$("z", ecx+48, "EC ")+d$(ct, 3))  ; City: Column z (=10+26+26), row ecx, foregroundcolour E (yellow), bg C (red)
Print At(#esi) Left$(esi, 13, "_")     ; for short strings, fill right half with "_"


esi points to a string with a specific format:
ABCD this is a string

A is the print column, where
0   0
9   9
A   10+0=10
Z   10+25=35
a   10+26+0=36
z   10+26+25=61

B is the print row, using the same scheme.
C and B are the foreground and background colours, with
Code: [Select]
cBlack = 0 ; http://support.microsoft.com/kb/319883
cDarkBlue = 1
cDarkGreen = 2
cDarkCyan = 3
cDarkRed = 4
cDarkMagenta = 5
cDarkYellow = 6
cGray = 7
cDarkGray = 8
cBlue = 9
cGreen = 10 ; A
cCyan = 11 ; B
cRed = 12 ; C
cMagenta = 13 ; D
cYellow = 14 ; E
cWhite = 15 ; F

The attachment contains sources and files to build this; including a new Left$() macro:

Print Left$("some string", 20, "_")  ; prints some string_________

The third optional argument is a fill char for padding the string to the right in case it's shorter than 20 chars. Can be quite useful in some situations, inter alia for overwriting the previous field when filling the screen as shown above. In the attached exe, the Street column does not have padding, and when scrolling through the database you can see the effect.