#include #include #include #include #include #include "assert.h" // UTILS typedef struct List List; typedef struct Strlist Strlist; typedef struct Procinfo Procinfo; // Thread group ids, used for distinguishing allocation arenas enum { GRnone, GRmain, GRnet, GRprog, GRalert }; // List of integers (and also generic list with next pointer at beginning) struct List { List* next; int val; }; struct Strlist { Strlist* next; Rune* val; }; extern int listlen(List* l); extern List* newlist(int val, List* rest); extern Strlist* newstrlist(Rune* val, Strlist* rest); extern List* revlist(List* l); extern void splitl(Rune* s, int n, Rune* cl, Rune** p1, int* n1, Rune** p2, int* n2); extern void splitr(Rune* s, int n, Rune* cl, Rune** p1, int* n1, Rune** p2, int* n2); extern int splitall(Rune* s, int n, Rune* cl, Rune** strarr, int* lenarr, int alen); extern void trimwhite(Rune* s, int n, Rune** pans, int* panslen); extern Rune* Strclass(Rune* s, Rune* cl); extern Rune* Strnclass(Rune* s, Rune* cl, int n); extern Rune* Strrclass(Rune* s, Rune* cl); extern Rune* Strnrclass(Rune* s, Rune* cl, int n); extern int inclass(Rune c, Rune* cl); extern int prefix(Rune* pre, Rune* s); extern int Strlen(Rune* s); extern int Strcmp(Rune* s1, Rune* s2); extern int Strncmpci(Rune* s1, int n1, Rune* s2); extern int Strncmp(Rune* s1, int n1, Rune* s2); extern int Streqn(Rune* s1, int n1, Rune* s2); extern Rune* Strrune(Rune* s, Rune c); extern Rune* Strnrune(Rune* s, Rune c, int n); extern Rune* Strdup(Rune* s); extern Rune* Strdup2(Rune* s, Rune* t); extern Rune* Strdup3(Rune* s, Rune* t, Rune* u); extern Rune* Strsubstr(Rune* s, int start, int stop); extern Rune* newstr(int n); extern Rune* Strndup(Rune* s, int n); extern void Strncpy(Rune* s1, Rune* s2, int n); extern Rune* Stradd(Rune*s1, Rune* s2, int n); extern long Strtol(Rune* s, Rune** eptr, int base); extern Rune* toStr(uchar* buf, int n, int chset); extern Rune* ltoStr(int n); extern uchar* fromStr(Rune* buf, int n, int chset); extern int max(int a, int b); extern int min(int a, int b); extern void* emalloc(int size); extern void* emallocz(int size); extern void* erealloc(void* p, int size); extern void freeshortlived(void); extern void meminit(int big); extern int validptr(void* p); extern int validStr(Rune* s); extern Rune* whitespace; extern Rune* notwhitespace; // some constants used for buffer lengths #define SMALLBUFSIZE 240 #define BIGBUFSIZE 2000 #define ATOMICIO 8192 #define STACKSIZE 32700 #define STACKSIZESMALL 8100 // URL typedef struct ParsedUrl ParsedUrl; enum { NOSCHEME, HTTP, HTTPS, FTP, FILE, GOPHER, MAILTO, NEWS, NNTP, TELNET, WAIS, PROSPERO , UNKNOWN, NSCHEMES }; // A ParsedUrl contains the whole url at the end, // and pointers into that string for the various pieces of the url. // together with counts for how long those pieces are. // The individual pieces shouldn't be changed, except via the // makeabsolute and addquery functions. struct ParsedUrl { int scheme; // HTTP, etc. Rune* user; // if have user:passwd@machine int nuser; // number of chars in user substring Rune* passwd; int npasswd; Rune* host; // machine name int nhost; Rune* port; // if have :portnumber after machine int nport; Rune* pstart; // Either '/' or empty int npstart; Rune* path; // part after the '/', before query int npath; Rune* query; // part after ? int nquery; Rune* frag; // part after # int nfrag; int nurl; // actual length of url array Rune url[1]; // the whole thing }; #pragma varargck type "U" ParsedUrl* extern Rune* schemes[]; extern void urlinit(void); extern ParsedUrl* makeurl(Rune* s, int makeabs); extern ParsedUrl* copyurl(ParsedUrl* url); extern ParsedUrl* makeabsoluteurl(ParsedUrl* url, ParsedUrl* base); extern ParsedUrl* makequeryurl(ParsedUrl* url, Rune* q); extern int urlequal(ParsedUrl* a, ParsedUrl* b); extern int validurl(ParsedUrl* u); // STRINTTAB typedef struct StringInt StringInt; // Element of String-Int table (used for keyword lookup) struct StringInt { Rune* key; int val; }; extern int lookup(StringInt* t, int n, Rune* key, int keylen, int* pans); extern Rune* revlookup(StringInt* t, int n, int val); // IUTILS typedef struct Config Config; typedef struct ReqInfo ReqInfo; typedef struct MaskedImage MaskedImage; typedef struct CImage CImage; typedef struct Netconn Netconn; typedef struct Header Header; typedef struct ByteSource ByteSource; typedef struct ResourceState ResourceState; // HTTP methods enum { HGet, HPost }; // Media types (must track mnames in chutils.c) enum { ApplMsword, ApplOctets, ApplPdf, ApplPostscript, ApplRtf, ApplFramemaker, ApplMsexcel, ApplMspowerpoint, UnknownType, Audio32kadpcm, AudioBasic, ImageCgm, ImageG3fax, ImageGif, ImageIef, ImageJpeg, ImagePng, ImageTiff, ImageXBit, ImageXBit2, ImageXBitmulti, ImageXXBitmap, ModelVrml, MultiDigest, MultiMixed, TextCss, TextEnriched, TextHtml, TextJavascript, TextPlain, TextRichtext, TextSgml, TextTabSeparatedValues, TextXml, VideoMpeg, VideoQuicktime, NMEDIATYPES }; // Charsets (must track chsetnames in chutils.c) enum { UnknownCharset, US_Ascii, ISO_8859_1, UTF_8, Unicode, NCHARSETS }; // Frame Target IDs enum { FTtop, FTself, FTparent, FTblank }; // Error codes. // The HC codes can also be used as error codes enum { ERRnone = 0, // (no error) ERRaborted, // User aborted the get ERRunsupscheme, // Unsupported scheme ERRunexphscode, // Unexpected HTTP answer code ERRredirloop, // Redirect loop ERRstaterr, // Can't get file status ERRreaderr, // Read error ERRwriteerr, // Write error ERReof, // Unexpected end of file ERRconnecterr, // Couldn't connect ERRftperr, // FTP protocol error ERRftpnologin, // FTP login failed ERRhttperr, // HTTP protocol error ERRauthfailed, // Authorization failed ERRunsupimg, // Unsupported image type ERRnomem, // Not enough memory ERRimgbad, // Image encoding is bad }; // Netconn states enum { NCfree, NCidle, NCconnect, NCgethdr, NCgetdata, NCdone, NCerr, NNCSTATES }; // Netget protocol values enum { NGstartreq, NGwaitreq, NGstatechg, NGfreebs, NGabort, Punused, Pstart, Pconnected, Phavehdr, Phavedata, Pdone, Perr, Paborted, NNGVALUES }; // Colors (RGB values in bottom bottom bytes) // and extra Plan 9-style colors (with alpha in bottom byte) enum { White = 0xFFFFFF, Black = 0x000000, Grey = 0xDDDDDD, DarkGrey = 0x9D9D9D, LightGrey = 0xEDEDED, DarkestGrey = 0x666666, Blue = 0x0000CC, Navy = 0x000080, Red = 0xFF0000, DarkRed = 0x9D0000, DGrey = 0xDDDDDDFF }; // Header major status values (code/100) enum { HSNone, HSInformation, HSOk, HSRedirect, HSError, HSServererr, NHSVALUES }; // Individual status code values (HTTP, but use for other transports too) enum { HCContinue = 100, HCSwitchProto = 101, HCOk = 200, HCCreated = 201, HCAccepted = 202, HCOkNonAuthoritative = 203, HCNoContent = 204, HCResetContent = 205, HCPartialContent = 206, HCMultipleChoices = 300, HCMovedPerm = 301, HCMovedTemp = 302, HCSeeOther = 303, HCNotModified = 304, HCUseProxy = 305, HCBadRequest = 400, HCUnauthorized = 401, HCPaymentRequired = 402, HCForbidden = 403, HCNotFound = 404, HCMethodNotAllowed = 405, HCNotAcceptable = 406, HCProxyAuthRequired = 407, HCRequestTimeout = 408, HCConflict = 409, HCGone = 410, HCLengthRequired = 411, HCPreconditionFailed = 412, HCRequestTooLarge = 413, HCRequestURITooLarge = 414, HCUnsupportedMedia = 415, HCRangeInvalid = 416, HCExpectFailed = 419, HCServerError = 500, HCNotImplemented = 501, HCBadGateway = 502, HCServiceUnavailable = 503, HCGatewayTimeout = 504, HCVersionUnsupported = 505, HCRedirectionFailed = 506, NHCCODES }; // Max number of redirections tolerated #define Maxredir 10 // Image level config options enum { ImgNone, ImgNoAnim, ImgProgressive, ImgFull }; // User Configuration Information (Options) // Debug option letters: // 'd' -> Basic operation info (navigation, etc.) // 'e' -> Events (timing of progress through get/layout/image conversion) // 'h' -> Build layout items from lex tokens // 'i' -> Image conversion // 'l' -> Layout // 'n' -> transport (Network access) // 'o' -> always use old http (http/1.0) // 'p' -> synch Protocol between ByteSource/Netconn // 'r' -> Resource usage // 's' -> Scripts // 't' -> Table layout // 'u' -> use Uninstalled dis modules // 'w' -> Warn about recoverable problems in retrieved pages // 'x -> lex Html tokens struct Config { Rune* userdir; // where to find bookmarks, cache, etc. ParsedUrl* starturl; // never nil (could be last of command args) ParsedUrl* homeurl; // never nil ParsedUrl* httpproxy; // nil, if no proxy int defaultwidth; // of entire browser int defaultheight; // of entire browser int x; // initial x position for browser int y; // initial y position for browser int nocache; // true if shouldn't retrieve from or store to int maxstale; // allow cache hit even if exceed expiration by maxstale int imagelvl; // ImgNone, etc. int imagecachenum; // imcache.nlimit int imagecachemem; // imcache.memlimit int docookies; // allow cookie storage/sending? int doscripts; // allow scripts to execute? int saveauthinfo; // save auth info in file? int showprogress; // show progress area? int usecci; // allow external (CCI) control int httpminor; // use HTTP 1.httpminor Rune* agentname; // what to send in HTTP header int nthreads; // number of simultaneous gets allowed Rune* dbgfile; // file to write debug messages to uchar dbg[128]; // ascii letters for different debugging kinds }; // Information for fulfilling HTTP request struct ReqInfo { ParsedUrl* url; // should be absolute int method; // HGet or HPost uchar* body; // used for HPost int bodylen; // length of body array Rune* auth; // optional auth info int target; // target frame name }; // An image, a possible mask, possible animation frame info struct MaskedImage { Image* im; // the image Image* mask; // if non-nil, a mask for the image int delay; // if animated, delay in millisec before next frame int more; // true if more frames follow int bgcolor; // if not -1, restore to this (RGB) color before next frame Point origin; // origin of im relative to first frame of an animation }; // Cached Image info. // If this is an animated image then len mims > 1 struct CImage { CImage* next; // next (newer) image in cache ParsedUrl* src; // source of image ParsedUrl* actual; // what came back as actual source of image int imhash; // hash of src, for fast comparison int width; int height; int refcnt; // reference count of users of this image MaskedImage** mims; // frames int mimslen; // number of elems in mims }; // An connection to some host struct Netconn { int id; // for debugging int rnpid; // runnetconn pid, when a proc int rntid; // runnetconn tid, when a thread Rune* host; // host name int port; // port number int scheme; // Url->HTTP, etc. int cfd; // Control fd int dfd; // Data fd int state; // NCfree, etc. ByteSource** queue; // bytesources processed by this netconn // following are indexes into queue int qalloclen; // allocated size (in slots) of queue int qlen; // queue[0:qlen] is queue of requests int gocur; // go thread currently processing int ngcur; // ng threads currently processing int reqsent; // next to send request for int pipeline; // are requests being pipelined? int connected; // are we connected to host? int tstate; // for use by transport int tn1; // for use by transport int tn2; // for use by transport uchar* tbuf; // for use by transport int tbuflen; // length of tbuf }; // Info from an HTTP response header struct Header { int code; // HC... (detailed response code) ParsedUrl* actual; // actual request url (may be result of redir) ParsedUrl* base; // Content-Base or request url ParsedUrl* location; // Content-Location int length; // -1 if unknown int mtype; // TextHtml, etc. int chset; // for text types: ISO_8859, etc. Rune* msg; // possible message explaining status Rune* refresh; // used for server push Rune* chal; // used if code is HSneedauth Rune* warn; // should show this to user }; // A source of raw bytes (with HTTP info) struct ByteSource { int id; // for debugging ReqInfo* req; // how/where to get bytes Header* hdr; // filled in from headers uchar* data; // all the data, maybe partially filled int dalloclen; // length of allocated data member int edata; // data[0:edata] is valid int err; // there was an error Netconn* net; // servicing fd, etc. int refgo; // go proc is still using int refnc; // netconn proc is still using // consumer changes only these fields: int lim; // consumer has seen data[0:lim] int seenhdr; // consumer has seen hdr }; // For debugging time and space usage struct ResourceState { int ms; // milliseconds int mem; // bytes of memory in use int memavail; // bytes of memory still available }; extern Rune* hmeth[]; // String rep of HGet, etc. extern Rune* mnames[]; // String rep of ApplMsword, etc. extern Rune* chsetnames[]; // String rep of UnknownCharset, etc. extern Rune* ncstatenames[]; // String rep of NCfree, etc. extern Rune* hsnames[]; // String rep of HSNone, etc. extern Config config; // configuration options extern ResourceState startres; // starting resource state extern int dbg; // config.dbg['d'] extern int warn; // dbg || config.dbg['w'] extern int dbgev; // config.dbg['e'] extern void iutilsinit(int argc, char** argv); extern ByteSource* startreq(ReqInfo* req); extern ByteSource* waitreq(void); extern ByteSource* newstringbytesource(Rune* s); extern void freebs(ByteSource* bs); extern void abortgo(void); extern void netget(void* arg); extern ReqInfo* newreqinfo(ParsedUrl* url, int method, uchar* body, int bodylen, Rune* auth, int target); extern MaskedImage* newmaskedimage(Image* im); extern CImage* newcimage(ParsedUrl* src, int width, int height); extern int cimagematch(CImage* a, CImage* b); extern int cimagebytes(CImage* ci); extern void imcacheresetlimits(void); extern CImage* imcachelook(CImage* ci); extern void imcacheadd(CImage* ci); extern void imcachedeletelru(void); extern void imcacheclear(void); extern int imcacheneed(int nbytes); extern Header* newheader(void); extern void setmediatype(Header* h, Rune* name, uchar* first, int firstlen); extern void printheader(Header* h); extern ResourceState curresstate(void); extern ResourceState resstatesince(ResourceState rnew, ResourceState rold); extern void resstateprint(ResourceState r, char* msg); extern int getline(int fd, uchar* buf, int bufsize, int* pbstart, int* pbend, uchar** pans, int* panslen); extern int Strlookup(Rune** a, int n, Rune* s, int slen); extern Rune* hcphrase(int code); extern Rune* errphrase(int code); extern int hdraction(ByteSource* bs, int ismain, int nredirs, int* perror, Rune** pchallenge, ParsedUrl** predir); extern StringInt* makestrinttab(Rune** a, int n); extern void logtime(char* msg, int data); extern int color(Rune* s, int dflt); extern int targetid(Rune* s); extern Rune* targetname(int targid); extern void sendprogress(int bsid, int state, int pcnt, Rune* s); // TRANSPORT typedef struct Transport Transport; struct Transport { void (*init)(void); void (*connect)(Netconn* nc, ByteSource* bs); void (*writereq)(Netconn* nc, ByteSource* bs); void (*gethdr)(Netconn* nc, ByteSource* bs); void (*getdata)(Netconn* nc, ByteSource* bs); int (*defaultport)(int scheme); }; extern void httpinit(void); extern void httpconnect(Netconn* nc, ByteSource* bs); extern void httpwritereq(Netconn* nc, ByteSource* bs); extern void httpgethdr(Netconn* nc, ByteSource* bs); extern void httpgetdata(Netconn* nc, ByteSource* bs); extern int httpdefaultport(int scheme); extern void ftpinit(void); extern void ftpconnect(Netconn* nc, ByteSource* bs); extern void ftpwritereq(Netconn* nc, ByteSource* bs); extern void ftpgethdr(Netconn* nc, ByteSource* bs); extern void ftpgetdata(Netconn* nc, ByteSource* bs); extern int ftpdefaultport(int scheme); extern void fileinit(void); extern void fileconnect(Netconn* nc, ByteSource* bs); extern void filewritereq(Netconn* nc, ByteSource* bs); extern void filegethdr(Netconn* nc, ByteSource* bs); extern void filegetdata(Netconn* nc, ByteSource* bs); extern int filedefaultport(int scheme); extern void transportinit(void); #define TRANSMAX (FILE+1) extern Transport *transports[TRANSMAX]; // LEX typedef struct Token Token; typedef struct Attr Attr; typedef struct TokenSource TokenSource; // HTML 4.0 tags (plus blink, nobr) // sorted in lexical order; used as array indices enum { Notfound, Comment, Ta, Tabbr, Tacronym, Taddress, Tapplet, Tarea, Tb, Tbase, Tbasefont, Tbdo, Tbig, Tblink, Tblockquote, Tbody, Tbq, Tbr, Tbutton, Tcaption, Tcenter, Tcite, Tcode, Tcol, Tcolgroup, Tdd, Tdel, Tdfn, Tdir, Tdiv, Tdl, Tdt, Tem, Tfieldset, Tfont, Tform, Tframe, Tframeset, Th1, Th2, Th3, Th4, Th5, Th6, Thead, Thr, Thtml, Ti, Tiframe, Timg, Tinput, Tins, Tisindex, Tkbd, Tlabel, Tlegend, Tli, Tlink, Tmap, Tmenu, Tmeta, Tnobr, Tnoframes, Tnoscript, Tobject, Tol, Toptgroup, Toption, Tp, Tparam, Tpre, Tq, Ts, Tsamp, Tscript, Tselect, Tsmall, Tspan, Tstrike, Tstrong, Tstyle, Tsub, Tsup, Ttable, Ttbody, Ttd, Ttextarea, Ttfoot, Tth, Tthead, Ttitle, Ttr, Ttt, Tu, Tul, Tvar, Numtags, RBRA = Numtags, Data = Numtags+RBRA }; //HTML 4.0 tag attributes // Keep sorted in lexical order enum { Aabbr, Aaccept_charset, Aaccess_key, Aaction, Aalign, Aalink, Aalt, Aarchive, Aaxis, Abackground, Abgcolor, Aborder, Acellpadding, Acellspacing, Achar, Acharoff, Acharset, Achecked, Acite, Aclass, Aclassid, Aclear, Acode, Acodebase, Acodetype, Acolor, Acols, Acolspan, Acompact, Acontent, Acoords, Adata, Adatetime, Adeclare, Adefer, Adir, Adisabled, Aenctype, Aface, Afor, Aframe, Aframeborder, Aheaders, Aheight, Ahref, Ahreflang, Ahspace, Ahttp_equiv, Aid, Aismap, Alabel, Alang, Alink, Alongdesc, Amarginheight, Amarginwidth, Amaxlength, Amedia, Amethod, Amultiple, Aname, Anohref, Anoresize, Anoshade, Anowrap, Aobject, Aonblur, Aonchange, Aonclick, Aondblclick, Aonfocus, Aonkeypress, Aonkeyup, Aonload, Aonmousedown, Aonmousemove, Aonmouseout, Aonmouseover, Aonmouseup, Aonreset, Aonselect, Aonsubmit, Aonunload, Aprofile, Aprompt, Areadonly, Arel, Arev, Arows, Arowspan, Arules, Ascheme, Ascope, Ascrolling, Aselected, Ashape, Asize, Aspan, Asrc, Astandby, Astart, Astyle, Asummary, Atabindex, Atarget, Atext, Atitle, Atype, Ausemap, Avalign, Avalue, Avaluetype, Aversion, Avlink, Avspace, Awidth, Numattrs }; struct Token { int tag; // Ta, etc Rune* text; // text in Data, attribute text in tag Attr* attr; // list of Attrs int starti; // index into source buffer of token start }; struct Attr { Attr* next; // in list of attrs for a token int attid; // Aabbr, etc. Rune* value; }; struct TokenSource { int i; // index of next byte to use ByteSource* b; int chset; // one of CU->US_Ascii, etc. int mtype; // CU->TextHtml or CU->TextPlain int ihigh; // high water mark of i }; extern Rune* tagnames[]; extern Rune* attrnames[]; extern void lexinit(void); extern int tokaval(Token* t, int attid, Rune** pans, int xfer); extern TokenSource* newtokensource(ByteSource* b, int chset, int mtype); extern Attr* newattr(int attid, Rune* value, Attr* link); extern Token* gettoks(TokenSource* ts, int* plen); #pragma varargck type "T" Token* // BUILD typedef struct Item Item; typedef struct Itext Itext; typedef struct Irule Irule; typedef struct Iimage Iimage; typedef struct Iformfield Iformfield; typedef struct Itable Itable; typedef struct Ifloat Ifloat; typedef struct Ispacer Ispacer; typedef struct Itemlist Itemlist; typedef struct Genattr Genattr; typedef struct Formfield Formfield; typedef struct Option Option; typedef struct Form Form; typedef struct Table Table; typedef struct Tablecol Tablecol; typedef struct Tablerow Tablerow; typedef struct Tablecell Tablecell; typedef struct Align Align; typedef struct Dimen Dimen; typedef struct Anchor Anchor; typedef struct DestAnchor DestAnchor; typedef struct Map Map; typedef struct Area Area; typedef struct Background Background; typedef struct Kidinfo Kidinfo; typedef struct Docinfo Docinfo; typedef struct Stack Stack; typedef struct Pstate Pstate; typedef struct ItemSource ItemSource; typedef struct Lay Lay; // defined in Layout module // Alignment types enum { ALnone = 0, ALleft, ALcenter, ALright, ALjustify, ALchar, ALtop, ALmiddle, ALbottom, ALbaseline }; struct Align { uchar halign; // one of ALnone, ALleft, etc. uchar valign; // one of ALnone, ALtop, etc. }; // A Dimen holds a dimension specification, especially for those // cases when a number can be followed by a % or a * to indicate // percentage of total or relative weight. // Dnone means no dimension was specified // To fit in a word, use top bits to identify kind, rest for value enum { Dnone = 0, Dpixels = (1<<29), Dpercent = (2<<29), Drelative = (3<<29), Dkindmask = (3<<29), Dspecmask = (~Dkindmask) }; struct Dimen { int kindspec; // kind | spec }; // Background is either an image or a color. // If both are set, the image has precedence. struct Background { CImage* image; int color; }; // There are about a half dozen Item variants. // The all look like this at the start, and then the tag // field dictates what extra fields there are. struct Item { Item* next; // successor in list of items int width; // width in pixels (0 for floating items) int height; // height in pixels int ascent; // ascent (from top to baseline) in pixels int anchorid; // if nonzero, which anchor we're in int state; // flags and values (see below) Genattr* genattr; // generic attributes and events int tag; // variant discriminator: Itexttag, etc. }; // Item variant tags enum { Itexttag, Iruletag, Iimagetag, Iformfieldtag, Itabletag, Ifloattag, Ispacertag }; struct Itext { Item* next; int width; int height; int ascent; int anchorid; int state; Genattr* genattr; int tag; // Itexttag Rune* s; // the characters int fnt; // style*NumSize+size (see font stuff, below) int fg; // Pixel (color) for text uchar voff; // Voffbias+vertical offset from baseline, in pixels (+ve == down) uchar ul; // ULnone, ULunder, or ULmid }; struct Irule { Item* next; int width; int height; int ascent; int anchorid; int state; Genattr* genattr; int tag; // Iruletag uchar align; // alignment spec uchar noshade; // if true, don't shade int size; // size attr (rule height) Dimen wspec; // width spec }; struct Iimage { Item* next; int width; int height; int ascent; int anchorid; int state; Genattr* genattr; int tag; // Iimagetag CImage* ci; // cached image (has src, actual width, height) int imwidth; // spec width (actual, if no spec) int imheight; // spec height (actual, if no spec) Rune* altrep; // alternate representation, in absence of image Map* map; // if non-nil, client side map int ctlid; // if animated uchar align; // vertical alignment uchar hspace; // in pixels; buffer space on each side uchar vspace; // in pixels; buffer space on top and bottom uchar border; // in pixels: border width to draw around image Iimage* nextimage; // next in list of document's images }; struct Iformfield { Item* next; int width; int height; int ascent; int anchorid; int state; Genattr* genattr; int tag; // Iformtag Formfield *formfield; }; struct Itable { Item* next; int width; int height; int ascent; int anchorid; int state; Genattr* genattr; int tag; // Itabletag Table* table; }; struct Ifloat { Item* next; int width; int height; int ascent; int anchorid; int state; Genattr* genattr; int tag; Item* item; // Ifloattag int x; // x coord of top (from right, if ALright) int y; // y coord of top uchar side; // margin it floats to: ALleft or ALright uchar infloats; // true if this has been added to a lay.floats Ifloat* nextfloat; // in list of floats }; struct Ispacer { Item* next; int width; int height; int ascent; int anchorid; int state; Genattr* genattr; int tag; // Ispacertag int spkind; // ISPnull, etc. }; // Item state flags and value fields enum { IFbrk = 0x80000000, // forced break before this item IFbrksp = 0x40000000, // add 1 line space to break (IFbrk set too) IFnobrk = 0x20000000, // break not allowed before this item IFcleft = 0x10000000, // clear left floats (IFbrk set too) IFcright = 0x08000000, // clear right floats (IFbrk set too) IFwrap = 0x04000000, // in a wrapping (non-pre) line IFhang = 0x02000000, // in a hanging (into left indent) item IFrjust = 0x01000000, // right justify current line IFcjust = 0x00800000, // center justify current line IFsmap = 0x00400000, // image is server-side map IFindentshift = 8, IFindentmask = (255<events of containing item }; enum { FFchecked = (1<<7), FFmultiple = (1<<6) }; // Option holds info about an option in a "select" form field struct Option { Option* next; // next in list of options for a field int selected; // true if selected initially Rune* value; // value attr Rune* display; // display string }; // Form holds info about a form struct Form { Form* next; // in list of forms for document int formid; // serial no. of form within its doc Rune* name; // name or id attr (netscape uses name, HTML 4.0 uses id) ParsedUrl* action; // action attr int target; // target attr as targetid int method; // HGet or HPost int nfields; // number of fields Formfield* fields; // field's forms, in input order }; // Flags used in various table structures enum { TFparsing = (1<<7), TFnowrap = (1<<6), TFisth = (1<<5) }; // Information about a table struct Table { Table* next; // next in list of document's tables int tableid; // serial no. of table within its doc Tablerow* rows; // array of row specs (list during parsing) int nrow; // total number of rows Tablecol* cols; // array of column specs int ncol; // total number of columns Tablecell* cells; // list of unique cells int ncell; // total number of cells Tablecell*** grid; // 2-D array of cells Align align; // alignment spec for whole table Dimen width; // width spec for whole table int border; // border attr int cellspacing; // cellspacing attr int cellpadding; // cellpadding attr Background background; // table background Item* caption; // linked list of Items, giving caption uchar caption_place; // ALtop or ALbottom Lay* caption_lay; // layout of caption int totw; // total width int toth; // total height int caph; // caption height int availw; // used for previous 3 sizes Token* tabletok; // token that started the table uchar flags; // Lchanged, perhaps }; struct Tablecol { int width; Align align; Point pos; }; struct Tablerow { Tablerow* next; // Next in list of rows, during parsing Tablecell* cells; // Cells in row, linked through nextinrow int height; int ascent; Align align; Background background; Point pos; uchar flags; // 0 or TFparsing }; // A Tablecell is one cell of a table. // It may span multiple rows and multiple columns. // Cells are linked on two lists: the list for all the cells of // a document (the next pointers), and the list of all the // cells that start in a given row (the nextinrow pointers) struct Tablecell { Tablecell* next; // next in list of table's cells Tablecell* nextinrow; // next in list of row's cells int cellid; // serial no. of cell within table Item* content; // contents before layout Lay* lay; // layout of cell int rowspan; // number of rows spanned by this cell int colspan; // number of cols spanned by this cell Align align; // alignment spec uchar flags; // TFparsing, TFnowrap, TFisth Dimen wspec; // suggested width int hspec; // suggested height Background background; // cell background int minw; // minimum possible width int maxw; // maximum width int ascent; // cell's ascent int row; // row of upper left corner int col; // col of upper left corner Point pos; // nw corner of cell contents, in cell }; // Anchor is for info about hyperlinks that go somewhere struct Anchor { Anchor* next; // next in list of document's anchors int index; // serial no. of anchor within its doc Rune* name; // name attr ParsedUrl* href; // href attr int target; // target attr as targetid }; // DestAnchor is for info about hyperlinks that are destinations struct DestAnchor { DestAnchor* next; // next in list of document's destanchors int index; // serial no. of anchor within its doc Rune* name; // name attr Item* item; // the destination }; // Maps (client side) struct Map { Map* next; // next in list of document's maps Rune* name; // map name Area* areas; // list of map areas }; struct Area { Area* next; // next in list of a map's areas int shape; // SHrect, etc. ParsedUrl* href; // associated hypertext link int target; // associated target frame Dimen* coords; // array of coords for shape int ncoords; // size of coords array }; // Area shapes enum { SHrect, SHcircle, SHpoly }; // Fonts are represented by integers: style*NumSize + size // Font styles enum { FntR, // roman FntI, // italic FntB, // bold FntT, // typewriter NumStyle }; // Font sizes enum { Tiny, Small, Normal, Large, Verylarge, NumSize }; enum { NumFnt = (NumStyle*NumSize), DefFnt = (FntR*NumSize+Normal) }; // Lines are needed through some text items, for underlining or strikethrough enum { ULnone, ULunder, ULmid }; // List number types enum { LTdisc, LTsquare, LTcircle, LT1, LTa, LTA, LTi, LTI }; // Kidinfo flags enum { FRnoresize = (1<<0), FRnoscroll = (1<<1), FRhscroll = (1<<2), FRvscroll = (1<<3), FRhscrollauto = (1<<4), FRvscrollauto = (1<<5) }; // Information about child frame or frameset struct Kidinfo { Kidinfo* next; // in list of kidinfos for a frameset int isframeset; // fields for "frame" ParsedUrl* src; // only nil if a "dummy" frame or this is frameset Rune* name; // always non-empty if this isn't frameset int marginw; int marginh; int framebd; int flags; // fields for "frameset" Dimen* rows; // array of row dimensions int nrows; // length of rows Dimen* cols; // array of col dimensions int ncols; // length of cols Kidinfo* kidinfos; Kidinfo* nextframeset; // parsing stack }; // Document info (global information about HTML page) struct Docinfo { // stuff from HTTP headers, doc head, and body tag ParsedUrl* src; // original source of doc ParsedUrl* base; // base URL of doc Rune* doctitle; // from element Background background; // background specification Iimage* backgrounditem; // Image Item for doc background image, or nil int text; // doc foreground (text) color int link; // unvisited hyperlink color int vlink; // visited hyperlink color int alink; // highlighting hyperlink color int target; // target frame default int chset; // ISO_8859, etc. int scripttype; // CU->TextJavascript, etc. int hasscripts; // true if scripts used Rune* refresh; // content of <http-equiv=Refresh ...> Kidinfo* kidinfo; // if a frameset int frameid; // id of document frame // info needed to respond to user actions Anchor* anchors; // list of href anchors DestAnchor* dests; // list of destination anchors Form* forms; // list of forms Table* tables; // list of tables Map* maps; // list of maps Iimage* images; // list of image items (through nextimage links) }; // Parsing stuff // A stack for holding integer values enum { Nestmax = 20 // max nesting level of lists, font styles, etc. }; struct Stack { int n; // next available slot (top of stack is stack[n-1]) int slots[Nestmax]; // stack entries }; // Parsing state struct Pstate { Pstate* next; // in stack of Pstates int skipping; // true when we shouldn't add items int skipwhite; // true when we should strip leading space int curfont; // font index for current font int curfg; // current foreground color Background curbg; // current background int curvoff; // current baseline offset uchar curul; // current underline/strike state uchar curjust; // current justify state int curanchor; // current (href) anchor id (if in one), or 0 int curstate; // current value of item state int literal; // current literal state int inpar; // true when in a paragraph-like construct int adjsize; // current font size adjustment Item* items; // dummy head of item list we're building Item* lastit; // tail of item list we're building Item* prelastit; // item before lastit Stack fntstylestk; // style stack Stack fntsizestk; // size stack Stack fgstk; // text color stack Stack ulstk; // underline stack Stack voffstk; // vertical offset stack Stack listtypestk; // list type stack Stack listcntstk; // list counter stack Stack juststk; // justification stack Stack hangstk; // hanging stack }; struct ItemSource { TokenSource* ts; int mtype; Docinfo* doc; Pstate* psstk; int nforms; int ntables; int nanchors; int nframes; Form* curform; Map* curmap; Table* tabstk; Kidinfo* kidstk; }; extern void buildinit(void); extern ItemSource* newitemsource(ByteSource* bs, Docinfo* di, int mtype); extern Item* getitems(ItemSource* is); extern Background makebackground(CImage* ci, int color); extern Item* newitext(Rune* s, int fnt, int fg, int voff, int ul); extern Item* newirule(int align, int size, int noshade, Dimen wspec); extern Item* newiimage(ParsedUrl* src, Rune* altrep, int align, int width, int height, int hspace, int vspace, int border, int ismap, Map* map); extern Item* newiformfield(Formfield* ff); extern Item* newitable(Table* t); extern Item* newifloat(Item* it, int side); extern Item* newispacer(int spkind); extern Itemlist* newitemlist(Item* val, Itemlist* rest); extern void printitems(Item* items, char* msg); extern Genattr* newgenattr(Rune* id, Rune* class, Rune* style, Rune* title, Attr* events); extern Formfield* newformfield(int ftype, int fieldid, Form* form, Rune* name, Rune* value, int size, int maxlength, Formfield* link); extern Option* newoption(int selected, Rune* value, Rune* display, Option* link); extern Form* newform(int formid, Rune* name, ParsedUrl* action, int target, int method, Form* link); extern Table* newtable(int tableid, Align align, Dimen width, int border, int cellspacing, int cellpadding, Background bg, Token* tok, Table* link); extern Tablerow* newtablerow(Align align, Background bg, int flags, Tablerow* link); extern Tablecell* newtablecell(int cellid, int rowspan, int colspan, Align align, Dimen wspec, int hspec, Background bg, int flags, Tablecell* link); extern Anchor* newanchor(int index, Rune* name, ParsedUrl* href, int target, Anchor* link); extern DestAnchor* newdestanchor(int index, Rune* name, Item* item, DestAnchor* link); extern Dimen makedimen(int kind, int spec); extern int dimenkind(Dimen d); extern int dimenspec(Dimen d); extern Area* newarea(int shape, ParsedUrl* href, int target, Area* link); extern Kidinfo* newkidinfo(int isframeset, Kidinfo* link); extern Docinfo* newdocinfo(void); extern void resetdocinfo(Docinfo* d); extern int validitem(Item* i); extern int validitems(Item* i); extern int validformfield(Formfield* f); extern int validtable(Table* t); extern int validtablerow(Tablerow* r); extern int validtablecol(Tablecol* c); extern int validtablecell(Tablecell* c); #pragma varargck type "I" Item* // LAYOUT typedef struct Frame Frame; typedef struct Framelist Framelist; typedef struct Line Line; typedef struct Loc Loc; typedef struct Locelem Locelem; typedef struct Control Control; typedef struct Cbutton Cbutton; typedef struct Centry Centry; typedef struct Ccheckbox Ccheckbox; typedef struct Cselect Cselect; typedef struct Cscrollbar Cscrollbar; typedef struct Canimimage Canimimage; typedef struct Cprogbox Cprogbox; typedef struct Clabel Clabel; // Border relief size and types enum { ReliefSunk, ReliefRaised, ReliefBd = 2 }; struct Frame { int id; // unique id Docinfo* doc; // various global attributes from HTML and headers ParsedUrl* src; // original source of page Rune* name; // current name (assigned by parent frame, or by default) int marginw; // margin on sides int marginh; // margin on top and bottom int framebd; // frame border desired int flags; // FRnoresize, etc. Lay* layout; // representation of layout Control** controls; // array of controls int controlslen; // number of control slots allocated int controlid; // next control id to use Image* cim; // image where we draw contents Rectangle r; // part of cimage.r for this frame (including scrollbars) Rectangle cr; //part of r for contents (excluding scrollbars, including margins) Rectangle totalr; // total rectangle for page -- (0,0) is top left Rectangle viewr; // view: subrect of pager currently on screen Control* vscr; // vertical scrollbar Control* hscr; // horizontal scrollbar Frame* parent; // if this frame is in a frameset Framelist* kids; // if this frame is a frameset }; struct Framelist { Framelist* next; Frame* val; }; // Line flags enum { Ldrawn = (1<<0), Lmoved = (1<<1), Lchanged = (1<<2) }; // Layout engine organizes Items into Lines struct Line { Line* next; // next line Line* prev; // previous line Item* items; // Items for the line Point pos; // position of line in frame cim coord system int width; // in pixels int height; // in pixels int ascent; // in pixels uchar flags; // Ldrawn, etc. }; // A place where an item, or a where mouse or keyboard focus could be. struct Loc { Locelem* le; // array of Locelems, from outermost inward int lelen; // number of slots allocated for le int n; // number of slots in use Point pos; // offset in final item }; struct Locelem { int kind; // LEframe, etc. Point pos; // position in screen coords of this element Frame* frame; // root, or kid of previous (a frame) Line* line; // a line in lay of previous Item* item; // an item in previous (a line or item) Tablecell* tcell; // a cell in previous (a table item) Control* control; // a control in previous item, or scrollbar in previous frame }; enum { LEframe, LEline, LEitem, LEtablecell, LEcontrol, }; // There are a number of different Control structure variants // They all start off like this. struct Control { Frame* f; // frame containing the control Formfield* ff; // formfield, if any, that control is for Rectangle r; // coords in f.cim coord system int flags; // CFactive, etc. int tag; // Cbuttontag, etc.: says which variant }; struct Cbutton { Frame* f; Formfield* ff; Rectangle r; int flags; int tag; // Cbuttontag Image* pic; // picture on button (if no label) Image* picmask; // mask for pic Image* dpic; // disabled ("greyed out") pic Image* dpicmask; // mask for dpic Rune* label; // label on button (if no pic), or else flyover hint int dorelief; // draw background & relief? }; struct Centry { Frame* f; Formfield* ff; Rectangle r; int flags; int tag; // Centrytag Rune* s; // current contents int curs; // index of character in s that cursor is before int left; // index of character in s that is at left of window int linewrap; // true if supposed to line-wrap }; struct Ccheckbox { Frame* f; Formfield* ff; Rectangle r; int flags; int tag; // Ccheckboxtag int isradio; // true if for radio button }; struct Cselect { Frame* f; Formfield* ff; Rectangle r; int flags; int tag; Cscrollbar* scr; // Scrollbar, if needed int nvis; // number of visible options int first; // index of current top visible option Option* options; // an array of the options int noptions; // length of options }; struct Cscrollbar { Frame* f; Formfield* ff; Rectangle r; int flags; int tag; // Cscrollbartag int top; // pixels in trough above/left of slider int bot; // pixels in trough below/right of slider int dragv; // drag point int mindelta; // need delta of at least this (pixels) Control* ctl; // if non-nil, scrolls this control }; struct Canimimage { Frame* f; Formfield* ff; Rectangle r; int flags; int tag; // Canimimagetag CImage* cim; // contains mims array to animate int cur; // current slot in mims array int redraw; // need to redraw all? Background bg; // if need restore-to-background }; struct Cprogbox { Frame* f; Formfield* ff; Rectangle r; int flags; int tag; // Cprogboxtag int state; // Pstart, etc. int pcnt; // percent done int bsid; // bytesource id Rune* src; // bytesource req.url Rune* err; // possible error string }; struct Clabel { Frame* f; Formfield* ff; Rectangle r; int flags; int tag; // Clabeltag Rune* s; // text of label }; // Control variants enum { Cbuttontag, Centrytag, Ccheckboxtag, Cselecttag, Cscrollbartag, Canimimagetag, Cprogboxtag, Clabeltag }; // Control flags enum { CFactive = (1<<0), CFenabled = (1<<1), CFhasfocus = (1<<2), CFscrvert = (1<<3), CFscracta1 = (1<<4), CFscracta2 = (1<<5), CFscracttr1 = (1<<6), CFscracttr2 = (1<<7), CFscrallact = (CFactive|CFscracta1|CFscracta2|CFscracttr1|CFscracttr2) }; // Control actions enum { CAnone, CAscrollpage, CAscrollline, CAscrolldelta, CAscrollabs, CAbuttonpush, CAflyover, CAreturnkey, CAtabkey, CAkeyfocus }; // Result of layout struct Lay { Line* start; // fake before-the-first-line Line* end; // fake after-the-last-line int targetwidth; // target width int width; // actual width int height; // actual height int margin; // extra space on all four sides Ifloat* floats; // floats, from bottom up Background background; // background for layout uchar just; // default line justification uchar flags; // Lchanged }; extern void layoutinit(void); extern int layout(Frame* f, ByteSource* bs, uchar** pbuf); extern void drawrelief(Image* im, Rectangle r, int style); extern void drawborder(Image* im, Rectangle r, int n, int color); extern void drawfill(Image* im, Rectangle r, int color); extern void drawstring(Image* im, Point p, Rune* s); extern Point measurestring(Rune* s); extern Frame* newkid(Frame* parent, Kidinfo* ki, Rectangle r); extern Frame* newframe(void); extern Frame* newkid(Frame* parent, Kidinfo* ki, Rectangle r); extern Framelist* newframelist(Frame* frame, Framelist* next); extern void resetframe(Frame* f); extern int addcontrol(Frame* f, Control* c); extern Point lptosp(Frame* f, Point lp); extern Point sptolp(Frame* f, Point sp); extern void xscroll(Frame* f, int kind, int val); extern void yscroll(Frame* f, int kind, int val); extern Loc* findloc(Frame* f, Point p, Item* it); extern Line* newline(void); extern Loc* newloc(void); extern void addloc(Loc* loc, int kind, Point pos); extern Frame* lastframe(Loc* loc); extern void printloc(Loc* loc, char* msg); extern Control* newff(Frame* f, Formfield* ff); extern Control* newscroll(Frame* f, int isvert, int length, int breadth); extern Control* newentry(Frame* f, int nh, int nv, int linewrap); extern Control* newbutton(Frame* f, Image* pic, Image* picmask, Rune* lab, Iimage* it, int candisable, int dorelief); extern Control* newcheckbox(Frame* f, int isradio); extern Control* newselect(Frame* f, int nvis, Option* options, int noptions); extern Control* newanimimage(Frame* f, CImage* cim, Background bg); extern Control* newprogbox(Frame* f); extern Control* newlabel(Frame* f, Rune* s); extern void disable(Control* b); extern void enable(Control* b); extern void losefocus(Control* b); extern void gainfocus(Control* b); extern void scrollset(Control* sc, int v1, int v2, int vmax, int mindelta); extern void entryset(Control* e, Rune* s); extern int dokey(Control* c, int keychar); extern int domouse(Control* c, Point p, int mtype); extern void resetctl(Control* c); extern void drawctl(Control* c, int flush); extern Lay* newlay(int targetwidth, int just, int margin, Background bg); // IMG typedef struct ImageSource ImageSource; typedef struct Jpegstate Jpegstate; typedef struct Huffman Huffman; typedef struct Framecomp Framecomp; typedef struct Scancomp Scancomp; typedef struct Gifstate Gifstate; typedef struct GifEntry GifEntry; enum { Mimerror, Mimnone, Mimpartial, Mimdone }; struct ImageSource { int width; int height; int origw; int origh; int mtype; int i; int curframe; ByteSource* bs; Gifstate* gstate; Jpegstate* jstate; int err; jmp_buf getmimsave; }; struct Jpegstate { int sr; int cnt; int Nf; Framecomp* comp; uchar mode; int X; int Y; int** qt; Huffman** dcht; Huffman** acht; int Ns; Scancomp* scomp; int Ss; int Se; int Ah; int Al; int ri; int nseg; int* nblock; int** dccoeff; int*** accoeff; int nacross; int ndown; int Hmax; int Vmax; }; struct Huffman { int* bits; int* size; int* code; int* val; int mincode[17]; int maxcode[17]; int valptr[17]; int value[256]; int shift[256]; }; struct Framecomp { int C; int H; int V; int Tq; }; struct Scancomp { int C; int tdc; int tac; }; struct Gifstate { int fields; int bgrnd; int aspect; int flags; int delay; uchar trindex; GifEntry* tbl; uchar* globalcmap; int globalcmaplen; uchar* cmap; int cmaplen; }; struct GifEntry { int prefix; int exten; }; extern void imginit(void); extern int supported(int mtype); extern int closest_rgbpix(int r, int g, int b); extern ImageSource* newimagesource(ByteSource* bs, int w, int h); extern int getmim(ImageSource* is, MaskedImage** pans); // EVENT typedef struct EV EV; typedef struct ScriptEvent ScriptEvent; enum { EVkeytag, EVmousetag, EVmovetag, EVresizetag, EVexposetag, EVhidetag, EVquittag, EVstoptag, EValerttag, EVformtag, EVgotag, EVanimtag, EVprogresstag, EVdelaytag }; struct EV { int tag; // EVkeytag, etc. int genframeid; // frame that generated event (or -1) union { int keychar; // Unicode char for pressed key struct { Point p; // coords of pointer int mtype; // Mmove, etc. } mouse; Point movept; // new top-left of moved window Rectangle resizer; // new window place and size struct { Rune* msg; // message to show Channel* sync; // wait for answer } alert; struct { int frameid; // which frame form is in int formid; // which form in the frame int ftype; // EFsubmit or EFreset } form; struct { ParsedUrl* url; // where to go int target; // frame to replace int gtype; // EGnormal, etc. } go; struct { int frameid; // frame where ai lives Canimimage* ai; // advance frame for this image } anim; struct { int bsid; // byte source id int state; // Pstart, etc. int pcnt; // percent done Rune* s; // message } progress; struct { int millisecs; // time to wait before acting on ev EV* ev; // the delayed event } delay; } u; }; // Events sent to scripting engines struct ScriptEvent { int kind; int frameid; int formid; int fieldid; int anchorid; int x; int y; int which; }; // some special keychars (use Unicode Private Area) enum { Kup = 0xF000, Kdown, Khome, Kleft, Kright }; // Mouse event subtypes enum { Mmove, Mlbuttondown, Mlbuttonup, Mldrag, Mmbuttondown, Mmbuttonup, Mmdrag, Mrbuttondown, Mrbuttonup, Mrdrag }; // Form event subtypes enum { EFsubmit, EFreset }; // Go event subtypes enum { EGnormal, EGreload, EGforward, EGback, EGhome, EGbookmarks }; extern Channel* evchan; extern void eventinit(void); extern EV evgo(ParsedUrl* u, int targ, int gtype, int genframeid); extern EV evmouse(Point p, int mtype); extern EV evkey(int keycode); #pragma varargck type "M" EV* // GUI extern Rectangle rmain; extern Rectangle rctl; extern Rectangle rprog; extern void guiinit(void); extern void pushclipr(Rectangle r); extern void replaceclipr(Rectangle r); extern void popclipr(void); extern Image* makepopup(int width, int height); // ICONS // Built-in icon identifiers enum { IClogo, ICback, ICfwd, ICreload, ICstop, IChist, ICbmark, ICexit, NICONS }; extern Image* geticon(int icon, Image** pmask); // I typedef struct GoSpec GoSpec; typedef struct DocConfig DocConfig; typedef struct HistNode HistNode; typedef struct HistNode_list HistNode_list; typedef struct History History; typedef struct AuthInfo AuthInfo; typedef struct CtlLayout CtlLayout; typedef struct ProgLayout ProgLayout; typedef struct PopupLayout PopupLayout; typedef struct PopupAns PopupAns; // package up info related to a navigation command struct GoSpec { int kind; // GoNormal, etc. ParsedUrl* url; // destination (absolute) int meth; // HGet or HPost Rune* body; // used if HPost int target; // name of target frame Rune* auth; // optional auth info HistNode* histnode; // if kind is GoHistnode }; enum { GoNormal, GoHistnode, GoBookmarks, GoHistory, GoStop }; // Information about a set of frames making up the screen struct DocConfig { Rune* framename; // nonempty, except possibly for topconfig Rune* title; int initconfig; // true unless this is a frameset and some subframe changed GoSpec* gospec; // TODO: add current y pos and form field values }; // Information about a particular screen configuration struct HistNode { DocConfig* topconfig; // config of top (whole doc, or frameset root) DocConfig** kidconfigs; // configs for kid frames (if a frameset) int nkids; HistNode_list* preds; // edges in (via normal navigation) HistNode_list* succs; // edges out (via normal navigation) }; // For keeping lists of HistNodes struct HistNode_list { HistNode_list* next; // in list HistNode* histnode; }; // The browsing history struct History { HistNode** h; // array of all visited HistNodes, in LRU order int hlen; // allocated length of h int n; // h[0:n] is valid part of h }; // Authentication strings struct AuthInfo { AuthInfo* next; // in list of all auths Rune* realm; Rune* credentials; }; // Indices into layout controls array enum { CLCbackbut, CLCfwdbut, CLCreloadbut, CLCstopbut, CLChistbut, CLCbmarkbut, CLCexitbut, CLCentry, NUMCLCS }; struct CtlLayout { Image* logoicon; Point logopos; Point butspos; Point entrypos; Point statuspos; Control* controls[NUMCLCS]; Rune* status; }; struct ProgLayout { Control** box; int boxlen; int nused; Point first; int dx; }; struct PopupLayout { int kind; // PopupNone, PopupAuth, PopupSaveAs, or PopupAlert Control** controls; int ncontrols; Control* okbut; Control* cancelbut; }; enum { PopupNone, PopupAuth, PopupSaveAs, PopupAlert }; struct PopupAns { int code; Rune* s; }; extern void fatalerror(char* msg); extern void finish(void); extern void trace(char* msg, ...); // GC extern void gcinit(void); // DEBUGGING extern void poolshow(void);