21 define LEFT_MARGIN = 10;
22 define RIGHT_MARGIN = 10;
23 define TOP_MARGIN = 10;
24 define BOTTOM_MARGIN = 10;
26 enum VerticalAlignment { middle, top, bottom };
28 enum HorizontalAlignment { none, left, middle, right };
30 define CELL_SPACING = 0;
32 class RenderFlags { bool lineW:1,width:1,render:1,minW:1; };
34 enum InputType { text, submit, radio, hidden };
36 class ImageEntry : struct
38 ImageEntry prev, next;
51 bitmapPtrs.Free(null);
55 class FontEntry : struct
69 class RequestLink : OldLink
74 class AlignedObject : struct
76 AlignedObject prev, next;
82 static HTMLView browserWindow;
84 class ObjectThread : Thread
86 bool objectThreadDead;
87 bool objectThreadTerminate;
88 Semaphore objectThreadSemaphore {};
92 objectThreadDead = false;
93 for(;!objectThreadTerminate;)
95 if(objectRequests.first)
99 //((GuiApplication)__thisModule).Lock();
101 for(;!objectThreadTerminate;)
106 char path[MAX_LOCATION], referer[MAX_LOCATION];
109 for(request = objectRequests.first; request && request.processed; request = (RequestLink)request.next);
112 request.processed = true;
113 objectsMutex.Release();
116 entry = request.data;
118 strcpy(path, entry.src);
119 //strcpy(referer, browserWindow.location ? browserWindow.location : "");
120 strcpy(referer, entry.referer); //browserWindow.location ? browserWindow.location : "");
122 //((GuiApplication)__thisModule).Unlock();
124 if(path && strstr(path, "http://") == path)
126 HTTPFile httpFile {};
128 //printf("Opening URL\n");
130 //((GuiApplication)__thisModule).PauseNetworkEvents();
131 if(httpFile.OpenURL(path, referer, null))
133 char extension[MAX_EXTENSION];
134 entry.bitmap = Bitmap { alphaBlend = true };
135 //printf("Loading File\n");
136 entry.bitmap.LoadFromFile(file, GetExtension(path, extension), null);
140 entry.missing = true;
141 //((GuiApplication)__thisModule).ResumeNetworkEvents();
145 file = FileOpen(path, read);
147 entry.missing = true;
150 char extension[MAX_EXTENSION];
151 entry.bitmap = Bitmap { alphaBlend = true };
152 entry.bitmap.LoadFromFile(file, GetExtension(path, extension), null);
158 objectRequests.Remove(request);
160 objectsMutex.Release();
162 ((GuiApplication)__thisModule).Lock();
163 if(!objectThreadTerminate)
166 Window rootWindow = browserWindow.rootWindow;
168 display = rootWindow.parent.display;
170 display = rootWindow.display;
175 entry.bitmap.MakeDD(browserWindow.displaySystem);
176 if(entry.bitmap && entry.bitmap.alphaBlend)
178 entry.bitmap.Convert(null, pixelFormat888, null);
179 // entry.bitmap.displaySystem = displaySystem;
182 for(bitmapPtr = entry.bitmapPtrs.first; bitmapPtr; bitmapPtr = bitmapPtr.next)
184 *((Bitmap*) bitmapPtr.data) = entry.bitmap;
186 browserWindow.ComputeMinSizes();
187 browserWindow.ComputeSizes();
188 browserWindow.PositionForms();
189 browserWindow.Update(null);
191 // ((GuiApplication)__thisModule).UpdateDisplay();
194 // TRIED MOVING THIS HERE BECAUSE OF printf("bug") in GuiApplication if(window.display.current)
195 ((GuiApplication)__thisModule).UpdateDisplay();
197 ((GuiApplication)__thisModule).Unlock();
199 //((GuiApplication)__thisModule).Unlock();
203 //printf("Waiting for Object Thread Semaphore\n");
204 objectThreadSemaphore.Wait();
207 objectThreadDead = true;
212 static ObjectThread objectThread1 { };
213 static ObjectThread objectThread2 { };
214 static ObjectThread objectThread3 { };
215 static ObjectThread objectThread4 { };
216 static Mutex objectsMutex {};
217 static OldList imageCache;
218 /*static */OldList fontCache;
220 static OldList objectRequests;
222 static void WriteBlock(File f, Block block)
224 static int indent = 0;
228 for(c = 0; c<indent; c++)
234 f.Printf("Text: %s\n", block.text);
237 f.Printf("Image: %d %d %s\n", block.w, block.h, block.src);
246 f.Printf("Anchor: %s\n", block.src);
249 f.Printf("Font: %s, %d\n", block.face, block.size);
252 f.Printf("Center\n");
265 for(child = block.subBlocks.first; child; child = child.next)
268 WriteBlock(f, child);
273 static void ComputeImageSize(Block block)
277 if(block.type == IMAGE)
280 block.w = block.width;
282 block.w = block.bitmap ? block.bitmap.width : 0;
285 block.h = block.height;
287 block.h = block.bitmap ? block.bitmap.height : 0;
289 for(child = block.subBlocks.first; child; child = child.next)
290 ComputeImageSize(child);
293 class HTMLView : Window
296 BitmapResource missing { "<:ecere>emblems/unreadable.png", window = this };
298 Block overLink, clickedLink;
302 void ComputeMinSizes()
306 ComputeImageSize(html.body);
308 // Pre compute some stuff
310 Block block = html.body;
314 Surface surface = display.GetSurface(0,0,null);
317 surface.TextFont(html.defaultFont.font.font);
324 ComputeLine(surface, block, textPos, &nextBlock, &nextTextPos, ¢ered, &w, MAXINT, 0, RenderFlags { minW = true }, 0, null, null, null, true, 0, LEFT_MARGIN);
326 textPos = nextTextPos;
334 void Clear(Block block)
338 if(block.type != TABLE && block.type != IMAGE)
343 if(block.type == TABLE)
345 block.columns.Free(null);
347 if(block.type != IMAGE)
353 block.rowSpan = block.span = 1;
356 for(b = block.subBlocks.first; b; b = b.next)
363 int width = clientSize.w;
364 int height = clientSize.h;
365 Block block = html.body;
366 int totalWidth = 0, totalHeight = 0;
370 Surface surface = display.GetSurface(0,0,null);
373 width = parent.clientSize.w;
375 height = parent.clientSize.h;
379 int maxH = height - BOTTOM_MARGIN;
382 if(html.defaultFont.font)
383 surface.TextFont(html.defaultFont.font.font);
389 int maxW = width - (LEFT_MARGIN + RIGHT_MARGIN);
392 newH = ComputeLine(surface, block, textPos, &nextBlock, &nextTextPos, ¢ered, &w, maxW, maxH - y, RenderFlags { lineW = true, width = true }, 0, null, null, &changeLine, true, y, LEFT_MARGIN);
399 textPos = nextTextPos;
401 totalWidth = Max(totalWidth, w);
405 totalHeight = y + BOTTOM_MARGIN;
406 totalWidth += LEFT_MARGIN + RIGHT_MARGIN;
408 SetScrollArea(totalWidth, totalHeight, false);
409 SetScrollArea(totalWidth, totalHeight, false);
412 if(!initSize.w || !initSize.h)
413 clientSize = Size {!initSize.w ? totalWidth : clientSize.w, !initSize.h ? totalHeight : clientSize.h };
416 void CreateForms(Block block)
420 if(block.type == INPUT)
422 switch(block.inputType)
425 block.window = Button { this, text = block.value, position = Point { 10, 50 }, id = (int64)block, NotifyClicked = ButtonClicked, isDefault = true };
426 eInstance_IncRef(block.window);
427 block.window.Create();
428 block.window.cursor = ((GuiApplication)__thisModule).GetCursor(arrow);
429 //if(!html.defaultButton) html.defaultButton = block.window;
432 block.window = Button { this, isRadio = true, position = Point { 10, 100 }, id = (int64)block, NotifyClicked = ButtonClicked };
433 eInstance_IncRef(block.window);
434 block.window.Create();
435 block.window.cursor = ((GuiApplication)__thisModule).GetCursor(arrow);
438 block.window = EditBox { this, position = Point { 10, 20 }, id = (int64)block };
439 eInstance_IncRef(block.window);
440 block.window.Create();
443 /*if(!activeChild && block.window)
444 block.window.Activate();*/
447 for(child = block.subBlocks.last; child; child = child.prev)
451 void LoadGraphics(Block block, void **previous)
455 if(block.src && (block.type == IMAGE || block.type == TD || block.type == TABLE))
457 char path[MAX_LOCATION];
460 strcpy(path, location ? location : "");
461 if(location && path[strlen(path)-1] != '/')
463 if(block.src[0] == '/' && block.src[1] == '/')
465 strcpy(path, "http:");
466 strcat(path, block.src);
469 PathCat(path, block.src);
471 for(entry = imageCache.first; entry; entry = entry.next)
472 if(!strcmp(entry.src, path))
477 entry = ImageEntry { src = CopyString(path), referer = CopyString(location) };
478 imageCache.Add(entry);
481 block.imageEntry = entry;
482 block.entryPtr = OldLink { data = &block.bitmap };
483 entry.bitmapPtrs.Add(block.entryPtr);
486 block.bitmap = entry.bitmap;
489 if(path && strstr(path, "http://") == path)
493 for(request = objectRequests.first; request; request = (RequestLink)request.next)
495 if(request.data == entry)
500 request = RequestLink { data = entry };
501 objectRequests.Insert(*previous, request);
503 objectThread1.objectThreadSemaphore.Release();
504 objectThread2.objectThreadSemaphore.Release();
505 objectThread3.objectThreadSemaphore.Release();
506 objectThread4.objectThreadSemaphore.Release();
508 else if(*previous != request)
510 objectRequests.Move(request, *previous);
513 objectsMutex.Release();
517 // ADDED THIS TO LOAD LOCAL FILES RIGHT HERE...
519 File file = FileOpen(path, read);
521 entry.missing = true;
524 char extension[MAX_EXTENSION];
525 entry.bitmap = Bitmap { alphaBlend = true };
526 entry.bitmap.LoadFromFile(file, GetExtension(path, extension), null);
529 for(bitmapPtr = entry.bitmapPtrs.first; bitmapPtr; bitmapPtr = bitmapPtr.next)
531 *((Bitmap*) bitmapPtr.data) = entry.bitmap;
533 block.bitmap = entry.bitmap;
536 block.font = block.parent.font;
538 else if(block.type == FONT || block.type == ANCHOR)
541 for(entry = fontCache.first; entry; entry = entry.next)
543 if(!strcmpi(entry.face, block.face) &&
544 entry.size == block.size &&
545 entry.attribs == block.attribs)
553 entry = FontEntry { /*font = displaySystem.LoadFont(block.face, block.size, block.attribs), */size = block.size, attribs = block.attribs, face = CopyString(block.face) };
554 fontCache.Add(entry);
564 else if(block.parent)
565 block.font = block.parent.font;
567 for(child = block.subBlocks.first; child; child = child.next)
568 LoadGraphics(child, previous);
571 bool OnLoadGraphics()
575 for(entry = imageCache.first; entry; entry = entry.next)
577 entry.bitmap.MakeDD(displaySystem);
578 if(entry.bitmap && entry.bitmap.alphaBlend)
580 entry.bitmap.Convert(null, pixelFormat888, null);
581 // entry.bitmap.displaySystem = displaySystem;
584 for(fEntry = fontCache.first; fEntry; fEntry = fEntry.next)
585 fEntry.font = browserWindow.displaySystem.LoadFont(fEntry.face, fEntry.size, fEntry.attribs);
589 void OnUnloadGraphics()
592 for(entry = fontCache.first; entry; entry = entry.next)
594 browserWindow.displaySystem.UnloadFont(entry.font);
599 void NormalizeSelection(Block * startBlock, int * startSel, Block * endBlock, int * endSel)
601 bool selAfter = false;
603 for(b = selBlock; b; b = GetNextBlock(b))
605 if(b != selBlock && b == textBlock)
612 if(textBlock == selBlock)
614 *startSel = Min(selPosition, curPosition);
615 *endSel = Max(selPosition, curPosition);
616 *startBlock = *endBlock = textBlock;
620 *startBlock = textBlock;
621 *startSel = curPosition;
622 *endSel = selPosition;
623 *endBlock = selBlock;
627 *startBlock = selBlock;
628 *startSel = selPosition;
629 *endSel = curPosition;
630 *endBlock = textBlock;
636 Block block = html.body;
640 int maxH = clientSize.h - BOTTOM_MARGIN;
641 OldList leftObjects { };
642 OldList rightObjects { };
643 AlignedObject object, nextObject;
646 Surface surface = display.GetSurface(0,0,null);
649 if(html.defaultFont.font)
650 surface.TextFont(html.defaultFont.font.font);
658 int thisLineCentered = centered;
659 Font font = surface.GetFont();
663 right = clientSize.w - RIGHT_MARGIN;
665 for(object = leftObjects.last; object; object = nextObject)
667 nextObject = object.prev;
668 if(y < object.untilY || object.next)
671 leftObjects.Delete(object);
673 for(object = rightObjects.last; object; object = nextObject)
675 nextObject = object.prev;
676 if(y < object.untilY || object.next)
679 rightObjects.Delete(object);
681 right = Max(left, right);
684 newH = ComputeLine(surface, block, textPos, &nextBlock, &nextTextPos, ¢ered, &w, maxW, maxH - y, RenderFlags {}, y, &leftObjects, &rightObjects, &changeLine, true, 0 /*y*/, LEFT_MARGIN);
686 x = Max(left,(left + right - w) / 2);
690 surface.TextFont(font);
692 PositionLine(this, surface, x - scroll.x, y - scroll.y,
693 maxW, newH, block, textPos, nextBlock, nextTextPos,
694 left - scroll.x, right - scroll.x);
702 textPos = nextTextPos;
708 void Open(char * location, char * firstReferer)
711 char referer[MAX_LOCATION] = "";
712 char relocation[MAX_LOCATION];
715 strcpy(relocation, location);
717 if(strstr(location, "http://") != location)
719 if(!FileExists(location))
721 strcpy(relocation, "http://");
722 strcat(relocation, location);
727 f = (HTTPFile)FileOpen(location, read);
737 strcpy(referer, firstReferer);
742 SetScrollArea(0,0,0);
747 char path[MAX_LOCATION];
750 delete this.location;
751 this.location = CopyString(relocation);
752 fileName = this.location;
753 ((GuiApplication)__thisModule).UpdateDisplay();
755 if(!(opened = f.OpenURL(this.location, referer, relocation)) && !strcmp(this.location, relocation))
760 //printf("Relocated to %s\n", relocation);
762 strcpy(referer, this.location);
764 // Fix up relocation relative paths
765 strcpy(path, this.location);
766 if(path[strlen(path)-1] != '/')
768 if(relocation[0] == '/' && relocation[1] == '/')
770 strcpy(path, "http:");
771 strcat(path, relocation);
774 PathCat(path, relocation);
775 strcpy(relocation, path);
778 delete this.location;
779 this.location = CopyString(relocation);
780 fileName = this.location;
784 void * previous = null;
786 LoadGraphics(html.defaultFont, &previous);
787 LoadGraphics(html.block, &previous);
788 CreateForms(html.block);
797 File f = FileOpen("debug2.txt", write);
800 WriteBlock(f, html.body);
808 NotifyPageOpened(master);
811 void OpenFile(File f, char * firstReferer)
813 char referer[MAX_LOCATION] = "";
814 char relocation[MAX_LOCATION];
822 strcpy(referer, firstReferer);
827 SetScrollArea(0,0,0);
831 this.location = null;
832 fileName = this.location;
836 void * previous = null;
838 LoadGraphics(html.defaultFont, &previous);
839 LoadGraphics(html.block, &previous);
840 CreateForms(html.block);
847 File f = FileOpen("debug2.txt", write);
850 WriteBlock(f, html.body);
856 NotifyPageOpened(master);
859 bool ScrollToAnchor(Block block, char * anchor)
862 if(block.type == ANCHOR && block.anchor && !strcmpi(block.anchor, anchor))
864 SetScrollPosition(0, block.startY);
870 for(subBlock = block.subBlocks.first; subBlock; subBlock = subBlock.next)
872 if((result = ScrollToAnchor(subBlock, anchor)))
879 bool GoToAnchor(char * anchor)
881 return anchor ? ScrollToAnchor(html.block, anchor) : false;
884 virtual bool Window::NotifyPageOpened();
888 objectThread1.objectThreadTerminate = true;
889 objectThread2.objectThreadTerminate = true;
890 objectThread3.objectThreadTerminate = true;
891 objectThread4.objectThreadTerminate = true;
892 ((GuiApplication)__thisModule).Unlock();
893 objectThread1.objectThreadSemaphore.Release();
894 objectThread2.objectThreadSemaphore.Release();
895 objectThread3.objectThreadSemaphore.Release();
896 objectThread4.objectThreadSemaphore.Release();
899 while(!objectThread1.objectThreadDead ||
900 !objectThread2.objectThreadDead ||
901 !objectThread3.objectThreadDead ||
902 !objectThread4.objectThreadDead)
904 // ((GuiApplication)__thisModule).ProcessNetworkEvents();
908 //objectThread.Wait();
909 objectRequests.Free(null);
911 ((GuiApplication)__thisModule).Lock();
916 browserWindow = this;
917 objectThread1.objectThreadTerminate = false;
918 objectThread2.objectThreadTerminate = false;
919 objectThread3.objectThreadTerminate = false;
920 objectThread4.objectThreadTerminate = false;
922 objectThread1.Create();
923 objectThread2.Create();
924 objectThread3.Create();
925 objectThread4.Create();
930 location = CopyString(location);
939 Open(location, null);
943 void OnResize(int width, int height)
953 // For text selection
954 Block textBlock, selBlock;
955 int curPosition, selPosition;
956 bool isSelected; // Persistent state changed by RenderLine
958 void OnRedraw(Surface surface)
960 Block block = html.body;
964 int maxH = clientSize.h - BOTTOM_MARGIN;
965 OldList leftObjects { };
966 OldList rightObjects { };
968 AlignedObject object, nextObject;
971 surface.SetBackground(html.background);
972 if(html.background.a < 255)
973 surface.Area(0,0,clientSize.w,clientSize.h);
975 surface.Clear(colorBuffer);
976 if(html.defaultFont.font) // TOFIX: Null! (No font set?)
977 surface.TextFont(html.defaultFont.font.font);
978 surface.SetForeground(html.defaultFont.textColor);
988 int thisLineCentered = centered;
989 Font font = surface.GetFont();
993 right = clientSize.w - RIGHT_MARGIN;
995 for(object = leftObjects.last; object; object = nextObject)
997 nextObject = object.prev;
998 if(y < object.untilY || object.next)
1001 leftObjects.Delete(object);
1003 for(object = rightObjects.last; object; object = nextObject)
1005 nextObject = object.prev;
1006 if(y < object.untilY || object.next)
1009 rightObjects.Delete(object);
1011 right = Max(left, right);
1012 maxW = right - left;
1014 newH = ComputeLine(surface, block, textPos, &nextBlock, &nextTextPos, ¢ered, &w, maxW, maxH - y, RenderFlags {}, y, &leftObjects, &rightObjects, &changeLine, false, 0, 0);
1015 if(thisLineCentered)
1016 x = Max(left,(left + right - w) / 2);
1020 surface.TextFont(font);
1023 RenderLine(this, surface, x - scroll.x, y - scroll.y, maxW, newH, block, textPos, nextBlock, nextTextPos, left - scroll.x, right - scroll.x);
1032 textPos = nextTextPos;
1037 void OnVScroll(ScrollBarAction action, int position, Key key)
1042 bool OnKeyHit(Key key, unichar character)
1047 CycleChildren(true, false, false, true);
1050 CycleChildren(false, false, false, true);
1052 case left: case right:
1053 horzScroll.OnKeyHit(key, character);
1055 case down: case up: case pageDown: case pageUp:
1056 vertScroll.OnKeyHit(key, character);
1062 bool OnKeyDown(Key key, unichar character)
1068 vertScroll.OnKeyDown(home, character);
1069 horzScroll.OnKeyDown(home, character);
1074 vertScroll.OnKeyDown(end, character);
1075 horzScroll.OnKeyDown(end, character);
1082 void OnHScroll(ScrollBarAction action, int position, Key key)
1087 bool PickHTML(int pickX, int pickY, Block* pickBlock, int * pickTextPos)
1089 bool result = false;
1090 Block block = html.body;
1094 int maxH = clientSize.h - BOTTOM_MARGIN;
1095 OldList leftObjects { };
1096 OldList rightObjects { };
1097 AlignedObject object, nextObject;
1100 Surface surface = display.GetSurface(0,0,null);
1103 if(html.defaultFont.font) // TOFIX: Null! (No font set?)
1104 surface.TextFont(html.defaultFont.font.font);
1112 int thisLineCentered = centered;
1113 Font font = surface.GetFont();
1117 right = clientSize.w - RIGHT_MARGIN;
1119 for(object = leftObjects.last; object; object = nextObject)
1121 nextObject = object.prev;
1122 if(y < object.untilY || object.next)
1125 leftObjects.Delete(object);
1127 for(object = rightObjects.last; object; object = nextObject)
1129 nextObject = object.prev;
1130 if(y < object.untilY || object.next)
1133 rightObjects.Delete(object);
1135 right = Max(left, right);
1136 maxW = right - left;
1138 newH = ComputeLine(surface, block, textPos, &nextBlock, &nextTextPos, ¢ered, &w, maxW, maxH - y, RenderFlags {}, y, &leftObjects, &rightObjects, &changeLine, false, 0, 0);
1139 if(thisLineCentered)
1140 x = Max(left,(left + right - w) / 2);
1144 surface.TextFont(font);
1146 if(PickLine(this, surface, x - scroll.x, y - scroll.y,
1147 maxW, newH, block, textPos, nextBlock, nextTextPos,
1148 left - scroll.x, right - scroll.x, pickX, pickY, pickBlock, pickTextPos))
1160 textPos = nextTextPos;
1167 bool OnMouseMove(int x, int y, Modifiers mods)
1169 Block pickBlock = null;
1170 Block linkBlock = null;
1171 int pickTextPos = 0;
1173 if(!mods.isSideEffect)
1175 PickHTML(x,y, &pickBlock, &pickTextPos);
1179 for(linkBlock = pickBlock; linkBlock; linkBlock = linkBlock.parent)
1181 if(linkBlock.type == ANCHOR)
1187 if(strstr(linkBlock.href, "edit://") == linkBlock.href)
1188 cursor = ((GuiApplication)__thisModule).GetCursor(iBeam);
1190 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
1191 overLink = linkBlock;
1195 if(pickBlock && pickBlock.type == TEXT)
1197 cursor = ((GuiApplication)__thisModule).GetCursor(iBeam);
1201 cursor = ((GuiApplication)__thisModule).GetCursor(arrow); //null);
1205 overBlock = pickBlock;
1206 overPos = pickTextPos;
1211 bool OnLeftButtonDown(int x, int y, Modifiers mods)
1213 OnMouseMove(x, y, mods);
1216 clickedLink = overLink;
1223 virtual bool OnOpen(char * href)
1225 char newLocation[MAX_LOCATION];
1227 strcpy(newLocation, location ? location : "");
1228 if(newLocation[strlen(newLocation)-1] != '/')
1229 PathCat(newLocation, "..");
1230 if(href[0] == '/' && href[1] == '/')
1232 strcpy(newLocation, "http:");
1233 strcat(newLocation, href);
1236 PathCat(newLocation, href);
1238 Open(newLocation, null);
1242 bool OnLeftButtonUp(int x, int y, Modifiers mods)
1247 if(clickedLink == overLink && clickedLink.href)
1249 if(OnOpen(clickedLink.href))
1256 void AddFormControls(char * location, Block block)
1259 if(block.type == INPUT)
1261 switch(block.inputType)
1271 if(location[strlen(location)-1] != '?')
1273 strcat(location, "&");
1275 strcat(location, block.name);
1276 strcat(location, "=");
1278 len = strlen(location);
1280 text = ((EditBox)block.window).contents;
1282 for(c = 0; text[c]; c++)
1285 location[len++] = '+';
1288 location[len++] = text[c];
1291 location[len] = '\0';
1297 for(child = block.subBlocks.first; child; child = child.next)
1299 AddFormControls(location, child);
1303 bool ButtonClicked(Button button, int x, int y, Modifiers mods)
1305 Block block = (Block)button.id;
1306 if(block.inputType == submit)
1310 for(formBlock = block; formBlock; formBlock = formBlock.parent)
1311 if(formBlock.type == FORM)
1314 if(formBlock && formBlock.action)
1316 char newLocation[MAX_LOCATION];
1318 strcpy(newLocation, location);
1319 if(newLocation[strlen(newLocation)-1] != '/')
1320 PathCat(newLocation, "..");
1322 if(formBlock.action[0] == '/' && formBlock.action[1] == '/')
1324 strcpy(newLocation, "http:");
1325 strcat(newLocation, formBlock.action);
1328 PathCat(newLocation, formBlock.action);
1329 strcat(newLocation, "?");
1333 strcat(newLocation, block.name);
1334 strcat(newLocation, "=");
1337 AddFormControls(newLocation, formBlock);
1339 Open(newLocation, null);
1349 html.background = white;
1354 delete this.location;
1358 FontEntry fontEntry;
1359 while((entry = imageCache.first))
1361 imageCache.Remove(entry);
1364 while((fontEntry = fontCache.first))
1366 fontCache.Remove(fontEntry);
1369 html.block.ClearEntries();
1373 property char * location
1379 location = CopyString(value);
1381 Open(location, null);
1383 get { return location; }