#include <u.h>
#include <libc.h>
#include <draw.h>
#include <ctype.h>
#include <thread.h>
#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<<IFindentshift), // current indent, in tab stops
IFhangmask = 255 // current hang into left indent, in 1/10th tabstops
};
// Bias added to Itext's voff field
enum { Voffbias = 128 };
// Spacer kinds
enum {
ISPnull, // 0 height and width
ISPvline, // height and ascent of current font
ISPhspace, // width of space in current font
ISPgeneral // other purposes (e.g., between markers and list)
};
struct Itemlist
{
Itemlist* next;
Item* val;
};
// Generic attributes and events (not many elements will have any of these set)
struct Genattr
{
Rune* id;
Rune* class;
Rune* style;
Rune* title;
Attr* events;
};
// Form field types
enum {
Ftext,
Fpassword,
Fcheckbox,
Fradio,
Fsubmit,
Fhidden,
Fimage,
Freset,
Ffile,
Fbutton,
Fselect,
Ftextarea
};
// Information about a field in a form
struct Formfield
{
Formfield* next; // in list of fields for a form
int ftype; // Ftext, Fpassword, etc.
int fieldid; // serial no. of field within its form
Form* form; // containing form
Rune* name; // name attr
Rune* value; // value attr
int size; // size attr
int maxlength; // maxlength attr
int rows; // rows attr
int cols; // cols attr
uchar flags; // FFchecked, etc.
Option* options; // for Fselect fields
Item* image; // image item, for Fimage fields
int ctlid; // identifies control for this field in layout
Attr* events; // same as genattr->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 <title> 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);
|