Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - psilwen

#1
newLISP in the real world / unless bug?
June 01, 2018, 07:20:02 AM
Quotesyntax: (unless exp-condition body)

The statements in body are only evaluated if exp-condition evaluates to nil or the empty list (). The result of the last expression in body is returned or nil or the empty list () if body was not executed.


newLISP v.10.7.3 32-bit on Windows IPv4/6 UTF-8 libffi, options: newlisp -h
> (unless (file? "hello") (make-dir "hello"))
true
> (unless (file? "hello") (make-dir "hello"))
true
> (unless (file? "hello") (make-dir "hello"))
true


newLISP v.10.7.3 32-bit on Windows IPv4/6 UTF-8 libffi, options: newlisp -h
> (when (not(file? "hello")) (make-dir "hello"))
true
> (when (not(file? "hello")) (make-dir "hello"))
nil
> (when (not(file? "hello")) (make-dir "hello"))
nil
#2
newLISP in the real world / It makes me a bit confused
November 09, 2017, 03:21:27 AM
> (struct 'A "char*")
A
> (pack A "HELLO")
"176154d00"
> (unpack A (pack A "HELLO"))
("HELLO")
> (setq a (pack A "HELLO"))
"0154d00"
> (unpack A a)
("06") ; <------------
> (setq b "HELLO")
"HELLO"
> (setq a (pack A b))
"p154d00"
> (unpack A a)
("HELLO")
#4
Thank you for the explanation.

But the struct function used to deal with ordinary C structure is also very useful.



In newLISP, we have two way to deal with C structure.

The first way, with the struct , pack and unpack.

The other way, without the struct, uses only pack and unpack.



But the 'struct' has its advantages.
; typedef struct {
;     unsigned long  Data1;
;     unsigned short Data2;
;     unsigned short Data3;
;     byte           Data4[6];
; } fakeGUID;
(struct 'fakeGUID.Data4 "byte" "byte" "byte" "byte" "byte" "byte")
(struct 'fakeGUID "unsigned int" "unsigned short int" "unsigned short int" "GUID.Data4")

> (pack fakeGUID) ; auto fill with 0 when pack
"00000000000000000000000000000000"
> (length(pack fakeGUID))
16
> (pack fakeGUID.Data4)
"000000000000"
> (length(pack fakeGUID.Data4))
6
> (setq fg (pack fakeGUID 1 2 3 (pack fakeGUID.Data4 4 5 6 7 8 9))) ; structure nested
"010000000200030004050607bt0000" ; structure aligned
> (length fg)
16
> (unpack fakeGUID fg)
(1 2 3 (4 5 6 7 8 9)) ;nested structures are unpacked recursively.

> (setq fakeGUID2 "lu u u bbbbbb")
> (pack fakeGUID2)
""
> (setq fg2 (pack fakeGUID2 0 0 0 0 0 0 0 0 0)) ; we have to give the data explicitly
"0000000000000000000000000000"
> (length fg2)
14

typedef struct
{
  int a1;
  int a2;
  int a3;
  int a4;
}A;
typedef struct
{
  int b1;
  int b2;
  int b3;
  int b4;
}B;
typedef struct
{
  int c1;
  int c2;
  int c3;
  int c4;
}C;
typedef struct
{
  int d1;
  int d2;
  int d3;
  int d4;
}D;
typedef struct
{
  A a[10];
  B b[10];
  C c[10];
  D d[10];
}ABCD;

without the 'struct', how uses only pack and unpack to deal with?



In fact, I'm trying to translate some Win32 C header files into newLISP syntax. There are a lot of C structures in these header files.

In these structures, there are some members that are arrays.

The data structures like these, is not easy to deal with in newLISP, fortunately we have the 'struct' function,

coupled with special treatment, I basically can be directly from the C structure translated into newLISP syntax,

make it becomes easy deal with.



for example
typedef struct {
    unsigned long  Data1;
    unsigned short Data2;
    unsigned short Data3;
    byte           Data4[ 8 ];
} GUID;

typedef struct _NOTIFYICONDATAA
{
    DWORD cbSize;
    HWND hWnd;
    UINT uID;
    UINT uFlags;
    UINT uCallbackMessage;
    HICON hIcon;
    #if (NTDDI_VERSION < NTDDI_WIN2K)
        CHAR szTip[64];
    #endif
    #if (NTDDI_VERSION >= NTDDI_WIN2K)
        CHAR szTip[128];
        DWORD dwState;
        DWORD dwStateMask;
        CHAR szInfo[256];
        union
        {
            UINT uTimeout;
            UINT uVersion; // used with NIM_SETVERSION, values 0, 3 and 4
        } DUMMYUNIONNAME;
        CHAR szInfoTitle[64];
        DWORD dwInfoFlags;
    #endif
    #if (NTDDI_VERSION >= NTDDI_WINXP)
        GUID guidItem;
    #endif
    #if (NTDDI_VERSION >= NTDDI_VISTA)
        HICON hBalloonIcon;
    #endif
} NOTIFYICONDATAA,  *PNOTIFYICONDATAA;

typedef struct _NOTIFYICONDATAW
{
    DWORD cbSize;
    HWND hWnd;
    UINT uID;
    UINT uFlags;
    UINT uCallbackMessage;
    HICON hIcon;
    #if (NTDDI_VERSION < NTDDI_WIN2K)
        WCHAR szTip[64];
    #endif
    #if (NTDDI_VERSION >= NTDDI_WIN2K)
        WCHAR szTip[128];
        DWORD dwState;
        DWORD dwStateMask;
        WCHAR szInfo[256];
        union
        {
            UINT uTimeout;
            UINT uVersion; // used with NIM_SETVERSION, values 0, 3 and 4
        } DUMMYUNIONNAME;
        WCHAR szInfoTitle[64];
        DWORD dwInfoFlags;
    #endif
    #if (NTDDI_VERSION >= NTDDI_WINXP)
        GUID guidItem;
    #endif
    #if (NTDDI_VERSION >= NTDDI_VISTA)
        HICON hBalloonIcon;
    #endif
}NOTIFYICONDATAW,  *PNOTIFYICONDATAW;

HWND, HICON are pointer, they are 32 bit on 32 bit platform, and 64 bit on 64 bit platform.



In newLISP, we can describe it in this way:
(define UINT  "unsigned int")
(define DWORD "unsigned int")
(define WORD  "unsigned short int")
(define BYTE  "byte")
(define CHAR  "char")
(define HANDLE "void*")
(define HWND  HANDLE)
(define HICON HANDLE)

(define (struct-array sym-name str-type len)
(apply struct (cons sym-name (map string (flat (dup (list str-type) len)))))
)

(define (struct* sym-name list-types)
(local (lst type-name type-value var-name)
(setq lst '())
(dolist (type list-types)
(setq type-name (first type))
(setq type-value (if (string? (eval type-name)) (eval type-name) (string type-name)))
(setq var-name (last type))
(if (regex {(w+)[(d+)]} (string var-name))
(extend lst (list (string (struct-array (sym (string sym-name "." $1)) type-value (int $2)))))
(extend lst (list type-value))
)
)
(apply struct (cons sym-name lst))
)
)

(struct* 'GUID '(
    (DWORD Data1)
    (WORD  Data2)
    (WORD  Data3)
    (BYTE  Data4[8])
))

(if UNICODE
(define TCHAR WCHAR)
#else
(define TCHAR CHAR)
)

(struct* 'NOTIFYICONDATA '(
(DWORD cbSize)
(HWND hWnd)
(UINT uID)
(UINT uFlags)
(UINT uCallbackMessage)
(HICON hIcon)
(TCHAR szTip[128])
(DWORD dwState)
(DWORD dwStateMask)
(TCHAR szInfo[256])
(UINT uTimeoutORhVersion)
(TCHAR szInfoTitle[64])
(DWORD dwInfoFlags)
(GUID guidItem)
(HICON hBalloonIcon)
))

this code can run on both newLISP 32-bit and newLISP 64-bit. (Assume we can have more than 32 members in a structure)
newLISP v.10.7.3 32-bit on Windows IPv4/6 UTF-8 libffi, options: newlisp -h
> (length (pack NOTIFYICONDATA))
508

newLISP v.10.7.3 64-bit on Windows IPv4/6 UTF-8 libffi, options: newlisp -h
> (length (pack NOTIFYICONDATA))
528

without the 'struct', processing it will be more complex. may be
(if UNICODE)
(if _WIN64
(setq NOTIFYICONDATAW "lu Lu lu lu lu Lu s256 lu lu s512 lu s128 lu s16 Lu")
#else
(setq NOTIFYICONDATAW "lu lu lu lu lu lu s256 lu lu s512 lu s128 lu s16 lu")
)
#else
(if _WIN64
(setq NOTIFYICONDATAA "lu Lu lu lu lu Lu s128 lu lu s256 lu s64 lu s16 Lu")
#else
(setq NOTIFYICONDATAA "lu lu lu lu lu lu s128 lu lu s256 lu s64 lu s16 lu")
)
)


But when I found that the members of struct restrictions can not exceed 32, the solution has been setbacks.



The IMAGE_VXD_HEADER structure in WinNT.h has 51 members.

The CONTEXT structure in WinNT.h has 208 members. Although this is very rare.
#5
newLISP v.10.7.3 32-bit on Windows IPv4/6 libffi, options: newlisp -h
; 33 "char"
(struct 'abc "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char" "char")
abc
> (pack abc)
"000000000000000000000000000000000000000
0000000000000000000000000"
> (length (pack abc))
32
> (length (pack abc (sequence 1 33)))
32


newLISP v.10.7.3 32-bit on Windows IPv4/6 UTF-8 libffi, options: newlisp -h
> (apply struct (cons 'a  (flat (dup (list "char") 16))))
a
> (length (pack a))
16
> (apply struct (cons 'b  (flat (dup (list "char") 32))))
b
> (length (pack b))
32
> (apply struct (cons 'c  (flat (dup (list "char") 64))))
c
> (length (pack c))
32     ; <-------- why is not 64?
> (apply struct (cons 'd  (flat (dup (list "char") 128))))
d
> (length (pack d))
32     ; <-------- why is not 128?


> (apply struct (cons 'A  (flat (dup (list "unsigned short int") 16))))
A
> (length (pack A))
32
> (apply struct (cons 'B  (flat (dup (list "unsigned short int") 32))))
B
> (length (pack B))
64
> (apply struct (cons 'C  (flat (dup (list "unsigned short int") 64))))
C
> (length (pack C))
64     ; <-------- why is not 128?
> (apply struct (cons 'D  (flat (dup (list "unsigned short int") 128))))
D
> (length (pack D))
64     ; <-------- why is not 256?


> (apply struct (cons 'AA  (flat (dup (list "unsigned int") 16))))
AA
> (length (pack AA))
64
> (apply struct (cons 'BB  (flat (dup (list "unsigned int") 32))))
BB
> (length (pack BB))
128
> (apply struct (cons 'CC  (flat (dup (list "unsigned int") 64))))
CC
> (length (pack CC))
128     ; <-------- why is not 256?
> (apply struct (cons 'DD  (flat (dup (list "unsigned int") 128))))
DD
> (length (pack DD))
128     ; <-------- why is not 512?
#6
newLISP v.10.7.3

newLISP v.10.7.1

newLISP v.10.7.0

All have this issues.



Usually starting from 8, 16, 24, 32...., depending on the version.



But newLISP v.10.6.2,I tested from 1 to 65536, everything was fine.
#7
newLISP v.10.7.3 32-bit on Windows IPv4/6 libffi, options: newlisp -h

> (setq str (dup "00" 8))
"0000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 1))
"00"
> (trim str)
""
> (setq str (dup "00" 2))
"0000"
> (trim str)
""
> (setq str (dup "00" 3))
"000000"
> (trim str)
""
> (setq str (dup "00" 4))
"00000000"
> (trim str)
""
> (setq str (dup "00" 5))
"0000000000"
> (trim str)
""
> (setq str (dup "00" 6))
"000000000000"
> (trim str)
""
> (setq str (dup "00" 7))
"00000000000000"
> (trim str)
""
> (setq str (dup "00" 8))
"0000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 9))
"000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 10))
"00000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 11))
"0000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 12))
"000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 13))
"00000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 14))
"0000000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 15))
"000000000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 16))
"00000000000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 17))
"0000000000000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 18))
"000000000000000000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 19))
"00000000000000000000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 20))
"000000000000000000000000000000000000000
0"
> (trim str)
""
> (setq str (dup "00" 21))
"000000000000000000000000000000000000000
000"
> (trim str)
""
> (setq str (dup "00" 22))
"000000000000000000000000000000000000000
00000"
> (trim str)
""
> (setq str (dup "00" 23))
"000000000000000000000000000000000000000
0000000"
> (trim str)
""
> (setq str (dup "00" 24))
"000000000000000000000000000000000000000
000000000"
> (trim str)
""
> (setq str (dup "00" 25))
"000000000000000000000000000000000000000
00000000000"
> (trim str)
""
> (setq str (dup "00" 26))
"000000000000000000000000000000000000000
0000000000000"
> (trim str)
""
> (setq str (dup "00" 27))
"000000000000000000000000000000000000000
000000000000000"
> (trim str)
""
> (setq str (dup "00" 28))
"000000000000000000000000000000000000000
00000000000000000"
> (trim str)
""
> (setq str (dup "00" 29))
"000000000000000000000000000000000000000
0000000000000000000"
> (trim str)
""
> (setq str (dup "00" 30))
"000000000000000000000000000000000000000
000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 31))
"000000000000000000000000000000000000000
00000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 32))
"000000000000000000000000000000000000000
0000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 33))
"000000000000000000000000000000000000000
000000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim





newLISP v.10.7.3 64-bit on Windows IPv4/6 libffi, options: newlisp -h

> (setq str (dup "00" 8))
"0000000000000000"
> (trim str)
""
> (setq str (dup "00" 1))
"00"
> (trim str)
""
> (setq str (dup "00" 2))
"0000"
> (trim str)
""
> (setq str (dup "00" 3))
"000000"
> (trim str)
""
> (setq str (dup "00" 4))
"00000000"
> (trim str)
""
> (setq str (dup "00" 5))
"0000000000"
> (trim str)
""
> (setq str (dup "00" 6))
"000000000000"
> (trim str)
""
> (setq str (dup "00" 7))
"00000000000000"
> (trim str)
""
> (setq str (dup "00" 8))
"0000000000000000"
> (trim str)
""
> (setq str (dup "00" 9))
"000000000000000000"
> (trim str)
""
> (setq str (dup "00" 10))
"00000000000000000000"
> (trim str)
""
> (setq str (dup "00" 11))
"0000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 12))
"000000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 13))
"00000000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 14))
"0000000000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 15))
"000000000000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 16))
"00000000000000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 17))
"0000000000000000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 18))
"000000000000000000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 19))
"00000000000000000000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 20))
"000000000000000000000000000000000000000
0"
> (trim str)
""
> (setq str (dup "00" 21))
"000000000000000000000000000000000000000
000"
> (trim str)
""
> (setq str (dup "00" 22))
"000000000000000000000000000000000000000
00000"
> (trim str)
""
> (setq str (dup "00" 23))
"000000000000000000000000000000000000000
0000000"
> (trim str)
""
> (setq str (dup "00" 24))
"000000000000000000000000000000000000000
000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 25))
"000000000000000000000000000000000000000
00000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 26))
"000000000000000000000000000000000000000
0000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 27))
"000000000000000000000000000000000000000
000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 28))
"000000000000000000000000000000000000000
00000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 29))
"000000000000000000000000000000000000000
0000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 30))
"000000000000000000000000000000000000000
000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 31))
"000000000000000000000000000000000000000
00000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 32))
"000000000000000000000000000000000000000
0000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 33))
"000000000000000000000000000000000000000
000000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 34))
"000000000000000000000000000000000000000
00000000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 35))
"000000000000000000000000000000000000000
0000000000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 36))
"000000000000000000000000000000000000000
000000000000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 37))
"000000000000000000000000000000000000000
00000000000000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 38))
"000000000000000000000000000000000000000
0000000000000000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 39))
"000000000000000000000000000000000000000
000000000000000000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
> (setq str (dup "00" 40))
"000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0"
> (trim str)
""
> (setq str (dup "00" 41))
"000000000000000000000000000000000000000
0000000000000000000000000000000000000000
000"
> (trim str)
""
> (setq str (dup "00" 42))
"000000000000000000000000000000000000000
0000000000000000000000000000000000000000
00000"
> (trim str)
""
#8
newLISP v.10.7.1 32-bit on Windows IPv4/6 UTF-8 libffi, options: newlisp -h

> (setq str (dup "00" 10))
"00000000000000000000"
> (trim str)
""
> (setq str (dup "00" 31))
"000000000000000000000000000000000000000
00000000000000000000000"
> (trim str)
""
> (setq str (dup "00" 32))
"000000000000000000000000000000000000000
0000000000000000000000000"
> (trim str)

ERR: not enough memory in function trim
#9
newLISP in the real world / Re: Is this newLISP's bug?
August 14, 2017, 09:41:44 AM
I found the reason for the problem!



The descriptions for the hWnd parameter of GetMessage:


QuoteA handle to the window whose messages are to be retrieved. The window must belong to the current thread.

If hWnd is NULL, GetMessage retrieves messages for any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL. Therefore if hWnd is NULL, both window messages and thread messages are processed.


The IME window belong to the current thread, but it's messages doesn't retrieved and processed, so it's hangs!



So, just change hwnd to 0 on it. It will be able to work as expected.



(GetMessage msg hwnd 0 0)  ==> (GetMessage msg 0 0 0)



Thanks everybody.
#10
newLISP in the real world / Is this newLISP's bug?
August 11, 2017, 05:50:30 AM
I created an edit window using following code:


(define (import-list library flist)
    (dolist (fname flist) (import library (string fname))))

(define-macro (@setq %var %value)
    (set %var (eval %value))
    (println %var " " (eval %var)))

; Constants
(define IDC_TEXTBOX   1000)
(define IDC_ARROW 0x7F00)
(define COLOR_WINDOW 5)

; Window Messages
(define WM_CREATE  1)
(define WM_DESTROY 2)
(define WM_SIZE    5)

; Window Styles
(define WS_CHILD            0x40000000)
(define WS_VISIBLE          0x10000000)
(define WS_VSCROLL          0x00200000)
(define WS_OVERLAPPEDWINDOW 0xCF0000)

; Class styles
(define CS_VREDRAW          0x0001)
(define CS_HREDRAW          0x0002)

; ShowWindow constant
(define SW_SHOWDEFAULT 10)
(define SW_HIDE 0)
(define SW_SHOW 5)

; Edit control
(define ES_MULTILINE        0x0004)
(define ES_AUTOVSCROLL      0x0040)

; CreateWindowEx
(define CW_USEDEFAULT       0x80000000)

(import-list "kernel32" '(GetModuleHandleA))
(import-list "user32" '(PostQuitMessage DefWindowProcA))
(import-list "user32" '(RegisterClassA CreateWindowExA))
(import-list "user32" '(ShowWindow UpdateWindow MoveWindow DestroyWindow))
(import-list "user32" '(GetMessageA TranslateMessage DispatchMessageA))
(import-list "user32" '(LoadCursorA GetClientRect))


(@setq hInstance (GetModuleHandleA 0))
(@setq hTextbox nil)
(@setq hCursor (LoadCursorA 0 IDC_ARROW))

(struct 'RECT "long" "long" "long" "long")

(define (CreateTextBox hWnd)
(let (r (pack RECT))
(GetClientRect hWnd r)
(setq r (unpack RECT r))
(CreateWindowExA
0
"Edit"
""
(| WS_VISIBLE WS_CHILD WS_VSCROLL ES_MULTILINE ES_AUTOVSCROLL)
50 50 (r 2) (r 3)
hWnd
IDC_TEXTBOX
hInstance
0
))
)

(define (OnCreate hwnd wparam lparam)
(setq hTextbox (CreateTextBox hwnd))
)
(define (OnSize hwnd wparam lparam)
(let (rc (pack RECT))
(GetClientRect hwnd rc)
(setq rc (unpack RECT rc))
(MoveWindow hTextbox (rc 0) (rc 1) (rc 2) (rc 3) 1)
)
)

(define (OnDestroy)
(println "destroyed")
(PostQuitMessage 0)
)

(define (window-callback-function hwnd message wparam lparam)
(cond
((= message WM_CREATE) (OnCreate hwnd wparam lparam) 0)
((= message WM_SIZE)        (OnSize hwnd wparam lparam)   0)
((= message WM_DESTROY)     (OnDestroy)                   0)
(true (DefWindowProcA hwnd message wparam lparam))))

(setq wndproc (callback 0 'window-callback-function))
(setq classname "newlisp class")

(setq wc (pack (dup "ld" 10)
(| CS_HREDRAW CS_VREDRAW)   ; style
wndproc                     ; lpfnWndProc
0                           ; cbClsExtra
0                           ; cbWndExtra
hInstance                   ; hInstance
0                           ; hIcon
hCursor                     ; hCursor
(+ COLOR_WINDOW 1)          ; hbrBackground
0                           ; lpszMenuName
classname                   ; lpszClassName
))

(@setq hwc (RegisterClassA wc))
(@setq hwnd (CreateWindowExA
0                       ; dwExStyle
"newlisp class"         ; lpClassName
"newlisp Edit Control Test"        ; lpWindowName
WS_OVERLAPPEDWINDOW     ; dwStyle
CW_USEDEFAULT CW_USEDEFAULT CW_USEDEFAULT CW_USEDEFAULT           ; x y w h
0                       ; hwndParent
0                       ; hMenu
hInstance               ; hInstance
0                       ; hParam
  ))

(ShowWindow hwnd SW_SHOWDEFAULT)
(UpdateWindow hwnd)

(setq msg (pack "n28"))

(until (member (GetMessageA msg hwnd 0 0) '(0 -1))
(TranslateMessage msg)
(DispatchMessageA msg))

(println "the end")

(exit)


It's no probrem when typing english text, but when i press CTRL + SPACE switch to Chinese IME, and typing something,

appears three window: a IME status bar at bottom left corner of the screen, a small IME input window and an IME candidate window that following the caret.



The small IME input window and the IME status bar is blank. (It's not the right situation)



The candidate window shows what it should display, but when i choose one from the candidate list by clicked it, it's caused newlisp hangs.



In addition, you can not use CTRL + SHIFT to switch between different input methods.



My test environment is Windows 7 Ultimate 64 bit.



It's also has this issues on Windows XP SP3 32bit.



I guess this problem also exists in the Japanese IME case.



I captured the picture and recorded to video, hoping to describe the problem clearly.



The behaviors of edit window with IME, in normal case.

snapshot: http://upgrade99.byethost7.com/newlisp/normal.png">http://upgrade99.byethost7.com/newlisp/normal.png

demo: http://upgrade99.byethost7.com/newlisp/good.wmv">http://upgrade99.byethost7.com/newlisp/good.wmv



In the case that the edit window created from newlisp.

snapshots: http://upgrade99.byethost7.com/newlisp/hangs.png">http://upgrade99.byethost7.com/newlisp/hangs.png

demo: http://upgrade99.byethost7.com/newlisp/hangs.wmv">http://upgrade99.byethost7.com/newlisp/hangs.wmv



I found a link that describes the fault that is very similar to this. at https://bugs.chromium.org/p/chromium/issues/detail?id=402782">//https://bugs.chromium.org/p/chromium/issues/detail?id=402782
#11
Whither newLISP? / why setf don't work?
August 01, 2017, 08:03:04 AM

newLISP v.10.7.1 32-bit on Windows IPv4/6 UTF-8 libffi, options: newlisp -h

> (struct 'RECT "long" "long" "long" "long")
RECT
> (unpack RECT (pack RECT 1 2 3 4))
(1 2 3 4)
> ((unpack RECT (pack RECT 1 2 3 4)) 0)
1
> (setf ((unpack RECT (pack RECT 1 2 3 4)) 0) 5)

ERR: symbol is protected : RECT
> (setq r (unpack RECT (pack RECT 1 2 3 4)))
(1 2 3 4)
> (setf (r 0) 5)
5
> r
(5 2 3 4)


why setf do in-place modifying don't work?

but

> (setf ('(1 2 3 4) 0) 5)
5
> (setf ((list 1 2 3 4) 0) 5)
5
#12
Quote from: "rickyboy"
Are you suggesting that newLISP allow the user to enter a number of arbitrary length (as input) and then parse and store the internal representation of the number (as an exact representation of the input, i.e. arbitrarily large)?



AFAIK, no programming language allows this.  There are always limits.


I certainly know that.



What I mean is



> newlisp
newLISP v.10.6.2 32-bit on Win32 IPv4/6 UTF-8, options: newlisp -h

> 12345678901234567890123456789012345678909999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999
999999999999999999.123456789
1.23456789012346e+255
123456789

> (string 123456789012345678901234567890123456789099999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999
99999999999999999999999999.123456789)
"1.23456789012346e+255123456789"


This result is very weird, counterintuitive.



Users never expecting completely legal a single decimal number (it only consists of digits and a single dot)  is parsed into multiple number.



The limits from 32 extended to 255, just cover up the issue, but does not really solve it.



In Python



>>> a = 111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999
        111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999
        111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999
        111111111122222222223333333333444444444.987654321
>>> a
1.1111111112222222e+308

>>> str(a)
'1.11111111122e+308'


When the number exceeds the limit



>>> b = 111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999
        111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999
        111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999
        1111111111222222222233333333334444444445.987654321
>>> b
inf


it evaluated to inf, not two values 1.1111111112222222e+308  and  987654321.



AND



>>> str(b)
'inf'


it evaluated to 'inf', not the string '1.1111111112222222e+308987654321'.



Python's behavior is reasonable, newLISP is not. I think.



This is my opinion.



Thank you for attention.
#13
Quote
In version 10.6.2 up to 255 characters will be parsed in decimal numbers


This can not completely solve the problem.



Core of these issues is not the right way to parse.



When the number exceeds 255 characters, the same issue will appear again.
#14
Quote
only 32 characters are parsed for decimal number including a potential sign and the decimal point.



> (length "1234567890123456789012345678901234567890.0")
42
> 1234567890123456789012345678901234567890.0
1.23456789012346e+039
0

It actually stops parsing at the first non-numeric department.


Quote
The rest of the source will be parsed as a different number


This strategy has the potential problems, it is easy to confusing.



Reported it as an error might be better.



At least we knows the error, rather than face the wrong results puzzled.





> (/   1234567890123456789012345678901234567890     123456)
10000063910409026608770296128995225L
> (/   1234567890123456789012345678901234567890.0   123456)

ERR: division by zero in function /

> (div 1234567890123456789012345678901234567890     123456)
1.0000063910409e+034
> (div 1234567890123456789012345678901234567890.0   123456)
inf
> (div 2   0)
inf



> (%   10000000000000000000000000000000000000000000000.0 10)

ERR: division by zero in function %
> (mod 10000000000000000000000000000000000000000000000.0 10)
nan
> (%   10000000000000000000000000000000000000000000000 10)
0L
> (mod 10000000000000000000000000000000000000000000000 10)
8
#15
I want convert big float point number to integer.

> (int 999999999999999999999999999999999999999999.99)
9223372036854775807


I tried

> (bigint 999999999999999999999999999999999999999999.99)
1000000000000000045259160000000000000000000L


because of
Quote
When converting from floating point, rounding errors occur going back and forth between decimal and binary arithmetic.


And



> (bigint "1234567890123456789012345678901234567890.123456789")
1234567890123456789012345678901234567890L


this is what i expected



it means that needs to be converted to a string first



But,

> (bigint (string 1234567890123456789012345678901234567890.123456789))
1L

> (string 1234567890123456789012345678901234567890.123456789)
"1.23456789012346e+039123456789"


not "1234567890123456789012345678901234567890.123456789"



and also, the result is incorrect!



Distinctly, literal 1234567890123456789012345678901234567890.123456789 to be parsed as two parts "1234567890123456789012345678901234567890." and "123456789"



> 1234567890123456789012345678901234567890.123456789
1.23456789012346e+039
123456789


More tests

> (setq d 1234567890123456789012345678901234567890.123456789)

ERR: missing argument in function setf




> 100000000000000000.9876543210123456789
1e+017
456789

> (length "100000000000000000.9876543210123")
32

> 1000000000000000000.9876543210123456789
1e+018
3456789
> 10000000000000000000.9876543210123456789
1e+019
23456789
> 100000000000000000000.9876543210123456789
1e+020
123456789
> 1000000000000000000000.9876543210123456789
1e+021
342391             <----- Where it comes
89
> 10000000000000000000000.9876543210123456789
1e+022
10123456789
> 100000000000000000000000.9876543210123456789
1e+023
210123456789
> 1000000000000000000000000.9876543210123456789
1e+024
3210123456789
> 10000000000000000000000000.9876543210123456789
1e+025
43210123456789
> 100000000000000000000000000.9876543210123456789
1e+026
543210123456789
> 1000000000000000000000000000.9876543210123456789
1e+027
6543210123456789
> 10000000000000000000000000000.9876543210123456789
1e+028
76543210123456789
> 100000000000000000000000000000.9876543210123456789
1e+029
876543210123456789
> 1000000000000000000000000000000.9876543210123456789
1e+030
9876543210123456789L

> 10.1234567890123456789012345678901234567890
10.1234567890123
342391                  <----- Where it comes
890


Does considered support bigdecimal feature?