00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "htio.h"
00022
00023 #include "htsys.h"
00024
00025 #include <ctype.h>
00026 #include <errno.h>
00027 #include <limits.h>
00028 #include <stdarg.h>
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <sys/stat.h>
00033
00034
00035
00036
00037
00038 #ifndef S_IFMT
00039 #define S_IFMT 0xf000
00040 #endif
00041
00042 #ifndef S_ISREG
00043 # ifndef S_IFREG
00044 # define S_ISREG(m) (0)
00045 # else
00046 # define S_ISREG(m) (((m) & S_IFMT)==S_IFREG)
00047 # endif
00048 #endif
00049
00050 #ifndef S_ISBLK
00051 # ifndef S_IFBLK
00052 # define S_ISBLK(m) (0)
00053 # else
00054 # define S_ISBLK(m) (((m) & S_IFMT)==S_IFBLK)
00055 # endif
00056 #endif
00057
00058
00059 #ifndef S_ISCHR
00060 # ifndef S_IFCHR
00061 # define S_ISCHR(m) (0)
00062 # else
00063 # define S_ISCHR(m) (((m) & S_IFMT)==S_IFCHR)
00064 # endif
00065 #endif
00066
00067 #ifndef S_ISDIR
00068 # ifndef S_IFDIR
00069 # define S_ISDIR(m) (0)
00070 # else
00071 # define S_ISDIR(m) (((m) & S_IFMT)==S_IFDIR)
00072 # endif
00073 #endif
00074
00075 #ifndef S_ISFIFO
00076 # ifndef S_IFFIFO
00077 # define S_ISFIFO(m) (0)
00078 # else
00079 # define S_ISFIFO(m) (((m) & S_IFMT)==S_IFFIFO)
00080 # endif
00081 #endif
00082
00083 #ifndef S_ISLNK
00084 # ifndef S_IFLNK
00085 # define S_ISLNK(m) (0)
00086 # else
00087 # define S_ISLNK(m) (((m) & S_IFMT)==S_IFLNK)
00088 # endif
00089 #endif
00090
00091 #ifndef S_ISSOCK
00092 # ifndef S_IFSOCK
00093 # define S_ISSOCK(m) (0)
00094 # else
00095 # define S_ISSOCK(m) (((m) & S_IFMT)==S_IFSOCK)
00096 # endif
00097 #endif
00098
00099 #ifndef S_IRUSR
00100 #define S_IRUSR 0
00101 #endif
00102 #ifndef S_IRGRP
00103 #define S_IRGRP 0
00104 #endif
00105 #ifndef S_IROTH
00106 #define S_IROTH 0
00107 #endif
00108
00109 #ifndef S_IWUSR
00110 #define S_IWUSR 0
00111 #endif
00112 #ifndef S_IWGRP
00113 #define S_IWGRP 0
00114 #endif
00115 #ifndef S_IWOTH
00116 #define S_IWOTH 0
00117 #endif
00118
00119 #ifndef S_IXUSR
00120 #define S_IXUSR 0
00121 #endif
00122 #ifndef S_IXGRP
00123 #define S_IXGRP 0
00124 #endif
00125 #ifndef S_IXOTH
00126 #define S_IXOTH 0
00127 #endif
00128
00129 int sys_basename(char *result, const char *filename)
00130 {
00131
00132 char *slash1 = strrchr(filename, '/');
00133 char *slash2 = strrchr(filename, '\\');
00134 char *slash=(slash1>slash2) ? slash1 : slash2;
00135 if (slash) {
00136 int l=strlen(filename);
00137 strncpy(result, slash+1, l-(slash-filename)-1);
00138 result[l-(slash-filename)-1]=0;
00139 return 0;
00140 }
00141 strcpy(result, filename);
00142 return 0;
00143 }
00144
00145 int sys_dirname(char *result, const char *filename)
00146 {
00147
00148 char *slash1 = strrchr(filename, '/');
00149 char *slash2 = strrchr(filename, '\\');
00150 char *slash = (slash1>slash2) ? slash1 : slash2;
00151 if (slash) {
00152 strncpy(result, filename, slash-filename);
00153 result[slash-filename] = 0;
00154 return 0;
00155 }
00156 strcpy(result, ".");
00157 return 0;
00158 }
00159
00160
00161 int sys_relname(char *result, const char *filename, const char *cwd)
00162 {
00163 const char *f = filename, *p = cwd;
00164 while ((*f == *p) && (*f)) {
00165 f++;
00166 p++;
00167 }
00168 if (*f == '/') f++;
00169 const char *last = f, *h = f;
00170 while (*h) {
00171 if (*h == '/') {
00172 *(result++) = '.';
00173 *(result++) = '.';
00174 *(result++) = '/';
00175 last = h+1;
00176 }
00177 h++;
00178 }
00179 while (f<last) {
00180 *(result++) = *f;
00181 f++;
00182 }
00183 *result = 0;
00184 strcat(result, last);
00185 return 0;
00186 }
00187
00188 int sys_ht_mode(int mode)
00189 {
00190 int m = 0;
00191 if (S_ISREG(mode)) {
00192 m |= HT_S_IFREG;
00193 } else if (S_ISBLK(mode)) {
00194 m |= HT_S_IFBLK;
00195 } else if (S_ISCHR(mode)) {
00196 m |= HT_S_IFCHR;
00197 } else if (S_ISDIR(mode)) {
00198 m |= HT_S_IFDIR;
00199 } else if (S_ISFIFO(mode)) {
00200 m |= HT_S_IFFIFO;
00201 } else if (S_ISLNK(mode)) {
00202 m |= HT_S_IFLNK;
00203 } else if (S_ISSOCK(mode)) {
00204 m |= HT_S_IFSOCK;
00205 }
00206 if (mode & S_IRUSR) m |= HT_S_IRUSR;
00207 if (mode & S_IRGRP) m |= HT_S_IRGRP;
00208 if (mode & S_IROTH) m |= HT_S_IROTH;
00209
00210 if (mode & S_IWUSR) m |= HT_S_IWUSR;
00211 if (mode & S_IWGRP) m |= HT_S_IWGRP;
00212 if (mode & S_IWOTH) m |= HT_S_IWOTH;
00213
00214 if (mode & S_IXUSR) m |= HT_S_IXUSR;
00215 if (mode & S_IXGRP) m |= HT_S_IXGRP;
00216 if (mode & S_IXOTH) m |= HT_S_IXOTH;
00217 return m;
00218 }
00219
00220 static char *next_delim(char *s, is_path_delim delim)
00221 {
00222 while (*s) {
00223 s++;
00224 if (delim(*s)) return s;
00225 }
00226 return NULL;
00227 }
00228
00229 static int flatten_path(char *path, is_path_delim delim)
00230 {
00231 if (!path || !*path)
00232 return 0;
00233 char *q = next_delim(path, delim);
00234 int pp = flatten_path(q, delim);
00235 int ll = q ? (q-path-1) : strlen(path)-1;
00236 if ((ll == 2) && (strncmp(path+1, "..", 2) == 0)) {
00237 if (q) memmove(path, q, strlen(q)+1); else *path = 0;
00238 pp++;
00239 } else if ((ll == 1) && (strncmp(path+1, ".", 1) == 0)) {
00240 if (q) memmove(path, q, strlen(q)+1); else *path = 0;
00241 } else if (pp) {
00242 if (q) memmove(path, q, strlen(q)+1); else *path = 0;
00243 pp--;
00244 }
00245 return pp;
00246 }
00247
00248 bool sys_path_is_absolute(const char *filename, is_path_delim delim)
00249 {
00250 return delim(filename[0]) || (isalpha(filename[0]) && (filename[1] == ':'));
00251 }
00252
00253 int sys_common_canonicalize(char *result, const char *filename, const char *cwd, is_path_delim delim)
00254 {
00255 char *o = result;
00256 if (!sys_path_is_absolute(filename, delim)) {
00257 if (cwd) strcpy(o, cwd); else return EINVAL;
00258 int ol = strlen(o);
00259 if (ol && !delim(o[ol-1])) {
00260 o[ol] = '/';
00261 o[ol+1] = 0;
00262 }
00263 } else *o = 0;
00264 strcat(o, filename);
00265 int k = flatten_path(o, delim);
00266 return (k==0) ? 0 : EINVAL;
00267 }
00268
00269 char *sys_filename_suffix(const char *fn)
00270 {
00271 const char *s = NULL;
00272 while (fn && *fn) {
00273 if (sys_is_path_delim(*fn)) s = fn+1;
00274 fn++;
00275 }
00276 char *p = s ? strrchr(s, '.') : NULL;
00277 return p ? p+1 : NULL;
00278 }
00279
00280 int sys_tmpfile()
00281 {
00282
00283 FILE *f = tmpfile();
00284 return fileno(f);
00285 }
00286
00287
00288
00289
00290
00291 #define IS_FGTRANS(c) (VC_GET_BASECOLOR(VCP_FOREGROUND((c)))==VC_TRANSPARENT)
00292 #define IS_BGTRANS(c) (VC_GET_BASECOLOR(VCP_BACKGROUND((c)))==VC_TRANSPARENT)
00293
00294 vcp vcp_mix(vcp base, vcp layer)
00295 {
00296 int fg, bg;
00297 if (IS_FGTRANS(layer)) {
00298 fg=VCP_FOREGROUND(base);
00299 } else {
00300 fg=VCP_FOREGROUND(layer);
00301 }
00302 if (IS_BGTRANS(layer)) {
00303 bg=VCP_BACKGROUND(base);
00304 } else {
00305 bg=VCP_BACKGROUND(layer);
00306 }
00307 if (IS_FGTRANS(layer) && (fg != VC_TRANSPARENT) && (fg == bg)) fg=(fg+1)%8;
00308 if (IS_BGTRANS(layer) && (bg != VC_TRANSPARENT) && (fg == bg)) bg=(bg+1)%8;
00309 return VCP(fg, bg);
00310 }
00311
00312
00313
00314
00315
00316 genericdrawbuf::genericdrawbuf()
00317 {
00318 }
00319
00320 genericdrawbuf::~genericdrawbuf()
00321 {
00322 }
00323
00324 void genericdrawbuf::b_line(int px1, int py1, int px2, int py2, int c)
00325 {
00326 }
00327
00328 void genericdrawbuf::b_putpixel(int px, int py, int c)
00329 {
00330 }
00331
00332 void genericdrawbuf::text_to_pixel_coord(int tx, int ty, int *px, int *py)
00333 {
00334 *px = tx;
00335 *py = ty;
00336 }
00337
00338 void genericdrawbuf::pixel_to_text_coord(int px, int py, int *tx, int *ty)
00339 {
00340 *tx = px;
00341 *ty = py;
00342 }
00343
00344 void genericdrawbuf::b_fill(int x, int y, int w, int h, int c, int ch)
00345 {
00346 }
00347
00348 int genericdrawbuf::b_printf(int x, int y, int c, char *format, ...)
00349 {
00350 char buf[1024];
00351 va_list arg;
00352 va_start(arg, format);
00353 vsprintf(buf, format, arg);
00354 va_end(arg);
00355 return b_print(x, y, c, buf);
00356 }
00357
00358 int genericdrawbuf::b_print(int x, int y, int c, char *text)
00359 {
00360 return b_lprint(x, y, c, 0x7fffffff, text);
00361 }
00362
00363 int genericdrawbuf::b_printw(int x, int y, int c, int *text)
00364 {
00365 return b_lprintw(x, y, c, 0x7fffffff, text);
00366 }
00367
00368 void genericdrawbuf::b_printchar(int x, int y, int c, int ch)
00369 {
00370 }
00371
00372 int genericdrawbuf::b_lprint(int x, int y, int c, int l, char *text)
00373 {
00374 return 0;
00375 }
00376
00377 int genericdrawbuf::b_lprintw(int x, int y, int c, int l, int *text)
00378 {
00379 return 0;
00380 }
00381
00382 void genericdrawbuf::b_resize(int rw, int rh)
00383 {
00384 size.w+=rw;
00385 size.h+=rh;
00386 b_setbounds(&size);
00387 }
00388
00389 void genericdrawbuf::b_rmove(int rx, int ry)
00390 {
00391 size.x+=rx;
00392 size.y+=ry;
00393 }
00394
00395 void genericdrawbuf::b_setbounds(bounds *b)
00396 {
00397 size=*b;
00398 }
00399
00400
00401
00402
00403
00404 drawbuf::drawbuf(bounds *b)
00405 {
00406 buf=0;
00407 b_setbounds(b);
00408 }
00409
00410 drawbuf::~drawbuf()
00411 {
00412 if (buf) free(buf);
00413 }
00414
00415 void drawbuf::b_fill(int x, int y, int w, int h, int c, int ch)
00416 {
00417 x-=size.x;
00418 y-=size.y;
00419 for (int iy=y; iy<y+h; iy++) {
00420 if (iy<size.h) {
00421 drawbufch *b=buf+x+iy*size.w;
00422 for (int ix=x; ix<x+w; ix++) {
00423 b->ch=ch;
00424 b->c=vcp_mix(b->c, c);
00425 b++;
00426 }
00427 }
00428 }
00429 }
00430
00431 void drawbuf::b_printchar(int x, int y, int c, int ch)
00432 {
00433 drawbufch *b=buf+(x-size.x)+(y-size.y)*size.w;
00434 b->ch=ch;
00435 b->c=vcp_mix(b->c, c);
00436 }
00437
00438 int drawbuf::b_lprint(int x, int y, int c, int l, char *text)
00439 {
00440 int ox=0;
00441 x-=size.x;
00442 y-=size.y;
00443 drawbufch *b=buf+x+y*size.w;
00444 if (y<size.h) {
00445 while ((ox<size.w) && (*text) && (ox<l)) {
00446 b->ch=(byte)*text;
00447 b->c=vcp_mix(b->c, c);
00448 text++;
00449 ox++;
00450 b++;
00451 }
00452 }
00453 return ox;
00454 }
00455
00456 int drawbuf::b_lprintw(int x, int y, int c, int l, int *text)
00457 {
00458 int ox=0;
00459 x-=size.x;
00460 y-=size.y;
00461 drawbufch *b=buf+x+y*size.w;
00462 if (y<size.h) {
00463 while ((ox<size.w) && (*text) && (ox<l)) {
00464 b->ch=(byte)*text;
00465 b->c=vcp_mix(b->c, c);
00466 text++;
00467 ox++;
00468 b++;
00469 }
00470 }
00471 return ox;
00472 }
00473
00474 void drawbuf::b_setbounds(bounds *b)
00475 {
00476 genericdrawbuf::b_setbounds(b);
00477 if (buf) free(buf);
00478 if (size.w * size.h) {
00479 buf=(drawbufch*)malloc(sizeof *buf * size.w * size.h);
00480 drawbufch *bb=buf;
00481 for (int iy=0; iy<size.h; iy++) {
00482 for (int ix=0; ix<size.w; ix++) {
00483 bb->ch=' ';
00484 bb->c=VCP(VC_TRANSPARENT, VC_TRANSPARENT);
00485 bb++;
00486 }
00487 }
00488 } else buf=0;
00489 }
00490
00491
00492
00493
00494
00495 ht_key ht_unmetakey(ht_key key)
00496 {
00497 switch (key) {
00498 case K_Alt_A: return K_A;
00499 case K_Alt_B: return K_B;
00500 case K_Alt_C: return K_C;
00501 case K_Alt_D: return K_D;
00502 case K_Alt_E: return K_E;
00503 case K_Alt_F: return K_F;
00504 case K_Alt_G: return K_G;
00505 case K_Alt_H: return K_H;
00506 case K_Alt_I: return K_I;
00507 case K_Alt_J: return K_J;
00508 case K_Alt_K: return K_K;
00509 case K_Alt_L: return K_L;
00510 case K_Alt_M: return K_M;
00511 case K_Alt_N: return K_N;
00512 case K_Alt_O: return K_O;
00513 case K_Alt_P: return K_P;
00514 case K_Alt_Q: return K_Q;
00515 case K_Alt_R: return K_R;
00516 case K_Alt_S: return K_S;
00517 case K_Alt_T: return K_T;
00518 case K_Alt_U: return K_U;
00519 case K_Alt_V: return K_V;
00520 case K_Alt_W: return K_W;
00521 case K_Alt_X: return K_X;
00522 case K_Alt_Y: return K_Y;
00523 case K_Alt_Z: return K_Z;
00524 default: return K_INVALID;
00525 }
00526 }
00527
00528 ht_key ht_lmetakey(ht_key key)
00529 {
00530 switch (key) {
00531 case K_A: return K_Alt_A;
00532 case K_B: return K_Alt_B;
00533 case K_C: return K_Alt_C;
00534 case K_D: return K_Alt_D;
00535 case K_E: return K_Alt_E;
00536 case K_F: return K_Alt_F;
00537 case K_G: return K_Alt_G;
00538 case K_H: return K_Alt_H;
00539 case K_I: return K_Alt_I;
00540 case K_J: return K_Alt_J;
00541 case K_K: return K_Alt_K;
00542 case K_L: return K_Alt_L;
00543 case K_M: return K_Alt_M;
00544 case K_N: return K_Alt_N;
00545 case K_O: return K_Alt_O;
00546 case K_P: return K_Alt_P;
00547 case K_Q: return K_Alt_Q;
00548 case K_R: return K_Alt_R;
00549 case K_S: return K_Alt_S;
00550 case K_T: return K_Alt_T;
00551 case K_U: return K_Alt_U;
00552 case K_V: return K_Alt_V;
00553 case K_W: return K_Alt_W;
00554 case K_X: return K_Alt_X;
00555 case K_Y: return K_Alt_Y;
00556 case K_Z: return K_Alt_Z;
00557 default: return K_INVALID;
00558 }
00559 }
00560
00561 ht_key ht_metakey(ht_key key)
00562 {
00563 if ((key>=K_A) && (key<=K_Z)) {
00564 return ht_lmetakey(key);
00565
00566
00567 }
00568 return K_INVALID;
00569 }
00570
00571 static int ht_keys1[K_COUNT];
00572 static int ht_keys2[K_COUNT];
00573 static int ht_keys3[K_COUNT];
00574
00575 ht_key ht_rawkey2key(int rawkey)
00576 {
00577 for (int i=0; i<K_COUNT; i++) {
00578 if (ht_keys1[i]==(int)rawkey) return (ht_key)i;
00579 if (ht_keys2[i]==(int)rawkey) return (ht_key)i;
00580 if (ht_keys3[i]==(int)rawkey) return (ht_key)i;
00581 }
00582 return K_INVALID;
00583 }
00584
00585 void ht_set_key(ht_key key, int rawkey)
00586 {
00587 int i = (int)key;
00588 if (i<K_COUNT) {
00589 if (rawkey == -1) {
00590 ht_keys1[i] = -1;
00591 ht_keys2[i] = -1;
00592 ht_keys3[i] = -1;
00593 }
00594 else if ((ht_keys1[i] == -1) || (ht_keys1[i] == rawkey)) ht_keys1[i] = rawkey;
00595 else if ((ht_keys2[i] == -1) || (ht_keys2[i] == rawkey)) ht_keys2[i] = rawkey;
00596 else if ((ht_keys3[i] == -1) || (ht_keys3[i] == rawkey)) ht_keys3[i] = rawkey;
00597 }
00598 }