You are not logged in.
I was only thinking of implementing the client side of Sample 4
Out of interest I've just had a go with compiling mormot with Lazarus on a Mac which wasn't completely successful. Here's a bit of feedback:
1. Could {$I Synopse.inc} be put before the comment block of source files. Otherwise if delphi mode isn't already set the compiler gets confused by comment nesting.
2. It makes use of the libC unit which hasn't been ported to osx. see http://wiki.freepascal.org/libc_unit
3. The uses clause at line 540 of SynCommons: SynLz should be SynLZ
4. TWindowsVersion type is not defined (at line 8057 of SynCommons).
It would be great if mac compatibility was there - at least enough to build an http client like in Sample 4.
What I'm aiming for is a PDF with a set of reports with their original page numbers. Would it be possible to use
property Pages: TGDIPageContentDynArray read fPages;to copy between two TGDIPages which are created at the same time. One would make all the sub-reports and the other would copy these as they are made and create a combined report at the end?
I want to create a report which is a concatenation of other reports and get the footer page numbering as shown in the original concatenated report ('Page #/#'). It doesn't seem that easy to do. Would one way be to add two private TIntegerDynArray variables to TGDIPages which parallel fPages in size? A 'ResetPageCount' function could be added to manage these new variables and then when EndDoc is called they would be used to build the footer page number text.
Instead you could use a TPdfImage object which has a CreateJpegDirect constructor.
Then you can do TPdfDocument.Canvas.DrawXObject
This should also mean that there's no need to uncompress the jpeg file.
Could there be a way of disabling TSQLTableToGrid.DrawGridKeyDown? At the moment it changes the sort order if the left or right arrow keys are pressed but if goRowSelect isn't defined it would be better to allow the default handling of changing the selected cell.
Thanks, removing the option worked ![]()
If a TSQLTableToGrid.drawgrid has lots of columns and is scrolled right selecting a row causes the horizontal scrollbar to jump back to the left.
I've found a solution on StackOverflow saying that it is caused by goRowSelect being in the DrawGrid options:
http://stackoverflow.com/questions/3355 … 404#336404
Is goRowSelect absolutely necessary for TSQLTableToGrid to work?
From my point of view the official "backup API" looks best. The link above gives an example of a non-blocking way of using it at the bottom of the page. It warns that a large number of writes may stop a backup ever finishing but that is only if multiple threads are used and as mORMot only uses a single thread to access SQLite that shouldn't matter.
Not so concerned about solutions for dbs other than SQLite.
I'm trying to set up a backup system using TSQLRestServer.OnUpdateEvent
The update event checks a timestamp of when the server started and makes a backup if it hasn't been done recently. The problem is this falls over if a transaction is active with the error 'a vacuum can't be done inside a transaction' (using SQLite).
Would it be better to create a service on the server which gets triggered/co-ordinated on the client side instead of using OnUpdateEvent?
with SQLite I've found that in order to combine MATCH queries UNION has to be used instead of OR. This has the side affect that the field names returned to TSQLTable also include the table name in the form: tableName.fieldName which breaks TSQLTable.IDColumnHide.
I can get round this by using 'select ... as ...' but would it be worth putting in a feature request for the IsRowID function to be extended to handle these cases?
Hi, I've got a problem with setting
CanSelect := False; within a TSQLTableToGrid.OnSelectCell procedure when onIdle is set.
If TSQLTableToGrid.OnSelectCell contains these lines
TSQLHttpClient(Database).ServerTimeStampSynchronize;
CanSelect := False;it is still possible to select rows by clicking but not by pressing the up and down keyboard buttons. If TSQLRestClientURI.onIdle is nil or the database call in onSelectCell is removed it works - ie clicking on a row doesn't select it. Any ideas where this is going wrong? Thanks
My network can be somewhat unreliable at times (I suspect a DNS problem but don't control the network).
If I set the DB.WinAPI.ConnectTimeout after DB.ServerTimeStampSynchronize; It can take 21 seconds before I get a timeout error (code 12002) but this is intermittent. (Also I find that the maximum timeout I can set is 21 seconds which maybe to do with Windows 7)
So ideally I would like to set DB.WinAPI.ConnectTimeout before DB.ServerTimeStampSynchronize; to avoid a possible 21 second wait.
Yes, I was trying to find a shortcut but now see this isn't so ok.
I've got a connected problem. I'm trying to set TSQLHttpClient.WinAPI.ConnectTimeout before a connection is made but get an AV as WinAPI is only created the moment the first connection is made. Is there a way round this? My test code is:
DB := TSQLHttpClient.Create('192.168.99.99', '80', TSQLModel.Create([]));//non-existant server
DB.WinAPI.ConnectTimeout := 5000;
DB.ServerTimeStampSynchronize;Thanks also for this.
I was using using the new OnIdle event to catch exceptions, checking the LastErrorCode when ElapsedMS = -1.
This doesn't seem possible with the latest implementation. Is there another way to globally check the LastErrorCode?
I'm trying to create an audit trail like in the MainDemo but I would also like to track the TSQLAuthUser ID as well.
Can this be done currently?
The implementation in the MainDemo seems to rely on:
TNotifySQLEvent = function(Sender: TSQLRestServer; Event: TSQLEvent;
aTable: TSQLRecordClass; aID: integer): boolean of object;Would this also need the TSQLAuthUser record ID passed to implement this?
Thanks for implementing the onSort event. It all seems to work fine ![]()
I had a similar problem and it seems TDateTimePicker.Date also includes a time part.
Try: trunc(myTDateTimePicker.Date)
Could goFixedRowClick be added to the drawgrid options which get set by TSQLTableToGrid.Create?
I'm trying to get multicoloured per row font and background colours with a TSQLTableToGrid.
To do this I'm using two dynamic arrays of TColor which are initialised immediately after the TSQLTable is created based on an enumerated field. When onBackground is called this array is used to fillrect the background colour and set the font colour. This works but fails when a TSQLTableToGrid drawgrid gets sorted by a click on the header. To solve this I added an onAfterSort TNotifyEvent called at the end of TSQLTableToGrid.SortForce routine. This event then reinitialised the colour arrays.
Does this seem a practical way to do it? If so I'll add a feature request for an onAfterSort event.
Could FieldLengthMax be changed so that with sftEnumerate it gives the max caption length, like below?
function TSQLTable.FieldLengthMax(Field: integer; NeverReturnsZero: boolean): cardinal;
var i: integer;
len: cardinal;
U: PPUTF8Char;
begin
result := 0;
if (self<>nil) and (cardinal(Field)<cardinal(FieldCount)) then begin
if not Assigned(fFieldType) then
InitFieldTypes;
if fFieldType[Field].ContentType = sftEnumerate then begin
for i := 0 to PEnumType(fFieldType[Field].EnumTypeInfo)^.MaxValue do begin
len := length(PEnumType(fFieldType[Field].EnumTypeInfo)^.GetCaption(i));
if len > result then
result := len;
end;
end else begin
U := @fResults[FieldCount+Field]; // start reading after first Row
for i := 1 to RowCount do begin
len := StrLen(U^);
if len>result then
result := len;
inc(U,FieldCount);
end;
end;
end;
if (result=0) and NeverReturnsZero then
result := 1; // minimal not null length
end;Another option could be to draw the barcode directly without using a font. I've pulled out of an old project my attempt at 'interleaved 2 of 5' below which might be helpful.
type
TBarCodeWidths = array[0..4] of shortint;
const
bar0 : TBarCodeWidths = (10,10,30,30,10);
bar1 : TBarCodeWidths = (30,10,10,10,30);
bar2 : TBarCodeWidths = (10,30,10,10,30);
bar3 : TBarCodeWidths = (30,30,10,10,10);
bar4 : TBarCodeWidths = (10,10,30,10,30);
bar5 : TBarCodeWidths = (30,10,30,10,10);
bar6 : TBarCodeWidths = (10,30,30,10,10);
bar7 : TBarCodeWidths = (10,10,10,30,30);
bar8 : TBarCodeWidths = (30,10,10,30,10);
bar9 : TBarCodeWidths = (10,30,10,30,10);
var
digits: string;
x, y, barHeight: integer;
barA, barB : TBarCodeWidths;
digit1, digit2 : char;
begin
...
while length(digits)<6 do digits := '0'+digits;
canvas.Brush.Style := bsSolid;
canvas.Brush.Color := clBlack;
barheight := 60;
x := 0;
y := 0;
Canvas.FillRect(Rect(y,x,y+10,x+BarHeight));
y := y+20 ;
Canvas.FillRect(Rect(y,x,y+10,x+BarHeight));
y := y+20 ;
for ii := 0 to 2 do begin
Digit1 := digits[(ii*2)+1];
Digit2 := digits[(ii*2)+2];
Case digit1 of
'0' : for z := 0 to 4 do bara[z] := bar0[z];
'1' : for z := 0 to 4 do bara[z] := bar1[z];
'2' : for z := 0 to 4 do bara[z] := bar2[z];
'3' : for z := 0 to 4 do bara[z] := bar3[z];
'4' : for z := 0 to 4 do bara[z] := bar4[z];
'5' : for z := 0 to 4 do bara[z] := bar5[z];
'6' : for z := 0 to 4 do bara[z] := bar6[z];
'7' : for z := 0 to 4 do bara[z] := bar7[z];
'8' : for z := 0 to 4 do bara[z] := bar8[z];
'9' : for z := 0 to 4 do bara[z] := bar9[z];
end;
Case digit2 of
'0' : for z := 0 to 4 do barb[z] := bar0[z];
'1' : for z := 0 to 4 do barb[z] := bar1[z];
'2' : for z := 0 to 4 do barb[z] := bar2[z];
'3' : for z := 0 to 4 do barb[z] := bar3[z];
'4' : for z := 0 to 4 do barb[z] := bar4[z];
'5' : for z := 0 to 4 do barb[z] := bar5[z];
'6' : for z := 0 to 4 do barb[z] := bar6[z];
'7' : for z := 0 to 4 do barb[z] := bar7[z];
'8' : for z := 0 to 4 do barb[z] := bar8[z];
'9' : for z := 0 to 4 do barb[z] := bar9[z];
end;
for z := 0 to 4 do begin
Canvas.FillRect(Rect(y,x,(y+bara[z]),x+BarHeight));
y := y+bara[z]+barb[z] ;
end;
end;
canvas.FillRect(Rect(y,x,y+30,x+BarHeight));
canvas.FillRect(Rect(y+40,x,y+50,x+BarHeight));
...With a TSQLTable made from the SQL statement below using TSQLRestClientURI.ExecuteList sorting fails on the authors.name field (using a TSQLTableToGrid). Tracing through the code it seems TSQLTable.InitFieldTypes sets this field's type to sftID instead of sftUTF8Text which is the defined type of authors.name. I guess this is because authors.name is referred to by an record id. Is sorting on a joined field implemented yet or am I going about it the wrong way?
Select books.title, authors.name from books left join authors on books.author=authors.ID
Just worked out that I needed to call TSQLTableToGrid.Refresh(true) after SetFieldLengthMean.
Just added a ticket. Sorry initially missed your response.
Thanks
I've created a form for selecting fields from a TSQLRecord. As it's fairly generic it could be useful to others so I've posted it below.
BTW I found a small typo in TSynButton.CreateKind where the 'right' parameter should be 'top'.
unit ColumnPicker;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, mORMot, SynCommons, SynTaskDialog,
Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.CheckLst;
type
TColumnPickerForm = class(TForm)
procedure ToggleAllCheckBoxClick(Sender: TObject);
procedure FieldsCheckListBoxClickCheck(Sender: TObject);
procedure FormDestroy(Sender: TObject);
protected
OKBtn, CancelBtn: TSynButton;
BottomPanel: TPanel;
ToggleAllCheckBox: TCheckBox;
FieldsCheckListBox: TCheckListbox;
private
fTableName: RawUTF8;
fFieldNames: TRawUTF8DynArray;
function getToggleAllCheckboxState: TCheckBoxState;
function getSelStatement: RawUTF8;
public
constructor Create(AOwner: TComponent; ARecord: TSQLRecord); reintroduce;
property SelectStatement: RawUTF8 read getSelStatement;
end;
implementation
{$R *.dfm}
constructor TColumnPickerForm.Create(AOwner: TComponent; ARecord: TSQLRecord);
var
i : integer;
begin
inherited Create(aOwner);
width := 300;
height := 400;
fTableName := ARecord.RecordProps.SQLTableName;
Caption := fTableName;
ToggleAllCheckBox := TCheckBox.Create(self);
ToggleAllCheckBox.Parent := self;
ToggleAllCheckBox.Align := alTop;
ToggleAllCheckBox.AlignWithMargins := true;
ToggleAllCheckBox.Margins.Left := 1;
ToggleAllCheckBox.OnClick := ToggleAllCheckBoxClick;
BottomPanel := TPanel.Create(self);
BottomPanel.Parent := self;
BottomPanel.Caption := '';
BottomPanel.Align := alBottom;
BottomPanel.BevelOuter := bvNone;
FieldsCheckListBox := TCheckListbox.Create(self);
FieldsCheckListBox.BorderStyle := bsNone;
FieldsCheckListBox.Parent := self;
FieldsCheckListBox.Align := alClient;
FieldsCheckListBox.OnClickCheck := FieldsCheckListBoxClickCheck;
SetLength(fFieldNames, ARecord.RecordProps.Fields.Count);
for i := 0 to ARecord.RecordProps.Fields.Count -1 do begin
FieldsCheckListBox.Items.Append(UTF8toString(UnCamelCase(ARecord.RecordProps.Fields.Items[i].Name)));
fFieldNames[i] := ARecord.RecordProps.Fields.Items[i].Name
end;
OKBtn := TSynButton.CreateKind(BottomPanel, cbOK, 180, 4, 89, 33);
CancelBtn := TSynButton.CreateKind(BottomPanel, cbCancel, 80, 4, 89, 33);
OnDestroy := FormDestroy;
end;
procedure TColumnPickerForm.FormDestroy(Sender: TObject);
begin
SetLength(fFieldNames, 0);
end;
procedure TColumnPickerForm.ToggleAllCheckBoxClick(Sender: TObject);
begin
if ToggleAllCheckBox.State <> cbGrayed then
if ToggleAllCheckBox.Checked then
FieldsCheckListBox.CheckAll(cbChecked, false, false)
else
FieldsCheckListBox.CheckAll(cbUnChecked, false, false);
end;
function TColumnPickerForm.getToggleAllCheckboxState: TCheckBoxState;
var
i, cnt : integer;
firstCheck: boolean;
begin
result := cbUnchecked;
if FieldsCheckListBox.Items.Count = 0 then exit;
firstCheck := FieldsCheckListBox.Checked[0];
if firstCheck then result := cbChecked;
for i := 1 to FieldsCheckListBox.Items.Count-1 do
if FieldsCheckListBox.Checked[i] <> firstCheck then begin
result := cbGrayed;
break;
end;
end;
procedure TColumnPickerForm.FieldsCheckListBoxClickCheck(Sender: TObject);
begin
ToggleAllCheckbox.State := getToggleAllCheckboxState;
end;
function TColumnPickerForm.getSelStatement: RawUTF8;
var
i : integer;
begin
result := 'SELECT ' + fTableName + '.ID';
if ToggleAllCheckBox.Checked then
result := 'SELECT *'
else if ToggleAllCheckBox.State = cbGrayed then begin
for i := 0 to FieldsCheckListBox.Items.Count-1 do
if FieldsCheckListBox.Checked[i] then
result := result + #32 + fTableName + '.' + fFieldNames[i];
end;
end;
end.Thanks, just tried it and it working fine.
In the code comments about TSQLRestClientURI.SessionUser (copied below) it gives an example of how to get the TSQlAuthUser fully filled out. Running the example gives me the error: 'Class TSQLAuthUser missing in model.' - I assume because TSQLAuthUser table is not visible client side. Could TSQLRestClientURI.SessionUser get the DisplayName and ID field filled out by default?
/// the current user as set by SetUser() method
// - returns nil if no User is currently authenticated
// - only available fields by default are LogonName and PasswordHashHexa:
// you can run code similar to the following to fill all needed properties:
// ! if fClient.SessionUser<>nil then
// ! begin
// ! fClient.Retrieve('LogonName=?',[],[fClient.SessionUser.LogonName],
// ! fClient.SessionUser); // fill ID, DisplayName, GroupRights
// ! fClient.RetrieveBlobFields(fClient.SessionUser); // optional Data
// ! end;
property SessionUser: TSQLAuthUser read fSessionUser;
The report preview form is shown with a default width a little less than a report page width. This causes a horizontal scrollbar to appear and cuts off the side of the report.
I've found changing line 4410 in mORMotReport.pas from:
PreviewForm.Width := (cx*PreviewForm.Height) div y+(64+PANELWIDTH);to:
PreviewForm.Width := (cx*PreviewForm.Height) div y+(64+PANELWIDTH)+PANELWIDTH;solves the problem but I don't fully understand the calculation. Why is the form height used to calculate PreviewForm.Width?
I'm trying to set the column widths with the following code but SetFieldLengthMean doesn't appear to work (using XE2). Can anyone see what's wrong?
Table.CalculateFieldLengthMean(colwidths);
s := '';
for i := 0 to length(colwidths)-1 do
s := s + Chr(colwidths[i] + 64);
Grid := TSQLTableToGrid.Create(DrawGrid, Table, nil);
Grid.SetFieldLengthMean(s, false);By default TSQLTableToGrid.Refresh auto resizes the column widths but I want to turn off this feature. Could a 'ResizeColumns' parameter be added to the function like below?
function TSQLTableToGrid.Refresh(ForceRefresh: Boolean=false; ResizeColumns: Boolean=true): boolean;
var Refreshed: boolean;
aID: integer;
begin
if self=nil then
result := false else begin
aID := Table.IDColumnHiddenValue(TDrawGrid(Owner).Row);
if ForceRefresh then
result := true else
result := Client.UpdateFromServer([Table],Refreshed) and Refreshed;
if result then
AfterRefresh(aID, ResizeColumns);
end;
end;
procedure TSQLTableToGrid.AfterRefresh(aID: integer, ResizeColumns: Boolean);
var CurrentRow: integer;
Bulk: boolean;
begin
with TDrawGrid(Owner) do begin
if Table.RowCount=0 then
RowCount := 2 else
RowCount := Table.RowCount+1;
if Table.FieldCount<>ColCount then begin
// we get results from a void table for the first time
ColCount := Table.FieldCount;
SetLength(fFieldOrder,Table.FieldCount);
end;
CurrentRow := Table.RowFromID(aID);
if CurrentRow=0 then
CurrentRow := 1;
Row := CurrentRow;
TopRow := 1;
Invalidate;
end;
if ResizeColumns then
Resize(nil); // auto resize columns
if Assigned(OnSelectCell) then
OnSelectCell(Owner,0,CurrentRow,Bulk); // refresh details
end;So if I have mORMot running as an HTTP server is it perfectly ok to have a separate utility program to manage user accounts which accesses the same local SQlite3 data file directly? This seems a simpler and more secure way of managing user accounts than using services.
Just tried out the new features and they work great ![]()
I'm wanting to change for font colour on a per line basis. Is setting it in the OnValueText event the best way to do it? Seems to work ok.
Thanks
Yes, that fixes the issues. Could you update mORMotUI.
Many thanks
I've got a problem changing the font when creating a TSQLTableToGrid in a form's onShow event.
DrawGrid.Font.Size := 12;
TableToGrid := TSQLTableToGrid.Create(DrawGrid, Table, database);The Drawgrid font size gets set ok but the row height gets adjusted to the smaller default font size by the following lines in TSQLTableToGrid.Create
with aOwner.Canvas.TextExtent('jQH°;') do
aOwner.DefaultRowHeight := cy+4;I only get the problem if creating the TSQLTableToGrid in the form's onShow event.
Any suggestions on getting this working?
Thanks
Thanks, I've created the tickets.
Can currency values displayed via TSQLTableToGrid be rounded to two decimal places and also be right-justified within the cell?
Could there be an alternate functionality for the id header checkbox whereby it selects/de-selects all marked items instead of sorting them. For some users this seems more instictive.
Many Thanks!
I'm not sure it is worth adding as a feature as everyone will probably want to customize the format differently.
Instead I've had a go at writing a version for my situation:
procedure TableToCSV(Table: TSQLTableJSON; CSV: TFileStream);
var
i, row, col, FMax: integer;
W: TTextWriter;
s : string;
E: PEnumType;
EP: PShortString;
P: TSQLPropInfo;
Sets, SetMax: cardinal;
SetItemName, RawSetItemName: RawUTF8;
begin
if (Table.FieldCount<=0) or (Table.RowCount<=0) then
exit;
W := TTextWriter.Create(CSV,8196);
FMax := Table.FieldCount -1;
try
W.AddShort(#$ef#$bb#$bf); // add UTF-8 Byte Order Mark
for row := 0 to Table.RowCount -1 do
for col := 0 to FMax do begin
case Table.ExpandAsString(Row,Col,database,s) of
sftBoolean: if s = '0' then
W.AddString('False')
else
W.AddString('True');
sftTimeLog: if Table.GetU(row,col) <> '120795955200' then
W.AddString(QuotedStr(stringtoUTF8(s),'"'))
else
W.AddString('""');
sftSet: begin
P := Table.QueryRecordType.RecordProps.Fields.List[col-1];
E := (P as TSQLPropInfoRTTISet).SetEnumType;
if E^.MaxValue>31 then // up to 32 elements in tkSet (GetOrdValue)
SetMax := 31
else
SetMax := E^.MaxValue;
Sets := GetInteger(pointer(s));
EP := @E^.NameList;
W.Add('"');
for i := 0 to SetMax do begin
if GetBit(Sets, i) then begin
setItemName := '';
RawSetItemName := ShortStringToAnsi7String(EP^);
SetLength(setItemName,PInteger(PtrInt(RawSetItemName)-sizeof(integer))^*2);
SetLength(setItemName,UnCamelCase(pointer(setItemName),TrimLeftLowerCase(RawSetItemName)));
W.AddString(setItemName);
W.Add(',');
end;
inc(PtrInt(EP),ord(EP^[0])+1); // next enumeration item
end;
W.CancelLastComma;
W.Add('"');
end;
else
W.AddString(QuotedStr(stringtoUTF8(s),'"'));
end;
if col=FMax then
W.AddCR
else
W.Add(',');
end;
W.Flush;
finally
W.Free;
end;
end;When using the function TSQLTableJSON.GetCSVValues I want the TTimeLog values to be formated as ISO 8601 text instead of the raw value. Is there a simple way to do this?
Also it would be nice if enumeration fields could be formated to make them more readable in CSV.
Thanks,
Esmond
I guess using 0/0/0 isn't such a good idea. In my case business rules make certain dates invalid so I think I'll pick one of those as a 'magic' date to indicate unassigned.
Thanks
I'm planning on using the date 0/0/0 as a sort of NULL value but have a problem with TTimeLog to TDateTime conversions.
function Iso8601.ToDate: TDateTime;
begin
if Value=0 then
result := 0 else
result := EncodeDate((Value shr (6+6+5+5+4)) and 4095,
1+(Int64Rec(Value).Lo shr (6+6+5+5)) and 15,
1+(Int64Rec(Value).Lo shr (6+6+5)) and 31);
end;Converts 0/0/0 to 30/12/1899. Could it be changed to:
function Iso8601.ToDate: TDateTime;
begin
if Value=0 then
result := -693594 else ...OK, Thanks
I can't find the RecordClassesToClasses() function anymore which I thought was in mORMot.pas. Has it been removed?
It looks like the latest freepascal offer the Delphi syntax as an alternative:
Thanks,
Managed to get TSynLabeledEdit installed the XE2 tool palette - don't know why but the compiler was trying to output C++ .obj files which caused problems.
Where can I find the latest SAD documentation?
The version at:
http://synopse.info/files/pdf/Synopse%2 … 201.18.pdf
Is a few days old and I noticed in fossil that something had since been added about compiling mORMot in a package (I'm having trouble adding TSynLabeledEdit to an XE2 package)
I've just tried it and it works for some tables but not for others in XE2. The AuthGroup table shows fine but Users table gives this exception:
Project Project16Client.exe raised exception class EInterfaceFaceFactoryException with message 'Invalid fake IRemoteSQL.Execute interface call:'.
You could try something like:
var
JSONBuffer: RawUTF8;
procedure example;
var
Table: TSQLTable;
Rows: ISQLDBRows;
begin
Rows := Client.Execute('select * from SGRUSR01',[]);
fJSONBuffer := Rows.FetchAllAsJSON(false);
Table := TSQLTableJSON.Create([],'',pointer(fJSONBuffer),length(fJSONBuffer));
...F.BufSize=1024 in XE2.
InputSock() is only called once before THttpSocket.GetBody. The rest of the calls are from GetBody.
One strange thing I've noticed is F.BufPtr gets truncated to 124 characters after the first call to InputSock when looked at at the start of the the InputSock function.
"neither... nor" is different to "either.. or"
"neither Peter nor Jane will go to the party" means none of them will go to the party. neither is a bit like "not... either... or..."
"either Peter or Jane will go to the party" means only one of them will go to the party.