March 28, 2024, 08:48:52 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Buffer size

Started by aurelCB, December 08, 2009, 12:30:20 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

aurelCB

Hi guys...
Maby i miss something here on forum but is there a chance to increase size of buffer
for edit control or RTF or even scintilla that i can load larger file then 64kb?
I use classic way:

def buffer[65536] : ISTRING
...
...
...
filename = FILEREQUEST("Load file",w1,1,filter,"txt")
'filename = filerequest("Load File",win,1):'doopen
if(len(filename) > 0)
buffer = ""
if( openfile(file1,filename,"R") = 0)
do
if(read(file1,ln) = 0)
if len(buffer) < (65536-257)
buffer = buffer + ln + chr$(13) + chr$(10)
endif
endif
until eof(file1)
closefile file1
setcontroltext w1,1,buffer
endif
endif

aurelCB

I find this post where Paul says:
QuoteAn actual read/write from an edit control to a file in a commercial application would never use a hard coded buffer limited to 32K like that.   Instead a dynamic buffer, allocated in memory, is commonly used to read the file once the length of the file is determined.  Writing depends on where the data is coming from.

Paul.

So is there any example or suggestion how load file to memory and then this file load to edit control ?

aurelCB

I also find this part of code from sapero eblexer.
is this right way for load file biger then 32kb?

if (p)
int filesize = GetFileSize(hFile, 0)
pointer text = new(char, filesize+1)

if (!text)
DestroyWindow(*p.win.hwnd)
else
ReadFile(hFile, text, filesize, &filesize, 0)
_SendMessage(*p.hwndSci, SCI_SetText, 0, text)
delete text

sapero

In Creatine you need to trick out the compiler - load the file into memory, then instead SetControlText use a raw api function:declare "user32", SetDlgItemTextA(win:int,id:int,text:memory)
def d1:dialog
DIALOG d1,0,0,542,323,0x80CA0080,0,"Caption",Handler
CONTROL d1,"E,Edit1,9,9,526,305,0x50B010C4,1000"
domodal d1

sub Handler
select @class
case @idinitdialog
def hFile:bfile
def text:memory
def size:int
def zero:char
if( openfile(hFile,"c:\windows\WindowsUpdate.log","R") = 0) ' open a >1MB file
size = len(hFile)
allocmem text,size+1,1
zero=0
writemem text,size+1,zero ' do I need this?
read hFile,text
SetDlgItemTextA(d1,1000+2024,text)
freemem text
closefile hFile
endif
case @idclosewindow
closedialog d1
endselect
return

aurelCB

Thank you very much Sapero  :)
It works perfectly with edit,richedit and with scintilla control.
here is code for richedit + scintilla:

CASE 7:'OPEN-------------- by sapero -----------------
def hFile:bfile
def htext:memory
def hsize:int
def zero:char
filename = FILEREQUEST("Load file",w1,1,filter,"abp")

IF( openfile(hFile,filename,"R") = 0): ' open a >1MB file
hsize = len(hFile)
Allocmem htext,hsize+1,1
zero=0
Writemem htext,hsize+1,zero :' do I need this?
Read hFile,htext
SetDlgItemTextA(w1,1+2024,htext)
'SendMessage(w1,SCI_CLEARALL,0,0,IDC_SCI)
SetDlgItemTextA(w1,IDC_SCI+2024,htext)
Freemem htext
closefile hFile
ENDIF


Just one thing(if is not problem).
Is the same method when i want save file to disk from this controls?

sapero

To save, use the memory again, but query the required size from control:declare "user32", GetDlgItemTextA(win:int,id:int,text:memory,size:int)
const WM_GETTEXTLENGTH = 0x000E

size = SendMessage(d1, WM_GETTEXTLENGTH, 0, 0, ID)
allocmem text,size+1,1
GetDlgItemTextA(d1, ID+2024, text, size+1)
openfile(hFile, PATH, "W")
write hFile,text
closefile hFile
freemem text

Note: file size will be size+1

aurelCB

Hi again ...
It seems that i do something wrong.
Loading part work perfectly but when i want save file i get saved file with biger size?
I think that is problem in two controls.
Let me explain.
I have richedit control with ID = 1 and scintilla control with ID = IDC_SCI .
So i want before saving file on disk that i can read text from scintilla control and this text (content of
sci control) add to richedit.Then that text from richedit save on disk.
I hope that you understand what i need.
Here is my code which loadad file 163 kb is later saved with size of 3.36MB ::)
CASE 6:'SAVE----------------by sapero --------------------------
   filename = FILEREQUEST("Save file",w1,0,filter,"yab")
   
    if(len(filename) > 0)
     
    hsize = SendMessage(w1, WM_GETTEXTLENGTH, 0, 0,IDC_SCI)
Allocmem htext,hsize+1,IDC_SCI
zero=0
Writemem htext,hsize+1,zero
GetDlgItemTextA(w1, IDC_SCI+2024, htext, hsize+1)
' Openfile(hFile, filename, "W")
'Read hFile,htext
READMEM htext, hsize+1,zero
SetDlgItemTextA(w1,1+2024,htext)
freemem htext

Allocmem htext,hsize+1,IDC_SCI
GetDlgItemTextA(w1, 1+2024, htext, hsize+1)
Openfile(hFile, filename, "W")
Write hFile,htext
Closefile hFile
Freemem htext
         
    Endif

sapero

I think you do not understand all the code. Strings are null-terminated, but not files.

When you read text from a file and want the text display in a control, you need first to allocate one more byte than file size, read the file, and terminate it with zero character. If ALLOCMEM returns zero-initialized memory, the zero character is already there, else you need the 'zero' variable and WRITEMEM.
Example: having a file with "abcd" string, LEN(file) returns 4, you allocate 4+1 bytes of memory, then read the file to memory. It will be stored at offsets 0,1,2 and 3, but the last (additional) memory byte can be undefined, so you need to put a zero there before passing it to a control.

When you save a text file, you need to allocate a memory buffer for text (WM_GETTEXTLENGTH bytes) plus one character (zero). After calling GetDlgItemText, the string in your buffer IS already zero terminated, so you need only to write it to file, without writemem. GetDlgItemText and other text-functions always terminate the string with NULL (if the size-of-buffer parameter is zero, the function quits without modifying your buffer).

Another note: if you copy text from a control more than one time, you should call WM_GETTEXTLENGTH more times if you want the buffer correctly sized. SetDlgItemText in your example can copy less than hsize characters, or can add additional characters, so you need to refresh the hsize variable before next ALLOCMEM:
' copy text from scintilla to richedit
hsize = SendMessage(scintilla, WM_GETTEXTLENGTH)
memory = allocate(hsize+1)
GetDlgItemText(scintilla, memory, hsize+1) /* scintilla -> memory */
SetDlgItemText(richedit, memory) /* memory -> richedit */
free memory

' copy text from richedit to file?
' actualize hsize
hsize = SendMessage(richedit, WM_GETTEXTLENGTH)
memory = allocate(hsize+1)
GetDlgItemText(richedit, memory, hsize+1)
...

Note it as a gold-rule: call WM_GETTEXTLENGTH always before allocmem+GetDlgItemText

aurelCB

Hmm OK i know that i dont understand how things work properly but i try this
and still saved file is biger then original.I use your method:
CASE 6:'SAVE----------------by sapero --------------------------
   filename = FILEREQUEST("Save file",w1,0,filter,"yab")
   
    if(len(filename) > 0)
      hsize=0
    hsize = SendMessage(w1, WM_GETTEXTLENGTH, 0, 0,IDC_SCI)
Allocmem htext,hsize+1,IDC_SCI
GetDlgItemTextA(w1, IDC_SCI+2024, htext, hsize+1)
Openfile(hFile, filename, "W")
Write hFile,htext
Closefile hFile
Freemem htext
     

      'IF len(filename)>0
      'ENABLECONTROL w1, 19,1
      'loadtext=1
      'ENDIF 
     Endif


This time is is only from scintilla and resulting file is grove up from 163kB to 3.36MB.
When i load new file file is the same, weird... 

sapero

Then instead WM_GETTEXTLENGTH, try with SCI_GETTEXTLENGTH (2183).
QuoteThe following messages are currently supported to emulate existing Windows controls, but they will be removed in future versions of Scintilla. If you use these messages you should replace them with the Scintilla equivalent
...
WM_GETTEXTLENGTH
...

aurelCB

Yes of course i try with SCI_GETTEXTLENGTH but resulting  file is still to big.
Maby is this some kind of bug ???

aurelCB

This code is modifayed from Pure Basic example for scintilla save file.
But again same thing - saved file is bigger then original.
PB code
If filename <> ""
        file.l = CreateFile(#PB_Any, filename)
        If file <> 0
            len.l = Scintilla(sciptr, #SCI_GETLENGTH) + 1
            *mem = AllocateMemory(len)
            If *mem
                Scintilla(sciptr, #SCI_GETTEXT, len, *mem)
                WriteData(file, *mem, len)
                FreeMemory(*mem)
            EndIf
            CloseFile(file)
        EndIf
    EndIf


And here is Creative code:
if(len(filename) > 0)
     hsize=0
hsize = SendMessage(w1, SCI_GETTEXTLENGTH, 0, 0,IDC_SCI)
'SetDlgItemTextA(w1,1+2024,scitext)
Allocmem htext,hsize+1,IDC_SCI
SendMessage(w1,SCI_GETTEXT,hsize+1,htext,IDC_SCI)
Openfile(hFile, filename, "W")
Write hFile,htext,hsize
Freemem htext
Closefile hFile
'Freemem htext
         
    Endif

aurelCB

Hi...
I hope that i finaly fix this problem with biger result file.
HoW?
We all sometimes forget read manual ::)
In CB manual fine says:
QuoteALLOCMEM (variable, count, size)
and i constantly use
Allocmem htext,hsize+1,IDC_SCI
In my case IDC_SCI is 24 and i have loaded file with 163 k.
So i try count 163 * 24 which is 3912 ha similiar with 3.38MB which i recive as result file.
Eh i constatly push number 24 in size ... ::)
Then i write Allocmem in this way:
Allocmem htext,1,hsize+1
so count is 1 and hsize is in place where size must be.
Both of us (me and spero )miss this thing...
Finaly this is code for saving file in same size:

If(len(filename) > 0)
     hsize=0
hsize = SendMessage(w1, SCI_GETTEXTLENGTH, 0, 0,IDC_SCI)
'SetDlgItemTextA(w1,1+2024,scitext)
Allocmem htext,1,hsize+1
SendMessage(w1,SCI_GETTEXT,hsize+1,htext,IDC_SCI)
Openfile(hFile, filename, "W")
Write hFile,htext,hsize
Freemem htext
Closefile hFile     
    Endif


all best
Aurel