void set_td_width(struct table *t, int x, int width, int f) { if (x >= t->xc) { int n = t->xc ? t->xc : 1; int i; int *nc; while (x >= n) { if ((unsigned)n > MAXINT / 2) overalloc(); n *= 2; } if ((unsigned)n > MAXINT / sizeof(int)) overalloc(); nc = mem_realloc(t->xcols, n * sizeof(int)); for (i = t->xc; i < n; i++) nc[i] = W_AUTO; t->xc = n; t->xcols = nc; } if (t->xcols[x] == W_AUTO || f) { set: t->xcols[x] = width; return; } if (width == W_AUTO) return; if (width < 0 && t->xcols[x] >= 0) goto set; if (width >= 0 && t->xcols[x] < 0) return; t->xcols[x] = (t->xcols[x] + width) / 2; }
void alloc_term_screen(struct terminal *term, int x, int y) { unsigned *s, *t; if (x && (unsigned)x * (unsigned)y / (unsigned)x != (unsigned)y) overalloc(); if ((unsigned)x * (unsigned)y > MAXINT / sizeof(unsigned)) overalloc(); s = mem_realloc(term->screen, x * y * sizeof(unsigned)); t = mem_realloc(term->last_screen, x * y * sizeof(unsigned)); memset(t, -1, x * y * sizeof(unsigned)); term->x = x; term->y = y; term->last_screen = t; memset(s, 0, x * y * sizeof(unsigned)); term->screen = s; term->dirty = 1; }
static void flip_buffer(void *buf,int width,int height) { if (htonl(0x12345678L)!=0x12345678L) /* little endian --- ja to chci na intelu rychly!!! */ { #ifdef t4c t4c* buffer=(t4c*)buf; register t4c a,b; t4c *p,*q; int i,l; for (l=0,p=buffer,q=buffer+width*(height-1);l<(height>>1);l++,q-=(width<<1)) for (i=0;i<width;a=*p,b=*q,*p++=b,*q++=a,i++); #else unsigned char* buffer=(unsigned char*)buf; unsigned char *p,*q; int l; unsigned char *tmp; int w=4*width; if ((unsigned)w > MAXINT) overalloc(); tmp=mem_alloc(w*sizeof(unsigned char)); /* tohle je pomalejsi, protoze se kopiruje pamet->pamet, pamet->pamet */ /* kdyz mame 4B typek, tak se kopiruje pamet->reg, reg->pamet */ for (l=0,p=buffer,q=buffer+w*(height-1);l<(height>>1);l++,q-=w,p+=w) memcpy(tmp,p,w),memcpy(p,q,w),memcpy(q,tmp,w); mem_free(tmp); #endif }
/* colors: number of triplets (color entries) */ static void alloc_color_map(int colors) { struct gif_decoder* deco=global_cimg->decoder; if (deco->color_map) mem_free(deco->color_map); if ((unsigned)colors > MAXINT / 3 / sizeof(*(deco->color_map))) overalloc(); deco->color_map=mem_alloc(colors*3*sizeof(*(deco->color_map))); }
void tiff_restart(struct cached_image *cimg, unsigned char *data, int length) { struct tiff_decoder * deco=(struct tiff_decoder*)cimg->decoder; unsigned char *p; if (!deco->tiff_data) { if ((unsigned)length > MAXINT) overalloc(); p=mem_alloc(length); } else { if ((unsigned)length + (unsigned)deco->tiff_size > MAXINT) overalloc(); if ((unsigned)length + (unsigned)deco->tiff_size < (unsigned)length) overalloc(); p=mem_realloc(deco->tiff_data,deco->tiff_size+length); } deco->tiff_data=p; memcpy(deco->tiff_data+deco->tiff_size,data,length); deco->tiff_size+=length; }
void r_xpand_spaces(struct part *p, int l) { unsigned char *c; if ((unsigned)l >= MAXINT) overalloc(); c = mem_realloc(p->spaces, l + 1); memset(c + p->spl, 0, l - p->spl + 1); p->spl = l + 1; p->spaces = c; }
static inline int pw2(int a) { int x = 1; while (x < a && x) { if ((unsigned)x > MAXINT / 2) overalloc(); x <<= 1; } return x; }
struct link *new_link(struct f_data *f) { if (!f) return NULL; if (!(f->nlinks & (ALLOC_GR - 1))) { if ((unsigned)f->nlinks > MAXINT / sizeof(struct link) - ALLOC_GR) overalloc(); f->links = mem_realloc(f->links, (f->nlinks + ALLOC_GR) * sizeof(struct link)); } memset(&f->links[f->nlinks], 0, sizeof(struct link)); return &f->links[f->nlinks++]; }
static inline void xpand_lines(struct part *p, int y) { /*if (y >= p->y) p->y = y + 1;*/ if (!p->data) return; if (XALIGN((unsigned)y + (unsigned)p->yp) > MAXINT) overalloc(); y += p->yp; if (y >= p->data->y) { /* !!! FIXME: out of inline */ int i; if (XALIGN(y + 1) > XALIGN(p->data->y)) { if (XALIGN((unsigned)y + 1) > MAXINT / sizeof(struct line)) overalloc(); p->data->data = mem_realloc(p->data->data, XALIGN(y+1)*sizeof(struct line)); } for (i = p->data->y; i <= y; i++) { p->data->data[i].l = 0; p->data->data[i].c = p->bgcolor; p->data->data[i].d = DUMMY; } p->data->y = i; } }
static inline void shift_chars(struct part *p, int y, int s) { chr *a; int l = LEN(y); if ((unsigned)l > MAXINT / sizeof(chr)) overalloc(); a = mem_alloc(l * sizeof(chr)); memcpy(a, &POS(0, y), l * sizeof(chr)); set_hchars(p, 0, y, s, (p->data->data[y].c << 11) | ' '); copy_chars(p, s, y, l, a); mem_free(a); move_links(p, 0, y, s, y); }
int init_virtual_devices(struct graphics_driver *drv, int n) { if (n_virtual_devices) { internal("init_virtual_devices: already initialized"); return -1; } if ((unsigned)n > MAXINT / sizeof(struct graphics_device *)) overalloc(); virtual_devices = mem_calloc(n * sizeof(struct graphics_device *)); n_virtual_devices = n; virtual_device_timer = NULL; current_virtual_device = NULL; return 0; }
void read_select(struct connection *c) { struct read_buffer *rb; int rd; if (!(rb = c->buffer)) { internal("read socket has no buffer"); setcstate(c, S_INTERNAL); abort_connection(c); return; } set_handlers(rb->sock, NULL, NULL, NULL, NULL); if ((unsigned)rb->len > MAXINT - sizeof(struct read_buffer) - READ_SIZE) overalloc(); rb = mem_realloc(rb, sizeof(struct read_buffer) + rb->len + READ_SIZE); c->buffer = rb; #ifdef HAVE_SSL if(c->ssl) { if ((rd = SSL_read(c->ssl, rb->data + rb->len, READ_SIZE)) <= 0) { int err; if ((err = SSL_get_error(c->ssl, rd)) == SSL_ERROR_WANT_READ) { read_from_socket(c, rb->sock, rb, rb->done); return; } if (rb->close && !rd) { rb->close = 2; rb->done(c, rb); return; } setcstate(c, rd ? (err == SSL_ERROR_SYSCALL ? get_error_from_errno(errno) : S_SSL_ERROR) : S_CANT_READ); /*mem_free(rb);*/ if (!rd || err == SSL_ERROR_SYSCALL) retry_connection(c); else abort_connection(c); return; } } else #endif if ((rd = read(rb->sock, rb->data + rb->len, READ_SIZE)) <= 0) { if (rb->close && !rd) { rb->close = 2; rb->done(c, rb); return; } setcstate(c, rd ? get_error_from_errno(errno) : S_CANT_READ); /*mem_free(rb);*/ retry_connection(c); return; } log_data(rb->data + rb->len, rd); rb->len += rd; rb->done(c, rb); }
void new_columns(struct table *t, int span, int width, int align, int valign, int group) { if ((unsigned)t->c + (unsigned)span > MAXINT) overalloc(); if (t->c + span > t->rc) { int n = t->rc; struct table_column *nc; while (t->c + span > n) { if ((unsigned)n > MAXINT / 2) overalloc(); n *= 2; } if ((unsigned)n > MAXINT / sizeof(struct table_column)) overalloc(); nc = mem_realloc(t->cols, n * sizeof(struct table_column)); t->rc = n; t->cols = nc; } while (span--) { t->cols[t->c].align = align; t->cols[t->c].valign = valign; t->cols[t->c].width = width; t->cols[t->c++].group = group; group = 0; } }
unsigned char *get_cwd() { int bufsize = 128; unsigned char *buf; while (1) { buf = mem_alloc(bufsize); if (getcwd(buf, bufsize)) return buf; mem_free(buf); if (errno == EINTR) continue; if (errno != ERANGE) return NULL; if ((unsigned)bufsize > MAXINT - 128) overalloc(); bufsize += 128; } return NULL; }
void write_to_socket(struct connection *c, int s, unsigned char *data, int len, void (*write_func)(struct connection *)) { struct write_buffer *wb; log_data(data, len); if ((unsigned)len > MAXINT - sizeof(struct write_buffer)) overalloc(); wb = mem_alloc(sizeof(struct write_buffer) + len); wb->sock = s; wb->len = len; wb->pos = 0; wb->done = write_func; memcpy(wb->data, data, len); if (c->buffer) mem_free(c->buffer); c->buffer = wb; set_handlers(s, NULL, (void (*)(void *))write_select, (void (*)(void *))exception, c); }
struct table_cell *new_cell(struct table *t, int x, int y) { struct table nt; int i, j; if (x < t->x && y < t->y) goto ret; rep: if (x < t->rx && y < t->ry) { expand_cells(t, x, y); goto ret; } nt.rx = t->rx; nt.ry = t->ry; while (x >= nt.rx) { if ((unsigned)nt.rx > MAXINT / 2) overalloc(); nt.rx *= 2; } while (y >= nt.ry) { if ((unsigned)nt.ry > MAXINT / 2) overalloc(); nt.ry *= 2; } if ((unsigned)nt.rx * (unsigned)nt.ry / (unsigned)nt.rx != (unsigned)nt.ry) overalloc(); if ((unsigned)nt.rx * (unsigned)nt.ry > MAXINT / sizeof(struct table_cell)) overalloc(); nt.cells = mem_alloc(nt.rx * nt.ry * sizeof(struct table_cell)); memset(nt.cells, 0, nt.rx * nt.ry * sizeof(struct table_cell)); for (i = 0; i < t->x; i++) for (j = 0; j < t->y; j++) memcpy(CELL(&nt, i, j), CELL(t, i, j), sizeof(struct table_cell)); mem_free(t->cells); t->cells = nt.cells; t->rx = nt.rx; t->ry = nt.ry; goto rep; ret: return CELL(t, x, y); }
static inline void xpand_line(struct part *p, int y, int x) { if (!p->data) return; /* !!! FIXME: p->x (?) */ if (XALIGN((unsigned)x + (unsigned)p->xp) > MAXINT) overalloc(); x += p->xp; y += p->yp; #ifdef DEBUG if (y >= p->data->y) { internal("line does not exist"); return; } #endif if (x >= p->data->data[y].l) { /* !!! FIXME: out of inline */ int i; if (XALIGN(x+1) > XALIGN(p->data->data[y].l)) { if (XALIGN((unsigned)x + 1) > MAXINT / sizeof(chr)) overalloc(); p->data->data[y].d = mem_realloc(p->data->data[y].d, XALIGN(x+1)*sizeof(chr)); } for (i = p->data->data[y].l; i <= x; i++) p->data->data[y].d[i] = (p->data->data[y].c << 11) | ' '; p->data->data[y].c = p->bgcolor; p->data->data[y].l = i; } }
/* adds graphics device to hash table */ static int x_add_to_table(struct graphics_device* gd) { int a=(*((Window*)(gd->driver_data)))&(X_HASH_TABLE_SIZE-1); int c=x_hash_table[a].count; if (!c) { x_hash_table[a].pointer=mem_alloc(sizeof(struct graphics_device *)); } else { if ((unsigned)c > MAXINT / sizeof(struct graphics_device *) - 1) overalloc(); x_hash_table[a].pointer=mem_realloc(x_hash_table[a].pointer,(c+1)*sizeof(struct graphics_device *)); } x_hash_table[a].pointer[c]=gd; x_hash_table[a].count++; return 0; }
int get_column_widths(struct table *t) { int i, j, s, ns; if ((unsigned)t->x > MAXINT / sizeof(int)) overalloc(); if (!t->min_c) t->min_c = mem_alloc(t->x * sizeof(int)); if (!t->max_c) t->max_c = mem_alloc(t->x * sizeof(int)); if (!t->w_c) t->w_c = mem_alloc(t->x * sizeof(int)); memset(t->min_c, 0, t->x * sizeof(int)); memset(t->max_c, 0, t->x * sizeof(int)); s = 1; do { ns = MAXINT; for (i = 0; i < t->x; i++) for (j = 0; j < t->y; j++) { struct table_cell *c = CELL(t, i, j); if (c->spanned || !c->used) continue; if (c->colspan + i > t->x) { /*internal("colspan out of table"); return -1;*/ continue; } if (c->colspan == s) { int k, p = 0; /*int pp = t->max_c[i];*/ int m = 0; for (k = 1; k < s; k++) { p += get_vline_width(t, i + k) >= 0; /*pp += t->max_c[i + k];*/ } /*if (0 && s > 1 && (t->p->data || t->p->xp)) { int d, cc = (!!(t->frame & F_LHS) + !!(t->frame & F_RHS)) * !!t->border; for (d = 0; d < t->c; c++) { cc += t->max_c[d]; if (d > 0) d += get_vline_width(t, d) >= 0; } if (cc >= t->width) goto nd; if (cc + c->max_width - p - pp >= t->width) { m = cc + c->max_width - p - pp - t->width; } }*/ dst_width(t->min_c + i, s, c->min_width - p, t->max_c + i); dst_width(t->max_c + i, s, c->max_width - p - m, NULL); for (k = 0; k < s; k++) if (t->min_c[i + k] > t->max_c[i + k]) t->max_c[i + k] = t->min_c[i + k]; } else if (c->colspan > s && c->colspan < ns) ns = c->colspan; } } while ((s = ns) != MAXINT); return 0; }
void png_row_callback(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, int pass) { struct cached_image *cimg; #ifdef REPACK_16 unsigned char *tmp; int channels; #endif /* #ifdef REPACK_16 */ cimg=global_cimg; #ifdef REPACK_16 if (cimg->buffer_bytes_per_pixel>4) { channels=cimg->buffer_bytes_per_pixel/sizeof(unsigned short); if (PNG_INTERLACE_NONE==png_get_interlace_type(png_ptr, ((struct png_decoder *)cimg->decoder)->info_ptr)) { unsigned_short_from_2char((unsigned short *)(cimg->buffer+cimg ->buffer_bytes_per_pixel *cimg->width *row_num), new_row, cimg->width *channels); }else{ if ((unsigned)cimg->width > MAXINT / 2 / channels) overalloc(); tmp=mem_alloc(cimg->width*2*channels); a2char_from_unsigned_short(tmp, (unsigned short *)(cimg->buffer +cimg->buffer_bytes_per_pixel *cimg->width*row_num), cimg->width*channels); png_progressive_combine_row(png_ptr, tmp, new_row); unsigned_short_from_2char((unsigned short *)(cimg->buffer +cimg->buffer_bytes_per_pixel *cimg->width*row_num), tmp, cimg->width*channels); mem_free(tmp); } }else #endif /* #ifdef REPACK_16 */ { png_progressive_combine_row(png_ptr, cimg->buffer+cimg->buffer_bytes_per_pixel *cimg->width*row_num, new_row); } cimg->rows_added=1; }
unsigned char *parse_header_param(unsigned char *x, unsigned char *e) { unsigned char u; size_t le = strlen(e); int lp; unsigned char *y = x; a: if (!(y = strchr(y, ';'))) return NULL; while (*y && (*y == ';' || *y <= ' ')) y++; if (strlen(y) < le) return NULL; if (casecmp(y, e, le)) goto a; y += le; while (*y && (*y <= ' ' || *y == '=')) y++; u = ';'; if (*y == '\'' || *y == '"') u = *y++; lp = 0; while (y[lp] >= ' ' && y[lp] != u) { lp++; if (lp == MAXINT) overalloc(); } return memacpy(y, lp); }
void distribute_widths(struct table *t, int width) { int i; int d = width - t->min_t; int om = 0; char *u; int *w, *mx; int mmax_c = 0; if (!t->x) return; if (d < 0) { /*internal("too small width %d, required %d", width, t->min_t);*/ return; } for (i = 0; i < t->x; i++) if (t->max_c[i] > mmax_c) mmax_c = t->max_c[i]; memcpy(t->w_c, t->min_c, t->x * sizeof(int)); t->rw = width; if ((unsigned)t->x > MAXINT / sizeof(int)) overalloc(); u = mem_alloc(t->x); w = mem_alloc(t->x * sizeof(int)); mx = mem_alloc(t->x * sizeof(int)); while (d) { int mss, mii; int p = 0; int wq; int dd; memset(w, 0, t->x * sizeof(int)); memset(mx, 0, t->x * sizeof(int)); for (i = 0; i < t->x; i++) { switch (om) { case 0: if (t->w_c[i] < t->xcols[i]) { w[i] = 1, mx[i] = (t->xcols[i] > t->max_c[i] ? t->max_c[i] : t->xcols[i]) - t->w_c[i]; if (mx[i] <= 0) w[i] = 0; } break; case 1: if (t->xcols[i] < -1 && t->xcols[i] != -2) { w[i] = t->xcols[i] <= -2 ? -2 - t->xcols[i] : 1; mx[i] = t->max_c[i] - t->w_c[i]; if (mx[i] <= 0) w[i] = 0; } break; case 2: case 3: if (t->w_c[i] < t->max_c[i] && (om == 3 || t->xcols[i] == W_AUTO)) { mx[i] = t->max_c[i] - t->w_c[i]; if (mmax_c) w[i] = 5 + t->max_c[i] * 10 / mmax_c; else w[i] = 1; } break; case 4: if (t->xcols[i] >= 0) { w[i] = 1, mx[i] = t->xcols[i] - t->w_c[i]; if (mx[i] <= 0) w[i] = 0; } break; case 5: if (t->xcols[i] < 0) w[i] = t->xcols[i] <= -2 ? -2 - t->xcols[i] : 1, mx[i] = MAXINT; break; case 6: w[i] = 1, mx[i] = MAXINT; break; default: /*internal("could not expand table");*/ goto end2; } p += w[i]; } if (!p) { om++; continue; } wq = 0; if (u) memset(u, 0, t->x); dd = d; a: mss = 0; mii = -1; for (i = 0; i < t->x; i++) if (w[i]) { int ss; if (u && u[i]) continue; if (!(ss = dd * w[i] / p)) ss = 1; if (ss > mx[i]) ss = mx[i]; if (ss > mss) mss = ss, mii = i; } if (mii != -1) { int q = t->w_c[mii]; if (u) u[mii] = 1; t->w_c[mii] += mss; d -= t->w_c[mii] - q; while (d < 0) t->w_c[mii]--, d++; if (t->w_c[mii] < q) { /*internal("shrinking cell");*/ t->w_c[mii] = q; } wq = 1; if (d) goto a; } else if (!wq) om++; } end2: mem_free(mx); mem_free(w); if (u) mem_free(u); }
void file_func(struct connection *c) { struct cache_entry *e; unsigned char *file, *name, *head; int fl; DIR *d; int h, r; struct stat stt; if (anonymous && !anonymousGinga) { setcstate(c, S_BAD_URL); abort_connection(c); return; } if (!(name = get_filename(c->url))) { setcstate(c, S_OUT_OF_MEM); abort_connection(c); return; } if (anonymousGinga && !allowedPath(name)){ setcstate(c, S_BAD_URL); abort_connection(c); return; } if (stat(name, &stt)) { mem_free(name); setcstate(c, -errno); abort_connection(c); return; } if (!S_ISDIR(stt.st_mode) && !S_ISREG(stt.st_mode)) { mem_free(name); setcstate(c, S_FILE_TYPE); abort_connection(c); return; } if ((h = open(name, O_RDONLY | O_NOCTTY)) == -1) { int er = errno; if ((d = opendir(name))) goto dir; mem_free(name); setcstate(c, -er); abort_connection(c); return; } set_bin(h); if (S_ISDIR(stt.st_mode)) { struct dirs *dir; int dirl; int i; struct dirent *de; d = opendir(name); close(h); if (!d) { mem_free(name); setcstate(c, -errno); abort_connection(c); return; } dir: dir = DUMMY, dirl = 0; if (name[0] && !dir_sep(name[strlen(name) - 1])) { if (get_cache_entry(c->url, &e)) { mem_free(name); closedir(d); setcstate(c, S_OUT_OF_MEM); abort_connection(c); return; } c->cache = e; if (e->redirect) mem_free(e->redirect); e->redirect = stracpy(c->url); e->redirect_get = 1; add_to_strn(&e->redirect, "/"); mem_free(name); closedir(d); goto end; } last_uid = -1; last_gid = -1; file = init_str(); fl = 0; add_to_str(&file, &fl, "<html><head><title>"); add_conv_str(&file, &fl, name, strlen(name), -1); add_to_str(&file, &fl, "</title></head><body><h2>Directory "); add_conv_str(&file, &fl, name, strlen(name), -1); add_to_str(&file, &fl, "</h2><pre>"); while ((de = readdir(d))) { struct stat stt, *stp; unsigned char **p; int l; unsigned char *n; if (!strcmp(de->d_name, ".")) continue; if ((unsigned)dirl > MAXINT / sizeof(struct dirs) - 1) overalloc(); dir = mem_realloc(dir, (dirl + 1) * sizeof(struct dirs)); dir[dirl].f = stracpy(de->d_name); *(p = &dir[dirl++].s) = init_str(); l = 0; n = stracpy(name); add_to_strn(&n, de->d_name); #ifdef FS_UNIX_SOFTLINKS if (lstat(n, &stt)) #else if (stat(n, &stt)) #endif stp = NULL; else stp = &stt; mem_free(n); stat_mode(p, &l, stp); stat_links(p, &l, stp); stat_user(p, &l, stp, 0); stat_user(p, &l, stp, 1); stat_size(p, &l, stp); stat_date(p, &l, stp); } closedir(d); if (dirl) qsort(dir, dirl, sizeof(struct dirs), (int(*)(const void *, const void *))comp_de); for (i = 0; i < dirl; i++) { unsigned char *lnk = NULL; #ifdef FS_UNIX_SOFTLINKS if (dir[i].s[0] == 'l') { unsigned char *buf = NULL; int size = 0; int r; unsigned char *n = stracpy(name); add_to_strn(&n, dir[i].f); do { if (buf) mem_free(buf); size += ALLOC_GR; if ((unsigned)size > MAXINT) overalloc(); buf = mem_alloc(size); r = readlink(n, buf, size); } while (r == size); if (r == -1) goto yyy; buf[r] = 0; lnk = buf; goto xxx; yyy: mem_free(buf); xxx: mem_free(n); } #endif /*add_to_str(&file, &fl, " ");*/ add_to_str(&file, &fl, dir[i].s); add_to_str(&file, &fl, "<a href=\""); add_conv_str(&file, &fl, dir[i].f, strlen(dir[i].f), 1); if (dir[i].s[0] == 'd') add_to_str(&file, &fl, "/"); else if (lnk) { struct stat st; unsigned char *n = stracpy(name); add_to_strn(&n, dir[i].f); if (!stat(n, &st)) if (S_ISDIR(st.st_mode)) add_to_str(&file, &fl, "/"); mem_free(n); } add_to_str(&file, &fl, "\">"); /*if (dir[i].s[0] == 'd') add_to_str(&file, &fl, "<font color=\"yellow\">");*/ add_conv_str(&file, &fl, dir[i].f, strlen(dir[i].f), 0); /*if (dir[i].s[0] == 'd') add_to_str(&file, &fl, "</font>");*/ add_to_str(&file, &fl, "</a>"); if (lnk) { add_to_str(&file, &fl, " -> "); add_to_str(&file, &fl, lnk); mem_free(lnk); } add_to_str(&file, &fl, "\n"); } mem_free(name); for (i = 0; i < dirl; i++) mem_free(dir[i].s), mem_free(dir[i].f); mem_free(dir); add_to_str(&file, &fl, "</pre></body></html>\n"); head = stracpy("\r\nContent-Type: text/html\r\n"); } else { mem_free(name); /* + !stt.st_size is there because of bug in Linux. Read returns -EACCES when reading 0 bytes to invalid address */ if (stt.st_size > MAXINT) { close(h); setcstate(c, S_LARGE_FILE); abort_connection(c); return; } file = mem_alloc(stt.st_size + !stt.st_size); if ((r = read(h, file, stt.st_size)) != stt.st_size) { mem_free(file); close(h); setcstate(c, r == -1 ? -errno : S_FILE_ERROR); abort_connection(c); return; } close(h); fl = stt.st_size; head = stracpy(""); } if (get_cache_entry(c->url, &e)) { mem_free(file); setcstate(c, S_OUT_OF_MEM); abort_connection(c); return; } if (e->head) mem_free(e->head); e->head = head; c->cache = e; add_fragment(e, 0, file, fl); truncate_entry(e, fl, 1); mem_free(file); end: c->cache->incomplete = 0; setcstate(c, S_OK); abort_connection(c); }
void put_chars(struct part *p, unsigned char *c, int l) { static struct text_attrib_beginning ta_cache = { -1, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; static int bg_cache; static int fg_cache; int bg, fg; int i; struct link *link; struct point *pt; if (l < 0) overalloc(); /*printf("%d-", p->cx);for (i=0; i<l; i++) printf("%c", c[i]); printf("-\n");sleep(1);*/ while (par_format.align != AL_NO && p->cx == -1 && l && *c == ' ') c++, l--; if (!l) return; if (c[0] != ' ' || (c[1] && c[1] != ' ')) { last_tag_for_newline = (void *)&p->data->tags; } if (p->cx < par_format.leftmargin) p->cx = par_format.leftmargin; if (last_link || last_image || last_form || format.link || format.image || format.form) goto process_link; no_l: /*printf("%d %d\n",p->cx, p->cy);*/ if (memcmp(&ta_cache, &format, sizeof(struct text_attrib_beginning))) goto format_change; bg = bg_cache, fg = fg_cache; end_format_change: if (p->cx == par_format.leftmargin && *c == ' ' && par_format.align != AL_NO) c++, l--; if (p->y < p->cy + 1) p->y = p->cy + 1; if (nowrap && p->cx + l > rm(par_format)) return; set_hline(p, p->cx, p->cy, l, c, (((fg&0x08)<<3)|(bg<<3)|(fg&0x07))<<8, 1); p->cx += l; nobreak = 0; if (par_format.align != AL_NO) while (p->cx > rm(par_format) && p->cx > par_format.leftmargin) { int x; /*if (p->cx > p->x) { p->x = p->cx + par_format.rightmargin; if (c[l - 1] == ' ') p->x--; }*/ if (!(x = split_line(p))) break; /*if (LEN(p->cy-1) > p->x) p->x = LEN(p->cy-1);*/ align_line(p, p->cy - 1); nobreak = x - 1; } if ((p->xa += l) - (c[l-1] == ' ' && par_format.align != AL_NO) + par_format.leftmargin + par_format.rightmargin > p->xmax) p->xmax = p->xa - (c[l-1] == ' ' && par_format.align != AL_NO) + par_format.leftmargin + par_format.rightmargin; return; process_link: if ((last_link /*|| last_target*/ || last_image || last_form) && !xstrcmp(format.link, last_link) && !xstrcmp(format.target, last_target) && !xstrcmp(format.image, last_image) && format.form == last_form) { if (!p->data) goto x; link = &p->data->links[p->data->nlinks - 1]; if (!p->data->nlinks) { internal("no link"); goto no_l; } goto set_link; x:; } else { if (last_link) mem_free(last_link); /* !!! FIXME: optimize */ if (last_target) mem_free(last_target); if (last_image) mem_free(last_image); last_link = last_target = last_image = NULL; last_form = NULL; if (!(format.link || format.image || format.form)) goto no_l; if (d_opt->num_links) { unsigned char s[64]; unsigned char *fl = format.link, *ft = format.target, *fi = format.image; struct form_control *ff = format.form; format.link = format.target = format.image = NULL; format.form = NULL; s[0] = '['; snzprint(s + 1, 62, p->link_num); strcat(s, "]"); put_chars(p, s, strlen(s)); if (ff && ff->type == FC_TEXTAREA) line_break(p); if (p->cx == -1) p->cx = par_format.leftmargin; format.link = fl, format.target = ft, format.image = fi; format.form = ff; } p->link_num++; last_link = stracpy(format.link); last_target = stracpy(format.target); last_image = stracpy(format.image); last_form = format.form; if (!p->data) goto no_l; if (!(link = new_link(p->data))) goto no_l; link->num = p->link_num - 1; link->pos = DUMMY; if (!last_form) { link->type = L_LINK; link->where = stracpy(last_link); link->target = stracpy(last_target); } else { link->type = last_form->type == FC_TEXT || last_form->type == FC_PASSWORD || last_form->type == FC_FILE ? L_FIELD : last_form->type == FC_TEXTAREA ? L_AREA : last_form->type == FC_CHECKBOX || last_form->type == FC_RADIO ? L_CHECKBOX : last_form->type == FC_SELECT ? L_SELECT : L_BUTTON; link->form = last_form; link->target = stracpy(last_form->target); } link->where_img = stracpy(last_image); if (link->type != L_FIELD && link->type != L_AREA) { bg = find_nearest_color(&format.clink, 8); fg = find_nearest_color(&format.bg, 8); fg = fg_color(fg, bg); } else { fg = find_nearest_color(&format.fg, 8); bg = find_nearest_color(&format.bg, 8); fg = fg_color(fg, bg); } link->sel_color = ((fg & 8) << 3) | (fg & 7) | (bg << 3); link->n = 0; set_link: if ((unsigned)link->n + (unsigned)l > MAXINT / sizeof(struct point)) overalloc(); pt = mem_realloc(link->pos, (link->n + l) * sizeof(struct point)); link->pos = pt; for (i = 0; i < l; i++) pt[link->n + i].x = X(p->cx) + i, pt[link->n + i].y = Y(p->cy); link->n += l; } goto no_l; format_change: bg = find_nearest_color(&format.bg, 8); fg = find_nearest_color(&format.fg, 16); fg = fg_color(fg, bg); if (format.attr & AT_ITALIC) fg = fg ^ 0x01; if (format.attr & AT_UNDERLINE) fg = (fg ^ 0x04) | 0x08; if (format.attr & AT_BOLD) fg = fg | 0x08; fg = fg_color(fg, bg); if (format.attr & AT_GRAPHICS) bg = bg | 0x10; memcpy(&ta_cache, &format, sizeof(struct text_attrib_beginning)); fg_cache = fg; bg_cache = bg; goto end_format_change; }
struct frameset_desc *create_frameset(struct f_data *fda, struct frameset_param *fp) { int i; struct frameset_desc *fd; if (!fp->x || !fp->y) { internal("zero size of frameset"); return NULL; } if (fp->x && (unsigned)fp->x * (unsigned)fp->y / (unsigned)fp->x != (unsigned)fp->y) overalloc(); if ((unsigned)fp->x * (unsigned)fp->y > (MAXINT - sizeof(struct frameset_desc)) / sizeof(struct frame_desc)) overalloc(); fd = mem_alloc(sizeof(struct frameset_desc) + fp->x * fp->y * sizeof(struct frame_desc)); memset(fd, 0, sizeof(struct frameset_desc) + fp->x * fp->y * sizeof(struct frame_desc)); fd->n = fp->x * fp->y; fd->x = fp->x; fd->y = fp->y; for (i = 0; i < fd->n; i++) { fd->f[i].xw = fp->xw[i % fp->x]; fd->f[i].yw = fp->yw[i / fp->x]; } if (fp->parent) add_frameset_entry(fp->parent, fd, NULL, NULL); else if (!fda->frame_desc) fda->frame_desc = fd; else mem_free(fd), fd = NULL; return fd; }
void in_term(struct terminal *term) { struct event *ev; int r; unsigned char *iq; if ((unsigned)term->qlen + ALLOC_GR > MAXINT) overalloc(); iq = mem_realloc(term->input_queue, term->qlen + ALLOC_GR); term->input_queue = iq; if ((r = read(term->fdin, iq + term->qlen, ALLOC_GR)) <= 0) { if (r == -1 && errno != ECONNRESET) error("ERROR: error %d on terminal: could not read event", errno); destroy_terminal(term); return; } term->qlen += r; test_queue: if ((size_t)term->qlen < sizeof(struct event)) return; ev = (struct event *)iq; r = sizeof(struct event); if (ev->ev != EV_INIT && ev->ev != EV_RESIZE && ev->ev != EV_REDRAW && ev->ev != EV_KBD && ev->ev != EV_MOUSE && ev->ev != EV_ABORT) { error("ERROR: error on terminal: bad event %d", ev->ev); goto mm; } if (ev->ev == EV_INIT) { int init_len; if ((size_t)term->qlen < sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + 2 * sizeof(int)) return; init_len = *(int *)(iq + sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + sizeof(int)); if ((size_t)term->qlen < sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + 2 * sizeof(int) + init_len) return; memcpy(term->term, iq + sizeof(struct event), MAX_TERM_LEN); term->term[MAX_TERM_LEN - 1] = 0; memcpy(term->cwd, iq + sizeof(struct event) + MAX_TERM_LEN, MAX_CWD_LEN); term->cwd[MAX_CWD_LEN - 1] = 0; term->environment = *(int *)(iq + sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN); ev->b = (long)(iq + sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + sizeof(int)); r = sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + 2 * sizeof(int) + init_len; sync_term_specs(); } if (ev->ev == EV_REDRAW || ev->ev == EV_RESIZE || ev->ev == EV_INIT) { struct window *win; send_redraw: if (ev->x < 0 || ev->y < 0) { error("ERROR: bad terminal size: %d, %d", (int)ev->x, (int)ev->y); goto mm; } alloc_term_screen(term, ev->x, ev->y); clear_terminal(term); erase_screen(term); term->redrawing = 1; foreachback(win, term->windows) win->handler(win, ev, 0); term->redrawing = 0; } if (ev->ev == EV_KBD || ev->ev == EV_MOUSE) { if (ev->ev == EV_KBD && upcase(ev->x) == 'L' && ev->y == KBD_CTRL) { ev->ev = EV_REDRAW; ev->x = term->x; ev->y = term->y; goto send_redraw; } else if (ev->ev == EV_KBD && ev->x == KBD_CTRL_C) ((struct window *)term->windows.prev)->handler(term->windows.prev, ev, 0); else ((struct window *)term->windows.next)->handler(term->windows.next, ev, 0); } if (ev->ev == EV_ABORT) { destroy_terminal(term); return; } /*redraw_screen(term);*/ mm: if (term->qlen == r) term->qlen = 0; else memmove(iq, iq + r, term->qlen -= r); goto test_queue; }
void jpeg_restart(struct cached_image *cimg, unsigned char *data, int length) { struct jpg_decoder *deco; deco=(struct jpg_decoder *)(cimg->decoder); #ifdef DEBUG if (!deco) internal("NULL decoder in jpeg_restart"); #endif /* #ifdef DEBUG */ global_cinfo=((struct jpg_decoder *)(cimg->decoder))->cinfo; global_jerr=((struct jpg_decoder *)(cimg->decoder))->jerr; /* These global variables are here so that we don't have to pass lots * of structure pointers into each function. The jpeg decoder is never * running twice at the same time so it doesn't matter. */ /* If the decoder wants us to skip bytes it's not interested in */ if (deco->skip_bytes>=length){ /* If the decoder wants to skip as much as or more bytes than * the chunk that has just arrived */ deco->skip_bytes-=length; return; }else{ /* If the decoder wants to skip less bytes than the chunk * that has just arrived */ data+=deco->skip_bytes; length-=deco->skip_bytes; deco->skip_bytes=0; } /* Add the arrived data chunk into the decoder buffer. Sometimes the * chunks are so small the decoder can't move on on a single chunk * so it has to accumulate more chunks together. This is why the buffer * is there. */ if ((unsigned)global_cinfo->src->bytes_in_buffer + (unsigned)length > MAXINT) overalloc(); if ((unsigned)global_cinfo->src->bytes_in_buffer + (unsigned)length < (unsigned)length) overalloc(); if (deco->jdata){ /* If there is already some decoder buffer, we have to * allocate more space */ memmove(deco->jdata,global_cinfo->src->next_input_byte, global_cinfo->src->bytes_in_buffer); deco->jdata=mem_realloc( deco->jdata, global_cinfo->src->bytes_in_buffer+length); }else{ /* If there is no decoder buffer we'll have to allocate * space for a new buffer */ deco->jdata=mem_alloc(global_cinfo->src->bytes_in_buffer+length); } /* Copy the data iself into the decoder buffer */ memcpy(deco->jdata+global_cinfo->src->bytes_in_buffer ,data,length); /* Update the next input byte pointer for the decoder to continue at * the right position */ global_cinfo->src->next_input_byte=deco->jdata; /* ...:::...:..:.:::.:.::::.::.:.:.:.::..::::.::::.:...: */ /* Update the length of data in the decoder buffer */ global_cinfo->src->bytes_in_buffer+=length; if (setjmp(global_jerr->setjmp_buffer)) goto decoder_ended; switch(deco->state){ case 0: /* jpeg_read_header */ if (JPEG_SUSPENDED==jpeg_read_header(global_cinfo,TRUE)) break; global_cinfo->buffered_image=TRUE; deco->state=1; case 1: /* If the scaling is sufficiently brutal we can leave out * some DCT coefficients...: */ /* jpeg_start_decompress */ if (jpeg_start_decompress(global_cinfo)==FALSE) break; cimg->width=global_cinfo->output_width; cimg->height=global_cinfo->output_height; switch(cimg->buffer_bytes_per_pixel= global_cinfo->output_components) { case 1: /* We'll do the conversion ourselves * because libjpeg seems to be buggy */ cimg->buffer_bytes_per_pixel=3; break; case 3: /* RGB or YCrCb. We will ask libjpeg to * possibly convert from YCrCb to RGB. */ global_cinfo->out_color_space=JCS_RGB; break; case 4: /* CMYK or YCCK. We need to enable conversion * to CMYK and then convert CMYK data to RGBA * with dummy A ourselves. * We will ask libjpeg to possibly convert from * YCCK to CMYK. */ global_cinfo->out_color_space=JCS_CMYK; break; default: /* Let's make a decompression fatal error here */ if (!mesg_unsup_emitted){ fprintf(stderr, "Unsupported JPEG output components number: %d.\n", cimg->buffer_bytes_per_pixel); mesg_unsup_emitted=1; } longjmp(global_jerr->setjmp_buffer,2); /* longjmp() and siglongjmp() make programs hard to * understand and maintain. If possible an alternative * should be used. Hahaha :) ;-) */ /* Free will makes people hard to understand * and maintain. If possible an alternative should be * used. */ /* With our new LongJump(TM) your jumps will be longer * than with ordinary commercially available jumps. */ } cimg->red_gamma=sRGB_gamma; cimg->green_gamma=sRGB_gamma; cimg->blue_gamma=sRGB_gamma; /* This is defined in the JPEG standard somehow that sRGB * color space is used. */ cimg->strip_optimized=0; /* Strip optimization yet waits to be written. This will * allow huge jpegs to be processed without consuming * Links memory and consuming Xserver memory instead ;-) * However strip optimization is already written for PNG's. */ header_dimensions_known(cimg); new_scan: deco->state=2; case 2: /* jpeg_start_output */ if (FALSE==jpeg_start_output(global_cinfo,global_cinfo->input_scan_number)){ susp0: /* Suspended */ break; } deco->state=3; case 3: /* jpeg_read_scanlines */ /* color */ while (global_cinfo->output_scanline <global_cinfo->output_height){ int a, lines; for (a=0;a<16;a++){ deco->scanlines[a]=cimg->buffer +(global_cinfo ->output_scanline+a) *global_cinfo->output_width*cimg-> buffer_bytes_per_pixel; } if ((lines= jpeg_read_scanlines( global_cinfo,deco->scanlines,1))){ /* Some lines were written into cimg buffer */ cimg->rows_added=1; fix_data(deco, lines); }else{ /* No lines have been written into cimg * buffer */ /* We are suspended and we want more data */ goto susp0; /* Break the outer * switch statement */ } } deco->state=4; case 4: /* jpeg_finish_output */ if (FALSE==jpeg_finish_output(global_cinfo)) { /* Suspended */ break; } if (!jpeg_input_complete(global_cinfo)) { /* Some more scans awaited... */ goto new_scan; } deco->state=5; case 5: /* jpeg_finish_decompress */ if (FALSE==jpeg_finish_decompress(global_cinfo)) break; decoder_ended: img_end(cimg); } }
struct table *parse_table(unsigned char *html, unsigned char *eof, unsigned char **end, struct rgb *bgcolor, int sh, struct s_e **bad_html, int *bhp) { int qqq; struct table *t; struct table_cell *cell; unsigned char *t_name, *t_attr, *en; int t_namelen; int x = 0, y = -1; int p = 0; unsigned char *lbhp = NULL; int l_al = AL_LEFT; int l_val = VAL_MIDDLE; int csp, rsp; int group = 0; int i, j, k; struct rgb l_col; int c_al = AL_TR, c_val = VAL_TR, c_width = W_AUTO, c_span = 0; memcpy(&l_col, bgcolor, sizeof(struct rgb)); *end = html; if (bad_html) { *bad_html = DUMMY; *bhp = 0; } if (!(t = new_table())) return NULL; se: en = html; see: html = en; if (bad_html && !p && !lbhp) { if (!(*bhp & (ALLOC_GR-1))) { if ((unsigned)*bhp > MAXINT / sizeof(struct s_e) - ALLOC_GR) overalloc(); *bad_html = mem_realloc(*bad_html, (*bhp + ALLOC_GR) * sizeof(struct s_e)); } lbhp = (*bad_html)[(*bhp)++].s = html; } while (html < eof && *html != '<') html++; if (html >= eof) { if (p) CELL(t, x, y)->end = html; if (lbhp) (*bad_html)[*bhp-1].e = html; goto scan_done; } if (html + 2 <= eof && (html[1] == '!' || html[1] == '?')) { html = skip_comment(html, eof); goto se; } if (parse_element(html, eof, &t_name, &t_namelen, &t_attr, &en)) { html++; goto se; } if (t_namelen == 5 && !casecmp(t_name, "TABLE", 5)) { en = skip_table(en, eof); goto see; } if (t_namelen == 6 && !casecmp(t_name, "/TABLE", 6)) { if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1); if (p) CELL(t, x, y)->end = html; if (lbhp) (*bad_html)[*bhp-1].e = html; goto scan_done; } if (t_namelen == 8 && !casecmp(t_name, "COLGROUP", 8)) { if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1); if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL; c_al = AL_TR; c_val = VAL_TR; c_width = W_AUTO; get_align(t_attr, &c_al); get_valign(t_attr, &c_val); get_c_width(t_attr, &c_width, sh); if ((c_span = get_num(t_attr, "span")) == -1) c_span = 1; goto see; } if (t_namelen == 9 && !casecmp(t_name, "/COLGROUP", 9)) { if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1); if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL; c_span = 0; c_al = AL_TR; c_val = VAL_TR; c_width = W_AUTO; goto see; } if (t_namelen == 3 && !casecmp(t_name, "COL", 3)) { int sp, wi, al, val; if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL; if ((sp = get_num(t_attr, "span")) == -1) sp = 1; wi = c_width; al = c_al; val = c_val; get_align(t_attr, &al); get_valign(t_attr, &val); get_c_width(t_attr, &wi, sh); new_columns(t, sp, wi, al, val, !!c_span); c_span = 0; goto see; } if (t_namelen == 3 && (!casecmp(t_name, "/TR", 3) || !casecmp(t_name, "/TD", 3) || !casecmp(t_name, "/TH", 3))) { if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1); if (p) CELL(t, x, y)->end = html, p = 0; if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL; } if (t_namelen == 2 && !casecmp(t_name, "TR", 2)) { if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1); if (p) CELL(t, x, y)->end = html, p = 0; if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL; if (group) group--; l_al = AL_LEFT; l_val = VAL_MIDDLE; memcpy(&l_col, bgcolor, sizeof(struct rgb)); get_align(t_attr, &l_al); get_valign(t_attr, &l_val); get_bgcolor(t_attr, &l_col); y++, x = 0; goto see; } if (t_namelen == 5 && ((!casecmp(t_name, "THEAD", 5)) || (!casecmp(t_name, "TBODY", 5)) || (!casecmp(t_name, "TFOOT", 5)))) { if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1); if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL; group = 2; } if (t_namelen != 2 || (casecmp(t_name, "TD", 2) && casecmp(t_name, "TH", 2))) goto see; if (c_span) new_columns(t, c_span, c_width, c_al, c_val, 1); if (lbhp) (*bad_html)[*bhp-1].e = html, lbhp = NULL; if (p) CELL(t, x, y)->end = html, p = 0; if (y == -1) y = 0, x = 0; nc: cell = new_cell(t, x, y); if (cell->used) { if (cell->colspan == -1) goto see; x++; goto nc; } cell->mx = x; cell->my = y; cell->used = 1; cell->start = en; p = 1; cell->align = l_al; cell->valign = l_val; if ((cell->b = upcase(t_name[1]) == 'H')) cell->align = AL_CENTER; if (group == 1) cell->group = 1; if (x < t->c) { if (t->cols[x].align != AL_TR) cell->align = t->cols[x].align; if (t->cols[x].valign != VAL_TR) cell->valign = t->cols[x].valign; } memcpy(&cell->bgcolor, &l_col, sizeof(struct rgb)); get_align(t_attr, &cell->align); get_valign(t_attr, &cell->valign); get_bgcolor(t_attr, &cell->bgcolor); if ((csp = get_num(t_attr, "colspan")) == -1) csp = 1; if (!csp) csp = -1; if ((rsp = get_num(t_attr, "rowspan")) == -1) rsp = 1; if (!rsp) rsp = -1; if (csp >= 0 && rsp >= 0 && csp * rsp > 100000) { if (csp > 10) csp = -1; if (rsp > 10) rsp = -1; } cell->colspan = csp; cell->rowspan = rsp; if (csp == 1) { int w = W_AUTO; get_c_width(t_attr, &w, sh); if (w != W_AUTO) set_td_width(t, x, w, 0); } qqq = t->x; for (i = 1; csp != -1 ? i < csp : x + i < qqq; i++) { struct table_cell *sc = new_cell(t, x + i, y); if (sc->used) { csp = i; for (k = 0; k < i; k++) CELL(t, x + k, y)->colspan = csp; break; } sc->used = sc->spanned = 1; sc->rowspan = rsp; sc->colspan = csp; sc->mx = x; sc->my = y; } qqq = t->y; for (j = 1; rsp != -1 ? j < rsp : y + j < qqq; j++) { for (k = 0; k < i; k++) { struct table_cell *sc = new_cell(t, x + k, y + j); if (sc->used) { int l, m; if (sc->mx == x && sc->my == y) continue; /*internal("boo");*/ for (l = 0; l < k; l++) memset(CELL(t, x + l, y + j), 0, sizeof(struct table_cell)); rsp = j; for (l = 0; l < i; l++) for (m = 0; m < j; m++) CELL(t, x + l, y + m)->rowspan = j; goto brk; } sc->used = sc->spanned = 1; sc->rowspan = rsp; sc->colspan = csp; sc->mx = x; sc->my = y; } } brk: goto see; scan_done: *end = html; for (x = 0; x < t->x; x++) for (y = 0; y < t->y; y++) { struct table_cell *c = CELL(t, x, y); if (!c->spanned) { if (c->colspan == -1) c->colspan = t->x - x; if (c->rowspan == -1) c->rowspan = t->y - y; } } if ((unsigned)t->y > MAXINT / sizeof(int)) overalloc(); t->r_heights = mem_alloc(t->y * sizeof(int)); memset(t->r_heights, 0, t->y * sizeof(int)); for (x = 0; x < t->c; x++) if (t->cols[x].width != W_AUTO) set_td_width(t, x, t->cols[x].width, 1); set_td_width(t, t->x, W_AUTO, 0); return t; }
void check_table_widths(struct table *t) { int *w; int i, j; int s, ns; int m, mi = 0; /* go away, warning! */ if ((unsigned)t->x > MAXINT / sizeof(int)) overalloc(); w = mem_alloc(t->x * sizeof(int)); memset(w, 0, t->x * sizeof(int)); for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) { struct table_cell *c = CELL(t, i, j); int k, p = 0; if (!c->start) continue; for (k = 1; k < c->colspan; k++) p += get_vline_width(t, i + k) >= 0; for (k = 0; k < c->colspan; k++) p += t->w_c[i + k]; get_cell_width(c->start, c->end, t->cellpd, p, 1, &c->x_width, NULL, c->link_num, NULL); if (c->x_width > p) { /*int min, max; get_cell_width(c->start, c->end, t->cellpd, 0, 0, &min, &max, c->link_num, NULL); internal("cell is now wider (%d > %d) min = %d, max = %d, now_min = %d, now_max = %d", c->x_width, p, t->min_c[i], t->max_c[i], min, max);*/ /* sbohem, internale. chytl jsi mi spoustu chyb v tabulkovaci, ale ted je proste cas jit ... ;-( */ c->x_width = p; } } s = 1; do { ns = MAXINT; for (i = 0; i < t->x; i++) for (j = 0; j < t->y; j++) { struct table_cell *c = CELL(t, i, j); if (!c->start) continue; if (c->colspan + i > t->x) { /*internal("colspan out of table");*/ mem_free(w); return; } if (c->colspan == s) { int k, p = 0; for (k = 1; k < s; k++) p += get_vline_width(t, i + k) >= 0; dst_width(w + i, s, c->x_width - p, t->max_c + i); /*for (k = i; k < i + s; k++) if (w[k] > t->w_c[k]) { int l; int c; ag: c = 0; for (l = i; l < i + s; l++) if (w[l] < t->w_c[k]) w[l]++, w[k]--, c = 1; if (w[k] > t->w_c[k]) { if (!c) internal("can't shrink cell"); else goto ag; } }*/ } else if (c->colspan > s && c->colspan < ns) ns = c->colspan; } } while ((s = ns) != MAXINT); s = 0; ns = 0; for (i = 0; i < t->x; i++) { s += t->w_c[i], ns += w[i]; /*if (w[i] > t->w_c[i]) { int k; for (k = 0; k < t->x; k++) debug("%d, %d", t->w_c[k], w[k]); debug("column %d: new width(%d) is larger than previous(%d)", i, w[i], t->w_c[i]); }*/ } if (ns > s) { /*internal("new width(%d) is larger than previous(%d)", ns, s);*/ mem_free(w); return; } m = -1; for (i = 0; i < t->x; i++) { /*if (table_level == 1) debug("%d: %d %d %d %d", i, t->max_c[i], t->min_c[i], t->w_c[i], w[i]);*/ if (t->max_c[i] > m) m = t->max_c[i], mi = i; } /*if (table_level == 1) debug("%d %d", mi, s - ns);*/ if (m != -1) { w[mi] += s - ns; if (w[mi] <= t->max_c[mi]) { mem_free(t->w_c); t->w_c = w; return; } } mem_free(w); }
void display_table_frames(struct table *t, int x, int y) { signed char *fh, *fv; int i, j; int cx, cy; if ((unsigned)t->x > MAXINT) overalloc(); if ((unsigned)t->y > MAXINT) overalloc(); if (((unsigned)t->x + 2) * ((unsigned)t->y + 2) / ((unsigned)t->x + 2) != ((unsigned)t->y + 2)) overalloc(); if (((unsigned)t->x + 2) * ((unsigned)t->y + 2) > MAXINT) overalloc(); fh = mem_alloc((t->x + 2) * (t->y + 1)); memset(fh, -1, (t->x + 2) * (t->y + 1)); fv = mem_alloc((t->x + 1) * (t->y + 2)); memset(fv, -1, (t->x + 1) * (t->y + 2)); #ifndef DEBUG #define H_LINE_X(xx, yy) fh[(xx) + 1 + (t->x + 2) * (yy)] #define V_LINE_X(xx, yy) fv[(yy) + 1 + (t->y + 2) * (xx)] #else #define H_LINE_X(xx, yy) (*(xx < -1 || xx > t->x + 1 || yy < 0 || yy > t->y ? (signed char *)NULL : &fh[(xx) + 1 + (t->x + 2) * (yy)])) #define V_LINE_X(xx, yy) (*(xx < 0 || xx > t->x || yy < -1 || yy > t->y + 1 ? (signed char *)NULL : &fv[(yy) + 1 + (t->y + 2) * (xx)])) #endif #define H_LINE(xx, yy) (H_LINE_X((xx), (yy)) == -1 ? 0 : H_LINE_X((xx), (yy))) #define V_LINE(xx, yy) (V_LINE_X((xx), (yy)) == -1 ? 0 : V_LINE_X((xx), (yy))) for (j = 0; j < t->y; j++) for (i = 0; i < t->x; i++) { int x, y; int xsp, ysp; struct table_cell *cell = CELL(t, i, j); if (!cell->used || cell->spanned) continue; if ((xsp = cell->colspan) == 0) xsp = t->x - i; if ((ysp = cell->rowspan) == 0) ysp = t->y - j; if (t->rules != R_NONE && t->rules != R_COLS) for (x = 0; x < xsp; x++) {H_LINE_X(i + x, j) = t->cellsp; H_LINE_X(i + x, j + ysp) = t->cellsp;} if (t->rules != R_NONE && t->rules != R_ROWS) for (y = 0; y < ysp; y++) {V_LINE_X(i, j + y) = t->cellsp; V_LINE_X(i + xsp, j + y) = t->cellsp;} } if (t->rules == R_GROUPS) { for (i = 1; i < t->x; i++) { if (/*i < t->xc &&*/ t->xcols[i]) continue; for (j = 0; j < t->y; j++) V_LINE_X(i, j) = 0; } for (j = 1; j < t->y; j++) { for (i = 0; i < t->x; i++) if (CELL(t, i, j)->group) goto c; for (i = 0; i < t->x; i++) H_LINE_X(i, j) = 0; c:; } } for (i = 0; i < t->x; i++) { H_LINE_X(i, 0) = t->border * !!(t->frame & F_ABOVE); H_LINE_X(i, t->y) = t->border * !!(t->frame & F_BELOW); } for (j = 0; j < t->y; j++) { V_LINE_X(0, j) = t->border * !!(t->frame & F_LHS); V_LINE_X(t->x, j) = t->border * !!(t->frame & F_RHS); } cy = y; for (j = 0; j <= t->y; j++) { cx = x; if ((j > 0 && j < t->y && get_hline_width(t, j) >= 0) || (j == 0 && t->border && (t->frame & F_ABOVE)) || (j == t->y && t->border && (t->frame & F_BELOW))) { for (i = 0; i < t->x; i++) { int w; if (i > 0) w = get_vline_width(t, i); else w = t->border && (t->frame & F_LHS) ? t->border : -1; if (w >= 0) { draw_frame_point(cx, cy, i, j); if (j < t->y) draw_frame_vline(cx, cy + 1, t->r_heights[j], i, j); cx++; } w = t->w_c[i]; draw_frame_hline(cx, cy, w, i, j); cx += w; } if (t->border && (t->frame & F_RHS)) { draw_frame_point(cx, cy, i, j); if (j < t->y) draw_frame_vline(cx, cy + 1, t->r_heights[j], i, j); cx++; } cy++; } else if (j < t->y) { for (i = 0; i <= t->x; i++) { if ((i > 0 && i < t->x && get_vline_width(t, i) >= 0) || (i == 0 && t->border && (t->frame & F_LHS)) || (i == t->x && t->border && (t->frame & F_RHS))) { draw_frame_vline(cx, cy, t->r_heights[j], i, j); cx++; } if (i < t->x) cx += t->w_c[i]; } } if (j < t->y) cy += t->r_heights[j]; /*for (cyy = cy1; cyy < cy; cyy++) xxpand_line(t->p, cyy, cx - 1);*/ } mem_free(fh); mem_free(fv); }