| #include "common.h" |
| |
| #define LINE_LEN 79 |
| #define STATUS_LEN 22 |
| #define PROGBAR_MAX (LINE_LEN - STATUS_LEN - 1) |
| |
| static char status_msg[128]; |
| static int progbar_scale = 0; |
| static int progbar_len = 0; |
| static int progbar_pos = -1; |
| |
| int quietmode = 0; |
| int errorlog = 0; |
| |
| static png_uint_32 counter; |
| static png_uint_32 maxcount; |
| static int barlen; |
| |
| #define isoption(p) (IsOptChar((p)[0]) && (p)[1]!='\0') |
| |
| static void print_status(void) |
| { |
| fprintf(stderr, "\r%-*.*s ", STATUS_LEN, STATUS_LEN, status_msg); |
| fflush(stderr); |
| progbar_pos = 0; |
| } |
| |
| static void put_dots(int dotchar, int num) |
| { |
| int i; |
| |
| if (num > PROGBAR_MAX) num = PROGBAR_MAX; |
| if (progbar_pos == -1) print_status(); |
| |
| for (i = progbar_pos; i < num; i++) |
| fputc(dotchar, stderr); |
| |
| if (progbar_pos < num) { |
| progbar_pos = num; |
| fflush(stderr); |
| } |
| } |
| |
| static void print_scale(void) |
| { |
| if (progbar_pos != 0) print_status(); |
| put_dots('.', progbar_len); |
| print_status(); |
| progbar_scale = 1; |
| } |
| |
| static void init_progress_bar(int max) |
| { |
| if (quietmode) return; |
| |
| progbar_len = max; |
| print_scale(); |
| } |
| |
| static void update_progress_bar(int num) |
| { |
| if (quietmode) return; |
| |
| if (!progbar_scale) print_scale(); |
| put_dots('o', num); |
| } |
| |
| static void clear_line(void) |
| { |
| if (quietmode) return; |
| |
| fprintf(stderr, "\r%*c\r", LINE_LEN, ' '); |
| progbar_scale = 0; |
| progbar_pos = -1; |
| } |
| |
| void xxprintf(const char *fmt, ...) |
| { |
| va_list ap; |
| FILE *f; |
| |
| va_start(ap, fmt); |
| |
| clear_line(); |
| vfprintf(stderr, fmt, ap); |
| fflush(stderr); |
| |
| if (errorlog && (f = fopen(errlogfile, "a")) != NULL) { |
| vfprintf(f, fmt, ap); |
| fclose(f); |
| } |
| |
| va_end(ap); |
| } |
| |
| void set_status(const char *fmt, ...) |
| { |
| va_list ap; |
| |
| if (quietmode) return; |
| |
| va_start(ap, fmt); |
| vsprintf(status_msg, fmt, ap); |
| va_end(ap); |
| |
| print_status(); |
| } |
| |
| void feed_line(void) |
| { |
| if (quietmode) return; |
| |
| fputc('\n', stderr); |
| fflush(stderr); |
| progbar_scale = 0; |
| progbar_pos = -1; |
| } |
| |
| static png_uint_32 maxcount_adam7(png_uint_32 width, png_uint_32 height) |
| { |
| png_uint_32 c = 0; |
| |
| if ( 1 ) c += ((height - 0 + 7) / 8) * 1; |
| if (width > 4) c += ((height - 0 + 7) / 8) * 1; |
| if ( 1 ) c += ((height - 4 + 7) / 8) * 2; |
| if (width > 2) c += ((height - 0 + 3) / 4) * 2; |
| if ( 1 ) c += ((height - 2 + 3) / 4) * 4; |
| if (width > 1) c += ((height - 0 + 1) / 2) * 4; |
| if ( 1 ) c += ((height - 1 + 1) / 2) * 8; |
| |
| return c; |
| } |
| |
| void init_progress_meter(png_structp png_ptr, png_uint_32 width, |
| png_uint_32 height) |
| { |
| enum { W = 1024, H = 768 }; |
| |
| if (png_set_interlace_handling(png_ptr) == 7) { |
| maxcount = maxcount_adam7(width, height); |
| } else { |
| maxcount = height; |
| } |
| if (height > ((png_uint_32)W * H) / width) { |
| barlen = PROGBAR_MAX; |
| } else { |
| barlen = (PROGBAR_MAX * width * height + (W * H - 1)) / (W * H); |
| } |
| counter = 0; |
| init_progress_bar(barlen); |
| } |
| |
| void row_callback(png_structp png_ptr, png_uint_32 row, int pass) |
| { |
| |
| if (row == 0) pass--; |
| |
| |
| counter += (1 << (pass >> 1)); /* step[pass]; */ |
| update_progress_bar(barlen * counter / maxcount); |
| } |
| |
| FILE *binary_stdio(int fd) |
| { |
| FILE *fp; |
| |
| if (fd != 0 && fd != 1) |
| return NULL; |
| |
| printf("---------binary_stdio----else ------\n"); |
| fp = (fd == 0) ? stdin : stdout; |
| |
| return fp; |
| } |
| |
| char *suffix(const char *path) |
| { |
| char c, *p, *q, *r; |
| |
| for (r = q = p = basname(path); (c = *p) != '\0'; p++) |
| if (c == '.') q = p; |
| if (q == r) q = p; /* dotfile with no suffix */ |
| |
| return q; |
| } |
| |
| char *basname(const char *path) |
| { |
| const char *p, *q; |
| |
| for (p = path_skiproot(path); |
| *(q = path_nextslash(p)) != '\0'; p = q + 1) ; |
| |
| return (char *)p; |
| } |
| |
| char *addslash(char *path) |
| { |
| char *p, *q; |
| |
| for (p = path_skiproot(path); |
| *(q = path_nextslash(p)) != '\0'; p = q + 1) ; |
| |
| if (q != p) { |
| *q++ = PATHDELIM; |
| *q = '\0'; |
| } |
| |
| return path; |
| } |
| |
| |
| char *path_skiproot(const char *path) |
| { |
| if (IsPathDelim(path[0])) path++; |
| return (char *)path; |
| } |
| |
| char *path_nextslash(const char *path) |
| { |
| char c; |
| |
| for (; (c = *path) != '\0'; path++) { |
| if (IsDBCSLead((unsigned char)c)) { |
| if (*(++path) == '\0') break; |
| continue; |
| } |
| if (IsPathDelim(c)) break; |
| } |
| return (char *)path; |
| } |
| |
| char *delslash(char *path) |
| { |
| char *p, *q, *s; |
| |
| for (p = s = path_skiproot(path); |
| *(q = path_nextslash(p)) != '\0'; p = q + 1) ; |
| |
| if (q == s) { |
| *q++ = '.'; |
| *q = '\0'; |
| } else if (q == p) { |
| *--q = '\0'; |
| } |
| |
| return path; |
| } |
| |
| |
| void png_my_error(png_structp png_ptr, png_const_charp message) |
| { |
| xxprintf("ERROR(libpng): %s - %s\n", message, |
| (char *)png_get_error_ptr(png_ptr)); |
| longjmp(png_jmpbuf(png_ptr), 1); |
| } |
| |
| void png_my_warning(png_structp png_ptr, png_const_charp message) |
| { |
| xxprintf("WARNING(libpng): %s - %s\n", message, |
| (char *)png_get_error_ptr(png_ptr)); |
| } |
| |
| BOOL imgbuf_alloc(IMAGE *img) |
| { |
| BYTE *bp, **rp; |
| LONG n; |
| |
| if (img->palnum > 0) { |
| img->palette = malloc((size_t)img->palnum * sizeof(PALETTE)); |
| if (img->palette == NULL) { imgbuf_init(img); return FALSE; } |
| } else { |
| img->palette = NULL; |
| } |
| img->rowbytes = ((DWORD)img->width * img->pixdepth + 31) / 32 * 4; |
| img->imgbytes = img->rowbytes * img->height; |
| img->rowptr = malloc((size_t)img->height * sizeof(BYTE *)); |
| img->bmpbits = malloc((size_t)img->imgbytes); |
| |
| if (img->rowptr == NULL || img->bmpbits == NULL) { |
| imgbuf_free(img); imgbuf_init(img); return FALSE; |
| } |
| |
| n = img->height; |
| rp = img->rowptr; |
| bp = img->bmpbits; |
| |
| if (img->topdown) { |
| while (--n >= 0) { |
| *(rp++) = bp; |
| bp += img->rowbytes; |
| |
| } |
| } else { /* bottom-up */ |
| bp += img->imgbytes; |
| while (--n >= 0) { |
| |
| ((DWORD *)bp)[-1] = 0; |
| bp -= img->rowbytes; |
| *(rp++) = bp; |
| } |
| } |
| |
| return TRUE; |
| } |
| |
| void imgbuf_free(IMAGE *img) |
| { |
| free(img->palette); |
| free(img->rowptr); |
| free(img->bmpbits); |
| } |
| |
| void imgbuf_init(IMAGE *img) |
| { |
| img->palette = NULL; |
| img->rowptr = NULL; |
| img->bmpbits = NULL; |
| } |
| |
| int parsearg(int *opt, char **arg, int argc, char **argv, char *aopts) |
| { |
| static int agi = 1; |
| static char *agp = NULL; |
| char *p; |
| int c, i; |
| |
| if (agp != NULL && *agp == '\0') { |
| agp = NULL; |
| agi++; |
| } |
| if (agi >= argc) |
| return 0; |
| |
| if (p = argv[agi], agp == NULL && !isoption(p)) { |
| |
| c = 0; |
| agi++; |
| } else { |
| if (agp == NULL) agp = p + 1; |
| if (c = (*agp & 0xFF), strchr(aopts, c) != NULL) { |
| |
| if (p = agp + 1, *p != '\0') { |
| /*NULL*/; |
| } else if (i = agi + 1, p = argv[i], i < argc && !isoption(p)) { |
| agi = i; |
| } else { |
| p = NULL; |
| } |
| agp = NULL; |
| agi++; |
| } else { |
| |
| p = NULL; |
| agp++; |
| } |
| } |
| *opt = c; |
| *arg = p; |
| |
| return 1; |
| } |
| |
| char **envargv(int *argcp, char ***argvp, const char *envn) |
| { |
| int argc, nagc, envc, i; |
| char **argv, **nagv, *envs, *ep; |
| |
| ep = getenv(envn); |
| if (ep == NULL || ep[0] == '\0') return NULL; |
| |
| envs = malloc(strlen(ep) + 1); |
| if (envs == NULL) return NULL; |
| strcpy(envs, ep); |
| |
| envc = tokenize(envs, envs); |
| if (envc == 0) { free(envs); return NULL; } |
| |
| argc = *argcp; |
| argv = *argvp; |
| nagv = malloc((argc + envc + 1) * sizeof(char *)); |
| if (nagv == NULL) { free(envs); return NULL; } |
| |
| nagc = 1; |
| nagv[0] = argv[0]; |
| |
| for (i = 0; i < envc; i++) { |
| nagv[nagc++] = envs; |
| while (*(envs++) != '\0') ; |
| } |
| for (i = 1; i < argc; i++) { |
| nagv[nagc++] = argv[i]; |
| } |
| nagv[nagc] = NULL; |
| |
| *argcp = nagc; |
| *argvp = nagv; |
| |
| return argv; |
| } |
| |
| int tokenize(char *buf, const char *str) |
| { |
| enum { STR = 0x01, QUOTE = 0x02 }; |
| int flag = 0; |
| int num = 0; |
| char c; |
| int i; |
| |
| while ((c = *str++) != '\0') { |
| if (!(flag & QUOTE) && |
| (c == ' ' || c == '\t' || c == '\n' || c == '\r')) { |
| if (flag & STR) { |
| flag &= ~STR; |
| *buf++ = '\0'; |
| } |
| } else { |
| if (!(flag & STR)) { |
| flag |= STR; |
| num++; |
| } |
| switch (c) { |
| case '\\': |
| |
| for (i = 1; (c = *str) == '\\'; str++, i++) ; |
| if (c == '"') { |
| while ((i -= 2) >= 0) |
| *buf++ = '\\'; |
| if (i == -1) { |
| *buf++ = '"'; |
| str++; |
| } |
| } else { |
| while ((--i) >= 0) |
| *buf++ = '\\'; |
| } |
| break; |
| |
| case '"': |
| flag ^= QUOTE; |
| break; |
| |
| default: |
| *buf++ = c; |
| } |
| } |
| } |
| if (flag & STR) *buf = '\0'; |
| |
| return num; |
| } |
| |
| int makedir(const char *path) |
| { |
| char dir[FILENAME_MAX]; |
| struct stat sbuf; |
| char *p, c; |
| int r; |
| |
| delslash(strcpy(dir, path)); |
| if (stat(dir, &sbuf) == 0) { |
| if ((sbuf.st_mode & S_IFMT) == S_IFDIR) return 0; |
| |
| return -1; |
| } |
| p = path_skiproot(dir); |
| do { |
| p = path_nextslash(p); |
| c = *p; *p = '\0'; |
| r = MKDIR(dir, 0777); |
| *p++ = c; |
| } while (c != '\0'); |
| |
| return r; |
| } |
| |
| int renbak(const char *path) |
| { |
| char bak[FILENAME_MAX]; |
| struct stat sbuf; |
| char *sfx; |
| int i; |
| |
| strcpy(bak, path); |
| if (stat(bak, &sbuf) != 0) return 0; |
| |
| sfx = bak + strlen(bak); |
| |
| strcpy(sfx, ".bak"); |
| i = 0; |
| while (1) { |
| if (stat(bak, &sbuf) != 0 && rename(path, bak) == 0) return 0; |
| if (i >= 1000) break; |
| sprintf(sfx, ".%03d", i++); |
| } |
| return -1; |
| } |
| |
| int cpyftime(const char *srcf, const char *dstf) |
| { |
| struct stat sbuf; |
| struct utimbuf ubuf; |
| |
| if (stat(srcf, &sbuf) != 0) return -1; |
| |
| ubuf.actime = sbuf.st_atime; |
| ubuf.modtime = sbuf.st_mtime; |
| |
| return utime(dstf, &ubuf); |
| } |
| |
| |