diff options
author | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2008-03-15 22:18:55 +0800 |
---|---|---|
committer | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2008-03-15 22:18:55 +0800 |
commit | ea9c870ae1208a0b6032102591dcecc76a897b2f (patch) | |
tree | d4ab8a91388390332849c6026bd46bcd0ccc4390 /mbbsd | |
parent | 7edce5f16e016665ada2d55aa5528ea947907fab (diff) | |
download | pttbbs-ea9c870ae1208a0b6032102591dcecc76a897b2f.tar pttbbs-ea9c870ae1208a0b6032102591dcecc76a897b2f.tar.gz pttbbs-ea9c870ae1208a0b6032102591dcecc76a897b2f.tar.bz2 pttbbs-ea9c870ae1208a0b6032102591dcecc76a897b2f.tar.lz pttbbs-ea9c870ae1208a0b6032102591dcecc76a897b2f.tar.xz pttbbs-ea9c870ae1208a0b6032102591dcecc76a897b2f.tar.zst pttbbs-ea9c870ae1208a0b6032102591dcecc76a897b2f.zip |
- Happy r4000!
- source code retab.
git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@4000 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
Diffstat (limited to 'mbbsd')
-rw-r--r-- | mbbsd/bbslua.c | 2382 | ||||
-rw-r--r-- | mbbsd/pfterm.c | 3440 | ||||
-rw-r--r-- | mbbsd/pmore.c | 4484 |
3 files changed, 5153 insertions, 5153 deletions
diff --git a/mbbsd/bbslua.c b/mbbsd/bbslua.c index 084b7698..0305bd78 100644 --- a/mbbsd/bbslua.c +++ b/mbbsd/bbslua.c @@ -65,8 +65,8 @@ // CONST DEFINITION ////////////////////////////////////////////////////////////////////////// -#define BBSLUA_INTERFACE_VER 0.119 // (0.201) -#define BBSLUA_SIGNATURE "--#BBSLUA" +#define BBSLUA_INTERFACE_VER 0.119 // (0.201) +#define BBSLUA_SIGNATURE "--#BBSLUA" // BBS-Lua script format: // $BBSLUA_SIGNATURE @@ -83,46 +83,46 @@ ////////////////////////////////////////////////////////////////////////// // CONFIGURATION VARIABLES ////////////////////////////////////////////////////////////////////////// -#define BLAPI_PROTO int - -#define BLCONF_BREAK_KEY Ctrl('C') -#define BLCONF_EXEC_COUNT (5000) -#define BLCONF_PEEK_TIME (0.01) -#define BLCONF_KBHIT_TMIN (BLCONF_PEEK_TIME) -#define BLCONF_KBHIT_TMAX (60*10) -#define BLCONF_SLEEP_TMIN (BLCONF_PEEK_TIME) -#define BLCONF_SLEEP_TMAX (BLCONF_KBHIT_TMAX) -#define BLCONF_U_SECOND (1000000L) +#define BLAPI_PROTO int + +#define BLCONF_BREAK_KEY Ctrl('C') +#define BLCONF_EXEC_COUNT (5000) +#define BLCONF_PEEK_TIME (0.01) +#define BLCONF_KBHIT_TMIN (BLCONF_PEEK_TIME) +#define BLCONF_KBHIT_TMAX (60*10) +#define BLCONF_SLEEP_TMIN (BLCONF_PEEK_TIME) +#define BLCONF_SLEEP_TMAX (BLCONF_KBHIT_TMAX) +#define BLCONF_U_SECOND (1000000L) #define BLCONF_PRINT_TOC_INDEX (2) #define BLCONF_MMAP_ATTACH -#define BLCONF_CURRENT_USERID cuser.userid +#define BLCONF_CURRENT_USERID cuser.userid #define BLCONF_CURRENT_USERNICK cuser.nickname // BBS-Lua Storage enum { - BLS_INVALID= 0, - BLS_GLOBAL = 1, - BLS_USER, + BLS_INVALID= 0, + BLS_GLOBAL = 1, + BLS_USER, }; // #define BLSCONF_ENABLED -#define BLSCONF_GLOBAL_VAL "global" -#define BLSCONF_USER_VAL "user" -#define BLSCONF_GMAXSIZE (16*1024) // should be aligned to block size -#define BLSCONF_UMAXSIZE (16*1024) // should be aligned to block size -#define BLSCONF_GPATH BBSHOME "/luastore" -#define BLSCONF_UPATH ".luastore" -#define BLSCONF_PREFIX "v1_" -#define BLSCONF_MAXIO 32 // prevent bursting system +#define BLSCONF_GLOBAL_VAL "global" +#define BLSCONF_USER_VAL "user" +#define BLSCONF_GMAXSIZE (16*1024) // should be aligned to block size +#define BLSCONF_UMAXSIZE (16*1024) // should be aligned to block size +#define BLSCONF_GPATH BBSHOME "/luastore" +#define BLSCONF_UPATH ".luastore" +#define BLSCONF_PREFIX "v1_" +#define BLSCONF_MAXIO 32 // prevent bursting system // #define BBSLUA_USAGE #ifdef _WIN32 # undef BLCONF_MMAP_ATTACH -# undef BLCONF_CURRENT_USERID +# undef BLCONF_CURRENT_USERID # define BLCONF_CURRENT_USERID "guest" -# undef BLCONF_CURRENT_USERNICK +# undef BLCONF_CURRENT_USERNICK # define BLCONF_CURRENT_USERNICK "´ú¸Õ±b¸¹" #endif @@ -130,10 +130,10 @@ enum { // GLOBAL VARIABLES ////////////////////////////////////////////////////////////////////////// typedef struct { - char running; // prevent re-entrant - char abort; // system break key hit - char iocounter; // prevent bursting i/o - Fnv32_t storename; // storage filename + char running; // prevent re-entrant + char abort; // system break key hit + char iocounter; // prevent bursting i/o + Fnv32_t storename; // storage filename } BBSLuaRT; // runtime information @@ -141,12 +141,12 @@ typedef struct { BBSLuaRT blrt = {0}; #define BL_INIT_RUNTIME() { \ - memset(&blrt, 0, sizeof(blrt)); \ - blrt.storename = FNV1_32_INIT; \ + memset(&blrt, 0, sizeof(blrt)); \ + blrt.storename = FNV1_32_INIT; \ } #define BL_END_RUNTIME() { \ - memset(&blrt, 0, sizeof(blrt)); \ + memset(&blrt, 0, sizeof(blrt)); \ } #ifdef BBSLUA_USAGE @@ -160,91 +160,91 @@ static int bbslua_count; static void bl_double2tv(double d, struct timeval *tv) { - tv->tv_sec = d; - tv->tv_usec = (d - tv->tv_sec) * BLCONF_U_SECOND; + tv->tv_sec = d; + tv->tv_usec = (d - tv->tv_sec) * BLCONF_U_SECOND; } static double bl_tv2double(const struct timeval *tv) { - double d = tv->tv_sec; - d += tv->tv_usec / (double)BLCONF_U_SECOND; - return d; + double d = tv->tv_sec; + d += tv->tv_usec / (double)BLCONF_U_SECOND; + return d; } static int bl_peekbreak(float f) { - if (input_isfull()) - drop_input(); - if (peek_input(f, BLCONF_BREAK_KEY)) - { - drop_input(); - blrt.abort = 1; - return 1; - } - return 0; + if (input_isfull()) + drop_input(); + if (peek_input(f, BLCONF_BREAK_KEY)) + { + drop_input(); + blrt.abort = 1; + return 1; + } + return 0; } static void bl_k2s(lua_State* L, int v) { - if (v <= 0) - lua_pushnil(L); - else if (v == KEY_TAB) - lua_pushstring(L, "TAB"); - else if (v == '\b' || v == 0x7F) - lua_pushstring(L, "BS"); - else if (v == '\n' || v == '\r' || v == Ctrl('M')) - lua_pushstring(L, "ENTER"); - else if (v < ' ') - lua_pushfstring(L, "^%c", v-1+'A'); - else if (v < 0x100) - lua_pushfstring(L, "%c", v); - else if (v >= KEY_F1 && v <= KEY_F12) - lua_pushfstring(L, "F%d", v - KEY_F1 +1); - else switch(v) - { - case KEY_UP: lua_pushstring(L, "UP"); break; - case KEY_DOWN: lua_pushstring(L, "DOWN"); break; - case KEY_RIGHT: lua_pushstring(L, "RIGHT"); break; - case KEY_LEFT: lua_pushstring(L, "LEFT"); break; - case KEY_HOME: lua_pushstring(L, "HOME"); break; - case KEY_END: lua_pushstring(L, "END"); break; - case KEY_INS: lua_pushstring(L, "INS"); break; - case KEY_DEL: lua_pushstring(L, "DEL"); break; - case KEY_PGUP: lua_pushstring(L, "PGUP"); break; - case KEY_PGDN: lua_pushstring(L, "PGDN"); break; - default: lua_pushnil(L); break; - } + if (v <= 0) + lua_pushnil(L); + else if (v == KEY_TAB) + lua_pushstring(L, "TAB"); + else if (v == '\b' || v == 0x7F) + lua_pushstring(L, "BS"); + else if (v == '\n' || v == '\r' || v == Ctrl('M')) + lua_pushstring(L, "ENTER"); + else if (v < ' ') + lua_pushfstring(L, "^%c", v-1+'A'); + else if (v < 0x100) + lua_pushfstring(L, "%c", v); + else if (v >= KEY_F1 && v <= KEY_F12) + lua_pushfstring(L, "F%d", v - KEY_F1 +1); + else switch(v) + { + case KEY_UP: lua_pushstring(L, "UP"); break; + case KEY_DOWN: lua_pushstring(L, "DOWN"); break; + case KEY_RIGHT: lua_pushstring(L, "RIGHT"); break; + case KEY_LEFT: lua_pushstring(L, "LEFT"); break; + case KEY_HOME: lua_pushstring(L, "HOME"); break; + case KEY_END: lua_pushstring(L, "END"); break; + case KEY_INS: lua_pushstring(L, "INS"); break; + case KEY_DEL: lua_pushstring(L, "DEL"); break; + case KEY_PGUP: lua_pushstring(L, "PGUP"); break; + case KEY_PGDN: lua_pushstring(L, "PGDN"); break; + default: lua_pushnil(L); break; + } } BLAPI_PROTO bl_newwin(int rows, int cols, const char *title) { - // input: (rows, cols, title) - int y = 0, x = 0, n = 0; - int oy = 0, ox = 0; + // input: (rows, cols, title) + int y = 0, x = 0, n = 0; + int oy = 0, ox = 0; - if (rows <= 0 || cols <= 0) - return 0; + if (rows <= 0 || cols <= 0) + return 0; - getyx(&oy, &ox); - // now, draw the window - newwin(rows, cols, oy, ox); + getyx(&oy, &ox); + // now, draw the window + newwin(rows, cols, oy, ox); - if (!title || !*title) - return 0; + if (!title || !*title) + return 0; - // draw center-ed title - n = strlen_noansi(title); - x = ox + (cols - n)/2; - y = oy + (rows)/2; - move(y, x); - outs(title); + // draw center-ed title + n = strlen_noansi(title); + x = ox + (cols - n)/2; + y = oy + (rows)/2; + move(y, x); + outs(title); - move(oy, ox); - return 0; + move(oy, ox); + return 0; } ////////////////////////////////////////////////////////////////////////// @@ -254,456 +254,456 @@ bl_newwin(int rows, int cols, const char *title) BLAPI_PROTO bl_getyx(lua_State* L) { - int y, x; - getyx(&y, &x); - lua_pushinteger(L, y); - lua_pushinteger(L, x); - return 2; + int y, x; + getyx(&y, &x); + lua_pushinteger(L, y); + lua_pushinteger(L, x); + return 2; } BLAPI_PROTO bl_getmaxyx(lua_State* L) { - lua_pushinteger(L, t_lines); - lua_pushinteger(L, t_columns); - return 2; + lua_pushinteger(L, t_lines); + lua_pushinteger(L, t_columns); + return 2; } BLAPI_PROTO bl_move(lua_State* L) { - int n = lua_gettop(L); - int y = 0, x = 0; - if (n > 0) - y = lua_tointeger(L, 1); - if (n > 1) - x = lua_tointeger(L, 2); - move_ansi(y, x); - return 0; + int n = lua_gettop(L); + int y = 0, x = 0; + if (n > 0) + y = lua_tointeger(L, 1); + if (n > 1) + x = lua_tointeger(L, 2); + move_ansi(y, x); + return 0; } BLAPI_PROTO bl_moverel(lua_State* L) { - int n = lua_gettop(L); - int y = 0, x = 0; - getyx(&y, &x); - if (n > 0) - y += lua_tointeger(L, 1); - if (n > 1) - x += lua_tointeger(L, 2); - move(y, x); - getyx(&y, &x); - lua_pushinteger(L, y); - lua_pushinteger(L, x); - return 2; + int n = lua_gettop(L); + int y = 0, x = 0; + getyx(&y, &x); + if (n > 0) + y += lua_tointeger(L, 1); + if (n > 1) + x += lua_tointeger(L, 2); + move(y, x); + getyx(&y, &x); + lua_pushinteger(L, y); + lua_pushinteger(L, x); + return 2; } BLAPI_PROTO bl_clear(lua_State* L) { - (void)L; /* to avoid warnings */ - clear(); - return 0; + (void)L; /* to avoid warnings */ + clear(); + return 0; } BLAPI_PROTO bl_clrtoeol(lua_State* L) { - (void)L; /* to avoid warnings */ - clrtoeol(); - return 0; + (void)L; /* to avoid warnings */ + clrtoeol(); + return 0; } BLAPI_PROTO bl_clrtobot(lua_State* L) { - (void)L; /* to avoid warnings */ - clrtobot(); - return 0; + (void)L; /* to avoid warnings */ + clrtobot(); + return 0; } BLAPI_PROTO bl_refresh(lua_State* L) { - (void)L; /* to avoid warnings */ - // refresh(); - // Seems like that most people don't understand the relationship - // between refresh() and input queue, so let's force update here. - doupdate(); - return 0; + (void)L; /* to avoid warnings */ + // refresh(); + // Seems like that most people don't understand the relationship + // between refresh() and input queue, so let's force update here. + doupdate(); + return 0; } BLAPI_PROTO bl_addstr(lua_State* L) { - int n = lua_gettop(L); - int i = 1; - for (i = 1; i <= n; i++) - { - const char *s = lua_tostring(L, i); - if(s) - outs(s); - } - return 0; + int n = lua_gettop(L); + int i = 1; + for (i = 1; i <= n; i++) + { + const char *s = lua_tostring(L, i); + if(s) + outs(s); + } + return 0; } BLAPI_PROTO bl_rect(lua_State *L) { - // input: (rows, cols, title) - int rows = 1, cols = 1; - int n = lua_gettop(L); - const char *title = NULL; - - if (n > 0) - rows = lua_tointeger(L, 1); - if (n > 1) - cols = lua_tointeger(L, 2); - if (n > 2) - title = lua_tostring(L, 3); - if (rows <= 0 || cols <= 0) - return 0; - - // now, draw the rectangle - bl_newwin(rows, cols, title); - return 0; + // input: (rows, cols, title) + int rows = 1, cols = 1; + int n = lua_gettop(L); + const char *title = NULL; + + if (n > 0) + rows = lua_tointeger(L, 1); + if (n > 1) + cols = lua_tointeger(L, 2); + if (n > 2) + title = lua_tostring(L, 3); + if (rows <= 0 || cols <= 0) + return 0; + + // now, draw the rectangle + bl_newwin(rows, cols, title); + return 0; } BLAPI_PROTO bl_print(lua_State* L) { - bl_addstr(L); - outc('\n'); - return 0; + bl_addstr(L); + outc('\n'); + return 0; } BLAPI_PROTO bl_getch(lua_State* L) { - int c = igetch(); - if (c == BLCONF_BREAK_KEY) - { - drop_input(); - blrt.abort = 1; - return lua_yield(L, 0); - } - bl_k2s(L, c); - return 1; + int c = igetch(); + if (c == BLCONF_BREAK_KEY) + { + drop_input(); + blrt.abort = 1; + return lua_yield(L, 0); + } + bl_k2s(L, c); + return 1; } BLAPI_PROTO bl_getstr(lua_State* L) { - int y, x; - // TODO not using fixed length here? - char buf[PATHLEN] = ""; - int len = 2, echo = 1; - int n = lua_gettop(L); - const char *pmsg = NULL; - - if (n > 0) - len = lua_tointeger(L, 1); - if (n > 1) - echo = lua_tointeger(L, 2); - if (n > 2) - pmsg = lua_tostring(L, 3); - - if (len < 2) - len = 2; - if (len >= sizeof(buf)) - len = sizeof(buf)-1; - /* - * this part now done in getdata_str - if (pmsg && *pmsg) - { - strlcpy(buf, pmsg, sizeof(buf)); - } - */ - - // TODO process Ctrl-C here - getyx(&y, &x); - if (!pmsg) pmsg = ""; - len = getdata_str(y, x, NULL, buf, len, echo, pmsg); - if (len <= 0) - { - len = 0; - // check if we got Ctrl-C? (workaround in getdata) - // TODO someday write 'ungetch()' in io.c to prevent - // such workaround. - if (buf[1] == Ctrl('C')) - { - drop_input(); - blrt.abort = 1; - return lua_yield(L, 0); - } - lua_pushstring(L, ""); - } - else - { - lua_pushstring(L, buf); - } - // return len ? 1 : 0; - return 1; + int y, x; + // TODO not using fixed length here? + char buf[PATHLEN] = ""; + int len = 2, echo = 1; + int n = lua_gettop(L); + const char *pmsg = NULL; + + if (n > 0) + len = lua_tointeger(L, 1); + if (n > 1) + echo = lua_tointeger(L, 2); + if (n > 2) + pmsg = lua_tostring(L, 3); + + if (len < 2) + len = 2; + if (len >= sizeof(buf)) + len = sizeof(buf)-1; + /* + * this part now done in getdata_str + if (pmsg && *pmsg) + { + strlcpy(buf, pmsg, sizeof(buf)); + } + */ + + // TODO process Ctrl-C here + getyx(&y, &x); + if (!pmsg) pmsg = ""; + len = getdata_str(y, x, NULL, buf, len, echo, pmsg); + if (len <= 0) + { + len = 0; + // check if we got Ctrl-C? (workaround in getdata) + // TODO someday write 'ungetch()' in io.c to prevent + // such workaround. + if (buf[1] == Ctrl('C')) + { + drop_input(); + blrt.abort = 1; + return lua_yield(L, 0); + } + lua_pushstring(L, ""); + } + else + { + lua_pushstring(L, buf); + } + // return len ? 1 : 0; + return 1; } BLAPI_PROTO bl_kbhit(lua_State *L) { - int n = lua_gettop(L); - double f = 0.1f; - - if (n > 0) - f = (double)lua_tonumber(L, 1); - - if (f < BLCONF_KBHIT_TMIN) f = BLCONF_KBHIT_TMIN; - if (f > BLCONF_KBHIT_TMAX) f = BLCONF_KBHIT_TMAX; - - refresh(); - if (num_in_buf() || wait_input(f, 0)) - lua_pushboolean(L, 1); - else - lua_pushboolean(L, 0); - return 1; + int n = lua_gettop(L); + double f = 0.1f; + + if (n > 0) + f = (double)lua_tonumber(L, 1); + + if (f < BLCONF_KBHIT_TMIN) f = BLCONF_KBHIT_TMIN; + if (f > BLCONF_KBHIT_TMAX) f = BLCONF_KBHIT_TMAX; + + refresh(); + if (num_in_buf() || wait_input(f, 0)) + lua_pushboolean(L, 1); + else + lua_pushboolean(L, 0); + return 1; } BLAPI_PROTO bl_kbreset(lua_State *L) { - // peek input queue first! - if (bl_peekbreak(BLCONF_PEEK_TIME)) - return lua_yield(L, 0); + // peek input queue first! + if (bl_peekbreak(BLCONF_PEEK_TIME)) + return lua_yield(L, 0); - drop_input(); - return 0; + drop_input(); + return 0; } BLAPI_PROTO bl_sleep(lua_State *L) { - int n = lua_gettop(L); - double us = 0, nus = 0; + int n = lua_gettop(L); + double us = 0, nus = 0; - // update screen first. - bl_refresh(L); + // update screen first. + bl_refresh(L); - if (n > 0) - us = lua_tonumber(L, 1); - if (us < BLCONF_SLEEP_TMIN) us = BLCONF_SLEEP_TMIN; - if (us > BLCONF_SLEEP_TMAX) us = BLCONF_SLEEP_TMAX; - nus = us; + if (n > 0) + us = lua_tonumber(L, 1); + if (us < BLCONF_SLEEP_TMIN) us = BLCONF_SLEEP_TMIN; + if (us > BLCONF_SLEEP_TMAX) us = BLCONF_SLEEP_TMAX; + nus = us; #ifdef _WIN32 - Sleep(us * 1000); + Sleep(us * 1000); #else // !_WIN32 - { - struct timeval tp, tdest; + { + struct timeval tp, tdest; - gettimeofday(&tp, NULL); + gettimeofday(&tp, NULL); - // nus is the destination time - nus = bl_tv2double(&tp) + us; - bl_double2tv(nus, &tdest); + // nus is the destination time + nus = bl_tv2double(&tp) + us; + bl_double2tv(nus, &tdest); - while ( (tp.tv_sec < tdest.tv_sec) || - ((tp.tv_sec == tdest.tv_sec) && (tp.tv_usec < tdest.tv_usec))) - { - // calculate new peek time - us = nus - bl_tv2double(&tp); + while ( (tp.tv_sec < tdest.tv_sec) || + ((tp.tv_sec == tdest.tv_sec) && (tp.tv_usec < tdest.tv_usec))) + { + // calculate new peek time + us = nus - bl_tv2double(&tp); - // check if input key is system break key. - if (bl_peekbreak(us)) - return lua_yield(L, 0); + // check if input key is system break key. + if (bl_peekbreak(us)) + return lua_yield(L, 0); - // check time - gettimeofday(&tp, NULL); - } - } + // check time + gettimeofday(&tp, NULL); + } + } #endif // !_WIN32 - return 0; + return 0; } BLAPI_PROTO bl_kball(lua_State *L) { - // first, sleep by given seconds - int r = 0, oldr = 0, i = 0; + // first, sleep by given seconds + int r = 0, oldr = 0, i = 0; - r = bl_sleep(L); - if (blrt.abort) - return r; + r = bl_sleep(L); + if (blrt.abort) + return r; - // pop all arguments - lua_pop(L, lua_gettop(L)); + // pop all arguments + lua_pop(L, lua_gettop(L)); #ifdef _WIN32 - while (peekch(0)) - { - bl_k2s(L, igetch()); - i++; - } + while (peekch(0)) + { + bl_k2s(L, igetch()); + i++; + } #else - // next, collect all input and return. - if (num_in_buf() < 1) - return 0; - - oldr = num_in_buf() +1; - i = 0; - - while ( i < LUA_MINSTACK && - (r = num_in_buf()) > 0 && oldr > r) - { - oldr = r; - bl_k2s(L, igetch()); - i++; - } + // next, collect all input and return. + if (num_in_buf() < 1) + return 0; + + oldr = num_in_buf() +1; + i = 0; + + while ( i < LUA_MINSTACK && + (r = num_in_buf()) > 0 && oldr > r) + { + oldr = r; + bl_k2s(L, igetch()); + i++; + } #endif - return i; + return i; } BLAPI_PROTO bl_pause(lua_State* L) { - int n = lua_gettop(L); - const char *s = NULL; - if (n > 0) - s = lua_tostring(L, 1); - - n = vmsg(s); - if (n == BLCONF_BREAK_KEY) - { - drop_input(); - blrt.abort = 1; - return lua_yield(L, 0); - } - bl_k2s(L, n); - return 1; + int n = lua_gettop(L); + const char *s = NULL; + if (n > 0) + s = lua_tostring(L, 1); + + n = vmsg(s); + if (n == BLCONF_BREAK_KEY) + { + drop_input(); + blrt.abort = 1; + return lua_yield(L, 0); + } + bl_k2s(L, n); + return 1; } BLAPI_PROTO bl_title(lua_State* L) { - int n = lua_gettop(L); - const char *s = NULL; - if (n > 0) - s = lua_tostring(L, 1); - if (s == NULL) - return 0; - - stand_title(s); - return 0; + int n = lua_gettop(L); + const char *s = NULL; + if (n > 0) + s = lua_tostring(L, 1); + if (s == NULL) + return 0; + + stand_title(s); + return 0; } BLAPI_PROTO bl_ansi_color(lua_State *L) { - char buf[PATHLEN] = ESC_STR "["; - char *p = buf + strlen(buf); - int i = 1; - int n = lua_gettop(L); - if (n >= 10) n = 10; - for (i = 1; i <= n; i++) - { - if (i > 1) *p++ = ';'; - sprintf(p, "%d", (int)lua_tointeger(L, i)); - p += strlen(p); - } - *p++ = 'm'; - *p = 0; - lua_pushstring(L, buf); - return 1; + char buf[PATHLEN] = ESC_STR "["; + char *p = buf + strlen(buf); + int i = 1; + int n = lua_gettop(L); + if (n >= 10) n = 10; + for (i = 1; i <= n; i++) + { + if (i > 1) *p++ = ';'; + sprintf(p, "%d", (int)lua_tointeger(L, i)); + p += strlen(p); + } + *p++ = 'm'; + *p = 0; + lua_pushstring(L, buf); + return 1; } BLAPI_PROTO bl_strip_ansi(lua_State *L) { - int n = lua_gettop(L); - const char *s = NULL; - char *s2 = NULL; - size_t os2 = 0; - - if (n < 1 || (s = lua_tostring(L, 1)) == NULL || - *s == 0) - { - lua_pushstring(L, ""); - return 1; - } - - os2 = strlen(s)+1; - s2 = (char*) lua_newuserdata(L, os2); - strip_ansi(s2, s, STRIP_ALL); - lua_pushstring(L, s2); - lua_remove(L, -2); - return 1; + int n = lua_gettop(L); + const char *s = NULL; + char *s2 = NULL; + size_t os2 = 0; + + if (n < 1 || (s = lua_tostring(L, 1)) == NULL || + *s == 0) + { + lua_pushstring(L, ""); + return 1; + } + + os2 = strlen(s)+1; + s2 = (char*) lua_newuserdata(L, os2); + strip_ansi(s2, s, STRIP_ALL); + lua_pushstring(L, s2); + lua_remove(L, -2); + return 1; } BLAPI_PROTO bl_attrset(lua_State *L) { - char buf[PATHLEN] = ESC_STR "["; - char *p = buf + strlen(buf); - int i = 1; - int n = lua_gettop(L); - if (n == 0) - outs(ANSI_RESET); - for (i = 1; i <= n; i++) - { - sprintf(p, "%dm",(int)lua_tointeger(L, i)); - outs(buf); - } - return 0; + char buf[PATHLEN] = ESC_STR "["; + char *p = buf + strlen(buf); + int i = 1; + int n = lua_gettop(L); + if (n == 0) + outs(ANSI_RESET); + for (i = 1; i <= n; i++) + { + sprintf(p, "%dm",(int)lua_tointeger(L, i)); + outs(buf); + } + return 0; } BLAPI_PROTO bl_time(lua_State *L) { - syncnow(); - lua_pushinteger(L, now); - return 1; + syncnow(); + lua_pushinteger(L, now); + return 1; } BLAPI_PROTO bl_ctime(lua_State *L) { - syncnow(); - lua_pushstring(L, ctime4(&now)); - return 1; + syncnow(); + lua_pushstring(L, ctime4(&now)); + return 1; } BLAPI_PROTO bl_clock(lua_State *L) { - double d = 0; + double d = 0; #ifdef _WIN32 - // XXX this is a fast hack because we don't want to do 64bit calculation. - SYSTEMTIME st; - GetSystemTime(&st); - syncnow(); - // XXX the may be some latency between our GetSystemTime and syncnow. - // So build again the "second" part. - d = (int)((now / 60) * 60); - d += st.wSecond; - d += (st.wMilliseconds / 1000.0f); + // XXX this is a fast hack because we don't want to do 64bit calculation. + SYSTEMTIME st; + GetSystemTime(&st); + syncnow(); + // XXX the may be some latency between our GetSystemTime and syncnow. + // So build again the "second" part. + d = (int)((now / 60) * 60); + d += st.wSecond; + d += (st.wMilliseconds / 1000.0f); #else // !_WIN32 - struct timeval tp; - gettimeofday(&tp, NULL); - d = bl_tv2double(&tp); + struct timeval tp; + gettimeofday(&tp, NULL); + d = bl_tv2double(&tp); #endif // !_WIN32 - lua_pushnumber(L, d); - return 1; + lua_pushnumber(L, d); + return 1; } ////////////////////////////////////////////////////////////////////////// @@ -712,162 +712,162 @@ bl_clock(lua_State *L) static int bls_getcat(const char *s) { - if (!s || !*s) - return BLS_INVALID; - if (strcmp(s, BLSCONF_GLOBAL_VAL) == 0) - return BLS_GLOBAL; - else if (strcmp(s, BLSCONF_USER_VAL) == 0) - return BLS_USER; - return BLS_INVALID; + if (!s || !*s) + return BLS_INVALID; + if (strcmp(s, BLSCONF_GLOBAL_VAL) == 0) + return BLS_GLOBAL; + else if (strcmp(s, BLSCONF_USER_VAL) == 0) + return BLS_USER; + return BLS_INVALID; } static int bls_getlimit(const char *p) { - switch(bls_getcat(p)) - { - case BLS_GLOBAL: - return BLSCONF_GMAXSIZE; - case BLS_USER: - return BLSCONF_UMAXSIZE; - } - return 0; + switch(bls_getcat(p)) + { + case BLS_GLOBAL: + return BLSCONF_GMAXSIZE; + case BLS_USER: + return BLSCONF_UMAXSIZE; + } + return 0; } static int bls_setfn(char *fn, size_t sz, const char *p) { - *fn = 0; - switch(bls_getcat(p)) - { - case BLS_GLOBAL: - snprintf(fn, sz, "%s/" BLSCONF_PREFIX "U%08x", - BLSCONF_GPATH, blrt.storename); - return 1; - - case BLS_USER: - setuserfile(fn, BLSCONF_UPATH); - mkdir(fn, 0755); - assert(strlen(fn) +8 <= sz); - snprintf(fn + strlen(fn), - sz - strlen(fn), - "/" BLSCONF_PREFIX "G%08x", blrt.storename); - return 1; - } - return 0; + *fn = 0; + switch(bls_getcat(p)) + { + case BLS_GLOBAL: + snprintf(fn, sz, "%s/" BLSCONF_PREFIX "U%08x", + BLSCONF_GPATH, blrt.storename); + return 1; + + case BLS_USER: + setuserfile(fn, BLSCONF_UPATH); + mkdir(fn, 0755); + assert(strlen(fn) +8 <= sz); + snprintf(fn + strlen(fn), + sz - strlen(fn), + "/" BLSCONF_PREFIX "G%08x", blrt.storename); + return 1; + } + return 0; } BLAPI_PROTO bls_iolimit(lua_State *L) { - lua_pushinteger(L, BLSCONF_MAXIO); - return 1; + lua_pushinteger(L, BLSCONF_MAXIO); + return 1; } BLAPI_PROTO bls_limit(lua_State *L) { - int n = lua_gettop(L); - const char *s = NULL; - if (n > 0) - s = lua_tostring(L, 1); - lua_pushinteger(L, bls_getlimit(s)); - return 1; + int n = lua_gettop(L); + const char *s = NULL; + if (n > 0) + s = lua_tostring(L, 1); + lua_pushinteger(L, bls_getlimit(s)); + return 1; } BLAPI_PROTO bls_load(lua_State *L) { - int n = lua_gettop(L); - const char *cat = NULL; - char fn[PATHLEN]; - - if (blrt.iocounter >= BLSCONF_MAXIO) - { - lua_pushnil(L); - return 1; - } - - if (n != 1) - { - lua_pushnil(L); - return 1; - } - cat = lua_tostring(L, 1); // category - if (!cat) - { - lua_pushnil(L); - return 1; - } - - blrt.iocounter++; - // read file! - if (bls_setfn(fn, sizeof(fn), cat)) - { - int fd = open(fn, O_RDONLY); - if (fd >= 0) - { - char buf[2048]; - luaL_Buffer b; - - luaL_buffinit(L, &b); - while ((n = read(fd, buf, sizeof(buf))) > 0) - luaL_addlstring(&b, buf, n); - close(fd); - luaL_pushresult(&b); - } else { - lua_pushnil(L); - } - } else { - lua_pushnil(L); - } - return 1; + int n = lua_gettop(L); + const char *cat = NULL; + char fn[PATHLEN]; + + if (blrt.iocounter >= BLSCONF_MAXIO) + { + lua_pushnil(L); + return 1; + } + + if (n != 1) + { + lua_pushnil(L); + return 1; + } + cat = lua_tostring(L, 1); // category + if (!cat) + { + lua_pushnil(L); + return 1; + } + + blrt.iocounter++; + // read file! + if (bls_setfn(fn, sizeof(fn), cat)) + { + int fd = open(fn, O_RDONLY); + if (fd >= 0) + { + char buf[2048]; + luaL_Buffer b; + + luaL_buffinit(L, &b); + while ((n = read(fd, buf, sizeof(buf))) > 0) + luaL_addlstring(&b, buf, n); + close(fd); + luaL_pushresult(&b); + } else { + lua_pushnil(L); + } + } else { + lua_pushnil(L); + } + return 1; } BLAPI_PROTO bls_save(lua_State *L) { - int n = lua_gettop(L), fd = -1; - int limit = 0, slen = 0; - const char *s = NULL, *cat = NULL; - char fn[PATHLEN] = "", ret = 0; - - if (blrt.iocounter >= BLSCONF_MAXIO) - { - lua_pushboolean(L, 0); - return 1; - } - - if (n != 2) { lua_pushboolean(L, 0); return 1; } - - cat = lua_tostring(L, 1); // category - s = lua_tostring(L, 2); // data - limit = bls_getlimit(cat); - - if (!cat || !s || limit < 1) - { - lua_pushboolean(L, 0); - return 1; - } - - slen = lua_objlen(L, 2); - if (slen >= limit) slen = limit; - - blrt.iocounter++; - // write file! - if (bls_setfn(fn, sizeof(fn), cat)) - { - fd = open(fn, O_WRONLY|O_CREAT, 0644); - if (fd >= 0) - { - write(fd, s, slen); - close(fd); - ret = 1; - } - } - - lua_pushboolean(L, ret); - return 1; + int n = lua_gettop(L), fd = -1; + int limit = 0, slen = 0; + const char *s = NULL, *cat = NULL; + char fn[PATHLEN] = "", ret = 0; + + if (blrt.iocounter >= BLSCONF_MAXIO) + { + lua_pushboolean(L, 0); + return 1; + } + + if (n != 2) { lua_pushboolean(L, 0); return 1; } + + cat = lua_tostring(L, 1); // category + s = lua_tostring(L, 2); // data + limit = bls_getlimit(cat); + + if (!cat || !s || limit < 1) + { + lua_pushboolean(L, 0); + return 1; + } + + slen = lua_objlen(L, 2); + if (slen >= limit) slen = limit; + + blrt.iocounter++; + // write file! + if (bls_setfn(fn, sizeof(fn), cat)) + { + fd = open(fn, O_WRONLY|O_CREAT, 0644); + if (fd >= 0) + { + write(fd, s, slen); + close(fd); + ret = 1; + } + } + + lua_pushboolean(L, ret); + return 1; } ////////////////////////////////////////////////////////////////////////// @@ -875,50 +875,50 @@ bls_save(lua_State *L) ////////////////////////////////////////////////////////////////////////// static const struct luaL_reg lib_bbslua [] = { - /* curses output */ - { "getyx", bl_getyx }, - { "getmaxyx", bl_getmaxyx }, - { "move", bl_move }, - { "moverel", bl_moverel }, - { "clear", bl_clear }, - { "clrtoeol", bl_clrtoeol }, - { "clrtobot", bl_clrtobot }, - { "refresh", bl_refresh }, - { "addstr", bl_addstr }, - { "outs", bl_addstr }, - { "print", bl_print }, - /* input */ - { "getch", bl_getch }, - { "getdata", bl_getstr }, - { "getstr", bl_getstr }, - { "kbhit", bl_kbhit }, - { "kbreset", bl_kbreset }, - { "kball", bl_kball }, - /* advanced output */ - { "rect", bl_rect }, - /* BBS utilities */ - { "pause", bl_pause }, - { "title", bl_title }, - /* time */ - { "time", bl_time }, - { "now", bl_time }, - { "clock", bl_clock }, - { "ctime", bl_ctime }, - { "sleep", bl_sleep }, - /* ANSI helpers */ - { "ANSI_COLOR", bl_ansi_color }, - { "color", bl_attrset }, - { "attrset", bl_attrset }, - { "strip_ansi", bl_strip_ansi }, - { NULL, NULL}, + /* curses output */ + { "getyx", bl_getyx }, + { "getmaxyx", bl_getmaxyx }, + { "move", bl_move }, + { "moverel", bl_moverel }, + { "clear", bl_clear }, + { "clrtoeol", bl_clrtoeol }, + { "clrtobot", bl_clrtobot }, + { "refresh", bl_refresh }, + { "addstr", bl_addstr }, + { "outs", bl_addstr }, + { "print", bl_print }, + /* input */ + { "getch", bl_getch }, + { "getdata", bl_getstr }, + { "getstr", bl_getstr }, + { "kbhit", bl_kbhit }, + { "kbreset", bl_kbreset }, + { "kball", bl_kball }, + /* advanced output */ + { "rect", bl_rect }, + /* BBS utilities */ + { "pause", bl_pause }, + { "title", bl_title }, + /* time */ + { "time", bl_time }, + { "now", bl_time }, + { "clock", bl_clock }, + { "ctime", bl_ctime }, + { "sleep", bl_sleep }, + /* ANSI helpers */ + { "ANSI_COLOR", bl_ansi_color }, + { "color", bl_attrset }, + { "attrset", bl_attrset }, + { "strip_ansi", bl_strip_ansi }, + { NULL, NULL}, }; static const struct luaL_reg lib_store [] = { - { "load", bls_load }, - { "save", bls_save }, - { "limit", bls_limit }, - { "iolimit", bls_iolimit }, - { NULL, NULL}, + { "load", bls_load }, + { "save", bls_save }, + { "limit", bls_limit }, + { "iolimit", bls_iolimit }, + { NULL, NULL}, }; // non-standard modules in bbsluaext.c @@ -966,59 +966,59 @@ typedef struct bbsluaL_RegNum { } bbsluaL_RegNum; static const bbsluaL_RegStr bbsluaStrs[] = { - {"ESC", ESC_STR}, - {"ANSI_RESET", ANSI_RESET}, - {"sitename", BBSNAME}, - {NULL, NULL}, + {"ESC", ESC_STR}, + {"ANSI_RESET", ANSI_RESET}, + {"sitename", BBSNAME}, + {NULL, NULL}, }; static const bbsluaL_RegNum bbsluaNums[] = { - {"interface", BBSLUA_INTERFACE_VER}, - {NULL, 0}, + {"interface", BBSLUA_INTERFACE_VER}, + {NULL, 0}, }; static void bbsluaRegConst(lua_State *L) { - int i = 0; - - // unbind unsafe API - lua_pushnil(L); lua_setglobal(L, "dofile"); - lua_pushnil(L); lua_setglobal(L, "loadfile"); - - // global - lua_pushcfunction(L, bl_print); - lua_setglobal(L, "print"); - - // bbs.* - lua_getglobal(L, "bbs"); - for (i = 0; bbsluaStrs[i].name; i++) - { - lua_pushstring(L, bbsluaStrs[i].val); - lua_setfield(L, -2, bbsluaStrs[i].name); - } - - for (i = 0; bbsluaNums[i].name; i++) - { - lua_pushnumber(L, bbsluaNums[i].val); - lua_setfield(L, -2, bbsluaNums[i].name); - } - // dynamic info - lua_pushstring(L, BLCONF_CURRENT_USERID); - lua_setfield(L, -2, "userid"); - lua_pushstring(L, BLCONF_CURRENT_USERNICK); - lua_setfield(L, -2, "usernick"); - - lua_pop(L, 1); + int i = 0; + + // unbind unsafe API + lua_pushnil(L); lua_setglobal(L, "dofile"); + lua_pushnil(L); lua_setglobal(L, "loadfile"); + + // global + lua_pushcfunction(L, bl_print); + lua_setglobal(L, "print"); + + // bbs.* + lua_getglobal(L, "bbs"); + for (i = 0; bbsluaStrs[i].name; i++) + { + lua_pushstring(L, bbsluaStrs[i].val); + lua_setfield(L, -2, bbsluaStrs[i].name); + } + + for (i = 0; bbsluaNums[i].name; i++) + { + lua_pushnumber(L, bbsluaNums[i].val); + lua_setfield(L, -2, bbsluaNums[i].name); + } + // dynamic info + lua_pushstring(L, BLCONF_CURRENT_USERID); + lua_setfield(L, -2, "userid"); + lua_pushstring(L, BLCONF_CURRENT_USERNICK); + lua_setfield(L, -2, "usernick"); + + lua_pop(L, 1); #ifdef BLSCONF_ENABLED - // store.* - lua_getglobal(L, "store"); - lua_pushstring(L, BLSCONF_USER_VAL); - lua_setfield(L, -2, "USER"); - lua_pushstring(L, BLSCONF_GLOBAL_VAL); - lua_setfield(L, -2, "GLOBAL"); - lua_pop(L, 1); + // store.* + lua_getglobal(L, "store"); + lua_pushstring(L, BLSCONF_USER_VAL); + lua_setfield(L, -2, "USER"); + lua_pushstring(L, BLSCONF_GLOBAL_VAL); + lua_setfield(L, -2, "GLOBAL"); + lua_pop(L, 1); #endif // BLSCONF_ENABLED } @@ -1029,157 +1029,157 @@ bbsluaRegConst(lua_State *L) static void bbsluaHook(lua_State *L, lua_Debug* ar) { - // vmsg("bbslua HOOK!"); - if (blrt.abort) - { - drop_input(); - lua_yield(L, 0); - return; - } - - if (ar->event != LUA_HOOKCOUNT) - return; + // vmsg("bbslua HOOK!"); + if (blrt.abort) + { + drop_input(); + lua_yield(L, 0); + return; + } + + if (ar->event != LUA_HOOKCOUNT) + return; #ifdef BBSLUA_USAGE - bbslua_count += BLCONF_EXEC_COUNT; + bbslua_count += BLCONF_EXEC_COUNT; #endif - // now, peek and check - if (input_isfull()) - drop_input(); - - // refresh(); - - // check if input key is system break key. - if (bl_peekbreak(BLCONF_PEEK_TIME)) - { - lua_yield(L, 0); - return; - } + // now, peek and check + if (input_isfull()) + drop_input(); + + // refresh(); + + // check if input key is system break key. + if (bl_peekbreak(BLCONF_PEEK_TIME)) + { + lua_yield(L, 0); + return; + } } static char * bbslua_attach(const char *fpath, size_t *plen) { - char *buf = NULL; + char *buf = NULL; #ifdef BLCONF_MMAP_ATTACH struct stat st; - int fd = open(fpath, O_RDONLY); + int fd = open(fpath, O_RDONLY); - *plen = 0; + *plen = 0; - if (fd < 0) return buf; + if (fd < 0) return buf; if (fstat(fd, &st) || ((*plen = st.st_size) < 1) || S_ISDIR(st.st_mode)) { - close(fd); - return buf; + close(fd); + return buf; } - *plen = *plen +1; + *plen = *plen +1; buf = mmap(NULL, *plen, PROT_READ, MAP_SHARED, fd, 0); - close(fd); + close(fd); - if (buf == NULL || buf == MAP_FAILED) - { - *plen = 0; - return NULL; - } + if (buf == NULL || buf == MAP_FAILED) + { + *plen = 0; + return NULL; + } madvise(buf, *plen, MADV_SEQUENTIAL); #else // !BLCONF_MMAP_ATTACH - FILE *fp = fopen(fpath, "rt"); - *plen = 0; - if (!fp) - return NULL; - fseek(fp, 0, SEEK_END); - *plen = ftell(fp); - buf = (char*) malloc (*plen); - rewind(fp); - fread(buf, *plen, 1, fp); + FILE *fp = fopen(fpath, "rt"); + *plen = 0; + if (!fp) + return NULL; + fseek(fp, 0, SEEK_END); + *plen = ftell(fp); + buf = (char*) malloc (*plen); + rewind(fp); + fread(buf, *plen, 1, fp); #endif // !BLCONF_MMAP_ATTACH - return buf; + return buf; } static void bbslua_detach(char *p, int len) { #ifdef BLCONF_MMAP_ATTACH - munmap(p, len); + munmap(p, len); #else // !BLCONF_MMAP_ATTACH - free(p); + free(p); #endif // !BLCONF_MMAP_ATTACH } int bbslua_isHeader(const char *ps, const char *pe) { - int szsig = strlen(BBSLUA_SIGNATURE); - if (ps + szsig > pe) - return 0; - if (strncmp(ps, BBSLUA_SIGNATURE, szsig) == 0) - return 1; - return 0; + int szsig = strlen(BBSLUA_SIGNATURE); + if (ps + szsig > pe) + return 0; + if (strncmp(ps, BBSLUA_SIGNATURE, szsig) == 0) + return 1; + return 0; } static int bbslua_detect_range(char **pbs, char **pbe, int *lineshift) { - int szsig = strlen(BBSLUA_SIGNATURE); - char *bs, *be, *ps, *pe; - int line = 0; - - bs = ps = *pbs; - be = pe = *pbe; - - // find start - while (ps + szsig < pe) - { - if (strncmp(ps, BBSLUA_SIGNATURE, szsig) == 0) - break; - // else, skip to next line - while (ps + szsig < pe && *ps++ != '\n'); - line++; - } - *lineshift = line; - - if (!(ps + szsig < pe)) - return 0; - - *pbs = ps; - *pbe = be; - - // find tail by SIGNATURE - pe = ps + 1; - while (pe + szsig < be) - { - if (strncmp(pe, BBSLUA_SIGNATURE, szsig) == 0) - break; - // else, skip to next line - while (pe + szsig < be && *pe++ != '\n'); - } - - if (pe + szsig < be) - { - // found sig, end at such line. - pe--; - *pbe = pe; - } else { - // abort. - *pbe = NULL; - *pbs = NULL; - return 0; - } - - // prevent trailing zeros - pe = *pbe; - while (pe > ps && !*pe) - pe--; - *pbe = pe; - - return 1; + int szsig = strlen(BBSLUA_SIGNATURE); + char *bs, *be, *ps, *pe; + int line = 0; + + bs = ps = *pbs; + be = pe = *pbe; + + // find start + while (ps + szsig < pe) + { + if (strncmp(ps, BBSLUA_SIGNATURE, szsig) == 0) + break; + // else, skip to next line + while (ps + szsig < pe && *ps++ != '\n'); + line++; + } + *lineshift = line; + + if (!(ps + szsig < pe)) + return 0; + + *pbs = ps; + *pbe = be; + + // find tail by SIGNATURE + pe = ps + 1; + while (pe + szsig < be) + { + if (strncmp(pe, BBSLUA_SIGNATURE, szsig) == 0) + break; + // else, skip to next line + while (pe + szsig < be && *pe++ != '\n'); + } + + if (pe + szsig < be) + { + // found sig, end at such line. + pe--; + *pbe = pe; + } else { + // abort. + *pbe = NULL; + *pbs = NULL; + return 0; + } + + // prevent trailing zeros + pe = *pbe; + while (pe > ps && !*pe) + pe--; + *pbe = pe; + + return 1; } ////////////////////////////////////////////////////////////////////////// @@ -1188,219 +1188,219 @@ bbslua_detect_range(char **pbs, char **pbe, int *lineshift) static const char *bbsluaTocTags[] = { - "interface", - "latestref", - - // BLCONF_PRINT_TOC_INDEX - "title", - "notes", - "author", - "version", - "date", - NULL + "interface", + "latestref", + + // BLCONF_PRINT_TOC_INDEX + "title", + "notes", + "author", + "version", + "date", + NULL }; static const char *bbsluaTocPrompts[] = { - "¬É±ª©¥»", - "³Ì·sª©¥»", - - // BLCONF_PRINT_TOC_INDEX - "¦WºÙ", - "»¡©ú", - "§@ªÌ", - "ª©¥»", - "¤é´Á", - NULL + "¬É±ª©¥»", + "³Ì·sª©¥»", + + // BLCONF_PRINT_TOC_INDEX + "¦WºÙ", + "»¡©ú", + "§@ªÌ", + "ª©¥»", + "¤é´Á", + NULL }; int bbslua_load_TOC(lua_State *L, const char *bs, const char *be, char **ppc) { - unsigned char *ps = NULL, *pe = NULL; - int i = 0; - - lua_newtable(L); - *ppc = NULL; - - while (bs < be) - { - // find stripped line start, end - ps = pe = (unsigned char *) bs; - while (pe < (unsigned char*)be && *pe != '\n' && *pe != '\r') - pe ++; - bs = (char*)pe+1; - while (ps < pe && *ps <= ' ') ps++; - while (pe > ps && *(pe-1) <= ' ') pe--; - // at least "--" - if (pe < ps+2) - break; - if (*ps++ != '-' || *ps++ != '-') - break; - while (ps < pe && *ps <= ' ') ps++; - // empty entry? - if (ps >= pe) - continue; - // find pattern - for (i = 0; bbsluaTocTags[i]; i++) - { - int l = strlen(bbsluaTocTags[i]); - if (ps + l > pe) - continue; - if (strncasecmp((char*)ps, bbsluaTocTags[i], l) != 0) - continue; - ps += l; - // found matching pattern, now find value - while (ps < pe && *ps <= ' ') ps++; - if (ps >= pe || *ps++ != ':') - break; - while (ps < pe && *ps <= ' ') ps++; - // finally, (ps, pe) is the value! - if (ps >= pe) - break; - - lua_pushlstring(L, (char*)ps, pe-ps); - - // accept only real floats for interface ([0]) - if (i == 0 && lua_tonumber(L, -1) <= 0) - { - lua_pop(L, 1); - } - else - { - lua_setfield(L, -2, bbsluaTocTags[i]); - } - break; - } - } - - if (ps >= (unsigned char*)bs && ps < (unsigned char*)be) - *ppc = (char*)ps; - lua_setglobal(L, "toc"); - return 0; + unsigned char *ps = NULL, *pe = NULL; + int i = 0; + + lua_newtable(L); + *ppc = NULL; + + while (bs < be) + { + // find stripped line start, end + ps = pe = (unsigned char *) bs; + while (pe < (unsigned char*)be && *pe != '\n' && *pe != '\r') + pe ++; + bs = (char*)pe+1; + while (ps < pe && *ps <= ' ') ps++; + while (pe > ps && *(pe-1) <= ' ') pe--; + // at least "--" + if (pe < ps+2) + break; + if (*ps++ != '-' || *ps++ != '-') + break; + while (ps < pe && *ps <= ' ') ps++; + // empty entry? + if (ps >= pe) + continue; + // find pattern + for (i = 0; bbsluaTocTags[i]; i++) + { + int l = strlen(bbsluaTocTags[i]); + if (ps + l > pe) + continue; + if (strncasecmp((char*)ps, bbsluaTocTags[i], l) != 0) + continue; + ps += l; + // found matching pattern, now find value + while (ps < pe && *ps <= ' ') ps++; + if (ps >= pe || *ps++ != ':') + break; + while (ps < pe && *ps <= ' ') ps++; + // finally, (ps, pe) is the value! + if (ps >= pe) + break; + + lua_pushlstring(L, (char*)ps, pe-ps); + + // accept only real floats for interface ([0]) + if (i == 0 && lua_tonumber(L, -1) <= 0) + { + lua_pop(L, 1); + } + else + { + lua_setfield(L, -2, bbsluaTocTags[i]); + } + break; + } + } + + if (ps >= (unsigned char*)bs && ps < (unsigned char*)be) + *ppc = (char*)ps; + lua_setglobal(L, "toc"); + return 0; } static void fullmsg(const char *s) { - clrtoeol(); - prints("%-*.*s\n", t_columns-1, t_columns-1, s); + clrtoeol(); + prints("%-*.*s\n", t_columns-1, t_columns-1, s); } void bbslua_logo(lua_State *L) { - int y, by = b_lines -1; // print - back from bottom - int i = 0; - double tocinterface = 0; - int tocs = 0; - char msg[STRLEN]; - - // get toc information - lua_getglobal(L, "toc"); - lua_getfield(L, -1, bbsluaTocTags[0]); - tocinterface = lua_tonumber(L, -1); lua_pop(L, 1); - - // query print-able toc tags - for (i = BLCONF_PRINT_TOC_INDEX; bbsluaTocTags[i]; i++) - { - lua_getfield(L, -1, bbsluaTocTags[i]); - if (lua_tostring(L, -1)) - tocs++; - lua_pop(L, 1); - } - - // prepare logo window - grayout(0, b_lines, GRAYOUT_DARK); - - // print compatibility test - // now (by) is the base of new information - if (tocinterface == 0) - { - by -= 4; y = by+2; - move(y-1, 0); - outs(ANSI_COLOR(0;31;47)); - fullmsg(""); - fullmsg(" ¡¶ ¦¹µ{¦¡¯Ê¤Ö¬Û®e©Ê¸ê°T¡A±z¥i¯àµLªk¥¿±`°õ¦æ"); - fullmsg(" Y°õ¦æ¥X²{¿ù»~¡A½Ð¦Vì§@ªÌ¨ú±o·sª©"); - fullmsg(""); - } - else if (tocinterface > BBSLUA_INTERFACE_VER) - { - by -= 4; y = by+2; - move(y-1, 0); - outs(ANSI_COLOR(0;1;37;41)); - fullmsg(""); - snprintf(msg, sizeof(msg), - " ¡¶ ¦¹µ{¦¡¨Ï¥Î·sª©ªº BBS-Lua ³W®æ (%0.3f)¡A±z¥i¯àµLªk¥¿±`°õ¦æ", - tocinterface); - fullmsg(msg); - fullmsg(" Y°õ¦æ¥X²{¿ù»~¡A«Øij±z«·sµn¤J BBS «á¦A«¸Õ"); - fullmsg(""); - } - else if (tocinterface == BBSLUA_INTERFACE_VER) - { - // do nothing! - } - else - { - // should be comtaible - // prints("¬Û®e (%.03f)", tocinterface); - } - - // print toc, if any. - if (tocs) - { - y = by - 1 - tocs; - by = y-1; - - move(y, 0); outs(ANSI_COLOR(0;1;30;47)); - fullmsg(""); - - // now try to print all TOC infos - for (i = BLCONF_PRINT_TOC_INDEX; bbsluaTocTags[i]; i++) - { - lua_getfield(L, -1, bbsluaTocTags[i]); - if (!lua_isstring(L, -1)) - { - lua_pop(L, 1); - continue; - } - move(++y, 0); - snprintf(msg, sizeof(msg), " %s: %-.*s", - bbsluaTocPrompts[i], STRLEN-12, lua_tostring(L, -1)); - msg[sizeof(msg)-1] = 0; - fullmsg(msg); - lua_pop(L, 1); - } - fullmsg(""); - } - - // print caption - move(by-2, 0); outc('\n'); - outs(ANSI_COLOR(0;1;37;44)); - snprintf(msg, sizeof(msg), - " ¡½ BBS-Lua %.03f (Build " __DATE__ " " __TIME__") ", - (double)BBSLUA_INTERFACE_VER); - fullmsg(msg); - - // system break key prompt - { - int sz = t_columns -1; - const char - *prompt1 = " ´£¿ô±z°õ¦æ¤¤ÀH®É¥i«ö ", - *prompt2 = "[Ctrl-C]", - *prompt3 = " ±j¨î¤¤Â_ BBS-Lua µ{¦¡"; - sz -= strlen(prompt1); - sz -= strlen(prompt2); - sz -= strlen(prompt3); - outs(ANSI_COLOR(22;37)); outs(prompt1); - outs(ANSI_COLOR(1;31)); outs(prompt2); - outs(ANSI_COLOR(0;37;44));outs(prompt3); - prints("%*s", sz, ""); - outs(ANSI_RESET); - } - lua_pop(L, 1); + int y, by = b_lines -1; // print - back from bottom + int i = 0; + double tocinterface = 0; + int tocs = 0; + char msg[STRLEN]; + + // get toc information + lua_getglobal(L, "toc"); + lua_getfield(L, -1, bbsluaTocTags[0]); + tocinterface = lua_tonumber(L, -1); lua_pop(L, 1); + + // query print-able toc tags + for (i = BLCONF_PRINT_TOC_INDEX; bbsluaTocTags[i]; i++) + { + lua_getfield(L, -1, bbsluaTocTags[i]); + if (lua_tostring(L, -1)) + tocs++; + lua_pop(L, 1); + } + + // prepare logo window + grayout(0, b_lines, GRAYOUT_DARK); + + // print compatibility test + // now (by) is the base of new information + if (tocinterface == 0) + { + by -= 4; y = by+2; + move(y-1, 0); + outs(ANSI_COLOR(0;31;47)); + fullmsg(""); + fullmsg(" ¡¶ ¦¹µ{¦¡¯Ê¤Ö¬Û®e©Ê¸ê°T¡A±z¥i¯àµLªk¥¿±`°õ¦æ"); + fullmsg(" Y°õ¦æ¥X²{¿ù»~¡A½Ð¦Vì§@ªÌ¨ú±o·sª©"); + fullmsg(""); + } + else if (tocinterface > BBSLUA_INTERFACE_VER) + { + by -= 4; y = by+2; + move(y-1, 0); + outs(ANSI_COLOR(0;1;37;41)); + fullmsg(""); + snprintf(msg, sizeof(msg), + " ¡¶ ¦¹µ{¦¡¨Ï¥Î·sª©ªº BBS-Lua ³W®æ (%0.3f)¡A±z¥i¯àµLªk¥¿±`°õ¦æ", + tocinterface); + fullmsg(msg); + fullmsg(" Y°õ¦æ¥X²{¿ù»~¡A«Øij±z«·sµn¤J BBS «á¦A«¸Õ"); + fullmsg(""); + } + else if (tocinterface == BBSLUA_INTERFACE_VER) + { + // do nothing! + } + else + { + // should be comtaible + // prints("¬Û®e (%.03f)", tocinterface); + } + + // print toc, if any. + if (tocs) + { + y = by - 1 - tocs; + by = y-1; + + move(y, 0); outs(ANSI_COLOR(0;1;30;47)); + fullmsg(""); + + // now try to print all TOC infos + for (i = BLCONF_PRINT_TOC_INDEX; bbsluaTocTags[i]; i++) + { + lua_getfield(L, -1, bbsluaTocTags[i]); + if (!lua_isstring(L, -1)) + { + lua_pop(L, 1); + continue; + } + move(++y, 0); + snprintf(msg, sizeof(msg), " %s: %-.*s", + bbsluaTocPrompts[i], STRLEN-12, lua_tostring(L, -1)); + msg[sizeof(msg)-1] = 0; + fullmsg(msg); + lua_pop(L, 1); + } + fullmsg(""); + } + + // print caption + move(by-2, 0); outc('\n'); + outs(ANSI_COLOR(0;1;37;44)); + snprintf(msg, sizeof(msg), + " ¡½ BBS-Lua %.03f (Build " __DATE__ " " __TIME__") ", + (double)BBSLUA_INTERFACE_VER); + fullmsg(msg); + + // system break key prompt + { + int sz = t_columns -1; + const char + *prompt1 = " ´£¿ô±z°õ¦æ¤¤ÀH®É¥i«ö ", + *prompt2 = "[Ctrl-C]", + *prompt3 = " ±j¨î¤¤Â_ BBS-Lua µ{¦¡"; + sz -= strlen(prompt1); + sz -= strlen(prompt2); + sz -= strlen(prompt3); + outs(ANSI_COLOR(22;37)); outs(prompt1); + outs(ANSI_COLOR(1;31)); outs(prompt2); + outs(ANSI_COLOR(0;37;44));outs(prompt3); + prints("%*s", sz, ""); + outs(ANSI_RESET); + } + lua_pop(L, 1); } ////////////////////////////////////////////////////////////////////////// @@ -1408,203 +1408,203 @@ bbslua_logo(lua_State *L) ////////////////////////////////////////////////////////////////////////// typedef struct LoadS { - const char *s; - size_t size; - int lineshift; + const char *s; + size_t size; + int lineshift; } LoadS; static const char* bbslua_reader(lua_State *L, void *ud, size_t *size) { - LoadS *ls = (LoadS *)ud; - (void)L; - if (ls->size == 0) return NULL; - if (ls->lineshift > 0) { - const char *linefeed = "\n"; - *size = 1; - ls->lineshift--; - return linefeed; - } - *size = ls->size; - ls->size = 0; - return ls->s; + LoadS *ls = (LoadS *)ud; + (void)L; + if (ls->size == 0) return NULL; + if (ls->lineshift > 0) { + const char *linefeed = "\n"; + *size = 1; + ls->lineshift--; + return linefeed; + } + *size = ls->size; + ls->size = 0; + return ls->s; } static int bbslua_loadbuffer (lua_State *L, const char *buff, size_t size, - const char *name, int lineshift) { - LoadS ls; - ls.s = buff; - ls.size = size; - ls.lineshift = lineshift; - return lua_load(L, bbslua_reader, &ls, name); + const char *name, int lineshift) { + LoadS ls; + ls.s = buff; + ls.size = size; + ls.lineshift = lineshift; + return lua_load(L, bbslua_reader, &ls, name); } typedef struct AllocData { - size_t alloc_size; - size_t max_alloc_size; - size_t alloc_limit; + size_t alloc_size; + size_t max_alloc_size; + size_t alloc_limit; } AllocData; static void alloc_init(AllocData *ad) { - memset(ad, 0, sizeof(*ad)); - // real limit is not determined yet, just assign a big value - ad->alloc_limit = 20*1048576; + memset(ad, 0, sizeof(*ad)); + // real limit is not determined yet, just assign a big value + ad->alloc_limit = 20*1048576; } static void *allocf (void *ud, void *ptr, size_t osize, size_t nsize) { - /* TODO use our own allocator, for better memory control, avoid fragment and leak */ - AllocData *ad = (AllocData*)ud; - - if (ad->alloc_size + nsize - osize > ad->alloc_limit) { - return NULL; - } - ad->alloc_size += nsize - osize; - if (ad->alloc_size > ad->max_alloc_size) { - ad->max_alloc_size = ad->alloc_size; - } - if (nsize == 0) { - free(ptr); - return NULL; - } - else - return realloc(ptr, nsize); + /* TODO use our own allocator, for better memory control, avoid fragment and leak */ + AllocData *ad = (AllocData*)ud; + + if (ad->alloc_size + nsize - osize > ad->alloc_limit) { + return NULL; + } + ad->alloc_size += nsize - osize; + if (ad->alloc_size > ad->max_alloc_size) { + ad->max_alloc_size = ad->alloc_size; + } + if (nsize == 0) { + free(ptr); + return NULL; + } + else + return realloc(ptr, nsize); } static int panic (lua_State *L) { - (void)L; /* to avoid warnings */ - fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", - lua_tostring(L, -1)); - return 0; + (void)L; /* to avoid warnings */ + fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; } void bbslua_loadLatest(lua_State *L, - char **pbs, char **pps, char **ppe, char **ppc, int *psz, - int *plineshift, char *bfpath, const char **pfpath) + char **pbs, char **pps, char **ppe, char **ppc, int *psz, + int *plineshift, char *bfpath, const char **pfpath) { - int r = 1; // max redirect for one article only. - - do { - char *xbs = NULL, *xps = NULL, *xpe = NULL, *xpc = NULL; - int xlineshift = 0; - size_t xsz; - const char *lastref = NULL; - char loadnext = 0, isnewver = 0; - - // detect file - xbs = bbslua_attach(bfpath, &xsz); - if (!xbs) - break; - - xps = xbs; - xpe = xps + xsz; - - if(!bbslua_detect_range(&xps, &xpe, &xlineshift)) - { - // not detected - bbslua_detach(xbs, xsz); - break; - } - - // detect and verify TOC meta data - lua_getglobal(L, "toc"); // stack 1 - if (lua_istable(L, -1)) - { - const char *oref, *otitle, *nref, *ntitle; - // load and verify tocinfo - lua_getfield(L, -1, "latestref"); // stack 2 - oref = lua_tostring(L, -1); - lua_getfield(L, -2, "title"); // stack 3 - otitle = lua_tostring(L, -1); - bbslua_load_TOC(L, xps, xpe, &xpc); - lua_getglobal(L, "toc"); // stack 4 - lua_getfield(L, -1, "latestref"); // stack 5 - nref = lua_tostring(L, -1); - lua_getfield(L, -2, "title"); // stack 6 - ntitle = lua_tostring(L, -1); - - if (oref && nref && otitle && ntitle && - strcmp(oref, nref) == 0 && - strcmp(otitle, ntitle) == 0) - isnewver = 1; - - // pop all - lua_pop(L, 5); // stack = 1 (old toc) - if (!isnewver) - lua_setglobal(L, "toc"); - else - lua_pop(L, 1); - } else { - lua_pop(L, 1); - bbslua_load_TOC(L, xps, xpe, &xpc); - } - - if (*pbs && !isnewver) - { - // different. - bbslua_detach(xbs, xsz); - break; - } - - // now, apply current buffer - if (*pbs) - { - bbslua_detach(*pbs, *psz); - // XXX fpath=bfpath, supporting only one level redirection now. - *pfpath = bfpath; - } - *pbs = xbs; *pps = xps; *ppe = xpe; *psz = xsz; - *ppc = xpc; - *plineshift = xlineshift; + int r = 1; // max redirect for one article only. + + do { + char *xbs = NULL, *xps = NULL, *xpe = NULL, *xpc = NULL; + int xlineshift = 0; + size_t xsz; + const char *lastref = NULL; + char loadnext = 0, isnewver = 0; + + // detect file + xbs = bbslua_attach(bfpath, &xsz); + if (!xbs) + break; + + xps = xbs; + xpe = xps + xsz; + + if(!bbslua_detect_range(&xps, &xpe, &xlineshift)) + { + // not detected + bbslua_detach(xbs, xsz); + break; + } + + // detect and verify TOC meta data + lua_getglobal(L, "toc"); // stack 1 + if (lua_istable(L, -1)) + { + const char *oref, *otitle, *nref, *ntitle; + // load and verify tocinfo + lua_getfield(L, -1, "latestref"); // stack 2 + oref = lua_tostring(L, -1); + lua_getfield(L, -2, "title"); // stack 3 + otitle = lua_tostring(L, -1); + bbslua_load_TOC(L, xps, xpe, &xpc); + lua_getglobal(L, "toc"); // stack 4 + lua_getfield(L, -1, "latestref"); // stack 5 + nref = lua_tostring(L, -1); + lua_getfield(L, -2, "title"); // stack 6 + ntitle = lua_tostring(L, -1); + + if (oref && nref && otitle && ntitle && + strcmp(oref, nref) == 0 && + strcmp(otitle, ntitle) == 0) + isnewver = 1; + + // pop all + lua_pop(L, 5); // stack = 1 (old toc) + if (!isnewver) + lua_setglobal(L, "toc"); + else + lua_pop(L, 1); + } else { + lua_pop(L, 1); + bbslua_load_TOC(L, xps, xpe, &xpc); + } + + if (*pbs && !isnewver) + { + // different. + bbslua_detach(xbs, xsz); + break; + } + + // now, apply current buffer + if (*pbs) + { + bbslua_detach(*pbs, *psz); + // XXX fpath=bfpath, supporting only one level redirection now. + *pfpath = bfpath; + } + *pbs = xbs; *pps = xps; *ppe = xpe; *psz = xsz; + *ppc = xpc; + *plineshift = xlineshift; #ifdef AID_DISPLAYNAME - // quick exit - if (r <= 0) - break; - - // LatestRef only works if system supports AID. - // try to load next reference. - lua_getglobal(L, "toc"); // stack 1 - lua_getfield(L, -1, "latestref"); // stack 2 - lastref = lua_tostring(L, -1); - - while (lastref && *lastref) - { - // try to load by AID - char bn[IDLEN+1] = ""; - aidu_t aidu = 0; - unsigned char *p = (unsigned char*)bn; - - if (*lastref == '#') lastref++; - aidu = aidc2aidu((char*)lastref); - if (aidu <= 0) break; - - while (*lastref > ' ') lastref ++; // lastref points to zero of space - while (*lastref && *lastref <= ' ') lastref++; // lastref points to zero or board name - if (*lastref == '(') lastref ++; - - if (!*lastref) break; - strlcpy(bn, lastref, sizeof(bn)); - // truncate board name - // (not_alnum(ch) && ch != '_' && ch != '-' && ch != '.') - while (*p && - (isalnum(*p) || *p == '_' || *p == '-' || *p == '.')) p++; - *p = 0; - if (bn[0]) - { - bfpath[0] = 0; - setaidfile(bfpath, bn, aidu); - } - - if (bfpath[0]) - loadnext = 1; - break; - } - lua_pop(L, 2); - - if (loadnext) continue; + // quick exit + if (r <= 0) + break; + + // LatestRef only works if system supports AID. + // try to load next reference. + lua_getglobal(L, "toc"); // stack 1 + lua_getfield(L, -1, "latestref"); // stack 2 + lastref = lua_tostring(L, -1); + + while (lastref && *lastref) + { + // try to load by AID + char bn[IDLEN+1] = ""; + aidu_t aidu = 0; + unsigned char *p = (unsigned char*)bn; + + if (*lastref == '#') lastref++; + aidu = aidc2aidu((char*)lastref); + if (aidu <= 0) break; + + while (*lastref > ' ') lastref ++; // lastref points to zero of space + while (*lastref && *lastref <= ' ') lastref++; // lastref points to zero or board name + if (*lastref == '(') lastref ++; + + if (!*lastref) break; + strlcpy(bn, lastref, sizeof(bn)); + // truncate board name + // (not_alnum(ch) && ch != '_' && ch != '-' && ch != '.') + while (*p && + (isalnum(*p) || *p == '_' || *p == '-' || *p == '.')) p++; + *p = 0; + if (bn[0]) + { + bfpath[0] = 0; + setaidfile(bfpath, bn, aidu); + } + + if (bfpath[0]) + loadnext = 1; + break; + } + lua_pop(L, 2); + + if (loadnext) continue; #endif // AID_DISPLAYNAME - break; + break; - } while (r-- > 0); + } while (r-- > 0); } ////////////////////////////////////////////////////////////////////////// @@ -1615,37 +1615,37 @@ void bbslua_loadLatest(lua_State *L, static int bbslua_hashWriter(lua_State *L, const void *p, size_t sz, void *ud) { - Fnv32_t *phash = (Fnv32_t*) ud; - *phash = fnv_32_buf(p, sz, *phash); - return 0; + Fnv32_t *phash = (Fnv32_t*) ud; + *phash = fnv_32_buf(p, sz, *phash); + return 0; } static Fnv32_t bbslua_f2hash(lua_State *L) { Fnv32_t fnvseed = FNV1_32_INIT; - lua_dump(L, bbslua_hashWriter, &fnvseed); - return fnvseed; + lua_dump(L, bbslua_hashWriter, &fnvseed); + return fnvseed; } static Fnv32_t bbslua_str2hash(const char *str) { - if (!str) - return 0; - return fnv_32_str(str, FNV1_32_INIT); + if (!str) + return 0; + return fnv_32_str(str, FNV1_32_INIT); } #endif static Fnv32_t bbslua_path2hash(const char *path) { - Fnv32_t seed = FNV1_32_INIT; - if (!path) - return 0; - if (path[0] != '/') // relative, append BBSHOME - seed = fnv_32_str(BBSHOME "/", seed); - return fnv_32_str(path, seed); + Fnv32_t seed = FNV1_32_INIT; + if (!path) + return 0; + if (path[0] != '/') // relative, append BBSHOME + seed = fnv_32_str(BBSHOME "/", seed); + return fnv_32_str(path, seed); } ////////////////////////////////////////////////////////////////////////// @@ -1655,147 +1655,147 @@ bbslua_path2hash(const char *path) int bbslua(const char *fpath) { - int r = 0; - lua_State *L; - char *bs = NULL, *ps = NULL, *pe = NULL, *pc = NULL; - char bfpath[PATHLEN] = ""; - int sz = 0; - int lineshift = 0; - AllocData ad; + int r = 0; + lua_State *L; + char *bs = NULL, *ps = NULL, *pe = NULL, *pc = NULL; + char bfpath[PATHLEN] = ""; + int sz = 0; + int lineshift = 0; + AllocData ad; #ifdef BBSLUA_USAGE - struct rusage rusage_begin, rusage_end; - struct timeval lua_begintime, lua_endtime; - gettimeofday(&lua_begintime, NULL); - getrusage(0, &rusage_begin); + struct rusage rusage_begin, rusage_end; + struct timeval lua_begintime, lua_endtime; + gettimeofday(&lua_begintime, NULL); + getrusage(0, &rusage_begin); #endif #ifdef UMODE_BBSLUA - unsigned int prevmode = getutmpmode(); + unsigned int prevmode = getutmpmode(); #endif - // re-entrant not supported! - if (blrt.running) - return 0; + // re-entrant not supported! + if (blrt.running) + return 0; - // initialize runtime - BL_INIT_RUNTIME(); + // initialize runtime + BL_INIT_RUNTIME(); #ifdef BBSLUA_USAGE - bbslua_count = 0; + bbslua_count = 0; #endif - // init lua - alloc_init(&ad); - L = lua_newstate(allocf, &ad); - if (!L) - return 0; - lua_atpanic(L, &panic); + // init lua + alloc_init(&ad); + L = lua_newstate(allocf, &ad); + if (!L) + return 0; + lua_atpanic(L, &panic); - strlcpy(bfpath, fpath, sizeof(bfpath)); + strlcpy(bfpath, fpath, sizeof(bfpath)); - // load file - bbslua_loadLatest(L, &ps, &ps, &pe, &pc, &sz, &lineshift, bfpath, &fpath); + // load file + bbslua_loadLatest(L, &ps, &ps, &pe, &pc, &sz, &lineshift, bfpath, &fpath); - if (!ps || !pe || ps >= pe) - { - if (bs) - bbslua_detach(bs, sz); - lua_close(L); - vmsg("BBS-Lua ¸ü¤J¿ù»~: ¥¼§t BBS-Lua µ{¦¡"); - return 0; - } + if (!ps || !pe || ps >= pe) + { + if (bs) + bbslua_detach(bs, sz); + lua_close(L); + vmsg("BBS-Lua ¸ü¤J¿ù»~: ¥¼§t BBS-Lua µ{¦¡"); + return 0; + } - // init library - bbsluaL_openlibs(L); - luaL_openlib(L, "bbs", lib_bbslua, 0); + // init library + bbsluaL_openlibs(L); + luaL_openlib(L, "bbs", lib_bbslua, 0); #ifdef BLSCONF_ENABLED - luaL_openlib(L, "store", lib_store, 0); + luaL_openlib(L, "store", lib_store, 0); #endif // BLSCONF_ENABLED - bbsluaRegConst(L); - - // load script - r = bbslua_loadbuffer(L, ps, pe-ps, "BBS-Lua", lineshift); - - // build hash or store name - blrt.storename = bbslua_path2hash(fpath); - // vmsgf("BBS-Lua Hash: %08X", blrt.storename); - - // unmap - bbslua_detach(bs, sz); - - if (r != 0) - { - const char *errmsg = lua_tostring(L, -1); - lua_close(L); - outs(ANSI_RESET); - move(b_lines-3, 0); clrtobot(); - outs("\n"); - outs(errmsg); - vmsg("BBS-Lua ¸ü¤J¿ù»~: ½Ð³qª¾§@ªÌ×¥¿µ{¦¡½X¡C"); - return 0; - } + bbsluaRegConst(L); + + // load script + r = bbslua_loadbuffer(L, ps, pe-ps, "BBS-Lua", lineshift); + + // build hash or store name + blrt.storename = bbslua_path2hash(fpath); + // vmsgf("BBS-Lua Hash: %08X", blrt.storename); + + // unmap + bbslua_detach(bs, sz); + + if (r != 0) + { + const char *errmsg = lua_tostring(L, -1); + lua_close(L); + outs(ANSI_RESET); + move(b_lines-3, 0); clrtobot(); + outs("\n"); + outs(errmsg); + vmsg("BBS-Lua ¸ü¤J¿ù»~: ½Ð³qª¾§@ªÌ×¥¿µ{¦¡½X¡C"); + return 0; + } #ifdef UMODE_BBSLUA - setutmpmode(UMODE_BBSLUA); + setutmpmode(UMODE_BBSLUA); #endif - bbslua_logo(L); - vmsgf("´£¿ô±z°õ¦æ¤¤ÀH®É¥i«ö [Ctrl-C] ±j¨î¤¤Â_ BBS-Lua µ{¦¡"); + bbslua_logo(L); + vmsgf("´£¿ô±z°õ¦æ¤¤ÀH®É¥i«ö [Ctrl-C] ±j¨î¤¤Â_ BBS-Lua µ{¦¡"); - // ready for running - clear(); - blrt.running =1; - lua_sethook(L, bbsluaHook, LUA_MASKCOUNT, BLCONF_EXEC_COUNT ); + // ready for running + clear(); + blrt.running =1; + lua_sethook(L, bbsluaHook, LUA_MASKCOUNT, BLCONF_EXEC_COUNT ); - refresh(); - // check is now done inside hook - r = lua_resume(L, 0); + refresh(); + // check is now done inside hook + r = lua_resume(L, 0); - // even if r == yield, let's abort - you cannot yield main thread. + // even if r == yield, let's abort - you cannot yield main thread. - if (r != 0) - { - const char *errmsg = lua_tostring(L, -1); - move(b_lines-3, 0); clrtobot(); - outs("\n"); - if (errmsg) outs(errmsg); - } + if (r != 0) + { + const char *errmsg = lua_tostring(L, -1); + move(b_lines-3, 0); clrtobot(); + outs("\n"); + if (errmsg) outs(errmsg); + } - lua_close(L); - blrt.running =0; - drop_input(); + lua_close(L); + blrt.running =0; + drop_input(); #ifdef BBSLUA_USAGE - { - double cputime; - double load; - double walltime; - getrusage(0, &rusage_end); - gettimeofday(&lua_endtime, NULL); - cputime = bl_tv2double(&rusage_end.ru_utime) - bl_tv2double(&rusage_begin.ru_utime); - walltime = bl_tv2double(&lua_endtime) - bl_tv2double(&lua_begintime); - load = cputime / walltime; - log_filef("log/bbslua.log", LOG_CREAT, - "maxalloc=%d leak=%d op=%d cpu=%.3f Mop/s=%.1f load=%f file=%s\n", - (int)ad.max_alloc_size, (int)ad.alloc_size, - bbslua_count, cputime, bbslua_count / cputime / 1000000.0, load * 100, - fpath); - } + { + double cputime; + double load; + double walltime; + getrusage(0, &rusage_end); + gettimeofday(&lua_endtime, NULL); + cputime = bl_tv2double(&rusage_end.ru_utime) - bl_tv2double(&rusage_begin.ru_utime); + walltime = bl_tv2double(&lua_endtime) - bl_tv2double(&lua_begintime); + load = cputime / walltime; + log_filef("log/bbslua.log", LOG_CREAT, + "maxalloc=%d leak=%d op=%d cpu=%.3f Mop/s=%.1f load=%f file=%s\n", + (int)ad.max_alloc_size, (int)ad.alloc_size, + bbslua_count, cputime, bbslua_count / cputime / 1000000.0, load * 100, + fpath); + } #endif - // grayout(0, b_lines, GRAYOUT_DARK); - move(b_lines, 0); clrtoeol(); - vmsgf("BBS-Lua °õ¦æµ²§ô%s¡C", - blrt.abort ? " (¨Ï¥ÎªÌ¤¤Â_)" : r ? " (µ{¦¡¿ù»~)" : ""); - BL_END_RUNTIME(); - clear(); + // grayout(0, b_lines, GRAYOUT_DARK); + move(b_lines, 0); clrtoeol(); + vmsgf("BBS-Lua °õ¦æµ²§ô%s¡C", + blrt.abort ? " (¨Ï¥ÎªÌ¤¤Â_)" : r ? " (µ{¦¡¿ù»~)" : ""); + BL_END_RUNTIME(); + clear(); #ifdef UMODE_BBSLUA - setutmpmode(prevmode); + setutmpmode(prevmode); #endif - return 0; + return 0; } -// vim:ts=4:sw=4 +// vim:ts=4:sw=4:expandtab diff --git a/mbbsd/pfterm.c b/mbbsd/pfterm.c index bffb225b..65a09a62 100644 --- a/mbbsd/pfterm.c +++ b/mbbsd/pfterm.c @@ -24,8 +24,8 @@ // # ifdef CONVERT // extern int bbs_convert_type; // # define FT_DBCS_NOINTRESC ( -// (cuser.uflag & DBCS_NOINTRESC) || -// (bbs_convert_type == CONV_UTF8)) +// (cuser.uflag & DBCS_NOINTRESC) || +// (bbs_convert_type == CONV_UTF8)) // # else # define FT_DBCS_NOINTRESC (cuser.uflag & DBCS_NOINTRESC) // # endif @@ -40,7 +40,7 @@ ////////////////////////////////////////////////////////////////////////// // #define DBG_SHOW_DIRTY -// #define DBG_SHOW_REPRINT // will not work if you enable SHOW_DIRTY. +// #define DBG_SHOW_REPRINT // will not work if you enable SHOW_DIRTY. // #define DBG_DISABLE_OPTMOVE // #define DBG_DISABLE_REPRINT @@ -76,8 +76,8 @@ // Typeahead ////////////////////////////////////////////////////////////////////////// #ifndef TYPEAHEAD_NONE -#define TYPEAHEAD_NONE (-1) -#define TYPEAHEAD_STDIN (0) +#define TYPEAHEAD_NONE (-1) +#define TYPEAHEAD_STDIN (0) #endif // TYPEAHEAD ////////////////////////////////////////////////////////////////////////// @@ -159,43 +159,43 @@ #define FTSZ_DEFAULT_ROW (24) #define FTSZ_DEFAULT_COL (80) -#define FTSZ_MIN_ROW (24) -#define FTSZ_MAX_ROW (100) -#define FTSZ_MIN_COL (80) -#define FTSZ_MAX_COL (320) - -#define FTCHAR_ERASE (' ') -#define FTATTR_ERASE (0x07) -#define FTCHAR_BLANK (' ') -#define FTATTR_DEFAULT (FTATTR_ERASE) +#define FTSZ_MIN_ROW (24) +#define FTSZ_MAX_ROW (100) +#define FTSZ_MIN_COL (80) +#define FTSZ_MAX_COL (320) + +#define FTCHAR_ERASE (' ') +#define FTATTR_ERASE (0x07) +#define FTCHAR_BLANK (' ') +#define FTATTR_DEFAULT (FTATTR_ERASE) #define FTCHAR_INVALID_DBCS ('?') // #define FTATTR_TRANSPARENT (0x80) -#define FTDIRTY_CHAR (0x01) -#define FTDIRTY_ATTR (0x02) -#define FTDIRTY_DBCS (0x04) -#define FTDIRTY_INVALID_DBCS (0x08) -#define FTDIRTY_RAWMOVE (0x10) +#define FTDIRTY_CHAR (0x01) +#define FTDIRTY_ATTR (0x02) +#define FTDIRTY_DBCS (0x04) +#define FTDIRTY_INVALID_DBCS (0x08) +#define FTDIRTY_RAWMOVE (0x10) -#define FTDBCS_SAFE (0) // standard DBCS -#define FTDBCS_UNSAFE (1) // not on all systems (better do rawmove) -#define FTDBCS_INVALID (2) // invalid +#define FTDBCS_SAFE (0) // standard DBCS +#define FTDBCS_UNSAFE (1) // not on all systems (better do rawmove) +#define FTDBCS_INVALID (2) // invalid -#define FTCMD_MAXLEN (63) // max escape command sequence length -#define FTATTR_MINCMD (16) +#define FTCMD_MAXLEN (63) // max escape command sequence length +#define FTATTR_MINCMD (16) #ifndef FTCONF_USE_ANSI_RELMOVE -# define FTMV_COST (8) // always ESC[m;nH will costs avg 8 bytes +# define FTMV_COST (8) // always ESC[m;nH will costs avg 8 bytes #else -# define FTMV_COST (5) // ESC[ABCD with ESC[m;nH costs avg 4+ bytes +# define FTMV_COST (5) // ESC[ABCD with ESC[m;nH costs avg 4+ bytes #endif ////////////////////////////////////////////////////////////////////////// // Flat Terminal Data Type ////////////////////////////////////////////////////////////////////////// -typedef unsigned char ftchar; // primitive character type -typedef unsigned char ftattr; // primitive attribute type +typedef unsigned char ftchar; // primitive character type +typedef unsigned char ftattr; // primitive attribute type ////////////////////////////////////////////////////////////////////////// // Flat Terminal Structure @@ -203,42 +203,42 @@ typedef unsigned char ftattr; // primitive attribute type typedef struct { - ftchar **cmap[2]; // character map - ftattr **amap[2]; // attribute map - ftchar *dmap; // dirty map - ftchar *dcmap; // processed display map - ftattr attr; - int rows, cols; - int y, x; - int sy,sx; // stored cursor - int mi; // map index, mi = current map and (1-mi) = old map - int dirty; - int scroll; + ftchar **cmap[2]; // character map + ftattr **amap[2]; // attribute map + ftchar *dmap; // dirty map + ftchar *dcmap; // processed display map + ftattr attr; + int rows, cols; + int y, x; + int sy,sx; // stored cursor + int mi; // map index, mi = current map and (1-mi) = old map + int dirty; + int scroll; - // memory allocation - int mrows, mcols; + // memory allocation + int mrows, mcols; - // raw terminal status - int ry, rx; - ftattr rattr; + // raw terminal status + int ry, rx; + ftattr rattr; - // typeahead - char typeahead; + // typeahead + char typeahead; - // escape command - ftchar cmd[FTCMD_MAXLEN+1]; - int szcmd; + // escape command + ftchar cmd[FTCMD_MAXLEN+1]; + int szcmd; } FlatTerm; static FlatTerm ft; #ifdef _WIN32 - // sorry, we support only 80x24 on Windows now. - HANDLE hStdout; - COORD coordBufSize = {80, 24}, coordBufCoord = {0, 0}; - SMALL_RECT winrect = {0, 0, 79, 23}; - CHAR_INFO winbuf[80*24]; + // sorry, we support only 80x24 on Windows now. + HANDLE hStdout; + COORD coordBufSize = {80, 24}, coordBufCoord = {0, 0}; + SMALL_RECT winrect = {0, 0, 79, 23}; + CHAR_INFO winbuf[80*24]; #endif ////////////////////////////////////////////////////////////////////////// @@ -252,23 +252,23 @@ static FlatTerm ft; #define FTATTR_GETBG(x) ((x >> FTATTR_BGSHIFT) & 0x7) #define FTATTR_FGMASK ((ftattr)(0x7 << FTATTR_FGSHIFT)) #define FTATTR_BGMASK ((ftattr)(0x7 << FTATTR_BGSHIFT)) -#define FTATTR_BOLD (0x08) -#define FTATTR_BLINK (0x80) -#define FTATTR_DEFAULT_FG (FTATTR_GETFG(FTATTR_DEFAULT)) -#define FTATTR_DEFAULT_BG (FTATTR_GETBG(FTATTR_DEFAULT)) -#define FTATTR_MAKE(f,b) (((f)<<FTATTR_FGSHIFT)|((b)<<FTATTR_BGSHIFT)) -#define FTCHAR_ISBLANK(x) ((x) == (FTCHAR_BLANK)) - -#define FTCMAP ft.cmap[ft.mi] -#define FTAMAP ft.amap[ft.mi] -#define FTCROW FTCMAP[ft.y] -#define FTAROW FTAMAP[ft.y] -#define FTC FTCROW[ft.x] -#define FTA FTAROW[ft.x] -#define FTD ft.dmap -#define FTDC ft.dcmap -#define FTPC (FTCROW+ft.x) -#define FTPA (FTAROW+ft.x) +#define FTATTR_BOLD (0x08) +#define FTATTR_BLINK (0x80) +#define FTATTR_DEFAULT_FG (FTATTR_GETFG(FTATTR_DEFAULT)) +#define FTATTR_DEFAULT_BG (FTATTR_GETBG(FTATTR_DEFAULT)) +#define FTATTR_MAKE(f,b) (((f)<<FTATTR_FGSHIFT)|((b)<<FTATTR_BGSHIFT)) +#define FTCHAR_ISBLANK(x) ((x) == (FTCHAR_BLANK)) + +#define FTCMAP ft.cmap[ft.mi] +#define FTAMAP ft.amap[ft.mi] +#define FTCROW FTCMAP[ft.y] +#define FTAROW FTAMAP[ft.y] +#define FTC FTCROW[ft.x] +#define FTA FTAROW[ft.x] +#define FTD ft.dmap +#define FTDC ft.dcmap +#define FTPC (FTCROW+ft.x) +#define FTPA (FTAROW+ft.x) #define FTOCMAP ft.cmap[1-ft.mi] #define FTOAMAP ft.amap[1-ft.mi] @@ -287,7 +287,7 @@ static FlatTerm ft; // #define FTDBCS_ISTAIL(x) (((unsigned char)(x)) & ((unsigned char)~0x3F)) #define FTDBCS_ISSBCSPRINT(x) \ - (((unsigned char)(x))>=' ' && ((unsigned char)(x))<0x80) + (((unsigned char)(x))>=' ' && ((unsigned char)(x))<0x80) #ifndef min #define min(x,y) (((x)<(y))?(x):(y)) @@ -311,102 +311,102 @@ static FlatTerm ft; //// common ncurse-like library interface // initialization -void initscr (void); -int resizeterm (int rows, int cols); -int endwin (void); +void initscr (void); +int resizeterm (int rows, int cols); +int endwin (void); // attributes -ftattr attrget (void); -void attrset (ftattr attr); -void attrsetfg (ftattr attr); -void attrsetbg (ftattr attr); +ftattr attrget (void); +void attrset (ftattr attr); +void attrsetfg (ftattr attr); +void attrsetbg (ftattr attr); // cursor -void getyx (int *y, int *x); -void getmaxyx (int *y, int *x); -void move (int y, int x); +void getyx (int *y, int *x); +void getmaxyx (int *y, int *x); +void move (int y, int x); // clear -void clear (void); // clrscr + move(0,0) -void clrtoeol (void); // end of line -void clrtobot (void); +void clear (void); // clrscr + move(0,0) +void clrtoeol (void); // end of line +void clrtobot (void); // clear (non-ncurses) -void clrtoln (int ln); // clear down to ln ( excluding ln, as [y,ln) ) -void clrcurln (void); // whole line -void clrtobeg (void); // begin of line -void clrtohome (void); -void clrscr (void); // clear and keep cursor untouched -void clrregion (int r1, int r2); // clear [r1,r2], bi-directional. +void clrtoln (int ln); // clear down to ln ( excluding ln, as [y,ln) ) +void clrcurln (void); // whole line +void clrtobeg (void); // begin of line +void clrtohome (void); +void clrscr (void); // clear and keep cursor untouched +void clrregion (int r1, int r2); // clear [r1,r2], bi-directional. // window control -void newwin (int nlines, int ncols, int y, int x); +void newwin (int nlines, int ncols, int y, int x); // flushing -void refresh (void); // optimized refresh -void doupdate (void); // optimized refresh, ignore input queue -void redrawwin (void); // invalidate whole screen -int typeahead (int fd);// prevent refresh if input queue is not empty +void refresh (void); // optimized refresh +void doupdate (void); // optimized refresh, ignore input queue +void redrawwin (void); // invalidate whole screen +int typeahead (int fd);// prevent refresh if input queue is not empty // scrolling -void scroll (void); // scroll up -void rscroll (void); // scroll down -void scrl (int rows); +void scroll (void); // scroll up +void rscroll (void); // scroll down +void scrl (int rows); // output (ncurses flavor) -void addch (unsigned char c); // equivalent to outc() -void addstr (const char *s); // equivalent to outs() -void addnstr (const char *s, int n); +void addch (unsigned char c); // equivalent to outc() +void addstr (const char *s); // equivalent to outs() +void addnstr (const char *s, int n); // output (non-ncurses) -void outc (unsigned char c); -void outs (const char *s); -void outns (const char *s, int n); -void outstr (const char *str); // prepare and print a complete string. -void addstring (const char *str); // ncurses-like of outstr(). +void outc (unsigned char c); +void outs (const char *s); +void outns (const char *s, int n); +void outstr (const char *str); // prepare and print a complete string. +void addstring (const char *str); // ncurses-like of outstr(). // readback -int instr (char *str); -int innstr (char *str, int n); // n includes \0 -int inansistr (char *str, int n); // n includes \0 +int instr (char *str); +int innstr (char *str, int n); // n includes \0 +int inansistr (char *str, int n); // n includes \0 // deprecated -void standout (void); -void standend (void); +void standout (void); +void standend (void); // grayout advanced control -void grayout (int y, int end, int level); +void grayout (int y, int end, int level); //// flat-term internal processor -int fterm_inbuf (void); // raw input adapter -void fterm_rawc (int c); // raw output adapter -void fterm_rawnewline(void); // raw output adapter -void fterm_rawflush (void); // raw output adapter -void fterm_raws (const char *s); -void fterm_rawnc (int c, int n); -void fterm_rawnum (int arg); -void fterm_rawcmd (int arg, int defval, char c); -void fterm_rawcmd2 (int arg1, int arg2, int defval, char c); -void fterm_rawattr (ftattr attr); // optimized changing attribute -void fterm_rawclear (void); -void fterm_rawclreol (void); -void fterm_rawhome (void); -void fterm_rawscroll (int dy); -void fterm_rawcursor (void); -void fterm_rawmove (int y, int x); -void fterm_rawmove_opt(int y, int x); -void fterm_rawmove_rel(int dy, int dx); - -int fterm_chattr (char *s, ftattr oa, ftattr na); // size(s) > FTATTR_MINCMD -void fterm_exec (void); // execute ft.cmd -void fterm_flippage (void); -void fterm_dupe2bk (void); -void fterm_markdirty (void); // mark as dirty -int fterm_strdlen (const char *s); // length of string for display -int fterm_prepare_str(int len); +int fterm_inbuf (void); // raw input adapter +void fterm_rawc (int c); // raw output adapter +void fterm_rawnewline(void); // raw output adapter +void fterm_rawflush (void); // raw output adapter +void fterm_raws (const char *s); +void fterm_rawnc (int c, int n); +void fterm_rawnum (int arg); +void fterm_rawcmd (int arg, int defval, char c); +void fterm_rawcmd2 (int arg1, int arg2, int defval, char c); +void fterm_rawattr (ftattr attr); // optimized changing attribute +void fterm_rawclear (void); +void fterm_rawclreol (void); +void fterm_rawhome (void); +void fterm_rawscroll (int dy); +void fterm_rawcursor (void); +void fterm_rawmove (int y, int x); +void fterm_rawmove_opt(int y, int x); +void fterm_rawmove_rel(int dy, int dx); + +int fterm_chattr (char *s, ftattr oa, ftattr na); // size(s) > FTATTR_MINCMD +void fterm_exec (void); // execute ft.cmd +void fterm_flippage (void); +void fterm_dupe2bk (void); +void fterm_markdirty (void); // mark as dirty +int fterm_strdlen (const char *s); // length of string for display +int fterm_prepare_str(int len); // DBCS supporting -int fterm_DBCS_Big5(unsigned char c1, unsigned char c2); +int fterm_DBCS_Big5(unsigned char c1, unsigned char c2); ////////////////////////////////////////////////////////////////////////// // Flat Terminal Implementation @@ -420,150 +420,150 @@ void initscr(void) { #ifdef _WIN32 - hStdout = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleScreenBufferSize(hStdout, coordBufSize); - SetConsoleCursorPosition(hStdout, coordBufCoord); + hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleScreenBufferSize(hStdout, coordBufSize); + SetConsoleCursorPosition(hStdout, coordBufCoord); #endif - memset(&ft, sizeof(ft), 0); - ft.attr = ft.rattr = FTATTR_DEFAULT; - resizeterm(FTSZ_DEFAULT_ROW, FTSZ_DEFAULT_COL); + memset(&ft, sizeof(ft), 0); + ft.attr = ft.rattr = FTATTR_DEFAULT; + resizeterm(FTSZ_DEFAULT_ROW, FTSZ_DEFAULT_COL); - // clear both pages - ft.mi = 0; clrscr(); - ft.mi = 1; clrscr(); - ft.mi = 0; + // clear both pages + ft.mi = 0; clrscr(); + ft.mi = 1; clrscr(); + ft.mi = 0; - // typeahead - ft.typeahead = 1; + // typeahead + ft.typeahead = 1; - fterm_rawclear(); - move(0, 0); + fterm_rawclear(); + move(0, 0); } -int +int endwin(void) { - int r, mi = 0; + int r, mi = 0; - // fterm_rawclear(); - - for (mi = 0; mi < 2; mi++) - { - for (r = 0; r < ft.mrows; r++) - { - free(ft.cmap[mi][r]); - free(ft.amap[mi][r]); - } - } - free(ft.dmap); - free(ft.dcmap); - memset(&ft, sizeof(ft), 0); - return 0; + // fterm_rawclear(); + + for (mi = 0; mi < 2; mi++) + { + for (r = 0; r < ft.mrows; r++) + { + free(ft.cmap[mi][r]); + free(ft.amap[mi][r]); + } + } + free(ft.dmap); + free(ft.dcmap); + memset(&ft, sizeof(ft), 0); + return 0; } int resizeterm(int rows, int cols) { - int dirty = 0, mi = 0, i = 0; - - rows = ranged(rows, FTSZ_MIN_ROW, FTSZ_MAX_ROW); - cols = ranged(cols, FTSZ_MIN_COL, FTSZ_MAX_COL); - - // adjust memory only for increasing buffer - if (rows > ft.mrows || cols > ft.mcols) - { - for (mi = 0; mi < 2; mi++) - { - // allocate rows - if (rows > ft.mrows) - { - ft.cmap[mi] = (ftchar**)realloc(ft.cmap[mi], - sizeof(ftchar*) * rows); - ft.amap[mi] = (ftattr**)realloc(ft.amap[mi], - sizeof(ftattr*) * rows); - - // allocate new columns - for (i = ft.mrows; i < rows; i++) - { - ft.cmap[mi][i] = (ftchar*)malloc((cols+1) * sizeof(ftchar)); - ft.amap[mi][i] = (ftattr*)malloc((cols+1) * sizeof(ftattr)); - // zero at end to prevent over-run - ft.cmap[mi][i][cols] = 0; - ft.amap[mi][i][cols] = 0; - } - } - - // resize cols - if (cols > ft.mcols) - { - for (i = 0; i < ft.mrows; i++) - { - ft.cmap[mi][i] = (ftchar*)realloc(ft.cmap[mi][i], - (cols+1) * sizeof(ftchar)); - ft.amap[mi][i] = (ftattr*)realloc(ft.amap[mi][i], - (cols+1) * sizeof(ftattr)); - // zero at end to prevent over-run - ft.cmap[mi][i][cols] = 0; - ft.amap[mi][i][cols] = 0; - } - } else { - // we have to deal one case: - // expand x, shrink x, expand y -> - // now new allocated lines will have small x(col) instead of mcol. - // the solution is to modify mcols here, or change the malloc above - // to max(ft.mcols, cols). - ft.mcols = cols; - } - } - - // adjusts dirty and display map. - // no need to initialize anyway. - if (cols > ft.mcols) - { - ft.dmap = (ftchar*) realloc(ft.dmap, - (cols+1) * sizeof(ftchar)); - ft.dcmap = (ftchar*) realloc(ft.dcmap, - (cols+1) * sizeof(ftchar)); - } - - // do mrows/mcols assignment here, because we had 2 maps running loop above. - if (cols > ft.mcols) ft.mcols = cols; - if (rows > ft.mrows) ft.mrows = rows; - dirty = 1; - } - - // clear new exposed buffer after resized - // because we will redawwin(), so need to change front buffer only. - for (i = ft.rows; i < rows; i++) - { - memset(FTCMAP[i], FTCHAR_ERASE, - (cols) * sizeof(ftchar)); - memset(FTAMAP[i], FTATTR_ERASE, - (cols) * sizeof(ftattr)); - } - if (cols > ft.cols) - { - for (i = 0; i < ft.rows; i++) - { - memset(FTCMAP[i]+ft.cols, FTCHAR_ERASE, - (cols-ft.cols) * sizeof(ftchar)); - memset(FTAMAP[i]+ft.cols, FTATTR_ERASE, - (cols-ft.cols) * sizeof(ftattr)); - } - } - - if (ft.rows != rows || ft.cols != cols) - { - ft.rows = rows; - ft.cols = cols; - redrawwin(); - } - - ft.x = ranged(ft.x, 0, ft.cols-1); - ft.y = ranged(ft.y, 0, ft.rows-1); - - return dirty; + int dirty = 0, mi = 0, i = 0; + + rows = ranged(rows, FTSZ_MIN_ROW, FTSZ_MAX_ROW); + cols = ranged(cols, FTSZ_MIN_COL, FTSZ_MAX_COL); + + // adjust memory only for increasing buffer + if (rows > ft.mrows || cols > ft.mcols) + { + for (mi = 0; mi < 2; mi++) + { + // allocate rows + if (rows > ft.mrows) + { + ft.cmap[mi] = (ftchar**)realloc(ft.cmap[mi], + sizeof(ftchar*) * rows); + ft.amap[mi] = (ftattr**)realloc(ft.amap[mi], + sizeof(ftattr*) * rows); + + // allocate new columns + for (i = ft.mrows; i < rows; i++) + { + ft.cmap[mi][i] = (ftchar*)malloc((cols+1) * sizeof(ftchar)); + ft.amap[mi][i] = (ftattr*)malloc((cols+1) * sizeof(ftattr)); + // zero at end to prevent over-run + ft.cmap[mi][i][cols] = 0; + ft.amap[mi][i][cols] = 0; + } + } + + // resize cols + if (cols > ft.mcols) + { + for (i = 0; i < ft.mrows; i++) + { + ft.cmap[mi][i] = (ftchar*)realloc(ft.cmap[mi][i], + (cols+1) * sizeof(ftchar)); + ft.amap[mi][i] = (ftattr*)realloc(ft.amap[mi][i], + (cols+1) * sizeof(ftattr)); + // zero at end to prevent over-run + ft.cmap[mi][i][cols] = 0; + ft.amap[mi][i][cols] = 0; + } + } else { + // we have to deal one case: + // expand x, shrink x, expand y -> + // now new allocated lines will have small x(col) instead of mcol. + // the solution is to modify mcols here, or change the malloc above + // to max(ft.mcols, cols). + ft.mcols = cols; + } + } + + // adjusts dirty and display map. + // no need to initialize anyway. + if (cols > ft.mcols) + { + ft.dmap = (ftchar*) realloc(ft.dmap, + (cols+1) * sizeof(ftchar)); + ft.dcmap = (ftchar*) realloc(ft.dcmap, + (cols+1) * sizeof(ftchar)); + } + + // do mrows/mcols assignment here, because we had 2 maps running loop above. + if (cols > ft.mcols) ft.mcols = cols; + if (rows > ft.mrows) ft.mrows = rows; + dirty = 1; + } + + // clear new exposed buffer after resized + // because we will redawwin(), so need to change front buffer only. + for (i = ft.rows; i < rows; i++) + { + memset(FTCMAP[i], FTCHAR_ERASE, + (cols) * sizeof(ftchar)); + memset(FTAMAP[i], FTATTR_ERASE, + (cols) * sizeof(ftattr)); + } + if (cols > ft.cols) + { + for (i = 0; i < ft.rows; i++) + { + memset(FTCMAP[i]+ft.cols, FTCHAR_ERASE, + (cols-ft.cols) * sizeof(ftchar)); + memset(FTAMAP[i]+ft.cols, FTATTR_ERASE, + (cols-ft.cols) * sizeof(ftattr)); + } + } + + if (ft.rows != rows || ft.cols != cols) + { + ft.rows = rows; + ft.cols = cols; + redrawwin(); + } + + ft.x = ranged(ft.x, 0, ft.cols-1); + ft.y = ranged(ft.y, 0, ft.rows-1); + + return dirty; } // attributes @@ -571,27 +571,27 @@ resizeterm(int rows, int cols) ftattr attrget(void) { - return ft.attr; + return ft.attr; } void attrset(ftattr attr) { - ft.attr = attr; + ft.attr = attr; } void attrsetfg(ftattr attr) { - ft.attr &= (~FTATTR_FGMASK); - ft.attr |= ((attr & FTATTR_FGMASK) << FTATTR_FGSHIFT); + ft.attr &= (~FTATTR_FGMASK); + ft.attr |= ((attr & FTATTR_FGMASK) << FTATTR_FGSHIFT); } void attrsetbg(ftattr attr) { - ft.attr &= (~FTATTR_BGMASK); - ft.attr |= ((attr & FTATTR_FGMASK) << FTATTR_BGSHIFT); + ft.attr &= (~FTATTR_BGMASK); + ft.attr |= ((attr & FTATTR_FGMASK) << FTATTR_BGSHIFT); } // clear @@ -599,119 +599,119 @@ attrsetbg(ftattr attr) void clrscr(void) { - int r; - for (r = 0; r < ft.rows; r++) - memset(FTCMAP[r], FTCHAR_ERASE, ft.cols * sizeof(ftchar)); - for (r = 0; r < ft.rows; r++) - memset(FTAMAP[r], FTATTR_ERASE, ft.cols * sizeof(ftattr)); - fterm_markdirty(); + int r; + for (r = 0; r < ft.rows; r++) + memset(FTCMAP[r], FTCHAR_ERASE, ft.cols * sizeof(ftchar)); + for (r = 0; r < ft.rows; r++) + memset(FTAMAP[r], FTATTR_ERASE, ft.cols * sizeof(ftattr)); + fterm_markdirty(); } void clear(void) { - clrscr(); - move(0,0); + clrscr(); + move(0,0); } void clrtoeol(void) { - ft.x = ranged(ft.x, 0, ft.cols-1); - ft.y = ranged(ft.y, 0, ft.rows-1); - memset(FTPC, FTCHAR_ERASE, ft.cols - ft.x); - memset(FTPA, FTATTR_ERASE, ft.cols - ft.x); - fterm_markdirty(); + ft.x = ranged(ft.x, 0, ft.cols-1); + ft.y = ranged(ft.y, 0, ft.rows-1); + memset(FTPC, FTCHAR_ERASE, ft.cols - ft.x); + memset(FTPA, FTATTR_ERASE, ft.cols - ft.x); + fterm_markdirty(); } void clrtobeg(void) { - ft.x = ranged(ft.x, 0, ft.cols-1); - ft.y = ranged(ft.y, 0, ft.rows-1); - memset(FTCROW, FTCHAR_ERASE, ft.x+1); - memset(FTAROW, FTATTR_ERASE, ft.x+1); - fterm_markdirty(); + ft.x = ranged(ft.x, 0, ft.cols-1); + ft.y = ranged(ft.y, 0, ft.rows-1); + memset(FTCROW, FTCHAR_ERASE, ft.x+1); + memset(FTAROW, FTATTR_ERASE, ft.x+1); + fterm_markdirty(); } void clrcurrline(void) { - ft.y = ranged(ft.y, 0, ft.rows-1); - memset(FTCROW, FTCHAR_ERASE, ft.cols); - memset(FTAROW, FTATTR_ERASE, ft.cols); - fterm_markdirty(); + ft.y = ranged(ft.y, 0, ft.rows-1); + memset(FTCROW, FTCHAR_ERASE, ft.cols); + memset(FTAROW, FTATTR_ERASE, ft.cols); + fterm_markdirty(); } void clrtoln(int line) { - if (line <= ft.y) - return; - clrregion(ft.y, line-1); + if (line <= ft.y) + return; + clrregion(ft.y, line-1); } void clrregion(int r1, int r2) { - // bi-direction - if (r1 > r2) - { - int r = r1; - r1 = r2; r2 = r; - } + // bi-direction + if (r1 > r2) + { + int r = r1; + r1 = r2; r2 = r; + } - // check r1, r2 range - r1 = ranged(r1, 0, ft.rows-1); - r2 = ranged(r2, 0, ft.rows-1); + // check r1, r2 range + r1 = ranged(r1, 0, ft.rows-1); + r2 = ranged(r2, 0, ft.rows-1); - for (; r1 <= r2; r1++) - { - memset(FTCMAP[r1], FTCHAR_ERASE, ft.cols); - memset(FTAMAP[r1], FTATTR_ERASE, ft.cols); - } - fterm_markdirty(); + for (; r1 <= r2; r1++) + { + memset(FTCMAP[r1], FTCHAR_ERASE, ft.cols); + memset(FTAMAP[r1], FTATTR_ERASE, ft.cols); + } + fterm_markdirty(); } void clrtobot(void) { - clrtoeol(); - clrregion(ft.y+1, ft.rows-1); + clrtoeol(); + clrregion(ft.y+1, ft.rows-1); } void clrtohome(void) { - clrtobeg(); - clrregion(ft.y-1, 0); + clrtobeg(); + clrregion(ft.y-1, 0); } -void newwin (int nlines, int ncols, int y, int x) +void newwin (int nlines, int ncols, int y, int x) { - int oy, ox; - // check range - - x = ranged(x, 0, ft.cols-1); - y = ranged(y, 0, ft.rows-1); - ncols = ranged(x+ncols-1, x, ft.cols-1); - nlines = ranged(y+nlines-1, y, ft.rows-1); - ncols = ncols - x + 1; - nlines= nlines- y + 1; + int oy, ox; + // check range + + x = ranged(x, 0, ft.cols-1); + y = ranged(y, 0, ft.rows-1); + ncols = ranged(x+ncols-1, x, ft.cols-1); + nlines = ranged(y+nlines-1, y, ft.rows-1); + ncols = ncols - x + 1; + nlines= nlines- y + 1; - if (nlines <= 0 || ncols <= 0) - return; - getyx(&oy, &ox); + if (nlines <= 0 || ncols <= 0) + return; + getyx(&oy, &ox); while (nlines-- > 0) { - move(y++, x); - // use prepare_str to erase character - fterm_prepare_str(ncols); - // memset(FTAMAP[y]+x, ft.attr, ncols); - // memset(FTCMAP[y]+x, FTCHAR_ERASE, ncols); + move(y++, x); + // use prepare_str to erase character + fterm_prepare_str(ncols); + // memset(FTAMAP[y]+x, ft.attr, ncols); + // memset(FTCMAP[y]+x, FTCHAR_ERASE, ncols); } - move(oy, ox); + move(oy, ox); } // dirty and flushing @@ -719,292 +719,292 @@ void newwin (int nlines, int ncols, int y, int x) void redrawwin(void) { - // flip page - fterm_flippage(); - clrscr(); + // flip page + fterm_flippage(); + clrscr(); - // clear raw terminal - fterm_rawclear(); + // clear raw terminal + fterm_rawclear(); - // flip page again - fterm_flippage(); + // flip page again + fterm_flippage(); - // mark for refresh. - fterm_markdirty(); + // mark for refresh. + fterm_markdirty(); } -int +int typeahead(int fd) { - switch(fd) - { - case TYPEAHEAD_NONE: - ft.typeahead = 0; - break; - case TYPEAHEAD_STDIN: - ft.typeahead = 1; - break; - default: // shall never reach here - assert(NULL); - break; - } - return 0; + switch(fd) + { + case TYPEAHEAD_NONE: + ft.typeahead = 0; + break; + case TYPEAHEAD_STDIN: + ft.typeahead = 1; + break; + default: // shall never reach here + assert(NULL); + break; + } + return 0; } void refresh(void) { - // prevent passive update - if(fterm_inbuf() && ft.typeahead) - return; - doupdate(); + // prevent passive update + if(fterm_inbuf() && ft.typeahead) + return; + doupdate(); } void doupdate(void) { - int y, x; - char touched = 0; + int y, x; + char touched = 0; - if (!ft.dirty) - { - fterm_rawcursor(); - return; - } + if (!ft.dirty) + { + fterm_rawcursor(); + return; + } #ifdef _WIN32 - assert(ft.rows == coordBufSize.Y); - assert(ft.cols == coordBufSize.X); - - for (y = 0; y < ft.rows; y++) - { - for (x = 0; x < ft.cols; x++) - { - WORD xAttr = FTAMAP[y][x], xxAttr; - // w32 attribute: bit swap (0,2) and (4, 6) - xxAttr = xAttr & 0xAA; - if (xAttr & 0x01) xxAttr |= 0x04; - if (xAttr & 0x04) xxAttr |= 0x01; - if (xAttr & 0x10) xxAttr |= 0x40; - if (xAttr & 0x40) xxAttr |= 0x10; - - winbuf[y*ft.cols + x].Attributes= xxAttr; - winbuf[y*ft.cols + x].Char.AsciiChar = FTCMAP[y][x]; - } - } - WriteConsoleOutputA(hStdout, winbuf, coordBufSize, coordBufCoord, &winrect); + assert(ft.rows == coordBufSize.Y); + assert(ft.cols == coordBufSize.X); + + for (y = 0; y < ft.rows; y++) + { + for (x = 0; x < ft.cols; x++) + { + WORD xAttr = FTAMAP[y][x], xxAttr; + // w32 attribute: bit swap (0,2) and (4, 6) + xxAttr = xAttr & 0xAA; + if (xAttr & 0x01) xxAttr |= 0x04; + if (xAttr & 0x04) xxAttr |= 0x01; + if (xAttr & 0x10) xxAttr |= 0x40; + if (xAttr & 0x40) xxAttr |= 0x10; + + winbuf[y*ft.cols + x].Attributes= xxAttr; + winbuf[y*ft.cols + x].Char.AsciiChar = FTCMAP[y][x]; + } + } + WriteConsoleOutputA(hStdout, winbuf, coordBufSize, coordBufCoord, &winrect); #else // !_WIN32 - // if scroll, do it first - if (ft.scroll) - fterm_rawscroll(ft.scroll); - - // calculate and optimize dirty - for (y = 0; y < ft.rows; y++) - { - int len = ft.cols, ds = 0, derase = 0; - char dbcs = 0, odbcs = 0; // 0: none, 1: lead, 2: tail - - // reset dirty and display map - memset(FTD, 0, ft.cols * sizeof(ftchar)); - memcpy(FTDC,FTCMAP[y], ft.cols * sizeof(ftchar)); - - // first run: character diff - for (x = 0; x < len; x++) - { - // build base dirty information - if (FTCMAP[y][x] != FTOCMAP[y][x]) - FTD[x] |= FTDIRTY_CHAR, ds++; - if (FTAMAP[y][x] != FTOAMAP[y][x]) - FTD[x] |= FTDIRTY_ATTR, ds++; - - // determine DBCS status - if (dbcs == 1) - { + // if scroll, do it first + if (ft.scroll) + fterm_rawscroll(ft.scroll); + + // calculate and optimize dirty + for (y = 0; y < ft.rows; y++) + { + int len = ft.cols, ds = 0, derase = 0; + char dbcs = 0, odbcs = 0; // 0: none, 1: lead, 2: tail + + // reset dirty and display map + memset(FTD, 0, ft.cols * sizeof(ftchar)); + memcpy(FTDC,FTCMAP[y], ft.cols * sizeof(ftchar)); + + // first run: character diff + for (x = 0; x < len; x++) + { + // build base dirty information + if (FTCMAP[y][x] != FTOCMAP[y][x]) + FTD[x] |= FTDIRTY_CHAR, ds++; + if (FTAMAP[y][x] != FTOAMAP[y][x]) + FTD[x] |= FTDIRTY_ATTR, ds++; + + // determine DBCS status + if (dbcs == 1) + { #ifdef FTCONF_PREVENT_INVALID_DBCS - switch(fterm_DBCS_Big5(FTCMAP[y][x-1], FTCMAP[y][x])) - { - case FTDBCS_SAFE: - // safe to print - FTD[x-1] &= ~FTDIRTY_INVALID_DBCS; - FTDC[x-1] = FTCMAP[y][x-1]; - break; - - case FTDBCS_UNSAFE: - // ok to print, but need to rawmove. - FTD[x-1] &= ~FTDIRTY_INVALID_DBCS; - FTDC[x-1] = FTCMAP[y][x-1]; - FTD[x-1] |= FTDIRTY_CHAR; - FTD[x] |= FTDIRTY_RAWMOVE; - break; - - case FTDBCS_INVALID: - // only SBCS safe characters can be print. - if (!FTDBCS_ISSBCSPRINT(FTCMAP[y][x])) - { - FTD[x] |= FTDIRTY_INVALID_DBCS; - FTDC[x] = FTCHAR_INVALID_DBCS; - } - break; - } + switch(fterm_DBCS_Big5(FTCMAP[y][x-1], FTCMAP[y][x])) + { + case FTDBCS_SAFE: + // safe to print + FTD[x-1] &= ~FTDIRTY_INVALID_DBCS; + FTDC[x-1] = FTCMAP[y][x-1]; + break; + + case FTDBCS_UNSAFE: + // ok to print, but need to rawmove. + FTD[x-1] &= ~FTDIRTY_INVALID_DBCS; + FTDC[x-1] = FTCMAP[y][x-1]; + FTD[x-1] |= FTDIRTY_CHAR; + FTD[x] |= FTDIRTY_RAWMOVE; + break; + + case FTDBCS_INVALID: + // only SBCS safe characters can be print. + if (!FTDBCS_ISSBCSPRINT(FTCMAP[y][x])) + { + FTD[x] |= FTDIRTY_INVALID_DBCS; + FTDC[x] = FTCHAR_INVALID_DBCS; + } + break; + } #endif // FTCONF_PREVENT_INVALID_DBCS - dbcs = 2; - // TAIL: dirty prev and me if any is dirty. - if (FTD[x] || FTD[x-1]) - { - FTD[x] |= FTDIRTY_DBCS; - FTD[x-1]|= FTDIRTY_CHAR; - } - } - else if (FTDBCS_ISLEAD(FTCMAP[y][x])) - { - // LEAD: clear dirty when tail was found. - dbcs = 1; + dbcs = 2; + // TAIL: dirty prev and me if any is dirty. + if (FTD[x] || FTD[x-1]) + { + FTD[x] |= FTDIRTY_DBCS; + FTD[x-1]|= FTDIRTY_CHAR; + } + } + else if (FTDBCS_ISLEAD(FTCMAP[y][x])) + { + // LEAD: clear dirty when tail was found. + dbcs = 1; #ifdef FTCONF_PREVENT_INVALID_DBCS - FTD[x] |= FTDIRTY_INVALID_DBCS; - FTDC[x] = FTCHAR_INVALID_DBCS; + FTD[x] |= FTDIRTY_INVALID_DBCS; + FTDC[x] = FTCHAR_INVALID_DBCS; #endif // FTCONF_PREVENT_INVALID_DBCS - } - else - { - // NON-DBCS - dbcs = 0; - } - - if (odbcs == 1) - { - // TAIL: dirty prev and me if any is dirty. - odbcs = 2; - if (FTD[x] || FTD[x-1]) - { - FTD[x] |= FTDIRTY_CHAR; - FTD[x-1]|= FTDIRTY_CHAR; - } - } - else if (FTDBCS_ISLEAD(FTOCMAP[y][x])) - { - // LEAD: dirty next? - odbcs = 1; - } - else - { - odbcs = 0; - } - } + } + else + { + // NON-DBCS + dbcs = 0; + } + + if (odbcs == 1) + { + // TAIL: dirty prev and me if any is dirty. + odbcs = 2; + if (FTD[x] || FTD[x-1]) + { + FTD[x] |= FTDIRTY_CHAR; + FTD[x-1]|= FTDIRTY_CHAR; + } + } + else if (FTDBCS_ISLEAD(FTOCMAP[y][x])) + { + // LEAD: dirty next? + odbcs = 1; + } + else + { + odbcs = 0; + } + } #ifndef DBG_SHOW_DIRTY - if (!ds) - continue; + if (!ds) + continue; #endif // DBG_SHOW_DIRTY - // Optimization: calculate ERASE section - // TODO ERASE takes 3 bytes (ESC [ K), so enable only if derase >= 3? - // TODO ERASE then print can avoid lots of space, optimize in future. - for (x = ft.cols - 1; x >= 0; x--) - if (FTCMAP[y][x] != FTCHAR_ERASE || - FTAMAP[y][x] != FTATTR_ERASE) - break; - else if (FTD[x]) - derase++; + // Optimization: calculate ERASE section + // TODO ERASE takes 3 bytes (ESC [ K), so enable only if derase >= 3? + // TODO ERASE then print can avoid lots of space, optimize in future. + for (x = ft.cols - 1; x >= 0; x--) + if (FTCMAP[y][x] != FTCHAR_ERASE || + FTAMAP[y][x] != FTATTR_ERASE) + break; + else if (FTD[x]) + derase++; - len = x+1; + len = x+1; - for (x = 0; x < len; x++) - { + for (x = 0; x < len; x++) + { #ifndef DBG_SHOW_DIRTY - if (!FTD[x]) - continue; + if (!FTD[x]) + continue; #endif // !DBG_SHOW_DIRTY - // Optimization: re-print or move? + // Optimization: re-print or move? #ifndef DBG_DISABLE_REPRINT - while (ft.ry == y && x > ft.rx && abs(x-ft.rx) < FTMV_COST) - { - int i; - // Special case: we may be in position of DBCS tail... - // Inside a refresh() loop, this will never happen. - // However it may occur for the first print entering refresh. - // So enable only space if this is the first run (!touched). - - // if we don't need to change attributes, - // just print remaining characters - for (i = ft.rx; i < x; i++) - { - // if same attribute, simply accept. - if (FTAMAP[y][i] == ft.rattr && touched) - continue; - // XXX spaces may accept (BG=rBG), - // but that will also change cached attribute. - if (!FTCHAR_ISBLANK(FTCMAP[y][i])) - break; - if (FTATTR_GETBG(FTAMAP[y][i]) != FTATTR_GETBG(ft.rattr)) - break; - } - if (i != x) - break; - - // safe to print all! - // printf("[re-print %d chars]", i-ft.rx); - + while (ft.ry == y && x > ft.rx && abs(x-ft.rx) < FTMV_COST) + { + int i; + // Special case: we may be in position of DBCS tail... + // Inside a refresh() loop, this will never happen. + // However it may occur for the first print entering refresh. + // So enable only space if this is the first run (!touched). + + // if we don't need to change attributes, + // just print remaining characters + for (i = ft.rx; i < x; i++) + { + // if same attribute, simply accept. + if (FTAMAP[y][i] == ft.rattr && touched) + continue; + // XXX spaces may accept (BG=rBG), + // but that will also change cached attribute. + if (!FTCHAR_ISBLANK(FTCMAP[y][i])) + break; + if (FTATTR_GETBG(FTAMAP[y][i]) != FTATTR_GETBG(ft.rattr)) + break; + } + if (i != x) + break; + + // safe to print all! + // printf("[re-print %d chars]", i-ft.rx); + #ifdef DBG_SHOW_REPRINT - // reverse to hint this is a re-print - fterm_rawattr(FTATTR_MAKE(0, 7) | FTATTR_BOLD); + // reverse to hint this is a re-print + fterm_rawattr(FTATTR_MAKE(0, 7) | FTATTR_BOLD); #endif // DBG_SHOW_REPRINT - for (i = ft.rx; i < x; i++) - { - fterm_rawc(FTDC[i]); - FTAMAP[y][i] = FTOAMAP[y][i]; // spaces may change attr... - ft.rx++; - } + for (i = ft.rx; i < x; i++) + { + fterm_rawc(FTDC[i]); + FTAMAP[y][i] = FTOAMAP[y][i]; // spaces may change attr... + ft.rx++; + } - break; - } + break; + } #endif // !DBG_DISABLE_REPRINT - if (y != ft.ry || x != ft.rx) - fterm_rawmove_opt(y, x); + if (y != ft.ry || x != ft.rx) + fterm_rawmove_opt(y, x); #ifdef DBCSAWARE - if ((FTD[x] & FTDIRTY_DBCS) && (FT_DBCS_NOINTRESC)) - { - // prevent changing attributes inside DBCS - } - else + if ((FTD[x] & FTDIRTY_DBCS) && (FT_DBCS_NOINTRESC)) + { + // prevent changing attributes inside DBCS + } + else #endif // DBCSAWARE #ifdef DBG_SHOW_DIRTY - fterm_rawattr(FTD[x] ? - (FTAMAP[y][x] | FTATTR_BOLD) : (FTAMAP[y][x] & ~FTATTR_BOLD)); + fterm_rawattr(FTD[x] ? + (FTAMAP[y][x] | FTATTR_BOLD) : (FTAMAP[y][x] & ~FTATTR_BOLD)); #else // !DBG_SHOW_DIRTY - fterm_rawattr(FTAMAP[y][x]); + fterm_rawattr(FTAMAP[y][x]); #endif // !DBG_SHOW_DIRTY - fterm_rawc(FTDC[x]); - ft.rx++; - touched = 1; - - if (FTD[x] & FTDIRTY_RAWMOVE) - { - fterm_rawcmd2(ft.ry+1, ft.rx+1, 1, 'H'); - } - } - - if (derase) - { - fterm_rawmove_opt(y, len); - fterm_rawclreol(); - } - } + fterm_rawc(FTDC[x]); + ft.rx++; + touched = 1; + + if (FTD[x] & FTDIRTY_RAWMOVE) + { + fterm_rawcmd2(ft.ry+1, ft.rx+1, 1, 'H'); + } + } + + if (derase) + { + fterm_rawmove_opt(y, len); + fterm_rawclreol(); + } + } #endif // !_WIN32 - // doing fterm_rawcursor() earlier to enable max display time - fterm_rawcursor(); - fterm_dupe2bk(); - ft.dirty = 0; + // doing fterm_rawcursor() earlier to enable max display time + fterm_rawcursor(); + fterm_dupe2bk(); + ft.dirty = 0; } // cursor management @@ -1012,26 +1012,26 @@ doupdate(void) void getyx(int *y, int *x) { - if (y) - *y = ft.y; - if (x) - *x = ft.x; + if (y) + *y = ft.y; + if (x) + *x = ft.x; } void getmaxyx(int *y, int *x) { - if (y) - *y = ft.rows; - if (x) - *x = ft.cols; + if (y) + *y = ft.rows; + if (x) + *x = ft.cols; } void move(int y, int x) { - ft.y = ranged(y, 0, ft.rows-1); - ft.x = ranged(x, 0, ft.cols-1); + ft.y = ranged(y, 0, ft.rows-1); + ft.x = ranged(x, 0, ft.cols-1); } // scrolling @@ -1039,1192 +1039,1192 @@ move(int y, int x) void scrl(int rows) { - if (!rows) - return; - if (rows > 0) - { - for (; rows > 0; rows--) - scroll(); - } else { - for (; rows < 0; rows++) - rscroll(); - } + if (!rows) + return; + if (rows > 0) + { + for (; rows > 0; rows--) + scroll(); + } else { + for (; rows < 0; rows++) + rscroll(); + } } void scroll() { - // scroll up - int y; - ftchar *c0 = FTCMAP[0], *oc0 = FTOCMAP[0]; - ftattr *a0 = FTAMAP[0], *oa0 = FTOAMAP[0]; - - // prevent mixing buffered scroll up+down - if (ft.scroll < 0) - fterm_rawscroll(ft.scroll); - - // smart scroll: move pointers - for (y = 0; y < ft.rows-1; y++) - { - FTCMAP[y] = FTCMAP[y+1]; - FTAMAP[y] = FTAMAP[y+1]; - FTOCMAP[y]= FTOCMAP[y+1]; - FTOAMAP[y]= FTOAMAP[y+1]; - } - FTCMAP[y] = c0; - FTAMAP[y] = a0; - FTOCMAP[y]= oc0; - FTOAMAP[y]= oa0; - - // XXX also clear backup buffer - // must carefully consider if up then down scrolling. - fterm_flippage(); - clrregion(ft.rows-1, ft.rows-1); - fterm_flippage(); - clrregion(ft.rows-1, ft.rows-1); - - ft.scroll ++; - // fterm_markdirty(); // should be already dirty + // scroll up + int y; + ftchar *c0 = FTCMAP[0], *oc0 = FTOCMAP[0]; + ftattr *a0 = FTAMAP[0], *oa0 = FTOAMAP[0]; + + // prevent mixing buffered scroll up+down + if (ft.scroll < 0) + fterm_rawscroll(ft.scroll); + + // smart scroll: move pointers + for (y = 0; y < ft.rows-1; y++) + { + FTCMAP[y] = FTCMAP[y+1]; + FTAMAP[y] = FTAMAP[y+1]; + FTOCMAP[y]= FTOCMAP[y+1]; + FTOAMAP[y]= FTOAMAP[y+1]; + } + FTCMAP[y] = c0; + FTAMAP[y] = a0; + FTOCMAP[y]= oc0; + FTOAMAP[y]= oa0; + + // XXX also clear backup buffer + // must carefully consider if up then down scrolling. + fterm_flippage(); + clrregion(ft.rows-1, ft.rows-1); + fterm_flippage(); + clrregion(ft.rows-1, ft.rows-1); + + ft.scroll ++; + // fterm_markdirty(); // should be already dirty } void rscroll() { - // scroll down - int y; - ftchar *c0 = FTCMAP[ft.rows -1], *oc0 = FTOCMAP[ft.rows -1]; - ftattr *a0 = FTAMAP[ft.rows -1], *oa0 = FTOAMAP[ft.rows -1]; - - // prevent mixing buffered scroll up+down - if (ft.scroll > 0) - fterm_rawscroll(ft.scroll); - - // smart scroll: move pointers - for (y = ft.rows -1; y > 0; y--) - { - FTCMAP[y] = FTCMAP[y-1]; - FTAMAP[y] = FTAMAP[y-1]; - FTOCMAP[y]= FTOCMAP[y-1]; - FTOAMAP[y]= FTOAMAP[y-1]; - } - FTCMAP[y] = c0; - FTAMAP[y] = a0; - FTOCMAP[y]= oc0; - FTOAMAP[y]= oa0; - - // XXX also clear backup buffer - // must carefully consider if up then down scrolling. - fterm_flippage(); - clrregion(0, 0); - fterm_flippage(); - clrregion(0, 0); - - ft.scroll --; - // fterm_markdirty(); // should be already dirty + // scroll down + int y; + ftchar *c0 = FTCMAP[ft.rows -1], *oc0 = FTOCMAP[ft.rows -1]; + ftattr *a0 = FTAMAP[ft.rows -1], *oa0 = FTOAMAP[ft.rows -1]; + + // prevent mixing buffered scroll up+down + if (ft.scroll > 0) + fterm_rawscroll(ft.scroll); + + // smart scroll: move pointers + for (y = ft.rows -1; y > 0; y--) + { + FTCMAP[y] = FTCMAP[y-1]; + FTAMAP[y] = FTAMAP[y-1]; + FTOCMAP[y]= FTOCMAP[y-1]; + FTOAMAP[y]= FTOAMAP[y-1]; + } + FTCMAP[y] = c0; + FTAMAP[y] = a0; + FTOCMAP[y]= oc0; + FTOAMAP[y]= oa0; + + // XXX also clear backup buffer + // must carefully consider if up then down scrolling. + fterm_flippage(); + clrregion(0, 0); + fterm_flippage(); + clrregion(0, 0); + + ft.scroll --; + // fterm_markdirty(); // should be already dirty } // output -void +void addch (unsigned char c) { - outc(c); + outc(c); } -void +void addstr (const char *s) { - outs(s); + outs(s); } void addnstr(const char *s, int n) { - outns(s, n); + outns(s, n); } void addstring(const char *s) { - outstr(s); + outstr(s); } -void +void outs(const char *s) { if (!s) - return; - while (*s) - outc(*s++); + return; + while (*s) + outc(*s++); } -void +void outns(const char *s, int n) { if (!s) - return; - while (*s && n-- > 0) - outc(*s++); + return; + while (*s && n-- > 0) + outc(*s++); } void outstr(const char *str) { - if (!str) - { - fterm_prepare_str(0); - return; - } + if (!str) + { + fterm_prepare_str(0); + return; + } - // calculate real length of str (stripping escapes) - // TODO only print by the returned size - - fterm_prepare_str(fterm_strdlen(str)); + // calculate real length of str (stripping escapes) + // TODO only print by the returned size + + fterm_prepare_str(fterm_strdlen(str)); - outs(str); + outs(str); - // maybe the source string itself is broken... - // basically this check should be done by clients, not term library. + // maybe the source string itself is broken... + // basically this check should be done by clients, not term library. #if 0 - { - int isdbcs = 0; - while (*str) - { - if (isdbcs == 1) isdbcs = 2; - else if (FTDBCS_ISLEAD(*str)) isdbcs = 1; - else isdbcs = 0; - str++; - } - - if (isdbcs == 1) // incomplete string! - outs("\b?"); - } + { + int isdbcs = 0; + while (*str) + { + if (isdbcs == 1) isdbcs = 2; + else if (FTDBCS_ISLEAD(*str)) isdbcs = 1; + else isdbcs = 0; + str++; + } + + if (isdbcs == 1) // incomplete string! + outs("\b?"); + } #endif } void outc(unsigned char c) { - // 0xFF is invalid for most cases (even DBCS), - if (c == 0xFF || c == 0x00) - return; - - fterm_markdirty(); - if (ft.szcmd) - { - // collecting commands - ft.cmd[ft.szcmd++] = c; - - if ((ft.szcmd == 2 && c == '[') || - (ANSI_IS_PARAM(c) && ft.szcmd < FTCMD_MAXLEN)) - return; - - // process as command - fterm_exec(); - ft.szcmd = 0; - } - else if (c == ESC_CHR) - { - // start of escaped commands - ft.cmd[ft.szcmd++] = c; - } - else if (c == '\t') - { - // tab: move by 8, and erase the moved range - int x = ft.x; - if (x % 8 == 0) - x += 8; - else - x += (8-(x%8)); - x = ranged(x, 0, ft.cols-1); - // erase the characters between - if (x > ft.x) - { - memset(FTCROW+ft.x, FTCHAR_ERASE, x - ft.x); - memset(FTAROW+ft.x, ft.attr, x-ft.x); - } - ft.x = x; - } - else if (c == '\b') - { - ft.x = ranged(ft.x-1, 0, ft.cols-1); - } - else if (c == '\r' || c == '\n') - { - // new line: cursor movement, and do not print anything - // XXX old screen.c also calls clrtoeol() for newlins. - clrtoeol(); - ft.x = 0; - ft.y ++; - while (ft.y >= ft.rows) - { - // XXX scroll at next dirty? - // screen.c ignored such scroll. - // scroll(); - ft.y --; - } - } - else if (iscntrl((unsigned char)c)) - { - // unknown control characters: ignore - } - else // normal characters - { - assert (ft.x >= 0 && ft.x < ft.cols); - - // normal characters - FTC = c; + // 0xFF is invalid for most cases (even DBCS), + if (c == 0xFF || c == 0x00) + return; + + fterm_markdirty(); + if (ft.szcmd) + { + // collecting commands + ft.cmd[ft.szcmd++] = c; + + if ((ft.szcmd == 2 && c == '[') || + (ANSI_IS_PARAM(c) && ft.szcmd < FTCMD_MAXLEN)) + return; + + // process as command + fterm_exec(); + ft.szcmd = 0; + } + else if (c == ESC_CHR) + { + // start of escaped commands + ft.cmd[ft.szcmd++] = c; + } + else if (c == '\t') + { + // tab: move by 8, and erase the moved range + int x = ft.x; + if (x % 8 == 0) + x += 8; + else + x += (8-(x%8)); + x = ranged(x, 0, ft.cols-1); + // erase the characters between + if (x > ft.x) + { + memset(FTCROW+ft.x, FTCHAR_ERASE, x - ft.x); + memset(FTAROW+ft.x, ft.attr, x-ft.x); + } + ft.x = x; + } + else if (c == '\b') + { + ft.x = ranged(ft.x-1, 0, ft.cols-1); + } + else if (c == '\r' || c == '\n') + { + // new line: cursor movement, and do not print anything + // XXX old screen.c also calls clrtoeol() for newlins. + clrtoeol(); + ft.x = 0; + ft.y ++; + while (ft.y >= ft.rows) + { + // XXX scroll at next dirty? + // screen.c ignored such scroll. + // scroll(); + ft.y --; + } + } + else if (iscntrl((unsigned char)c)) + { + // unknown control characters: ignore + } + else // normal characters + { + assert (ft.x >= 0 && ft.x < ft.cols); + + // normal characters + FTC = c; #ifdef FTATTR_TRANSPARENT - if (ft.attr != FTATTR_TRANSPARENT) + if (ft.attr != FTATTR_TRANSPARENT) #endif // FTATTR_TRANSPARENT - FTA = ft.attr; - - ft.x++; - // XXX allow x == ft.cols? - if (ft.x >= ft.cols) - { - ft.x = 0; - ft.y ++; - while (ft.y >= ft.rows) - { - // XXX scroll at next dirty? - // screen.c ignored such scroll. - // scroll(); - ft.y --; - } - } - } + FTA = ft.attr; + + ft.x++; + // XXX allow x == ft.cols? + if (ft.x >= ft.cols) + { + ft.x = 0; + ft.y ++; + while (ft.y >= ft.rows) + { + // XXX scroll at next dirty? + // screen.c ignored such scroll. + // scroll(); + ft.y --; + } + } + } } // readback -int -instr (char *str) -{ - int x = ft.cols -1; - *str = 0; - if (ft.y < 0 || ft.y >= ft.rows || ft.x < 0 || ft.x >= ft.cols) - return 0; - - // determine stopping location - while (x >= ft.x && FTCROW[x] == FTCHAR_ERASE) - x--; - if (x < ft.x) return 0; - x = x - ft.x + 1; - memcpy(str, FTCROW+ft.x, x); - str[x] = 0; - return x; -} - -int -innstr (char *str, int n) -{ - int on = n; - int x = ranged(ft.x + n-1, 0, ft.cols-1); - *str = 0; - n = x - ft.x+1; - if (on < 1 || ft.y < 0 || ft.y >= ft.rows || ft.x < 0 || ft.x >= ft.cols) - return 0; - - // determine stopping location - while (x >= ft.x && FTCROW[x] == FTCHAR_ERASE) - x--; - if (x < ft.x) return 0; - n = x - ft.x + 1; - if (n >= on) n = on-1; - memcpy(str, FTCROW+ft.x, n); - str[n] = 0; - return n; -} - -int -inansistr (char *str, int n) -{ - int x = ft.cols -1, i = 0, szTrail = 0; - char *ostr = str; - char cmd[FTATTR_MINCMD*2] = ""; - - ftattr a = FTATTR_DEFAULT; - *str = 0; - if (ft.y < 0 || ft.y >= ft.rows || ft.x < 0 || ft.x >= ft.cols) - return 0; - - if (n < 1) - return 0; - n--; // preserve last zero - - // determine stopping location - while (x >= ft.x && FTCROW[x] == FTCHAR_ERASE && FTAROW[x] == FTATTR_ERASE) - x--; - - // retrieve [rt.x, x] - if (x < ft.x) return 0; - - // preserve some bytes if last attribute is not FTATTR_DEFAULT - for (i = ft.x; n > szTrail && i <= x; i++) - { - *str = 0; - - if (a != FTAROW[i]) - { - fterm_chattr(cmd, a, FTAROW[i]); - a = FTAROW[i]; - - if (a != FTATTR_DEFAULT) - szTrail = 3; // ESC [ m - else - szTrail = 0; - - if (strlen(cmd) >= n-szTrail) - break; - - strcpy(str, cmd); - n -= strlen(cmd); - str += strlen(cmd); - } - - // n should > szTrail - *str ++ = FTCROW[i]; - n--; - } - - if (szTrail && n >= szTrail) - { - *str++ = ESC_CHR; *str++ = '['; *str++ = 'm'; - } - - *str = 0; - return (str - ostr); +int +instr (char *str) +{ + int x = ft.cols -1; + *str = 0; + if (ft.y < 0 || ft.y >= ft.rows || ft.x < 0 || ft.x >= ft.cols) + return 0; + + // determine stopping location + while (x >= ft.x && FTCROW[x] == FTCHAR_ERASE) + x--; + if (x < ft.x) return 0; + x = x - ft.x + 1; + memcpy(str, FTCROW+ft.x, x); + str[x] = 0; + return x; +} + +int +innstr (char *str, int n) +{ + int on = n; + int x = ranged(ft.x + n-1, 0, ft.cols-1); + *str = 0; + n = x - ft.x+1; + if (on < 1 || ft.y < 0 || ft.y >= ft.rows || ft.x < 0 || ft.x >= ft.cols) + return 0; + + // determine stopping location + while (x >= ft.x && FTCROW[x] == FTCHAR_ERASE) + x--; + if (x < ft.x) return 0; + n = x - ft.x + 1; + if (n >= on) n = on-1; + memcpy(str, FTCROW+ft.x, n); + str[n] = 0; + return n; +} + +int +inansistr (char *str, int n) +{ + int x = ft.cols -1, i = 0, szTrail = 0; + char *ostr = str; + char cmd[FTATTR_MINCMD*2] = ""; + + ftattr a = FTATTR_DEFAULT; + *str = 0; + if (ft.y < 0 || ft.y >= ft.rows || ft.x < 0 || ft.x >= ft.cols) + return 0; + + if (n < 1) + return 0; + n--; // preserve last zero + + // determine stopping location + while (x >= ft.x && FTCROW[x] == FTCHAR_ERASE && FTAROW[x] == FTATTR_ERASE) + x--; + + // retrieve [rt.x, x] + if (x < ft.x) return 0; + + // preserve some bytes if last attribute is not FTATTR_DEFAULT + for (i = ft.x; n > szTrail && i <= x; i++) + { + *str = 0; + + if (a != FTAROW[i]) + { + fterm_chattr(cmd, a, FTAROW[i]); + a = FTAROW[i]; + + if (a != FTATTR_DEFAULT) + szTrail = 3; // ESC [ m + else + szTrail = 0; + + if (strlen(cmd) >= n-szTrail) + break; + + strcpy(str, cmd); + n -= strlen(cmd); + str += strlen(cmd); + } + + // n should > szTrail + *str ++ = FTCROW[i]; + n--; + } + + if (szTrail && n >= szTrail) + { + *str++ = ESC_CHR; *str++ = '['; *str++ = 'm'; + } + + *str = 0; + return (str - ostr); } // internal core of piaip's flat-term -void +void fterm_flippage (void) { - // we have only 2 pages now. - ft.mi = 1 - ft.mi; + // we have only 2 pages now. + ft.mi = 1 - ft.mi; } #ifndef fterm_markdirty void fterm_markdirty (void) { - ft.dirty = 1; + ft.dirty = 1; } #endif void fterm_dupe2bk(void) { - int r = 0; - - for (r = 0; r < ft.rows; r++) - { - memcpy(FTOCMAP[r], FTCMAP[r], ft.cols * sizeof(ftchar)); - memcpy(FTOAMAP[r], FTAMAP[r], ft.cols * sizeof(ftattr)); - } + int r = 0; + + for (r = 0; r < ft.rows; r++) + { + memcpy(FTOCMAP[r], FTCMAP[r], ft.cols * sizeof(ftchar)); + memcpy(FTOAMAP[r], FTAMAP[r], ft.cols * sizeof(ftattr)); + } } int fterm_DBCS_Big5(unsigned char c1, unsigned char c2) { - // ref: http://www.cns11643.gov.tw/web/word/big5/index.html - // High byte: 0xA1-0xFE, 0x8E-0xA0, 0x81-0x8D - // Low byte: 0x40-0x7E, 0xA1-0xFE - // C1: 0x80-0x9F - if (FTDBCS_ISBADLEAD(c1)) - return FTDBCS_INVALID; - if (!FTDBCS_ISTAIL(c2)) - return FTDBCS_INVALID; - if (c1 >= 0x80 && c1 <= 0x9F) - return FTDBCS_UNSAFE; - return FTDBCS_SAFE; + // ref: http://www.cns11643.gov.tw/web/word/big5/index.html + // High byte: 0xA1-0xFE, 0x8E-0xA0, 0x81-0x8D + // Low byte: 0x40-0x7E, 0xA1-0xFE + // C1: 0x80-0x9F + if (FTDBCS_ISBADLEAD(c1)) + return FTDBCS_INVALID; + if (!FTDBCS_ISTAIL(c2)) + return FTDBCS_INVALID; + if (c1 >= 0x80 && c1 <= 0x9F) + return FTDBCS_UNSAFE; + return FTDBCS_SAFE; } int fterm_prepare_str(int len) { - // clear and make (cursor, +len) as DBCS-ready. - int x = ranged(ft.x, 0, ft.cols-1); - int y = ranged(ft.y, 0, ft.rows-1); - int dbcs = 0, sdbcs = 0; - - // TODO what if x+len is outside range? - - // check if (x,y) is in valid range - if (x != ft.x || y != ft.y) - return -1; - - len = ranged(x+len, x, ft.cols); - - for (x = 0; x < len; x++) - { - // determine DBCS status - if (dbcs == 1) - dbcs = 2; // TAIL - else if (FTDBCS_ISLEAD(FTCROW[x])) - dbcs = 1; // LEAD - else - dbcs = 0; - if (x == ft.x) sdbcs = dbcs; - } - - x = ft.x; - // fix start and end - if(sdbcs == 2 && x > 0) // TAIL, remove word - x--; - if (dbcs == 1 && len < ft.cols) // LEAD, remove word - len ++; - len = ranged(len, 0, ft.cols); - len -= x; - if (len < 0) len = 0; - - memset(FTCROW + x, FTCHAR_ERASE, len); - memset(FTAROW + x, ft.attr, len); - return len; -} - - -void + // clear and make (cursor, +len) as DBCS-ready. + int x = ranged(ft.x, 0, ft.cols-1); + int y = ranged(ft.y, 0, ft.rows-1); + int dbcs = 0, sdbcs = 0; + + // TODO what if x+len is outside range? + + // check if (x,y) is in valid range + if (x != ft.x || y != ft.y) + return -1; + + len = ranged(x+len, x, ft.cols); + + for (x = 0; x < len; x++) + { + // determine DBCS status + if (dbcs == 1) + dbcs = 2; // TAIL + else if (FTDBCS_ISLEAD(FTCROW[x])) + dbcs = 1; // LEAD + else + dbcs = 0; + if (x == ft.x) sdbcs = dbcs; + } + + x = ft.x; + // fix start and end + if(sdbcs == 2 && x > 0) // TAIL, remove word + x--; + if (dbcs == 1 && len < ft.cols) // LEAD, remove word + len ++; + len = ranged(len, 0, ft.cols); + len -= x; + if (len < 0) len = 0; + + memset(FTCROW + x, FTCHAR_ERASE, len); + memset(FTAROW + x, ft.attr, len); + return len; +} + + +void fterm_exec(void) { - ftchar cmd = ft.cmd[ft.szcmd-1]; - char *p = (char*)ft.cmd + 2; // ESC [ - int n = -1, x = -1, y; - - ft.cmd[ft.szcmd] = 0; - - if (isdigit(*p)) - { - n = atoi(p); - - while (*p && isdigit(*p)) - p++; - - if (*p == ';') - p++; - // p points to next param now - } - - switch(cmd) - { - // Cursor Movement - - case 'A': // CUU: CSI n A - case 'B': // CUD: CSI n B - case 'C': // CUF: CSI n C - case 'D': // CUB: CSI n D - // Moves the cursor n (default 1) cells in the given direction. - // If the cursor is already at the edge of the screen, this has no effect. - if (n < 1) - n = 1; - getyx(&y, &x); - if (cmd == 'A') { y -= n; } - else if (cmd == 'B') { y += n; } - else if (cmd == 'C') { x += n; } - else if (cmd == 'D') { x -= n; } - move(y, x); - break; - - case 'E': // CNL: CSI n E - case 'F': // CPL: CSI n F - // Moves cursor to beginning of the line - // n (default 1) lines up/down (next/previous line). - if (n < 1) - n = 1; - getyx(&y, &x); - if (cmd == 'E') { y -= n; } - else if (cmd == 'F') { y += n; } - move(y, 0); - break; - - case 'G': // CHA: CSI n G - // Moves the cursor to column n. - if (n < 1) - n = 1; - getyx(&y, &x); - move(y, n-1); - break; - - case 'H': // CUP: CSI n ; m H - case 'f': // HVP: CSI n ; m f - // Moves the cursor to row n, column m. - // The values are 1-based, and default to 1 (top left corner) if omitted. - // A sequence such as CSI ;5H is a synonym for CSI 1;5H as well as - // CSI 17;H is the same as CSI 17H and CSI 17;1H - y = n; - if (y >= 0 && isdigit(*p)) - x = atoi((char*)p); - if (y < 0) y = 1; - if (x < 0) x = 1; - move(y-1, x-1); - break; - - // Clear - - case 'J': // ED: CSI n J - // Clears part of the screen. - // If n is zero (or missing), clear from cursor to end of screen. - // If n is one, clear from cursor to beginning of the screen. - // If n is two, clear entire screen - if (n == 0 || n < 0) - clrtobot(); - else if (n == 1) - clrtohome(); - else if (n == 2) - { - clrregion(0, ft.rows-1); - } - break; - - case 'K': // EL: CSI n K - // Erases part of the line. - // If n is zero (or missing), clear from cursor to the end of the line. - // If n is one, clear from cursor to beginning of the line. - // If n is two, clear entire line. Cursor position does not change. - if (n == 0 || n < 0) - clrtoeol(); - else if (n == 1) - clrtobeg(); - else if (n == 2) - clrcurrline(); - break; - - case 's': // SCP: CSI s - // Saves the cursor position. - getyx(&ft.sy, &ft.sx); - break; - - case 'u': // RCP: CSI u - // Restores the cursor position. - move(ft.sy, ft.sx); - break; - - case 'S': // SU: CSI n S - // Scroll whole page up by n (default 1) lines. - // New lines are added at the bottom. - if (n < 1) - n = 1; - scrl(n); - break; - - case 'T': // SD: CSI n T - // Scroll whole page down by n (default 1) lines. - // New lines are added at the top. - if (n < 1) - n = 1; - scrl(-n); - break; - - case 'm': // SGR: CSI n [;k] m - // Sets SGR (Select Graphic Rendition) parameters. - // After CSI can be zero or more parameters separated with ;. - // With no parameters, CSI m is treated as CSI 0 m (reset / normal), - // which is typical of most of the ANSI codes. - // --------------------------------------------------------- - // SGR implementation: - // SGR 0 (reset/normal) is supported. - // SGR 1 (intensity: bold) is supported. - // SGR 2 (intensity: faint) is not supported. - // SGR 3 (italic: on) is not supported. (converted to inverse?) - // SGR 4 (underline: single) is not supported. - // SGR 5 (blink: slow) is supported. - // SGR 6 (blink: rapid) is converted to (blink: slow) - // SGR 7 (image: negative) is partially supported (not a really attribute). - // SGR 8 (conceal) is not supported. - // SGR 21(underline: double) is not supported. - // SGR 22(intensity: normal) is supported. - // SGR 24(underline: none) is not supported. - // SGR 25(blink: off) is supported. - // SGR 27(image: positive) is not supported. - // SGR 28(reveal) is not supported. - // SGR 30-37 (FG) is supported. - // SGR 39 (FG-reset) is supported. - // SGR 40-47 (BG) is supported. - // SGR 49 (BG-reset) is supported. - if (n == -1) // first param - n = 0; - while (n > -1) - { - if (n >= 30 && n <= 37) - { - // set foreground - attrsetfg(n - 30); - } - else if (n >= 40 && n <= 47) - { - // set background - attrsetbg(n - 40); - } - else switch(n) - { - case 0: - attrset(FTATTR_DEFAULT); - break; - case 1: - attrset(attrget() | FTATTR_BOLD); - break; - case 22: - attrset(attrget() & ~FTATTR_BOLD); - break; - case 5: - case 6: - attrset(attrget() | FTATTR_BLINK); - break; - case 25: - attrset(attrget() & ~FTATTR_BLINK); - break; - case 3: - case 7: - { - ftattr a = attrget(); - attrsetfg(FTATTR_GETBG(a)); - attrsetbg(FTATTR_GETFG(a)); - } - break; - case 39: - attrsetfg(FTATTR_DEFAULT_FG); - break; - case 49: - attrsetbg(FTATTR_DEFAULT_BG); - break; - } - - // parse next command - n = -1; - if (*p == ';') - { - n = 0; - p++; - } - else if (isdigit(*p)) - { - n = atoi(p); - while (isdigit(*p)) p++; - if (*p == ';') - p++; - } - } - break; - - default: // unknown command. - break; - } + ftchar cmd = ft.cmd[ft.szcmd-1]; + char *p = (char*)ft.cmd + 2; // ESC [ + int n = -1, x = -1, y; + + ft.cmd[ft.szcmd] = 0; + + if (isdigit(*p)) + { + n = atoi(p); + + while (*p && isdigit(*p)) + p++; + + if (*p == ';') + p++; + // p points to next param now + } + + switch(cmd) + { + // Cursor Movement + + case 'A': // CUU: CSI n A + case 'B': // CUD: CSI n B + case 'C': // CUF: CSI n C + case 'D': // CUB: CSI n D + // Moves the cursor n (default 1) cells in the given direction. + // If the cursor is already at the edge of the screen, this has no effect. + if (n < 1) + n = 1; + getyx(&y, &x); + if (cmd == 'A') { y -= n; } + else if (cmd == 'B') { y += n; } + else if (cmd == 'C') { x += n; } + else if (cmd == 'D') { x -= n; } + move(y, x); + break; + + case 'E': // CNL: CSI n E + case 'F': // CPL: CSI n F + // Moves cursor to beginning of the line + // n (default 1) lines up/down (next/previous line). + if (n < 1) + n = 1; + getyx(&y, &x); + if (cmd == 'E') { y -= n; } + else if (cmd == 'F') { y += n; } + move(y, 0); + break; + + case 'G': // CHA: CSI n G + // Moves the cursor to column n. + if (n < 1) + n = 1; + getyx(&y, &x); + move(y, n-1); + break; + + case 'H': // CUP: CSI n ; m H + case 'f': // HVP: CSI n ; m f + // Moves the cursor to row n, column m. + // The values are 1-based, and default to 1 (top left corner) if omitted. + // A sequence such as CSI ;5H is a synonym for CSI 1;5H as well as + // CSI 17;H is the same as CSI 17H and CSI 17;1H + y = n; + if (y >= 0 && isdigit(*p)) + x = atoi((char*)p); + if (y < 0) y = 1; + if (x < 0) x = 1; + move(y-1, x-1); + break; + + // Clear + + case 'J': // ED: CSI n J + // Clears part of the screen. + // If n is zero (or missing), clear from cursor to end of screen. + // If n is one, clear from cursor to beginning of the screen. + // If n is two, clear entire screen + if (n == 0 || n < 0) + clrtobot(); + else if (n == 1) + clrtohome(); + else if (n == 2) + { + clrregion(0, ft.rows-1); + } + break; + + case 'K': // EL: CSI n K + // Erases part of the line. + // If n is zero (or missing), clear from cursor to the end of the line. + // If n is one, clear from cursor to beginning of the line. + // If n is two, clear entire line. Cursor position does not change. + if (n == 0 || n < 0) + clrtoeol(); + else if (n == 1) + clrtobeg(); + else if (n == 2) + clrcurrline(); + break; + + case 's': // SCP: CSI s + // Saves the cursor position. + getyx(&ft.sy, &ft.sx); + break; + + case 'u': // RCP: CSI u + // Restores the cursor position. + move(ft.sy, ft.sx); + break; + + case 'S': // SU: CSI n S + // Scroll whole page up by n (default 1) lines. + // New lines are added at the bottom. + if (n < 1) + n = 1; + scrl(n); + break; + + case 'T': // SD: CSI n T + // Scroll whole page down by n (default 1) lines. + // New lines are added at the top. + if (n < 1) + n = 1; + scrl(-n); + break; + + case 'm': // SGR: CSI n [;k] m + // Sets SGR (Select Graphic Rendition) parameters. + // After CSI can be zero or more parameters separated with ;. + // With no parameters, CSI m is treated as CSI 0 m (reset / normal), + // which is typical of most of the ANSI codes. + // --------------------------------------------------------- + // SGR implementation: + // SGR 0 (reset/normal) is supported. + // SGR 1 (intensity: bold) is supported. + // SGR 2 (intensity: faint) is not supported. + // SGR 3 (italic: on) is not supported. (converted to inverse?) + // SGR 4 (underline: single) is not supported. + // SGR 5 (blink: slow) is supported. + // SGR 6 (blink: rapid) is converted to (blink: slow) + // SGR 7 (image: negative) is partially supported (not a really attribute). + // SGR 8 (conceal) is not supported. + // SGR 21(underline: double) is not supported. + // SGR 22(intensity: normal) is supported. + // SGR 24(underline: none) is not supported. + // SGR 25(blink: off) is supported. + // SGR 27(image: positive) is not supported. + // SGR 28(reveal) is not supported. + // SGR 30-37 (FG) is supported. + // SGR 39 (FG-reset) is supported. + // SGR 40-47 (BG) is supported. + // SGR 49 (BG-reset) is supported. + if (n == -1) // first param + n = 0; + while (n > -1) + { + if (n >= 30 && n <= 37) + { + // set foreground + attrsetfg(n - 30); + } + else if (n >= 40 && n <= 47) + { + // set background + attrsetbg(n - 40); + } + else switch(n) + { + case 0: + attrset(FTATTR_DEFAULT); + break; + case 1: + attrset(attrget() | FTATTR_BOLD); + break; + case 22: + attrset(attrget() & ~FTATTR_BOLD); + break; + case 5: + case 6: + attrset(attrget() | FTATTR_BLINK); + break; + case 25: + attrset(attrget() & ~FTATTR_BLINK); + break; + case 3: + case 7: + { + ftattr a = attrget(); + attrsetfg(FTATTR_GETBG(a)); + attrsetbg(FTATTR_GETFG(a)); + } + break; + case 39: + attrsetfg(FTATTR_DEFAULT_FG); + break; + case 49: + attrsetbg(FTATTR_DEFAULT_BG); + break; + } + + // parse next command + n = -1; + if (*p == ';') + { + n = 0; + p++; + } + else if (isdigit(*p)) + { + n = atoi(p); + while (isdigit(*p)) p++; + if (*p == ';') + p++; + } + } + break; + + default: // unknown command. + break; + } } int fterm_chattr(char *s, ftattr oattr, ftattr nattr) { - ftattr - fg, bg, bold, blink, - ofg, obg, obold, oblink; - char lead = 1; - - if (oattr == nattr) - return 0; - - *s++ = ESC_CHR; - *s++ = '['; - - // optimization: reset as default - if (nattr == FTATTR_DEFAULT) - { - *s++ = 'm'; - *s++ = 0; - return 1; - } - - fg = FTATTR_GETFG(nattr); - bg = FTATTR_GETBG(nattr); - bold = (nattr & FTATTR_BOLD) ? 1 : 0; - blink = (nattr & FTATTR_BLINK)? 1 : 0; - - ofg = FTATTR_GETFG(oattr); - obg = FTATTR_GETBG(oattr); - obold = (oattr & FTATTR_BOLD) ? 1 : 0; - oblink = (oattr & FTATTR_BLINK)? 1 : 0; - - // we dont use "disable blink/bold" commands, - // so if these settings are changed then we must reset. - // another case is changing background to default background - - // better use "RESET" to override it. - // Same for foreground. - // Possible optimization: when blink/bold on, don't RESET - // for background change? - if ((oblink != blink && !blink) || - (obold != bold && !bold) || - (bg == FTATTR_DEFAULT_BG && obg != bg) || - (fg == FTATTR_DEFAULT_FG && ofg != fg) ) - { - if (lead) lead = 0; else *s++ = ';'; - *s++ = '0'; - - ofg = FTATTR_DEFAULT_FG; - obg = FTATTR_DEFAULT_BG; - obold = 0; oblink = 0; - } - - if (bold && !obold) - { - if (lead) lead = 0; else *s++ = ';'; - *s++ = '1'; + ftattr + fg, bg, bold, blink, + ofg, obg, obold, oblink; + char lead = 1; + + if (oattr == nattr) + return 0; + + *s++ = ESC_CHR; + *s++ = '['; + + // optimization: reset as default + if (nattr == FTATTR_DEFAULT) + { + *s++ = 'm'; + *s++ = 0; + return 1; + } + + fg = FTATTR_GETFG(nattr); + bg = FTATTR_GETBG(nattr); + bold = (nattr & FTATTR_BOLD) ? 1 : 0; + blink = (nattr & FTATTR_BLINK)? 1 : 0; + + ofg = FTATTR_GETFG(oattr); + obg = FTATTR_GETBG(oattr); + obold = (oattr & FTATTR_BOLD) ? 1 : 0; + oblink = (oattr & FTATTR_BLINK)? 1 : 0; + + // we dont use "disable blink/bold" commands, + // so if these settings are changed then we must reset. + // another case is changing background to default background - + // better use "RESET" to override it. + // Same for foreground. + // Possible optimization: when blink/bold on, don't RESET + // for background change? + if ((oblink != blink && !blink) || + (obold != bold && !bold) || + (bg == FTATTR_DEFAULT_BG && obg != bg) || + (fg == FTATTR_DEFAULT_FG && ofg != fg) ) + { + if (lead) lead = 0; else *s++ = ';'; + *s++ = '0'; + + ofg = FTATTR_DEFAULT_FG; + obg = FTATTR_DEFAULT_BG; + obold = 0; oblink = 0; + } + + if (bold && !obold) + { + if (lead) lead = 0; else *s++ = ';'; + *s++ = '1'; #ifdef FTCONF_WORKAROUND_BOLD - // Issue here: - // PacketSite does not understand ESC[1m. It needs ESC[1;37m - // NetTerm defaults bold color to yellow. - // As a result, we use ESC[1;37m for the case. - if (fg == FTATTR_DEFAULT_FG) - ofg = ~ofg; + // Issue here: + // PacketSite does not understand ESC[1m. It needs ESC[1;37m + // NetTerm defaults bold color to yellow. + // As a result, we use ESC[1;37m for the case. + if (fg == FTATTR_DEFAULT_FG) + ofg = ~ofg; #endif // FTCONF_WORKAROUND_BOLD - } - if (blink && !oblink) - { - if (lead) lead = 0; else *s++ = ';'; - *s++ = '5'; // XXX 5(slow) or 6(fast)? - } - if (ofg != fg) - { - if (lead) lead = 0; else *s++ = ';'; - *s++ = '3'; - *s++ = '0' + fg; - } - if (obg != bg) - { - if (lead) lead = 0; else *s++ = ';'; - *s++ = '4'; - *s++ = '0' + bg; - } - *s++ = 'm'; - *s++ = 0; - return 1; -} - -int + } + if (blink && !oblink) + { + if (lead) lead = 0; else *s++ = ';'; + *s++ = '5'; // XXX 5(slow) or 6(fast)? + } + if (ofg != fg) + { + if (lead) lead = 0; else *s++ = ';'; + *s++ = '3'; + *s++ = '0' + fg; + } + if (obg != bg) + { + if (lead) lead = 0; else *s++ = ';'; + *s++ = '4'; + *s++ = '0' + bg; + } + *s++ = 'm'; + *s++ = 0; + return 1; +} + +int fterm_strdlen(const char *s) { - char ansi = 0; - int sz = 0; - - // the logic should match outc(). - - while (s && *s) - { - if (!ansi) // ansi == 0 - { - switch(*s) - { - case ESC_CHR: - ansi++; - break; - - case '\r': - case '\n': - break; - - case '\b': - if (sz) sz--; - break; - - case '\t': - // XXX how to deal with this? - sz ++; - break; - - default: - if (!iscntrl((unsigned char)*s)) - sz++; - break; - } - } - else if (ansi == 1) - { - if (*s == '[') - ansi++; - else - ansi = 0; - } - else if (!ANSI_IS_PARAM(*s)) // ansi == 2 - { - // TODO outc() take max to FTCMD_MAXLEN now... - ansi = 0; - } - s++; - } - return sz; -} - -void + char ansi = 0; + int sz = 0; + + // the logic should match outc(). + + while (s && *s) + { + if (!ansi) // ansi == 0 + { + switch(*s) + { + case ESC_CHR: + ansi++; + break; + + case '\r': + case '\n': + break; + + case '\b': + if (sz) sz--; + break; + + case '\t': + // XXX how to deal with this? + sz ++; + break; + + default: + if (!iscntrl((unsigned char)*s)) + sz++; + break; + } + } + else if (ansi == 1) + { + if (*s == '[') + ansi++; + else + ansi = 0; + } + else if (!ANSI_IS_PARAM(*s)) // ansi == 2 + { + // TODO outc() take max to FTCMD_MAXLEN now... + ansi = 0; + } + s++; + } + return sz; +} + +void fterm_rawattr(ftattr rattr) { - static char cmd[FTATTR_MINCMD*2]; - if (!fterm_chattr(cmd, ft.rattr, rattr)) - return; + static char cmd[FTATTR_MINCMD*2]; + if (!fterm_chattr(cmd, ft.rattr, rattr)) + return; - fterm_raws(cmd); - ft.rattr = rattr; + fterm_raws(cmd); + ft.rattr = rattr; } void fterm_rawnum(int arg) { - if (arg < 0 || arg > 99) - { - // complex. use printf. - char sarg[16]; // max int - sprintf(sarg, "%d", arg); - fterm_raws(sarg); - } else if (arg < 10) { - // 0 .. 10 - fterm_rawc('0' + arg); - } else { - fterm_rawc('0' + arg/10); - fterm_rawc('0' + arg%10); - } + if (arg < 0 || arg > 99) + { + // complex. use printf. + char sarg[16]; // max int + sprintf(sarg, "%d", arg); + fterm_raws(sarg); + } else if (arg < 10) { + // 0 .. 10 + fterm_rawc('0' + arg); + } else { + fterm_rawc('0' + arg/10); + fterm_rawc('0' + arg%10); + } } void fterm_rawcmd(int arg, int defval, char c) { - fterm_rawc(ESC_CHR); - fterm_rawc('['); - if (arg != defval) - fterm_rawnum(arg); - fterm_rawc(c); + fterm_rawc(ESC_CHR); + fterm_rawc('['); + if (arg != defval) + fterm_rawnum(arg); + fterm_rawc(c); } void fterm_rawcmd2(int arg1, int arg2, int defval, char c) { - fterm_rawc(ESC_CHR); - fterm_rawc('['); + fterm_rawc(ESC_CHR); + fterm_rawc('['); - // See FTCONF_ANSICMD2_OMIT - // XXX Win/DOS telnet does now accept omitting first value - // ESC[nX and ESC[n;X works, but ESC[;mX does not work. - if (arg1 != defval || arg2 != defval) - { + // See FTCONF_ANSICMD2_OMIT + // XXX Win/DOS telnet does now accept omitting first value + // ESC[nX and ESC[n;X works, but ESC[;mX does not work. + if (arg1 != defval || arg2 != defval) + { #if (FTCONF_ANSICMD2_OMIT >= 2) - if (arg1 != defval) + if (arg1 != defval) #endif - fterm_rawnum(arg1); + fterm_rawnum(arg1); #if (FTCONF_ANSICMD2_OMIT >= 1) - if (arg2 != defval) + if (arg2 != defval) #endif - { - fterm_rawc(';'); - fterm_rawnum(arg2); - } - } - fterm_rawc(c); + { + fterm_rawc(';'); + fterm_rawnum(arg2); + } + } + fterm_rawc(c); } -void +void fterm_rawclear(void) { - fterm_rawhome(); - // ED: CSI n J, 0 = cursor to bottom, 2 = whole - fterm_raws(ESC_STR "[2J"); + fterm_rawhome(); + // ED: CSI n J, 0 = cursor to bottom, 2 = whole + fterm_raws(ESC_STR "[2J"); } -void +void fterm_rawclreol(void) { #ifdef FTCONF_CLEAR_SETATTR - // ftattr oattr = ft.rattr; - // XXX If we skip with "backround only" here, future updating - // may get wrong attributes. Or not? (consider DBCS...) - // if (FTATTR_GETBG(oattr) != FTATTR_GETBG(FTATTR_ERASE)) - fterm_rawattr(FTATTR_ERASE); + // ftattr oattr = ft.rattr; + // XXX If we skip with "backround only" here, future updating + // may get wrong attributes. Or not? (consider DBCS...) + // if (FTATTR_GETBG(oattr) != FTATTR_GETBG(FTATTR_ERASE)) + fterm_rawattr(FTATTR_ERASE); #endif - // EL: CSI n K, n = 0 - fterm_raws(ESC_STR "[K"); + // EL: CSI n K, n = 0 + fterm_raws(ESC_STR "[K"); #ifdef FTCONF_CLEAR_SETATTR - // No need to do so? because we will always reset attribute... - // fterm_rawattr(oattr); + // No need to do so? because we will always reset attribute... + // fterm_rawattr(oattr); #endif } void fterm_rawhome(void) { - // CUP: CSI n ; m H - fterm_raws(ESC_STR "[H"); - ft.rx = ft.ry = 0; + // CUP: CSI n ; m H + fterm_raws(ESC_STR "[H"); + ft.rx = ft.ry = 0; } void fterm_rawmove_rel(int dy, int dx) { #ifndef FTCONF_USE_ANSI_RELMOVE - // Old BBS system does not output relative moves (ESC[ABCD) . - // Poor terminals (ex, pcman-1.0.5-FF20.xpi) - // do not support relmoves - fterm_rawmove(ft.ry + dy, ft.rx + dx); + // Old BBS system does not output relative moves (ESC[ABCD) . + // Poor terminals (ex, pcman-1.0.5-FF20.xpi) + // do not support relmoves + fterm_rawmove(ft.ry + dy, ft.rx + dx); #else - if (!dx) - { - int y = ranged(dy + ft.ry, 0, ft.rows-1); - dy = y - ft.ry; - if (!dy) - return; - - fterm_rawcmd(abs(dy), 1, dy < 0 ? 'A' : 'B'); - ft.ry = y; - } - else if (!dy) - { - int x = ranged(dx + ft.rx, 0, ft.cols-1); - dx = x - ft.rx; - if (!dx) - return; - - fterm_rawcmd(abs(dx), 1, dx < 0 ? 'D' : 'C'); - ft.rx = x; - } - else - { - // (dy, dx) are given - use fterm_move. - fterm_rawmove(ft.ry + dy, ft.rx + dx); - } + if (!dx) + { + int y = ranged(dy + ft.ry, 0, ft.rows-1); + dy = y - ft.ry; + if (!dy) + return; + + fterm_rawcmd(abs(dy), 1, dy < 0 ? 'A' : 'B'); + ft.ry = y; + } + else if (!dy) + { + int x = ranged(dx + ft.rx, 0, ft.cols-1); + dx = x - ft.rx; + if (!dx) + return; + + fterm_rawcmd(abs(dx), 1, dx < 0 ? 'D' : 'C'); + ft.rx = x; + } + else + { + // (dy, dx) are given - use fterm_move. + fterm_rawmove(ft.ry + dy, ft.rx + dx); + } #endif } void fterm_rawmove(int y, int x) { - y = ranged(y, 0, ft.rows-1); - x = ranged(x, 0, ft.cols-1); + y = ranged(y, 0, ft.rows-1); + x = ranged(x, 0, ft.cols-1); - if (y == ft.ry && x == ft.rx) - return; + if (y == ft.ry && x == ft.rx) + return; - // CUP: CSI n ; m H - fterm_rawcmd2(y+1, x+1, 1, 'H'); + // CUP: CSI n ; m H + fterm_rawcmd2(y+1, x+1, 1, 'H'); - ft.ry = y; - ft.rx = x; + ft.ry = y; + ft.rx = x; } void fterm_rawmove_opt(int y, int x) { - // optimized move - int ady = abs(y-ft.ry), adx=abs(x-ft.rx); + // optimized move + int ady = abs(y-ft.ry), adx=abs(x-ft.rx); - if (!adx && !ady) - return; + if (!adx && !ady) + return; #ifdef DBG_DISABLE_OPTMOVE - return fterm_rawmove(y, x); + return fterm_rawmove(y, x); #endif - // known hacks: \r = (x=0), \b=(x--), \n = (y++) - // - // Warning: any optimization here should not change displayed content, - // because we don't have information about content variation information - // (eg, invalid DBCS bytes will become special marks) here. - // Any hacks which will try to display data from FTCMAP should be done - // inside dirty-map calculation, for ex, using spaces to move right, - // or re-print content. - + // known hacks: \r = (x=0), \b=(x--), \n = (y++) + // + // Warning: any optimization here should not change displayed content, + // because we don't have information about content variation information + // (eg, invalid DBCS bytes will become special marks) here. + // Any hacks which will try to display data from FTCMAP should be done + // inside dirty-map calculation, for ex, using spaces to move right, + // or re-print content. + #ifndef DBG_TEXT_FD - // x=0: the cheapest output. However not work for text mode fd output. - // a special case is "if we have to move y to up". - // and FTCONF_ANSICMD2_OMIT < 1 (cannot omit x). + // x=0: the cheapest output. However not work for text mode fd output. + // a special case is "if we have to move y to up". + // and FTCONF_ANSICMD2_OMIT < 1 (cannot omit x). #if FTCONF_ANSICMD2_OMIT < 1 - if (y >= ft.ry) + if (y >= ft.ry) #endif - if (adx && x == 0) - { - fterm_rawc('\r'); - ft.rx = x = adx = 0; - } + if (adx && x == 0) + { + fterm_rawc('\r'); + ft.rx = x = adx = 0; + } #endif // !DBG_TEXT_FD - // x--: compare with FTMV_COST: ESC[m;nH costs 5-8 bytes - if (x < ft.rx && y >= ft.ry && (adx+ady) < FTMV_COST) - { - while (adx > 0) - fterm_rawc('\b'), adx--; - ft.rx = x; - } - - // finishing movement - if (y > ft.ry && ady < FTMV_COST && adx == 0) - { - while (ft.ry++ < y) - fterm_rawc('\n'); - ft.ry = y; - } - else if (ady && adx) - { - fterm_rawmove(y, x); - } - else if (ady) - { - fterm_rawmove_rel(y-ft.ry, 0); - } - else if (adx) - { - fterm_rawmove_rel(0, x-ft.rx); - } + // x--: compare with FTMV_COST: ESC[m;nH costs 5-8 bytes + if (x < ft.rx && y >= ft.ry && (adx+ady) < FTMV_COST) + { + while (adx > 0) + fterm_rawc('\b'), adx--; + ft.rx = x; + } + + // finishing movement + if (y > ft.ry && ady < FTMV_COST && adx == 0) + { + while (ft.ry++ < y) + fterm_rawc('\n'); + ft.ry = y; + } + else if (ady && adx) + { + fterm_rawmove(y, x); + } + else if (ady) + { + fterm_rawmove_rel(y-ft.ry, 0); + } + else if (adx) + { + fterm_rawmove_rel(0, x-ft.rx); + } } void fterm_rawcursor(void) { #ifdef _WIN32 - COORD cursor; - cursor.X = ft.x; - cursor.Y = ft.y; - SetConsoleCursorPosition(hStdout, cursor); + COORD cursor; + cursor.X = ft.x; + cursor.Y = ft.y; + SetConsoleCursorPosition(hStdout, cursor); #else - // fterm_rawattr(FTATTR_DEFAULT); - fterm_rawattr(ft.attr); - fterm_rawmove_opt(ft.y, ft.x); - fterm_rawflush(); + // fterm_rawattr(FTATTR_DEFAULT); + fterm_rawattr(ft.attr); + fterm_rawmove_opt(ft.y, ft.x); + fterm_rawflush(); #endif // !_WIN32 } -void -fterm_rawscroll (int dy) +void +fterm_rawscroll (int dy) { #ifdef FTCONF_USE_ANSI_SCROLL - // SU: CSI n S (up) - // SD: CSI n T (down) + // SU: CSI n S (up) + // SD: CSI n T (down) - char cmd = (dy > 0) ? 'S' : 'T'; - int ady = abs(dy); - if (ady == 0) - return; - if (ady >= ft.rows) ady = ft.rows; - fterm_rawcmd(ady, 1, cmd); - ft.scroll -= dy; + char cmd = (dy > 0) ? 'S' : 'T'; + int ady = abs(dy); + if (ady == 0) + return; + if (ady >= ft.rows) ady = ft.rows; + fterm_rawcmd(ady, 1, cmd); + ft.scroll -= dy; #else - // VT100 flavor: - // * ESC D: scroll down - // * ESC M: scroll up - // - // Elder BBS systems works in a mixed way: - // \n at (rows-1) as scroll() - // and ESC-M at(0) as rscoll(). - // - // SCP: CSI s / RCP: CSI u - // Warning: cannot use SCP/RCP here, because on Win/DOS telnet - // the position will change after scrolling (ex, (25,0)->(24,0). - // - // Since scroll does not happen very often, let's relax and not - // optimize these commands here... - - int ady = abs(dy); - if (ady == 0) - return; - if (ady >= ft.rows) ady = ft.rows; - - // we are not going to preserve (rx,ry) - // so don't use fterm_move*. - if (dy > 0) - fterm_rawcmd2(ft.rows, 1, 1, 'H'); - else - fterm_rawcmd2(1, 1, 1, 'H'); - - for (; ady > 0; ady--) - { - if (dy >0) - { - // Win/DOS telnet may have extra text in new line, - // because of the IME line. + // VT100 flavor: + // * ESC D: scroll down + // * ESC M: scroll up + // + // Elder BBS systems works in a mixed way: + // \n at (rows-1) as scroll() + // and ESC-M at(0) as rscoll(). + // + // SCP: CSI s / RCP: CSI u + // Warning: cannot use SCP/RCP here, because on Win/DOS telnet + // the position will change after scrolling (ex, (25,0)->(24,0). + // + // Since scroll does not happen very often, let's relax and not + // optimize these commands here... + + int ady = abs(dy); + if (ady == 0) + return; + if (ady >= ft.rows) ady = ft.rows; + + // we are not going to preserve (rx,ry) + // so don't use fterm_move*. + if (dy > 0) + fterm_rawcmd2(ft.rows, 1, 1, 'H'); + else + fterm_rawcmd2(1, 1, 1, 'H'); + + for (; ady > 0; ady--) + { + if (dy >0) + { + // Win/DOS telnet may have extra text in new line, + // because of the IME line. #ifdef FTCONF_USE_VT100_SCROLL - fterm_raws(ESC_STR "D" ESC_STR "[K"); // ESC_STR "[K"); + fterm_raws(ESC_STR "D" ESC_STR "[K"); // ESC_STR "[K"); #else - fterm_raws("\n" ESC_STR "[K"); + fterm_raws("\n" ESC_STR "[K"); #endif - } else { - fterm_raws(ESC_STR "M"); // ESC_STR "[K"); - } - } - - // Do not use optimized move here, because in poor terminals - // the coordinates are already out of sync. - fterm_rawcmd2(ft.ry+1, ft.rx+1, 1, 'H'); - ft.scroll -= dy; + } else { + fterm_raws(ESC_STR "M"); // ESC_STR "[K"); + } + } + + // Do not use optimized move here, because in poor terminals + // the coordinates are already out of sync. + fterm_rawcmd2(ft.ry+1, ft.rx+1, 1, 'H'); + ft.scroll -= dy; #endif } -void +void fterm_raws(const char *s) { - while (*s) - fterm_rawc(*s++); + while (*s) + fterm_rawc(*s++); } -void +void fterm_rawnc(int c, int n) { - while (n-- > 0) - fterm_rawc(c); + while (n-- > 0) + fterm_rawc(c); } ////////////////////////////////////////////////////////////////////////// // grayout advanced control ////////////////////////////////////////////////////////////////////////// -void +void grayout(int y, int end, int level) { - char grattr = FTATTR_DEFAULT; - - y = ranged(y, 0, ft.rows-1); - end = ranged(end, 0, ft.rows-1); - - if (level == GRAYOUT_COLORBOLD) - { - int x = 0; - for (; y < end; y++) - { - for (x = 0; x < ft.cols-1; x++) - FTAMAP[y][x] |= FTATTR_BOLD; - } - return; - } - - if (level == GRAYOUT_COLORNORM) - { - int x = 0; - for (; y < end; y++) - { - for (x = 0; x < ft.cols-1; x++) - FTAMAP[y][x] &= ~(FTATTR_BLINK | FTATTR_BOLD); - } - return; - } - - if (level == GRAYOUT_BOLD) - { - grattr |= FTATTR_BOLD; - } - else if (level == GRAYOUT_DARK) - { - grattr = FTATTR_MAKE(0,0); - grattr |= FTATTR_BOLD; - } - else if (level == GRAYOUT_NORM) - { - // normal text - } - else - { - // not supported yet - } - - for (; y <= end; y++) - { - memset(FTAMAP[y], grattr, ft.cols); - } + char grattr = FTATTR_DEFAULT; + + y = ranged(y, 0, ft.rows-1); + end = ranged(end, 0, ft.rows-1); + + if (level == GRAYOUT_COLORBOLD) + { + int x = 0; + for (; y < end; y++) + { + for (x = 0; x < ft.cols-1; x++) + FTAMAP[y][x] |= FTATTR_BOLD; + } + return; + } + + if (level == GRAYOUT_COLORNORM) + { + int x = 0; + for (; y < end; y++) + { + for (x = 0; x < ft.cols-1; x++) + FTAMAP[y][x] &= ~(FTATTR_BLINK | FTATTR_BOLD); + } + return; + } + + if (level == GRAYOUT_BOLD) + { + grattr |= FTATTR_BOLD; + } + else if (level == GRAYOUT_DARK) + { + grattr = FTATTR_MAKE(0,0); + grattr |= FTATTR_BOLD; + } + else if (level == GRAYOUT_NORM) + { + // normal text + } + else + { + // not supported yet + } + + for (; y <= end; y++) + { + memset(FTAMAP[y], grattr, ft.cols); + } } ////////////////////////////////////////////////////////////////////////// @@ -2234,7 +2234,7 @@ grayout(int y, int end, int level) void standout(void) { - outs(ANSI_COLOR(7)); + outs(ANSI_COLOR(7)); } void @@ -2248,96 +2248,96 @@ standend(void) void scr_dump(screen_backup_t *psb) { - int y = 0; - char *p = NULL; + int y = 0; + char *p = NULL; - psb->row= ft.rows; - psb->col= ft.cols; - psb->y = ft.y; - psb->x = ft.x; - p = psb->raw_memory = - malloc (ft.rows * ft.cols * (sizeof(ftchar) + sizeof(ftattr))); + psb->row= ft.rows; + psb->col= ft.cols; + psb->y = ft.y; + psb->x = ft.x; + p = psb->raw_memory = + malloc (ft.rows * ft.cols * (sizeof(ftchar) + sizeof(ftattr))); - for (y = 0; y < ft.rows; y++) - { - memcpy(p, FTCMAP[y], ft.cols * sizeof(ftchar)); - p += ft.cols * sizeof(ftchar); - memcpy(p, FTAMAP[y], ft.cols * sizeof(ftattr)); - p += ft.cols * sizeof(ftattr); - } + for (y = 0; y < ft.rows; y++) + { + memcpy(p, FTCMAP[y], ft.cols * sizeof(ftchar)); + p += ft.cols * sizeof(ftchar); + memcpy(p, FTAMAP[y], ft.cols * sizeof(ftattr)); + p += ft.cols * sizeof(ftattr); + } } void scr_restore(const screen_backup_t *psb) { - int y = 0; - char *p = NULL; - int c = ft.cols, r = ft.rows; - if (!psb || !psb->raw_memory) - return; + int y = 0; + char *p = NULL; + int c = ft.cols, r = ft.rows; + if (!psb || !psb->raw_memory) + return; - p = psb->raw_memory; - c = ranged(c, 0, psb->col); - r = ranged(r, 0, psb->row); + p = psb->raw_memory; + c = ranged(c, 0, psb->col); + r = ranged(r, 0, psb->row); - ft.y = ranged(psb->y, 0, ft.rows-1); - ft.x = ranged(psb->x, 0, ft.cols-1); - clrscr(); + ft.y = ranged(psb->y, 0, ft.rows-1); + ft.x = ranged(psb->x, 0, ft.cols-1); + clrscr(); - for (y = 0; y < r; y++) - { - memcpy(FTCMAP[y], p, c * sizeof(ftchar)); - p += psb->col * sizeof(ftchar); - memcpy(FTAMAP[y], p, c * sizeof(ftattr)); - p += psb->col * sizeof(ftattr); - } + for (y = 0; y < r; y++) + { + memcpy(FTCMAP[y], p, c * sizeof(ftchar)); + p += psb->col * sizeof(ftchar); + memcpy(FTAMAP[y], p, c * sizeof(ftattr)); + p += psb->col * sizeof(ftattr); + } - free(psb->raw_memory); - ft.dirty = 1; - refresh(); + free(psb->raw_memory); + ft.dirty = 1; + refresh(); } void move_ansi(int y, int x) { - move(y, x); + move(y, x); } void getyx_ansi(int *y, int *x) { - getyx(y, x); + getyx(y, x); } void region_scroll_up(int top, int bottom) { - int i; - ftchar *c0; - ftattr *a0; + int i; + ftchar *c0; + ftattr *a0; - // logic same with old screen.c - if (top > bottom) { - i = top; - top = bottom; - bottom = i; - } + // logic same with old screen.c + if (top > bottom) { + i = top; + top = bottom; + bottom = i; + } if (top < 0 || bottom >= ft.rows) - return; + return; - c0 = FTCMAP[top]; - a0 = FTAMAP[top]; + c0 = FTCMAP[top]; + a0 = FTAMAP[top]; - for (i = top; i < bottom; i++) - { - FTCMAP[i] = FTCMAP[i+1]; - FTAMAP[i] = FTAMAP[i+1]; - } - FTCMAP[bottom] = c0; - FTAMAP[bottom] = a0; + for (i = top; i < bottom; i++) + { + FTCMAP[i] = FTCMAP[i+1]; + FTAMAP[i] = FTAMAP[i+1]; + } + FTCMAP[bottom] = c0; + FTAMAP[bottom] = a0; - clrregion(bottom, bottom); - fterm_markdirty(); + clrregion(bottom, bottom); + fterm_markdirty(); } #endif @@ -2346,24 +2346,24 @@ region_scroll_up(int top, int bottom) // adapter ////////////////////////////////////////////////////////////////////////// -int +int fterm_inbuf(void) { #ifdef _PFTERM_TEST_MAIN - return 0; + return 0; #else - return num_in_buf(); + return num_in_buf(); #endif } -void +void fterm_rawc(int c) { #ifdef _PFTERM_TEST_MAIN - // if (c == ESC_CHR) putchar('*'); else - putchar(c); + // if (c == ESC_CHR) putchar('*'); else + putchar(c); #else - ochar(c); + ochar(c); #endif } @@ -2371,10 +2371,10 @@ void fterm_rawnewline(void) { #ifdef _PFTERM_TEST_MAIN - putchar('\n'); + putchar('\n'); #else - ochar('\r'); - ochar('\n'); + ochar('\r'); + ochar('\n'); #endif } @@ -2382,9 +2382,9 @@ void fterm_rawflush(void) { #ifdef _PFTERM_TEST_MAIN - fflush(stdout); + fflush(stdout); #else - oflush(); + oflush(); #endif } @@ -2395,108 +2395,108 @@ fterm_rawflush(void) #ifdef _PFTERM_TEST_MAIN int main(int argc, char* argv[]) { - char buf[512]; - initscr(); + char buf[512]; + initscr(); - if (argc < 2) - { + if (argc < 2) + { #if 0 - // DBCS test - char *a1 = ANSI_COLOR(1;33) "´ú¸Õ" ANSI_COLOR(34) "¤¤¤å" - ANSI_COLOR(7) "´ú¸Õ" ANSI_RESET "´ú¸Õ" - "´ú¸Õa" ANSI_RESET "\n"; - outstr(a1); - move(0, 2); - outstr("¤¤¤å1"); - outstr(ANSI_COLOR(1;33)"¤¤¤å2"); - outstr(" ¤¤\x85"); - outstr("okok herer\x8a"); - - move(0, 8); - inansistr(buf, sizeof(buf)-1); - - move(3,5); outs(ANSI_RESET "(From inansistr:) "); outs(buf); - move(7, 3); - sprintf(buf, "strlen()=%d\n", fterm_strdlen(a1)); - outstr(buf); - refresh(); - getchar(); - - outs(ANSI_COLOR(1;33) "test " ANSI_COLOR(34) "x" - ANSI_RESET "te" ANSI_COLOR(43;0;1;35) " st" - ANSI_COLOR(0) "testx\n"); - refresh(); - getchar(); - - clear(); - outs("¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å"); - move(0, 0); - outs(" this\xFF (ff)is te.(80 tail)->\x80 (80)"); - refresh(); - getchar(); + // DBCS test + char *a1 = ANSI_COLOR(1;33) "´ú¸Õ" ANSI_COLOR(34) "¤¤¤å" + ANSI_COLOR(7) "´ú¸Õ" ANSI_RESET "´ú¸Õ" + "´ú¸Õa" ANSI_RESET "\n"; + outstr(a1); + move(0, 2); + outstr("¤¤¤å1"); + outstr(ANSI_COLOR(1;33)"¤¤¤å2"); + outstr(" ¤¤\x85"); + outstr("okok herer\x8a"); + + move(0, 8); + inansistr(buf, sizeof(buf)-1); + + move(3,5); outs(ANSI_RESET "(From inansistr:) "); outs(buf); + move(7, 3); + sprintf(buf, "strlen()=%d\n", fterm_strdlen(a1)); + outstr(buf); + refresh(); + getchar(); + + outs(ANSI_COLOR(1;33) "test " ANSI_COLOR(34) "x" + ANSI_RESET "te" ANSI_COLOR(43;0;1;35) " st" + ANSI_COLOR(0) "testx\n"); + refresh(); + getchar(); + + clear(); + outs("¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å¤¤¤å"); + move(0, 0); + outs(" this\xFF (ff)is te.(80 tail)->\x80 (80)"); + refresh(); + getchar(); #endif #if 1 - // test resize - clear(); move(1, 0); outs("test resize\n"); - doupdate(); getchar(); - // expand X - resizeterm(25,200); - clear(); move(20, 0); clrtoeol(); outs("200x25"); - doupdate(); getchar(); - // resize back - resizeterm(25,80); - clear(); move(20, 0); clrtoeol(); outs("80x25"); - doupdate(); getchar(); - // expand Y - resizeterm(60,80); - clear(); move(20, 0); clrtoeol(); outs("80x60"); - doupdate(); getchar(); - // see if you crash here. - resizeterm(60,200); - clear(); move(20, 0); clrtoeol(); outs("200x60"); - doupdate(); getchar(); + // test resize + clear(); move(1, 0); outs("test resize\n"); + doupdate(); getchar(); + // expand X + resizeterm(25,200); + clear(); move(20, 0); clrtoeol(); outs("200x25"); + doupdate(); getchar(); + // resize back + resizeterm(25,80); + clear(); move(20, 0); clrtoeol(); outs("80x25"); + doupdate(); getchar(); + // expand Y + resizeterm(60,80); + clear(); move(20, 0); clrtoeol(); outs("80x60"); + doupdate(); getchar(); + // see if you crash here. + resizeterm(60,200); + clear(); move(20, 0); clrtoeol(); outs("200x60"); + doupdate(); getchar(); #endif #if 0 - // test optimization - clear(); - move(1, 0); - outs("x++ optimization test\n"); - outs("1 2 3 4 5 6 7 8 9 0\n"); - outs("1122233334444455555566666667777777788888888899999999990\n"); - refresh(); - getchar(); - - move(2, 0); - outs("1122233334444455555566666667777777788888888899999999990\n"); - outs("1 2 3 4 5 6 7 8 9 0\n"); - refresh(); - getchar(); - - rscroll(); - refresh(); - getchar(); + // test optimization + clear(); + move(1, 0); + outs("x++ optimization test\n"); + outs("1 2 3 4 5 6 7 8 9 0\n"); + outs("1122233334444455555566666667777777788888888899999999990\n"); + refresh(); + getchar(); + + move(2, 0); + outs("1122233334444455555566666667777777788888888899999999990\n"); + outs("1 2 3 4 5 6 7 8 9 0\n"); + refresh(); + getchar(); + + rscroll(); + refresh(); + getchar(); #endif - } else { - FILE *fp = fopen(argv[1], "r"); - int c = 0; - - while (fp && (c=getc(fp)) > 0) - { - outc(c); - } - fclose(fp); - refresh(); - } - - endwin(); - printf("\ncomplete. enter to exit.\n"); - getchar(); - return 0; + } else { + FILE *fp = fopen(argv[1], "r"); + int c = 0; + + while (fp && (c=getc(fp)) > 0) + { + outc(c); + } + fclose(fp); + refresh(); + } + + endwin(); + printf("\ncomplete. enter to exit.\n"); + getchar(); + return 0; } #endif // _PFTERM_TEST_MAIN #endif // defined(EXP_PFTERM) || defined(USE_PFTERM) -// vim:ts=4:sw=4 +// vim:ts=4:sw=4:expandtab diff --git a/mbbsd/pmore.c b/mbbsd/pmore.c index ea460ea4..fde26f3a 100644 --- a/mbbsd/pmore.c +++ b/mbbsd/pmore.c @@ -58,24 +58,24 @@ /* These are default values. * You may override them in your bbs.h or config.h etc etc. */ -#define PMORE_PRELOAD_SIZE (64*1024L) // on busy system set smaller or undef - -#define PMORE_USE_PTT_PRINTS // support PTT or special printing -#define PMORE_USE_OPT_SCROLL // optimized scroll -#define PMORE_USE_DBCS_WRAP // safe wrap for DBCS. -#define PMORE_USE_ASCII_MOVIE // support ascii movie -//#define PMORE_RESTRICT_ANSI_MOVEMENT // user cannot use ANSI escapes to move -#define PMORE_ACCURATE_WRAPEND // try more harder to find file end in wrap mode -#define PMORE_TRADITIONAL_PROMPTEND // when prompt=NA, show only page 1 -#define PMORE_TRADITIONAL_FULLCOL // to work with traditional ascii arts -#define PMORE_LOG_SYSOP_EDIT // log whenever sysop uses E -#define PMORE_OVERRIDE_TIME // override time format if possible +#define PMORE_PRELOAD_SIZE (64*1024L) // on busy system set smaller or undef + +#define PMORE_USE_PTT_PRINTS // support PTT or special printing +#define PMORE_USE_OPT_SCROLL // optimized scroll +#define PMORE_USE_DBCS_WRAP // safe wrap for DBCS. +#define PMORE_USE_ASCII_MOVIE // support ascii movie +//#define PMORE_RESTRICT_ANSI_MOVEMENT // user cannot use ANSI escapes to move +#define PMORE_ACCURATE_WRAPEND // try more harder to find file end in wrap mode +#define PMORE_TRADITIONAL_PROMPTEND // when prompt=NA, show only page 1 +#define PMORE_TRADITIONAL_FULLCOL // to work with traditional ascii arts +#define PMORE_LOG_SYSOP_EDIT // log whenever sysop uses E +#define PMORE_OVERRIDE_TIME // override time format if possible // if you are working with a terminal without ANSI control, // you are using a poor term (define PMORE_USING_POOR_TERM). -#ifndef USE_PFTERM // pfterm is a good terminal system. +#ifndef USE_PFTERM // pfterm is a good terminal system. #define PMORE_USING_POOR_TERM -#define PMORE_WORKAROUND_CLRTOEOL // try to work with poor terminal sys +#define PMORE_WORKAROUND_CLRTOEOL // try to work with poor terminal sys #endif // USE_PFTERM // -------------------------------------------------------------- </FEATURES> @@ -190,9 +190,9 @@ int debug = 0; #endif /* DBCS users tend to write unsigned char. let's make compiler happy */ -#define ustrlen(x) strlen((char*)x) -#define ustrchr(x,y) (unsigned char*)strchr((char*)x, y) -#define ustrrchr(x,y) (unsigned char*)strrchr((char*)x, y) +#define ustrlen(x) strlen((char*)x) +#define ustrchr(x,y) (unsigned char*)strchr((char*)x, y) +#define ustrrchr(x,y) (unsigned char*)strrchr((char*)x, y) // --------------------------------------------- <Defines and constants> @@ -212,13 +212,13 @@ int debug = 0; #define ESC_CHR '\x1b' // Common ANSI commands. -#define ANSI_RESET ESC_STR "[m" -#define ANSI_COLOR(x) ESC_STR "[" #x "m" -#define ANSI_CLRTOEND ESC_STR "[K" +#define ANSI_RESET ESC_STR "[m" +#define ANSI_COLOR(x) ESC_STR "[" #x "m" +#define ANSI_CLRTOEND ESC_STR "[K" #define ANSI_MOVETO(y,x) ESC_STR "[" #y ";" #x "H" #define ANSI_IN_ESCAPE(x) (((x) >= '0' && (x) <= '9') || \ - (x) == ';' || (x) == ',' || (x) == '[') + (x) == ';' || (x) == ',' || (x) == '[') #endif /* PMORE_STYLE_ANSI */ @@ -245,7 +245,7 @@ pmore_clrtoeol(int y, int x) int i; move(y, x); for (i = x; i < t_columns; i++) - outc(' '); + outc(' '); clrtoeol(); move(y, x); // this is required, due to outc(). #else @@ -260,44 +260,44 @@ pmore_clrtoeol(int y, int x) typedef struct { unsigned char - *start, *end, // file buffer - *disps, *dispe, // displayed content start/end - *maxdisps; // a very special pointer, - // consider as "disps of last page" - off_t len; // file total length - long lineno, // lineno of disps - oldlineno, // last drawn lineno, < 0 means full update - xpos, // starting x position - // - wraplines, // wrapped lines in last display - trunclines, // truncated lines in last display - dispedlines, // how many different lines displayed - // usually dispedlines = PAGE-wraplines, - // but if last line is incomplete(wrapped), - // dispedlines = PAGE-wraplines + 1 - lastpagelines,// lines of last page to show - // this indicates how many lines can - // maxdisps(maxlinenoS) display. - maxlinenoS; // lineno of maxdisps, "S"! - // What does the magic "S" mean? - // Just trying to notify you that it's - // NOT REAL MAX LINENO NOR FILELENGTH!!! - // You may consider "S" of "Start" (disps). + *start, *end, // file buffer + *disps, *dispe, // displayed content start/end + *maxdisps; // a very special pointer, + // consider as "disps of last page" + off_t len; // file total length + long lineno, // lineno of disps + oldlineno, // last drawn lineno, < 0 means full update + xpos, // starting x position + // + wraplines, // wrapped lines in last display + trunclines, // truncated lines in last display + dispedlines, // how many different lines displayed + // usually dispedlines = PAGE-wraplines, + // but if last line is incomplete(wrapped), + // dispedlines = PAGE-wraplines + 1 + lastpagelines,// lines of last page to show + // this indicates how many lines can + // maxdisps(maxlinenoS) display. + maxlinenoS; // lineno of maxdisps, "S"! + // What does the magic "S" mean? + // Just trying to notify you that it's + // NOT REAL MAX LINENO NOR FILELENGTH!!! + // You may consider "S" of "Start" (disps). } MmappedFile; MmappedFile mf = { 0, 0, 0, 0, 0, 0L, 0, -1L, 0, 0, -1L, -1L, -1L,-1L -}; // current file +}; // current file /* mf_* navigation commands return value meanings */ enum MF_NAV_COMMANDS { - MFNAV_OK, // navigation ok - MFNAV_EXCEED, // request exceeds buffer + MFNAV_OK, // navigation ok + MFNAV_EXCEED, // request exceeds buffer }; /* Navigation units (dynamic, so not in enum const) */ -#define MFNAV_PAGE (t_lines-2) // when navigation, how many lines in a page to move +#define MFNAV_PAGE (t_lines-2) // when navigation, how many lines in a page to move /* Display system */ enum MF_DISP_CONST { @@ -333,9 +333,9 @@ enum MF_DISP_CONST { #define MFDISP_DIRTY() { mf.oldlineno = -1; } /* Indicators */ -#define MFDISP_TRUNC_INDICATOR ANSI_COLOR(0;1;37) ">" ANSI_RESET -#define MFDISP_WRAP_INDICATOR ANSI_COLOR(0;1;37) "\\" ANSI_RESET -#define MFDISP_WNAV_INDICATOR ANSI_COLOR(0;1;37) "<" ANSI_RESET +#define MFDISP_TRUNC_INDICATOR ANSI_COLOR(0;1;37) ">" ANSI_RESET +#define MFDISP_WRAP_INDICATOR ANSI_COLOR(0;1;37) "\\" ANSI_RESET +#define MFDISP_WNAV_INDICATOR ANSI_COLOR(0;1;37) "<" ANSI_RESET // --------------------------- </Main Navigation> // --------------------------- <Aux. Structures> @@ -344,13 +344,13 @@ typedef struct { /* mode flags */ unsigned char - wrapmode, // wrap? - separator, // separator style - wrapindicator, // show wrap indicators + wrapmode, // wrap? + separator, // separator style + wrapindicator, // show wrap indicators - oldwrapmode, // traditional wrap - oldstatusbar, // traditional statusbar - rawmode; // show file as-is. + oldwrapmode, // traditional wrap + oldstatusbar, // traditional statusbar + rawmode; // show file as-is. } MF_BrowsingPreference; MF_BrowsingPreference bpref = @@ -366,7 +366,7 @@ static const char *_fh_disp_heads[FH_HEADERS] = typedef struct { - int lines; // header lines + int lines; // header lines unsigned char *headers[FH_HEADERS]; unsigned char *floats [FH_FLOATS]; } MF_PrettyFormattedHeader; @@ -378,7 +378,7 @@ typedef struct { int len; int (*cmpfunc) (const char *, const char *, size_t); - unsigned char *search_str; // maybe we can change to dynamic allocation + unsigned char *search_str; // maybe we can change to dynamic allocation } MF_SearchRecord; MF_SearchRecord sr = { 0, strncmp, NULL}; @@ -395,11 +395,11 @@ enum MFSEARCH_DIRECTION { fh.lines = -1; } // Artwork -#define OPTATTR_NORMAL ANSI_COLOR(0;34;47) +#define OPTATTR_NORMAL ANSI_COLOR(0;34;47) #define OPTATTR_NORMAL_KEY ANSI_COLOR(0;31;47) #define OPTATTR_SELECTED ANSI_COLOR(0;1;37;46) #define OPTATTR_SELECTED_KEY ANSI_COLOR(0;31;46) -#define OPTATTR_BAR ANSI_COLOR(0;1;30;47) +#define OPTATTR_BAR ANSI_COLOR(0;1;30;47) // --------------------------- </Aux. Structures> @@ -420,22 +420,22 @@ typedef struct { struct timeval frameclk; struct timeval synctime; unsigned char *options, - *optkeys; + *optkeys; unsigned char mode, - compat24, - interactive, - pause; + compat24, + interactive, + pause; } MF_Movie; MF_Movie mfmovie; -#define STOP_MOVIE() { \ +#define STOP_MOVIE() { \ mfmovie.options = NULL; \ mfmovie.pause = 0; \ if (mfmovie.mode == MFDISP_MOVIE_PLAYING) \ - mfmovie.mode = MFDISP_MOVIE_YES; \ + mfmovie.mode = MFDISP_MOVIE_YES; \ if (mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD) \ - mfmovie.mode = MFDISP_MOVIE_NO; \ + mfmovie.mode = MFDISP_MOVIE_NO; \ mf_determinemaxdisps(MFNAV_PAGE, 0); \ mf_forward(0); \ } @@ -446,7 +446,7 @@ MF_Movie mfmovie; mfmovie.optkeys = NULL; \ mfmovie.compat24 = 1; \ mfmovie.pause = 0; \ - mfmovie.interactive = 0; \ + mfmovie.interactive = 0; \ mfmovie.synctime.tv_sec = mfmovie.synctime.tv_usec = 0; \ mfmovie.frameclk.tv_sec = 1; mfmovie.frameclk.tv_usec = 0; \ } @@ -496,13 +496,13 @@ mf_attach(const char *fn) int fd = open(fn, O_RDONLY, 0600); if(fd < 0) - return 0; + return 0; if (fstat(fd, &st) || ((mf.len = st.st_size) <= 0) || S_ISDIR(st.st_mode)) { - mf.len = 0; - close(fd); - return 0; + mf.len = 0; + close(fd); + return 0; } /* @@ -511,13 +511,13 @@ mf_attach(const char *fn) */ mf.start = mmap(NULL, mf.len, PROT_READ, - MF_MMAP_OPTION, fd, 0); + MF_MMAP_OPTION, fd, 0); close(fd); if(mf.start == MAP_FAILED) { - RESETMF(); - return 0; + RESETMF(); + return 0; } // BSD mmap advise. comment if your OS does not support this. @@ -537,10 +537,10 @@ mf_attach(const char *fn) /* a workaround for wrapped separators */ if(mf.maxlinenoS > 0 && - fh.lines >= mf.maxlinenoS && - bpref.separator & MFDISP_SEP_WRAP) + fh.lines >= mf.maxlinenoS && + bpref.separator & MFDISP_SEP_WRAP) { - mf_determinemaxdisps(+1, 1); + mf_determinemaxdisps(+1, 1); } return 1; @@ -551,8 +551,8 @@ mf_detach() { mf_freeHeaders(); if(mf.start) { - munmap(mf.start, mf.len); - RESETMF(); + munmap(mf.start, mf.len); + RESETMF(); } } @@ -566,15 +566,15 @@ mf_sync_lineno() if(mf.disps == mf.maxdisps && mf.maxlinenoS >= 0) { - mf.lineno = mf.maxlinenoS; + mf.lineno = mf.maxlinenoS; } else { - mf.lineno = 0; - for (p = mf.start; p < mf.disps; p++) - if(*p == '\n') - mf.lineno ++; + mf.lineno = 0; + for (p = mf.start; p < mf.disps; p++) + if(*p == '\n') + mf.lineno ++; - if(mf.disps == mf.maxdisps && mf.maxlinenoS < 0) - mf.maxlinenoS = mf.lineno; + if(mf.disps == mf.maxdisps && mf.maxlinenoS < 0) + mf.maxlinenoS = mf.lineno; } } @@ -589,35 +589,35 @@ mf_determinemaxdisps(int backlines, int update_by_offset) if(update_by_offset) { - if(backlines > 0) - { - /* tricky way because usually - * mf_forward checks maxdisps. - */ - mf.disps = mf.maxdisps; - mf.maxdisps = mf.end-1; - mf_forward(backlines); - mf_backward(0); - } else - mf_backward(backlines); + if(backlines > 0) + { + /* tricky way because usually + * mf_forward checks maxdisps. + */ + mf.disps = mf.maxdisps; + mf.maxdisps = mf.end-1; + mf_forward(backlines); + mf_backward(0); + } else + mf_backward(backlines); } else { - mf.lineno = backlines; - mf.disps = mf.end - 1; - backlines = mf_backward(backlines); + mf.lineno = backlines; + mf.disps = mf.end - 1; + backlines = mf_backward(backlines); } if(mf.disps != mbak) { - mf.maxdisps = mf.disps; - if(update_by_offset) - mf.lastpagelines -= backlines; - else - mf.lastpagelines = backlines; + mf.maxdisps = mf.disps; + if(update_by_offset) + mf.lastpagelines -= backlines; + else + mf.lastpagelines = backlines; - mf.maxlinenoS = -1; + mf.maxlinenoS = -1; #ifdef PMORE_PRELOAD_SIZE - if(mf.len <= PMORE_PRELOAD_SIZE) - mf_sync_lineno(); // maxlinenoS will be automatically updated + if(mf.len <= PMORE_PRELOAD_SIZE) + mf_sync_lineno(); // maxlinenoS will be automatically updated #endif } mf.disps = pbak; @@ -643,13 +643,13 @@ mf_backward(int lines) while (1) { - if (mf.disps < mf.start || *mf.disps == '\n') - { - real_moved ++; - if(lines-- <= 0 || mf.disps < mf.start) - break; - } - mf.disps --; + if (mf.disps < mf.start || *mf.disps == '\n') + { + real_moved ++; + if(lines-- <= 0 || mf.disps < mf.start) + break; + } + mf.disps --; } /* now disps points to previous 1 byte of new address */ @@ -667,33 +667,33 @@ mf_forward(int lines) while(mf.disps <= mf.maxdisps && lines > 0) { - while (mf.disps <= mf.maxdisps && *mf.disps++ != '\n'); + while (mf.disps <= mf.maxdisps && *mf.disps++ != '\n'); - if(mf.disps <= mf.maxdisps) - mf.lineno++, lines--, real_moved++; + if(mf.disps <= mf.maxdisps) + mf.lineno++, lines--, real_moved++; } if(mf.disps > mf.maxdisps) - mf.disps = mf.maxdisps; + mf.disps = mf.maxdisps; /* please make sure you have lineno synced. */ if(mf.disps == mf.maxdisps && mf.maxlinenoS < 0) - mf.maxlinenoS = mf.lineno; + mf.maxlinenoS = mf.lineno; return real_moved; /* if(lines > 0) - return MFNAV_OK; + return MFNAV_OK; else - return MFNAV_EXCEED; - */ + return MFNAV_EXCEED; + */ } int mf_goTop() { if(mf.disps == mf.start && mf.xpos > 0) - mf.xpos = 0; + mf.xpos = 0; mf.disps = mf.start; mf.lineno = 0; return MFNAV_OK; @@ -738,55 +738,55 @@ mf_search(int direction) int flFound = 0; if(!s || !*s) - return 0; + return 0; if(direction == MFSEARCH_FORWARD) { - mf_forward(1); - while(mf.disps < mf.end - l) - { - if(sr.cmpfunc((char*)mf.disps, (char*)s, l) == 0) - { - flFound = 1; - break; - } else { - /* DBCS check here. */ - if(PMORE_DBCS_LEADING(*mf.disps++)) - mf.disps++; - } - } - mf_backward(0); - if(mf.disps > mf.maxdisps) - mf.disps = mf.maxdisps; - mf_sync_lineno(); + mf_forward(1); + while(mf.disps < mf.end - l) + { + if(sr.cmpfunc((char*)mf.disps, (char*)s, l) == 0) + { + flFound = 1; + break; + } else { + /* DBCS check here. */ + if(PMORE_DBCS_LEADING(*mf.disps++)) + mf.disps++; + } + } + mf_backward(0); + if(mf.disps > mf.maxdisps) + mf.disps = mf.maxdisps; + mf_sync_lineno(); } else if(direction == MFSEARCH_BACKWARD) { - mf_backward(1); - while (!flFound && mf.disps > mf.start) - { - while(!flFound && mf.disps < mf.end-l && *mf.disps != '\n') - { - if(sr.cmpfunc((char*)mf.disps, (char*)s, l) == 0) - { - flFound = 1; - } else - { - /* DBCS check here. */ - if(PMORE_DBCS_LEADING(*mf.disps++)) - mf.disps++; - } - } - if(!flFound) - mf_backward(1); - } - mf_backward(0); - if(mf.disps < mf.start) - mf.disps = mf.start; - mf_sync_lineno(); + mf_backward(1); + while (!flFound && mf.disps > mf.start) + { + while(!flFound && mf.disps < mf.end-l && *mf.disps != '\n') + { + if(sr.cmpfunc((char*)mf.disps, (char*)s, l) == 0) + { + flFound = 1; + } else + { + /* DBCS check here. */ + if(PMORE_DBCS_LEADING(*mf.disps++)) + mf.disps++; + } + } + if(!flFound) + mf_backward(1); + } + mf_backward(0); + if(mf.disps < mf.start) + mf.disps = mf.start; + mf_sync_lineno(); } if(flFound) - MFDISP_DIRTY(); + MFDISP_DIRTY(); return flFound; } @@ -799,29 +799,29 @@ mf_search(int direction) #define ISSPACE(x) (x <= ' ') MFPROTO void -pmore_str_strip_ansi(unsigned char *p) // warning: p is NULL terminated +pmore_str_strip_ansi(unsigned char *p) // warning: p is NULL terminated { unsigned char *pb = p; while (*p != 0) { - if (*p == ESC_CHR) - { - // ansi code sequence, ignore them. - pb = p++; - while (ANSI_IN_ESCAPE(*p)) - p++; - memmove(pb, p, ustrlen(p)+1); - p = pb; - } - else if (*p < ' ' || *p == 0xff) - { - // control codes, ignore them. - // what is 0xff? old BBS does not handle telnet protocol - // so IACs were inserted. - memmove(p, p+1, ustrlen(p+1)+1); - } - else - p++; + if (*p == ESC_CHR) + { + // ansi code sequence, ignore them. + pb = p++; + while (ANSI_IN_ESCAPE(*p)) + p++; + memmove(pb, p, ustrlen(p)+1); + p = pb; + } + else if (*p < ' ' || *p == 0xff) + { + // control codes, ignore them. + // what is 0xff? old BBS does not handle telnet protocol + // so IACs were inserted. + memmove(p, p+1, ustrlen(p+1)+1); + } + else + p++; } } @@ -834,16 +834,16 @@ pmore_str_chomp(unsigned char *p) unsigned char *pb = p + ustrlen(p)-1; while (pb >= p) - if(ISSPACE(*pb)) - *pb-- = 0; - else - break; + if(ISSPACE(*pb)) + *pb-- = 0; + else + break; pb = p; while (*pb && ISSPACE(*pb)) - pb++; + pb++; if(pb != p) - memmove(p, pb, ustrlen(pb)+1); + memmove(p, pb, ustrlen(pb)+1); } #if 0 @@ -863,13 +863,13 @@ mf_freeHeaders() { if(fh.lines > 0) { - int i; + int i; - for (i = 0; i < FH_HEADERS; i++) - free(fh.headers[i]); - for (i = 0; i < FH_FLOATS; i++) - free(fh.floats[i]); - RESETFH(); + for (i = 0; i < FH_HEADERS; i++) + free(fh.headers[i]); + for (i = 0; i < FH_FLOATS; i++) + free(fh.floats[i]); + RESETFH(); } } @@ -878,8 +878,8 @@ mf_parseHeaders() { /* file format: * AUTHOR: author BOARD: blah <- headers[0], floats[0], floats[1] - * XXX: xxx <- headers[1] - * XXX: xxx <- headers[n] + * XXX: xxx <- headers[1] + * XXX: xxx <- headers[n] * [blank, fill with separator] <- lines * * #define STR_AUTHOR1 "§@ªÌ:" @@ -891,88 +891,88 @@ mf_parseHeaders() RESETFH(); if(mf.len < LEN_AUTHOR2) - return; + return; if (strncmp((char*)mf.start, STR_AUTHOR1, LEN_AUTHOR1) == 0) { - fh.lines = 3; // local + fh.lines = 3; // local } else if (strncmp((char*)mf.start, STR_AUTHOR2, LEN_AUTHOR2) == 0) { - fh.lines = 4; + fh.lines = 4; } else - return; + return; for (i = 0; i < fh.lines; i++) { - unsigned char *p = pmf, *pb = pmf; - int l; - - /* first, go to line-end */ - while(pmf < mf.end && *pmf != '\n') - pmf++; - if(pmf >= mf.end) - break; - p = pmf; - pmf ++; // move to next line. - - // p is pointing at a new line. (\n) - l = (int)(p - pb); + unsigned char *p = pmf, *pb = pmf; + int l; + + /* first, go to line-end */ + while(pmf < mf.end && *pmf != '\n') + pmf++; + if(pmf >= mf.end) + break; + p = pmf; + pmf ++; // move to next line. + + // p is pointing at a new line. (\n) + l = (int)(p - pb); #ifdef CRITICAL_MEMORY - // kcwu: dirty hack, avoid 64byte slot. use 128byte slot instead. - if (l<100) { - p = (unsigned char*) malloc (100+1); - } else { - p = (unsigned char*) malloc (l+1); - } + // kcwu: dirty hack, avoid 64byte slot. use 128byte slot instead. + if (l<100) { + p = (unsigned char*) malloc (100+1); + } else { + p = (unsigned char*) malloc (l+1); + } #else - p = (unsigned char*) malloc (l+1); + p = (unsigned char*) malloc (l+1); #endif - fh.headers[i] = p; - memcpy(p, pb, l); - p[l] = 0; + fh.headers[i] = p; + memcpy(p, pb, l); + p[l] = 0; - // now, postprocess p. - pmore_str_strip_ansi(p); + // now, postprocess p. + pmore_str_strip_ansi(p); #ifdef PMORE_OVERRIDE_TIME - // (deprecated: too many formats for newsgroup) - // try to see if this is a valid time line - // use strptime to convert + // (deprecated: too many formats for newsgroup) + // try to see if this is a valid time line + // use strptime to convert #endif // PMORE_OVERRIDE_TIME - // strip to quotes[+1 space] - if((pb = ustrchr((char*)p, ':')) != NULL) - { - if(*(pb+1) == ' ') pb++; - memmove(p, pb, ustrlen(pb)+1); - } - - // kill staring and trailing spaces - pmore_str_chomp(p); - - // special case, floats are in line[0]. - if(i == 0 && (pb = ustrrchr(p, ':')) != NULL && *(pb+1)) - { - unsigned char *np = (unsigned char*)strdup((char*)(pb+1)); - - fh.floats[1] = np; - pmore_str_chomp(np); - // remove quote and traverse back - *pb-- = 0; - while (pb > p && *pb != ',' && !(ISSPACE(*pb))) - pb--; - - if (pb > p) { - fh.floats[0] = (unsigned char*)strdup((char*)(pb+1)); - pmore_str_chomp(fh.floats[0]); - *pb = 0; - pmore_str_chomp(fh.headers[0]); - } else { - fh.floats[0] = (unsigned char*)strdup(""); - } - } + // strip to quotes[+1 space] + if((pb = ustrchr((char*)p, ':')) != NULL) + { + if(*(pb+1) == ' ') pb++; + memmove(p, pb, ustrlen(pb)+1); + } + + // kill staring and trailing spaces + pmore_str_chomp(p); + + // special case, floats are in line[0]. + if(i == 0 && (pb = ustrrchr(p, ':')) != NULL && *(pb+1)) + { + unsigned char *np = (unsigned char*)strdup((char*)(pb+1)); + + fh.floats[1] = np; + pmore_str_chomp(np); + // remove quote and traverse back + *pb-- = 0; + while (pb > p && *pb != ',' && !(ISSPACE(*pb))) + pb--; + + if (pb > p) { + fh.floats[0] = (unsigned char*)strdup((char*)(pb+1)); + pmore_str_chomp(fh.floats[0]); + *pb = 0; + pmore_str_chomp(fh.headers[0]); + } else { + fh.floats[0] = (unsigned char*)strdup(""); + } + } } } @@ -983,7 +983,7 @@ MFPROTO void MFDISP_SKIPCURLINE() { while (mf.dispe < mf.end && *mf.dispe != '\n') - mf.dispe++; + mf.dispe++; } MFPROTO int @@ -996,17 +996,17 @@ MFDISP_PREDICT_LINEWIDTH(unsigned char *p) while (p < mf.end && *p != '\n') { - if(inAnsi) - { - if(!ANSI_IN_ESCAPE(*p)) - inAnsi = 0; - } else { - if(*p == ESC_CHR) - inAnsi = 1; - else - off ++; - } - p++; + if(inAnsi) + { + if(!ANSI_IN_ESCAPE(*p)) + inAnsi = 0; + } else { + if(*p == ESC_CHR) + inAnsi = 1; + else + off ++; + } + p++; } return off; } @@ -1022,8 +1022,8 @@ MFDISP_DBCS_HEADERWIDTH(int originalw) #define MFDISP_FORCEUPDATE2BOT() { endline = MFDISP_PAGE - 1; } #define MFDISP_FORCEDIRTY2BOT() \ if(optimized == MFDISP_OPT_OPTIMIZED) { \ - optimized = MFDISP_OPT_FORCEDIRTY; \ - MFDISP_FORCEUPDATE2BOT(); \ + optimized = MFDISP_OPT_FORCEDIRTY; \ + MFDISP_FORCEUPDATE2BOT(); \ } static char *override_msg = NULL; @@ -1056,7 +1056,7 @@ mf_display() int newline_default = MFDISP_NEWLINE_CLEAR; if(mf.wraplines || mf.trunclines) - MFDISP_DIRTY(); // we can't scroll with wrapped lines. + MFDISP_DIRTY(); // we can't scroll with wrapped lines. mf.wraplines = 0; mf.trunclines = 0; @@ -1072,562 +1072,562 @@ mf_display() // Let's enable for good terminals (which does not need workarounds) if (MOVIE_IS_PLAYING()) { - clear(); move(0, 0); + clear(); move(0, 0); } else #endif // PMORE_USE_ASCII_MOVIE && (!PMORE_USING_POOR_TERM) /* process scrolling */ if (mf.oldlineno >= 0 && mf.oldlineno != mf.lineno) { - int scrll = mf.lineno - mf.oldlineno, i; - int reverse = (scrll > 0 ? 0 : 1); - - if(reverse) - scrll = -scrll; - else - { - /* because bottom status line is also scrolled, - * we have to erase it here. - */ - pmore_clrtoeol(b_lines, 0); - // move(b_lines, 0); - // clrtoeol(); - } - - if(scrll > MFDISP_PAGE) - scrll = MFDISP_PAGE; - - i = scrll; + int scrll = mf.lineno - mf.oldlineno, i; + int reverse = (scrll > 0 ? 0 : 1); + + if(reverse) + scrll = -scrll; + else + { + /* because bottom status line is also scrolled, + * we have to erase it here. + */ + pmore_clrtoeol(b_lines, 0); + // move(b_lines, 0); + // clrtoeol(); + } + + if(scrll > MFDISP_PAGE) + scrll = MFDISP_PAGE; + + i = scrll; #if defined(USE_PFTERM) - // In fact, pfterm will flash black screen when scrolling pages... - // So it may work better if we refresh whole screen. - if (i >= b_lines / 2) - { - clear(); move(0, 0); - scrll = MFDISP_PAGE; - } else + // In fact, pfterm will flash black screen when scrolling pages... + // So it may work better if we refresh whole screen. + if (i >= b_lines / 2) + { + clear(); move(0, 0); + scrll = MFDISP_PAGE; + } else #endif // defined(USE_PFTERM) - while(i-- > 0) - if (reverse) - rscroll(); // v - else - scroll(); // ^ - - if(reverse) - { - endline = scrll-1; // v - // clear the line which will be scrolled - // to bottom (status line position). - pmore_clrtoeol(b_lines, 0); - // move(b_lines, 0); - // clrtoeol(); - } - else - { - startline = MFDISP_PAGE - scrll; // ^ - } - move(startline, 0); - optimized = MFDISP_OPT_OPTIMIZED; - // return; // uncomment if you want to observe scrolling + while(i-- > 0) + if (reverse) + rscroll(); // v + else + scroll(); // ^ + + if(reverse) + { + endline = scrll-1; // v + // clear the line which will be scrolled + // to bottom (status line position). + pmore_clrtoeol(b_lines, 0); + // move(b_lines, 0); + // clrtoeol(); + } + else + { + startline = MFDISP_PAGE - scrll; // ^ + } + move(startline, 0); + optimized = MFDISP_OPT_OPTIMIZED; + // return; // uncomment if you want to observe scrolling } else #endif - clear(), move(0, 0); + clear(), move(0, 0); mf.dispe = mf.disps; while (lines < MFDISP_PAGE) { - int inAnsi = 0; - int newline = newline_default; - int predicted_linewidth = -1; - int xprefix = mf.xpos; + int inAnsi = 0; + int newline = newline_default; + int predicted_linewidth = -1; + int xprefix = mf.xpos; #ifdef PMORE_USE_DBCS_WRAP - unsigned char *dbcs_incomplete = NULL; + unsigned char *dbcs_incomplete = NULL; #endif - currline = mf.lineno + lines; - col = 0; + currline = mf.lineno + lines; + col = 0; - if(!wrapping && mf.dispe < mf.end) - mf.dispedlines++; + if(!wrapping && mf.dispe < mf.end) + mf.dispedlines++; - if(optimized == MFDISP_OPT_FORCEDIRTY) - { - /* btw, apparently this line should be visible. - * if not, maybe something wrong. - */ - pmore_clrtoeol(lines, 0); - } + if(optimized == MFDISP_OPT_FORCEDIRTY) + { + /* btw, apparently this line should be visible. + * if not, maybe something wrong. + */ + pmore_clrtoeol(lines, 0); + } #ifdef PMORE_USE_ASCII_MOVIE - if(mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD && - mfmovie.compat24) - { - if(mf.dispedlines == 23) - return; - } - else if (mfmovie.mode == MFDISP_MOVIE_DETECTED) - { - // detected only applies for first page. - // since this is not very often, let's prevent - // showing control codes. - if(mf_movieFrameHeader(mf.dispe, mf.end)) - MFDISP_SKIPCURLINE(); - } - else if(mfmovie.mode == MFDISP_MOVIE_UNKNOWN || - mfmovie.mode == MFDISP_MOVIE_PLAYING) - { - if(mf_movieFrameHeader(mf.dispe, mf.end)) - switch(mfmovie.mode) - { - - case MFDISP_MOVIE_UNKNOWN: - mfmovie.mode = MFDISP_MOVIE_DETECTED; - /* let's remove the first control sequence. */ - MFDISP_SKIPCURLINE(); - break; - - case MFDISP_MOVIE_PLAYING: - /* - * maybe we should do clrtobot() here, - * but it's even better if we do clear() - * all time. so we set dirty here for - * next frame, and please set dirty before - * playing. - */ - MFDISP_DIRTY(); - return; - } - } + if(mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD && + mfmovie.compat24) + { + if(mf.dispedlines == 23) + return; + } + else if (mfmovie.mode == MFDISP_MOVIE_DETECTED) + { + // detected only applies for first page. + // since this is not very often, let's prevent + // showing control codes. + if(mf_movieFrameHeader(mf.dispe, mf.end)) + MFDISP_SKIPCURLINE(); + } + else if(mfmovie.mode == MFDISP_MOVIE_UNKNOWN || + mfmovie.mode == MFDISP_MOVIE_PLAYING) + { + if(mf_movieFrameHeader(mf.dispe, mf.end)) + switch(mfmovie.mode) + { + + case MFDISP_MOVIE_UNKNOWN: + mfmovie.mode = MFDISP_MOVIE_DETECTED; + /* let's remove the first control sequence. */ + MFDISP_SKIPCURLINE(); + break; + + case MFDISP_MOVIE_PLAYING: + /* + * maybe we should do clrtobot() here, + * but it's even better if we do clear() + * all time. so we set dirty here for + * next frame, and please set dirty before + * playing. + */ + MFDISP_DIRTY(); + return; + } + } #endif - /* Is currentline visible? */ - if (lines < startline || lines > endline) - { - MFDISP_SKIPCURLINE(); - newline = MFDISP_NEWLINE_SKIP; - } - /* Now, consider what kind of line - * (header, separator, or normal text) - * is current line. - */ - else if (currline == fh.lines && bpref.rawmode == MFDISP_RAW_NA) - { - /* case 1, header separator line */ - if (bpref.separator & MFDISP_SEP_LINE) - { - outs(ANSI_COLOR(36)); - for(col = 0; col < headerw; col+=2) - { - // prints("%02d", col); - outs("¢w"); - } - outs(ANSI_RESET); - } - - /* Traditional 'more' adds separator as a newline. - * This is buggy, however we can support this - * by using wrapping features. - * Anyway I(piaip) don't like this. And using wrap - * leads to slow display (we cannt speed it up with - * optimized scrolling. - */ - if(bpref.separator & MFDISP_SEP_WRAP) - { - /* we have to do all wrapping stuff - * in normal text section. - * make sure this is updated. - */ - wrapping = 1; - mf.wraplines ++; - MFDISP_FORCEDIRTY2BOT(); - if(mf.dispe > mf.start && - mf.dispe < mf.end && - *mf.dispe == '\n') - mf.dispe --; - } - else - MFDISP_SKIPCURLINE(); - } - else if (currline < fh.lines && bpref.rawmode == MFDISP_RAW_NA ) - { - /* case 2, we're printing headers */ - const char *val = (const char*)fh.headers[currline]; - const char *name = _fh_disp_heads[currline]; - int w = headerw - FH_HEADER_LEN - 3; - - outs(ANSI_COLOR(47;34) " "); - outs(name); - outs(" " ANSI_COLOR(44;37) " "); - - /* right floating stuff? */ - if (currline == 0 && fh.floats[0]) - { - w -= ustrlen(fh.floats[0]) + ustrlen(fh.floats[1]) + 4; - } - - prints("%-*.*s", w, w, - (val ? val : "")); - - if (currline == 0 && fh.floats[0]) - { - outs(ANSI_COLOR(47;34) " "); - outs((const char*)fh.floats[0]); - outs(" " ANSI_COLOR(44;37) " "); - outs((const char*)fh.floats[1]); - outs(" "); - } - - outs(ANSI_RESET); - MFDISP_SKIPCURLINE(); - } - else if(mf.dispe < mf.end) - { - /* case 3, normal text */ - long dist = mf.end - mf.dispe; - long flResetColor = 0; - int srlen = -1; - int breaknow = 0; - - unsigned char c; - - if(xprefix > 0 && !bpref.oldwrapmode && bpref.wrapindicator) - { - outs(MFDISP_WNAV_INDICATOR); - col++; - } - - // first check quote - if(bpref.rawmode == MFDISP_RAW_NA) - { - if(dist > 1 && - (*mf.dispe == ':' || *mf.dispe == '>') && - *(mf.dispe+1) == ' ') - { - outs(ANSI_COLOR(36)); - flResetColor = 1; - } else if (dist > 2 && - (!strncmp((char*)mf.dispe, "¡°", 2) || - !strncmp((char*)mf.dispe, "==>", 3))) - { - outs(ANSI_COLOR(32)); - flResetColor = 1; - } - } - - while(!breaknow && mf.dispe < mf.end && (c = *mf.dispe) != '\n') - { - if(inAnsi) - { - if (!ANSI_IN_ESCAPE(c)) - inAnsi = 0; - /* whatever this is, output! */ - mf.dispe ++; - switch(bpref.rawmode) - { - case MFDISP_RAW_NOANSI: - /* TODO - * col++ here may be buggy. */ - if(col < t_columns) - { - /* we tried our best to determine */ - if(xprefix > 0) - xprefix --; - else - { - outc(c); - col++; - } - } - if(!inAnsi) - outs(ANSI_RESET); - break; - case MFDISP_RAW_PLAIN: - break; - - default: - if(ANSI_IN_MOVECMD(c)) - { + /* Is currentline visible? */ + if (lines < startline || lines > endline) + { + MFDISP_SKIPCURLINE(); + newline = MFDISP_NEWLINE_SKIP; + } + /* Now, consider what kind of line + * (header, separator, or normal text) + * is current line. + */ + else if (currline == fh.lines && bpref.rawmode == MFDISP_RAW_NA) + { + /* case 1, header separator line */ + if (bpref.separator & MFDISP_SEP_LINE) + { + outs(ANSI_COLOR(36)); + for(col = 0; col < headerw; col+=2) + { + // prints("%02d", col); + outs("¢w"); + } + outs(ANSI_RESET); + } + + /* Traditional 'more' adds separator as a newline. + * This is buggy, however we can support this + * by using wrapping features. + * Anyway I(piaip) don't like this. And using wrap + * leads to slow display (we cannt speed it up with + * optimized scrolling. + */ + if(bpref.separator & MFDISP_SEP_WRAP) + { + /* we have to do all wrapping stuff + * in normal text section. + * make sure this is updated. + */ + wrapping = 1; + mf.wraplines ++; + MFDISP_FORCEDIRTY2BOT(); + if(mf.dispe > mf.start && + mf.dispe < mf.end && + *mf.dispe == '\n') + mf.dispe --; + } + else + MFDISP_SKIPCURLINE(); + } + else if (currline < fh.lines && bpref.rawmode == MFDISP_RAW_NA ) + { + /* case 2, we're printing headers */ + const char *val = (const char*)fh.headers[currline]; + const char *name = _fh_disp_heads[currline]; + int w = headerw - FH_HEADER_LEN - 3; + + outs(ANSI_COLOR(47;34) " "); + outs(name); + outs(" " ANSI_COLOR(44;37) " "); + + /* right floating stuff? */ + if (currline == 0 && fh.floats[0]) + { + w -= ustrlen(fh.floats[0]) + ustrlen(fh.floats[1]) + 4; + } + + prints("%-*.*s", w, w, + (val ? val : "")); + + if (currline == 0 && fh.floats[0]) + { + outs(ANSI_COLOR(47;34) " "); + outs((const char*)fh.floats[0]); + outs(" " ANSI_COLOR(44;37) " "); + outs((const char*)fh.floats[1]); + outs(" "); + } + + outs(ANSI_RESET); + MFDISP_SKIPCURLINE(); + } + else if(mf.dispe < mf.end) + { + /* case 3, normal text */ + long dist = mf.end - mf.dispe; + long flResetColor = 0; + int srlen = -1; + int breaknow = 0; + + unsigned char c; + + if(xprefix > 0 && !bpref.oldwrapmode && bpref.wrapindicator) + { + outs(MFDISP_WNAV_INDICATOR); + col++; + } + + // first check quote + if(bpref.rawmode == MFDISP_RAW_NA) + { + if(dist > 1 && + (*mf.dispe == ':' || *mf.dispe == '>') && + *(mf.dispe+1) == ' ') + { + outs(ANSI_COLOR(36)); + flResetColor = 1; + } else if (dist > 2 && + (!strncmp((char*)mf.dispe, "¡°", 2) || + !strncmp((char*)mf.dispe, "==>", 3))) + { + outs(ANSI_COLOR(32)); + flResetColor = 1; + } + } + + while(!breaknow && mf.dispe < mf.end && (c = *mf.dispe) != '\n') + { + if(inAnsi) + { + if (!ANSI_IN_ESCAPE(c)) + inAnsi = 0; + /* whatever this is, output! */ + mf.dispe ++; + switch(bpref.rawmode) + { + case MFDISP_RAW_NOANSI: + /* TODO + * col++ here may be buggy. */ + if(col < t_columns) + { + /* we tried our best to determine */ + if(xprefix > 0) + xprefix --; + else + { + outc(c); + col++; + } + } + if(!inAnsi) + outs(ANSI_RESET); + break; + case MFDISP_RAW_PLAIN: + break; + + default: + if(ANSI_IN_MOVECMD(c)) + { #ifdef PMORE_RESTRICT_ANSI_MOVEMENT - c = 's'; // "save cursor pos" + c = 's'; // "save cursor pos" #else // PMORE_RESTRICT_ANSI_MOVEMENT - // some user cannot live without this. - // make them happy. - newline_default = newline = MFDISP_NEWLINE_MOVE; + // some user cannot live without this. + // make them happy. + newline_default = newline = MFDISP_NEWLINE_MOVE; #ifdef PMORE_USE_ASCII_MOVIE - // relax for movies - if (!MOVIE_IS_PLAYING()) + // relax for movies + if (!MOVIE_IS_PLAYING()) #endif // PMORE_USE_ASCII_MOVIE - { - override_attr = ANSI_COLOR(1;37;41); - override_msg = PMORE_MSG_WARN_MOVECMD; - } + { + override_attr = ANSI_COLOR(1;37;41); + override_msg = PMORE_MSG_WARN_MOVECMD; + } #endif // PMORE_RESTRICT_ANSI_MOVEMENT - needMove2bot = 1; - } - outc(c); - break; - } - continue; - - } else { - - if(c == ESC_CHR) - { - inAnsi = 1; - /* we can't output now because maybe - * ptt_prints wants to do something. - */ - } - else if(sr.search_str && srlen < 0 && // support search + needMove2bot = 1; + } + outc(c); + break; + } + continue; + + } else { + + if(c == ESC_CHR) + { + inAnsi = 1; + /* we can't output now because maybe + * ptt_prints wants to do something. + */ + } + else if(sr.search_str && srlen < 0 && // support search #ifdef PMORE_USE_DBCS_WRAP - dbcs_incomplete == NULL && + dbcs_incomplete == NULL && #endif - mf.end - mf.dispe > sr.len && - sr.cmpfunc((char*)mf.dispe, (char*)sr.search_str, sr.len) == 0) - { - outs(ANSI_COLOR(7)); - srlen = sr.len-1; - flResetColor = 1; - } + mf.end - mf.dispe > sr.len && + sr.cmpfunc((char*)mf.dispe, (char*)sr.search_str, sr.len) == 0) + { + outs(ANSI_COLOR(7)); + srlen = sr.len-1; + flResetColor = 1; + } #ifdef PMORE_USE_PTT_PRINTS - /* special case to resolve dirty Ptt_prints */ - if(inAnsi && - mf.end - mf.dispe > 2 && - *(mf.dispe+1) == '*') - { - int i; - char buf[64]; // make sure ptt_prints will not exceed - - memset(buf, 0, sizeof(buf)); - memcpy(buf, mf.dispe, 3); // ^[*s - mf.dispe += 2; - - if(bpref.rawmode) - buf[0] = '*'; - else - { + /* special case to resolve dirty Ptt_prints */ + if(inAnsi && + mf.end - mf.dispe > 2 && + *(mf.dispe+1) == '*') + { + int i; + char buf[64]; // make sure ptt_prints will not exceed + + memset(buf, 0, sizeof(buf)); + memcpy(buf, mf.dispe, 3); // ^[*s + mf.dispe += 2; + + if(bpref.rawmode) + buf[0] = '*'; + else + { #ifdef LOW_SECURITY # define PTTPRINT_WARN_PATTERN "slpnbm" #else # define PTTPRINT_WARN_PATTERN "slpn" #endif // LOW_SECURITY - if(strchr(PTTPRINT_WARN_PATTERN, buf[2]) != NULL) - { - override_attr = ANSI_COLOR(1;37;41); - override_msg = PMORE_MSG_WARN_FAKEUSERINFO; - } - Ptt_prints(buf, sizeof(buf), NO_RELOAD); // result in buf - } - i = strlen(buf); - - if (col + i > maxcol) - i = maxcol - col; - if(i > 0) - { - buf[i] = 0; - col += i; - outs(buf); - } - inAnsi = 0; - } else + if(strchr(PTTPRINT_WARN_PATTERN, buf[2]) != NULL) + { + override_attr = ANSI_COLOR(1;37;41); + override_msg = PMORE_MSG_WARN_FAKEUSERINFO; + } + Ptt_prints(buf, sizeof(buf), NO_RELOAD); // result in buf + } + i = strlen(buf); + + if (col + i > maxcol) + i = maxcol - col; + if(i > 0) + { + buf[i] = 0; + col += i; + outs(buf); + } + inAnsi = 0; + } else #endif - if(inAnsi) - { - switch(bpref.rawmode) - { - case MFDISP_RAW_NOANSI: - /* TODO - * col++ here may be buggy. */ - if(col < t_columns) - { - /* we tried our best to determine */ - if(xprefix > 0) - xprefix --; - else - { - outs(ANSI_COLOR(1) "*"); - col++; - } - } - break; - case MFDISP_RAW_PLAIN: - break; - default: - outc(ESC_CHR); - break; - } - } else { - int canOutput = 0; - /* if col > maxcol, - * because we have the space for - * "indicators" (one byte), - * so we can tolerate one more byte. - */ - if(col <= maxcol) // normal case - canOutput = 1; - else if (bpref.oldwrapmode && // oldwrapmode - col < t_columns) - { - canOutput = 1; - newline = MFDISP_NEWLINE_MOVE; - } else { - int off = 0; - // put more efforts to determine - // if we can use indicator space - // determine real offset between \n - if(predicted_linewidth < 0) - predicted_linewidth = col + 1 + - MFDISP_PREDICT_LINEWIDTH(mf.dispe+1); - off = predicted_linewidth - (col + 1); - - if (col + off <= (maxcol+1)) - { - canOutput = 1; // indicator space - } + if(inAnsi) + { + switch(bpref.rawmode) + { + case MFDISP_RAW_NOANSI: + /* TODO + * col++ here may be buggy. */ + if(col < t_columns) + { + /* we tried our best to determine */ + if(xprefix > 0) + xprefix --; + else + { + outs(ANSI_COLOR(1) "*"); + col++; + } + } + break; + case MFDISP_RAW_PLAIN: + break; + default: + outc(ESC_CHR); + break; + } + } else { + int canOutput = 0; + /* if col > maxcol, + * because we have the space for + * "indicators" (one byte), + * so we can tolerate one more byte. + */ + if(col <= maxcol) // normal case + canOutput = 1; + else if (bpref.oldwrapmode && // oldwrapmode + col < t_columns) + { + canOutput = 1; + newline = MFDISP_NEWLINE_MOVE; + } else { + int off = 0; + // put more efforts to determine + // if we can use indicator space + // determine real offset between \n + if(predicted_linewidth < 0) + predicted_linewidth = col + 1 + + MFDISP_PREDICT_LINEWIDTH(mf.dispe+1); + off = predicted_linewidth - (col + 1); + + if (col + off <= (maxcol+1)) + { + canOutput = 1; // indicator space + } #ifdef PMORE_TRADITIONAL_FULLCOL - else if (col + off < t_columns) - { - canOutput = 1; - newline = MFDISP_NEWLINE_MOVE; - } + else if (col + off < t_columns) + { + canOutput = 1; + newline = MFDISP_NEWLINE_MOVE; + } #endif - } + } - if(canOutput) - { - /* the real place to output text - */ + if(canOutput) + { + /* the real place to output text + */ #ifdef PMORE_USE_DBCS_WRAP - if(mf.xpos > 0 && dbcs_incomplete && col < 2) - { - /* col = 0 or 1 only */ - if(col == 0) /* no indicators */ - c = ' '; - else if(!bpref.oldwrapmode && bpref.wrapindicator) - c = ' '; - } - - if (dbcs_incomplete) - dbcs_incomplete = NULL; - else if(PMORE_DBCS_LEADING(c)) - dbcs_incomplete = mf.dispe; + if(mf.xpos > 0 && dbcs_incomplete && col < 2) + { + /* col = 0 or 1 only */ + if(col == 0) /* no indicators */ + c = ' '; + else if(!bpref.oldwrapmode && bpref.wrapindicator) + c = ' '; + } + + if (dbcs_incomplete) + dbcs_incomplete = NULL; + else if(PMORE_DBCS_LEADING(c)) + dbcs_incomplete = mf.dispe; #endif - if(xprefix > 0) - xprefix --; - else - { - outc(c); - col++; - } - - if (srlen == 0) - outs(ANSI_RESET); - if(srlen >= 0) - srlen --; - } - else - /* wrap modes */ - if(mf.xpos > 0 || bpref.wrapmode == MFDISP_WRAP_TRUNCATE) - { - breaknow = 1; - mf.trunclines ++; - MFDISP_SKIPCURLINE(); - wrapping = 0; - } - else if (bpref.wrapmode == MFDISP_WRAP_WRAP) - { - breaknow = 1; - wrapping = 1; - mf.wraplines ++; + if(xprefix > 0) + xprefix --; + else + { + outc(c); + col++; + } + + if (srlen == 0) + outs(ANSI_RESET); + if(srlen >= 0) + srlen --; + } + else + /* wrap modes */ + if(mf.xpos > 0 || bpref.wrapmode == MFDISP_WRAP_TRUNCATE) + { + breaknow = 1; + mf.trunclines ++; + MFDISP_SKIPCURLINE(); + wrapping = 0; + } + else if (bpref.wrapmode == MFDISP_WRAP_WRAP) + { + breaknow = 1; + wrapping = 1; + mf.wraplines ++; #ifdef PMORE_USE_DBCS_WRAP - if(dbcs_incomplete) - { - mf.dispe = dbcs_incomplete; - dbcs_incomplete = NULL; - /* to be more dbcs safe, - * use the followings to - * erase printed character. - */ - if(col > 0) { - /* TODO BUG BUGGY - * using move is maybe actually non-sense - * because BBS terminal system cannot - * display this when ANSI escapes were used - * in same line. However, on most - * situation this works. - * So we used an alternative, forced ANSI - * move command. - */ - // move(lines, col-1); - char ansicmd[16]; - sprintf(ansicmd, ANSI_MOVETO(%d,%d), - lines+1, col-1+1); - /* to preven ANSI ESCAPE being tranlated as - * DBCS trailing byte. */ - outc(' '); - /* move back one column */ - outs(ansicmd); - /* erase it (previous leading byte)*/ - outc(' '); - /* go to correct position */ - outs(ansicmd); - } - } + if(dbcs_incomplete) + { + mf.dispe = dbcs_incomplete; + dbcs_incomplete = NULL; + /* to be more dbcs safe, + * use the followings to + * erase printed character. + */ + if(col > 0) { + /* TODO BUG BUGGY + * using move is maybe actually non-sense + * because BBS terminal system cannot + * display this when ANSI escapes were used + * in same line. However, on most + * situation this works. + * So we used an alternative, forced ANSI + * move command. + */ + // move(lines, col-1); + char ansicmd[16]; + sprintf(ansicmd, ANSI_MOVETO(%d,%d), + lines+1, col-1+1); + /* to preven ANSI ESCAPE being tranlated as + * DBCS trailing byte. */ + outc(' '); + /* move back one column */ + outs(ansicmd); + /* erase it (previous leading byte)*/ + outc(' '); + /* go to correct position */ + outs(ansicmd); + } + } #endif - } - } - } - if(!breaknow) - mf.dispe ++; - } - if(flResetColor) - outs(ANSI_RESET); - - /* "wrapping" should be only in normal text section. - * We don't support wrap within scrolling, - * so if we have to wrap, invalidate all lines. - */ - if(breaknow) - { - if(wrapping) - MFDISP_FORCEDIRTY2BOT(); - - if(!bpref.oldwrapmode && bpref.wrapindicator && col < t_columns) - { - if(wrapping) - outs(MFDISP_WRAP_INDICATOR); - else - outs(MFDISP_TRUNC_INDICATOR); - } else { - outs(ANSI_RESET); - } - } - else - wrapping = 0; - } - - if(mf.dispe < mf.end && *mf.dispe == '\n') - mf.dispe ++; - // else, we're in wrap mode. - - switch(newline) - { - case MFDISP_NEWLINE_SKIP: - break; - case MFDISP_NEWLINE_CLEAR: - FORCE_CLRTOEOL(); - outc('\n'); - break; - case MFDISP_NEWLINE_MOVE: - move(lines+1, 0); - break; - } - lines ++; + } + } + } + if(!breaknow) + mf.dispe ++; + } + if(flResetColor) + outs(ANSI_RESET); + + /* "wrapping" should be only in normal text section. + * We don't support wrap within scrolling, + * so if we have to wrap, invalidate all lines. + */ + if(breaknow) + { + if(wrapping) + MFDISP_FORCEDIRTY2BOT(); + + if(!bpref.oldwrapmode && bpref.wrapindicator && col < t_columns) + { + if(wrapping) + outs(MFDISP_WRAP_INDICATOR); + else + outs(MFDISP_TRUNC_INDICATOR); + } else { + outs(ANSI_RESET); + } + } + else + wrapping = 0; + } + + if(mf.dispe < mf.end && *mf.dispe == '\n') + mf.dispe ++; + // else, we're in wrap mode. + + switch(newline) + { + case MFDISP_NEWLINE_SKIP: + break; + case MFDISP_NEWLINE_CLEAR: + FORCE_CLRTOEOL(); + outc('\n'); + break; + case MFDISP_NEWLINE_MOVE: + move(lines+1, 0); + break; + } + lines ++; } /* * we've displayed the file. @@ -1636,36 +1636,36 @@ mf_display() */ if(mf.disps == mf.maxdisps && mf.dispe < mf.end) { - /* - * never mind if that's caused by separator - * however this code is rarely used now. - * only if no preload file. - */ - if (bpref.separator & MFDISP_SEP_WRAP && - mf.wraplines == 1 && - mf.lineno < fh.lines) - { - /* - * o.k, now we know maxline should be one line forward. - */ - mf_determinemaxdisps(+1, 1); - } else - { - /* not caused by separator? - * ok, then it's by wrapped lines. - * - * old flavor: go bottom: - * mf_determinemaxdisps(0) - * however we have "update" method now, - * so we can achieve more user friendly behavior. - */ - mf_determinemaxdisps(+mf.wraplines, 1); - } + /* + * never mind if that's caused by separator + * however this code is rarely used now. + * only if no preload file. + */ + if (bpref.separator & MFDISP_SEP_WRAP && + mf.wraplines == 1 && + mf.lineno < fh.lines) + { + /* + * o.k, now we know maxline should be one line forward. + */ + mf_determinemaxdisps(+1, 1); + } else + { + /* not caused by separator? + * ok, then it's by wrapped lines. + * + * old flavor: go bottom: + * mf_determinemaxdisps(0) + * however we have "update" method now, + * so we can achieve more user friendly behavior. + */ + mf_determinemaxdisps(+mf.wraplines, 1); + } } mf.oldlineno = mf.lineno; if (needMove2bot) - move(b_lines, 0); + move(b_lines, 0); } /* --------------------- MAIN PROCEDURE ------------------------- */ @@ -1726,10 +1726,10 @@ PMORE_UINAV_FORWARDPAGE() int i = mf.dispedlines - 1; if(mf_viewedAll()) - return; + return; if(i < 1) - i = 1; + i = 1; mf_forward(i); } @@ -1737,7 +1737,7 @@ MFPROTO void PMORE_UINAV_FORWARDLINE() { if(mf_viewedAll()) - return; + return; mf_forward(1); } @@ -1776,701 +1776,701 @@ pmore(char *fpath, int promptend) STATINC(STAT_MORE); if(!mf_attach(fpath)) { - REENTRANT_RESTORE(); - return -1; + REENTRANT_RESTORE(); + return -1; } clear(); while(!flExit) { - if(invalidate) - { - mf_display(); - invalidate = 0; - } + if(invalidate) + { + mf_display(); + invalidate = 0; + } - /* in current implementation, - * we want to invalidate for each keypress. - */ - invalidate = 1; + /* in current implementation, + * we want to invalidate for each keypress. + */ + invalidate = 1; -#ifdef PMORE_TRADITIONAL_PROMPTEND +#ifdef PMORE_TRADITIONAL_PROMPTEND - if(promptend == NA) - { + if(promptend == NA) + { #ifdef PMORE_USE_ASCII_MOVIE - if(mfmovie.mode == MFDISP_MOVIE_DETECTED) - { - /* quick auto play */ - mfmovie.mode = MFDISP_MOVIE_YES; - RESET_MOVIE(); - mfmovie.mode = MFDISP_MOVIE_PLAYING; - mf_determinemaxdisps(0, 0); // display until last line - mf_movieNextFrame(); - MFDISP_DIRTY(); - continue; - } else if (mfmovie.mode != MFDISP_MOVIE_PLAYING) + if(mfmovie.mode == MFDISP_MOVIE_DETECTED) + { + /* quick auto play */ + mfmovie.mode = MFDISP_MOVIE_YES; + RESET_MOVIE(); + mfmovie.mode = MFDISP_MOVIE_PLAYING; + mf_determinemaxdisps(0, 0); // display until last line + mf_movieNextFrame(); + MFDISP_DIRTY(); + continue; + } else if (mfmovie.mode != MFDISP_MOVIE_PLAYING) #endif - break; - } + break; + } #else - if(promptend == NA && mf_viewedAll()) - break; + if(promptend == NA && mf_viewedAll()) + break; #endif - move(b_lines, 0); - // clrtoeol(); // this shall be done in mf_display to speed up. - + move(b_lines, 0); + // clrtoeol(); // this shall be done in mf_display to speed up. + #ifdef USE_BBSLUA - // TODO prompt BBS Lua status here. + // TODO prompt BBS Lua status here. #endif // USE_BBSLUA #ifdef PMORE_USE_ASCII_MOVIE - switch (mfmovie.mode) - { - case MFDISP_MOVIE_UNKNOWN: - mfmovie.mode = MFDISP_MOVIE_NO; - break; - - case MFDISP_MOVIE_DETECTED: - mfmovie.mode = MFDISP_MOVIE_YES; - { - // query if user wants to play movie. - - int w = t_columns-1; - const char *s = PMORE_MSG_MOVIE_DETECTED; - - outs(ANSI_RESET ANSI_COLOR(1;33;44)); - w -= strlen(s); outs(s); - - while(w-- > 0) outc(' '); outs(ANSI_RESET ANSI_CLRTOEND); - w = tolower(igetch()); - - if( w != 'n' && - w != KEY_UP && w != KEY_LEFT && - w != 'q') - { - RESET_MOVIE(); - mfmovie.mode = MFDISP_MOVIE_PLAYING; - mf_determinemaxdisps(0, 0); // display until last line - mf_movieNextFrame(); - MFDISP_DIRTY(); - // remove override messages - RESET_OVERRIDE_MSG(); - continue; - } - /* else, we have to clean up. */ - move(b_lines, 0); - clrtoeol(); - } - break; - - case MFDISP_MOVIE_PLAYING_OLD: - case MFDISP_MOVIE_PLAYING: - - mf_moviePromptPlaying(0); - - // doing refresh() here is better, - // to prevent that we forgot to refresh - // in SyncFrame. - refresh(); - - if(mf_movieSyncFrame()) - { - /* user did not hit anything. - * play next frame. - */ - if(mfmovie.mode == MFDISP_MOVIE_PLAYING) - { - if(!mf_movieNextFrame()) - { - STOP_MOVIE(); - - if(promptend == NA) - { - /* if we played to end, - * no need to prevent pressanykey(). - */ - flExit = 1, retval = 0; - } - } - } - else if(mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD) - { - if(mf_viewedAll()) - { - mfmovie.mode = MFDISP_MOVIE_NO; - mf_determinemaxdisps(MFNAV_PAGE, 0); - mf_forward(0); - } - else - { - if(!mfmovie.compat24) - PMORE_UINAV_FORWARDPAGE(); - else - mf_forward(22); - } - } - } else { - /* TODO simple navigation here? */ - - /* stop playing */ - if(mfmovie.mode == MFDISP_MOVIE_PLAYING) - { - STOP_MOVIE(); - if(promptend == NA) - { - flExit = 1, retval = READ_NEXT; - } - } - else if(mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD) - { - mfmovie.mode = MFDISP_MOVIE_NO; - mf_determinemaxdisps(MFNAV_PAGE, 0); - mf_forward(0); - } - } - continue; - } + switch (mfmovie.mode) + { + case MFDISP_MOVIE_UNKNOWN: + mfmovie.mode = MFDISP_MOVIE_NO; + break; + + case MFDISP_MOVIE_DETECTED: + mfmovie.mode = MFDISP_MOVIE_YES; + { + // query if user wants to play movie. + + int w = t_columns-1; + const char *s = PMORE_MSG_MOVIE_DETECTED; + + outs(ANSI_RESET ANSI_COLOR(1;33;44)); + w -= strlen(s); outs(s); + + while(w-- > 0) outc(' '); outs(ANSI_RESET ANSI_CLRTOEND); + w = tolower(igetch()); + + if( w != 'n' && + w != KEY_UP && w != KEY_LEFT && + w != 'q') + { + RESET_MOVIE(); + mfmovie.mode = MFDISP_MOVIE_PLAYING; + mf_determinemaxdisps(0, 0); // display until last line + mf_movieNextFrame(); + MFDISP_DIRTY(); + // remove override messages + RESET_OVERRIDE_MSG(); + continue; + } + /* else, we have to clean up. */ + move(b_lines, 0); + clrtoeol(); + } + break; + + case MFDISP_MOVIE_PLAYING_OLD: + case MFDISP_MOVIE_PLAYING: + + mf_moviePromptPlaying(0); + + // doing refresh() here is better, + // to prevent that we forgot to refresh + // in SyncFrame. + refresh(); + + if(mf_movieSyncFrame()) + { + /* user did not hit anything. + * play next frame. + */ + if(mfmovie.mode == MFDISP_MOVIE_PLAYING) + { + if(!mf_movieNextFrame()) + { + STOP_MOVIE(); + + if(promptend == NA) + { + /* if we played to end, + * no need to prevent pressanykey(). + */ + flExit = 1, retval = 0; + } + } + } + else if(mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD) + { + if(mf_viewedAll()) + { + mfmovie.mode = MFDISP_MOVIE_NO; + mf_determinemaxdisps(MFNAV_PAGE, 0); + mf_forward(0); + } + else + { + if(!mfmovie.compat24) + PMORE_UINAV_FORWARDPAGE(); + else + mf_forward(22); + } + } + } else { + /* TODO simple navigation here? */ + + /* stop playing */ + if(mfmovie.mode == MFDISP_MOVIE_PLAYING) + { + STOP_MOVIE(); + if(promptend == NA) + { + flExit = 1, retval = READ_NEXT; + } + } + else if(mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD) + { + mfmovie.mode = MFDISP_MOVIE_NO; + mf_determinemaxdisps(MFNAV_PAGE, 0); + mf_forward(0); + } + } + continue; + } #endif - /* PRINT BOTTOM STATUS BAR */ + /* PRINT BOTTOM STATUS BAR */ #ifdef DEBUG - if(debug) - { - /* in debug mode don't print ANSI codes - * because themselves are buggy. - */ - prints("L#%ld(w%ld,lp%ld) pmt=%d Dsp:%08X/%08X/%08X, " - "F:%08X/%08X(%d) tScr(%dx%d)", - mf.lineno, mf.wraplines, mf.lastpagelines, - promptend, - (unsigned int)mf.disps, - (unsigned int)mf.maxdisps, - (unsigned int)mf.dispe, - (unsigned int)mf.start, (unsigned int)mf.end, - (int)mf.len, - t_columns, - t_lines - ); - } - else + if(debug) + { + /* in debug mode don't print ANSI codes + * because themselves are buggy. + */ + prints("L#%ld(w%ld,lp%ld) pmt=%d Dsp:%08X/%08X/%08X, " + "F:%08X/%08X(%d) tScr(%dx%d)", + mf.lineno, mf.wraplines, mf.lastpagelines, + promptend, + (unsigned int)mf.disps, + (unsigned int)mf.maxdisps, + (unsigned int)mf.dispe, + (unsigned int)mf.start, (unsigned int)mf.end, + (int)mf.len, + t_columns, + t_lines + ); + } + else #endif - { - char *printcolor; - - char buf[256]; // orz - int prefixlen = 0; - int barlen = 0; - int postfix1len = 0, postfix2len = 0; - - int progress = - (int)((unsigned long)(mf.dispe-mf.start) * 100 / mf.len); - /* - * page determination is hard. - * should we use starting line, or finishing line? - */ - int nowpage = - (int)((mf.lineno + mf.dispedlines/2) / MFNAV_PAGE)+1; - int allpages = -1; /* unknown yet */ - if (mf.maxlinenoS >= 0) - { - allpages = - (int)((mf.maxlinenoS + mf.lastpagelines - - ((bpref.separator & MFDISP_SEP_WRAP) && - (fh.lines >= 0) ? 0:1)) / MFNAV_PAGE)+1; - if (mf.lineno >= mf.maxlinenoS || nowpage > allpages) - nowpage = allpages; - /* - nowpage = - (int)((mf.lineno + mf.dispedlines-2) / MFNAV_PAGE)+1 ; - */ - } - /* why -2 and -1? - * because we want to determine by nav_page, - * and mf.dispedlines is based on disp_page (nav_page+1) - * mf.lastpagelines is based on nav_page - */ - - if(mf_viewedAll()) - printcolor = ANSI_COLOR(37;44); - else if (mf_viewedNone()) - printcolor = ANSI_COLOR(33;45); - else - printcolor = ANSI_COLOR(34;46); - - outs(ANSI_RESET); - outs(printcolor); - - if(bpref.oldstatusbar) - { - - prints(" ÂsÄý P.%d(%d%%) %s %-30.30s%s", - nowpage, - progress, - ANSI_COLOR(31;47), - "(h)" - ANSI_COLOR(30) "¨D§U " - ANSI_COLOR(31) "¡÷¡õ[PgUp][", - "PgDn][Home][End]" - ANSI_COLOR(30) "´å¼Ð²¾°Ê " - ANSI_COLOR(31) "¡ö[q]" - ANSI_COLOR(30) "µ²§ô "); - - } else { - - if(allpages >= 0) - sprintf(buf, - " ÂsÄý ²Ä %1d/%1d ¶ (%3d%%) ", - nowpage, - allpages, - progress - ); - else - sprintf(buf, - " ÂsÄý ²Ä %1d ¶ (%3d%%) ", - nowpage, - progress - ); - outs(buf); prefixlen += strlen(buf); - - outs(ANSI_COLOR(1;30;47)); - - if(override_msg) - { - buf[0] = 0; - if(override_attr) outs(override_attr); - snprintf(buf, sizeof(buf), override_msg); - RESET_OVERRIDE_MSG(); - } - else - if(mf.xpos > 0) - { - snprintf(buf, sizeof(buf), - " Åã¥Ü½d³ò: %d~%d Äæ¦ì, %02d~%02d ¦æ", - (int)mf.xpos+1, - (int)(mf.xpos + t_columns-(mf.trunclines ? 2 : 1)), - (int)(mf.lineno + 1), - (int)(mf.lineno + mf.dispedlines) - ); - } else { - snprintf(buf, sizeof(buf), - " ¥Ø«eÅã¥Ü: ²Ä %02d~%02d ¦æ", - (int)(mf.lineno + 1), - (int)(mf.lineno + mf.dispedlines) - ); - } - - outs(buf); prefixlen += strlen(buf); - - postfix1len = 12; // check msg below - postfix2len = 10; - if(mf_viewedAll()) postfix1len = 17; - - if (prefixlen + postfix1len + postfix2len + 1 > t_columns) - { - postfix1len = 0; - if (prefixlen + postfix1len + postfix2len + 1 > t_columns) - postfix2len = 0; - } - barlen = t_columns - 1 - postfix1len - postfix2len - prefixlen; - - while(barlen-- > 0) - outc(' '); - - if(postfix1len > 0) - outs( - mf_viewedAll() ? - ANSI_COLOR(0;31;47)"(y)" ANSI_COLOR(30) "¦^«H" - ANSI_COLOR(31) "(X/%)" ANSI_COLOR(30) "±À¤å " - : - ANSI_COLOR(0;31;47) "(h)" - ANSI_COLOR(30) "«öÁ仡©ú " - ); - if(postfix2len > 0) - outs( - ANSI_COLOR(0;31;47) "¡ö[q]" - ANSI_COLOR(30) "Â÷¶} " - ); - } - outs(ANSI_RESET); - FORCE_CLRTOEOL(); - } - - /* igetch() will do refresh(); */ - ch = igetch(); - switch (ch) { - /* -------------- NEW EXITING KEYS ------------------ */ + { + char *printcolor; + + char buf[256]; // orz + int prefixlen = 0; + int barlen = 0; + int postfix1len = 0, postfix2len = 0; + + int progress = + (int)((unsigned long)(mf.dispe-mf.start) * 100 / mf.len); + /* + * page determination is hard. + * should we use starting line, or finishing line? + */ + int nowpage = + (int)((mf.lineno + mf.dispedlines/2) / MFNAV_PAGE)+1; + int allpages = -1; /* unknown yet */ + if (mf.maxlinenoS >= 0) + { + allpages = + (int)((mf.maxlinenoS + mf.lastpagelines - + ((bpref.separator & MFDISP_SEP_WRAP) && + (fh.lines >= 0) ? 0:1)) / MFNAV_PAGE)+1; + if (mf.lineno >= mf.maxlinenoS || nowpage > allpages) + nowpage = allpages; + /* + nowpage = + (int)((mf.lineno + mf.dispedlines-2) / MFNAV_PAGE)+1 ; + */ + } + /* why -2 and -1? + * because we want to determine by nav_page, + * and mf.dispedlines is based on disp_page (nav_page+1) + * mf.lastpagelines is based on nav_page + */ + + if(mf_viewedAll()) + printcolor = ANSI_COLOR(37;44); + else if (mf_viewedNone()) + printcolor = ANSI_COLOR(33;45); + else + printcolor = ANSI_COLOR(34;46); + + outs(ANSI_RESET); + outs(printcolor); + + if(bpref.oldstatusbar) + { + + prints(" ÂsÄý P.%d(%d%%) %s %-30.30s%s", + nowpage, + progress, + ANSI_COLOR(31;47), + "(h)" + ANSI_COLOR(30) "¨D§U " + ANSI_COLOR(31) "¡÷¡õ[PgUp][", + "PgDn][Home][End]" + ANSI_COLOR(30) "´å¼Ð²¾°Ê " + ANSI_COLOR(31) "¡ö[q]" + ANSI_COLOR(30) "µ²§ô "); + + } else { + + if(allpages >= 0) + sprintf(buf, + " ÂsÄý ²Ä %1d/%1d ¶ (%3d%%) ", + nowpage, + allpages, + progress + ); + else + sprintf(buf, + " ÂsÄý ²Ä %1d ¶ (%3d%%) ", + nowpage, + progress + ); + outs(buf); prefixlen += strlen(buf); + + outs(ANSI_COLOR(1;30;47)); + + if(override_msg) + { + buf[0] = 0; + if(override_attr) outs(override_attr); + snprintf(buf, sizeof(buf), override_msg); + RESET_OVERRIDE_MSG(); + } + else + if(mf.xpos > 0) + { + snprintf(buf, sizeof(buf), + " Åã¥Ü½d³ò: %d~%d Äæ¦ì, %02d~%02d ¦æ", + (int)mf.xpos+1, + (int)(mf.xpos + t_columns-(mf.trunclines ? 2 : 1)), + (int)(mf.lineno + 1), + (int)(mf.lineno + mf.dispedlines) + ); + } else { + snprintf(buf, sizeof(buf), + " ¥Ø«eÅã¥Ü: ²Ä %02d~%02d ¦æ", + (int)(mf.lineno + 1), + (int)(mf.lineno + mf.dispedlines) + ); + } + + outs(buf); prefixlen += strlen(buf); + + postfix1len = 12; // check msg below + postfix2len = 10; + if(mf_viewedAll()) postfix1len = 17; + + if (prefixlen + postfix1len + postfix2len + 1 > t_columns) + { + postfix1len = 0; + if (prefixlen + postfix1len + postfix2len + 1 > t_columns) + postfix2len = 0; + } + barlen = t_columns - 1 - postfix1len - postfix2len - prefixlen; + + while(barlen-- > 0) + outc(' '); + + if(postfix1len > 0) + outs( + mf_viewedAll() ? + ANSI_COLOR(0;31;47)"(y)" ANSI_COLOR(30) "¦^«H" + ANSI_COLOR(31) "(X/%)" ANSI_COLOR(30) "±À¤å " + : + ANSI_COLOR(0;31;47) "(h)" + ANSI_COLOR(30) "«öÁ仡©ú " + ); + if(postfix2len > 0) + outs( + ANSI_COLOR(0;31;47) "¡ö[q]" + ANSI_COLOR(30) "Â÷¶} " + ); + } + outs(ANSI_RESET); + FORCE_CLRTOEOL(); + } + + /* igetch() will do refresh(); */ + ch = igetch(); + switch (ch) { + /* -------------- NEW EXITING KEYS ------------------ */ #ifdef RET_DOREPLY - case 'r': case 'R': - flExit = 1, retval = RET_DOREPLY; - break; - case 'Y': case 'y': - flExit = 1, retval = RET_DOREPLYALL; - break; + case 'r': case 'R': + flExit = 1, retval = RET_DOREPLY; + break; + case 'Y': case 'y': + flExit = 1, retval = RET_DOREPLYALL; + break; #endif #ifdef RET_DORECOMMEND - // recommend - case '%': - case 'X': - flExit = 1, retval = RET_DORECOMMEND; - break; + // recommend + case '%': + case 'X': + flExit = 1, retval = RET_DORECOMMEND; + break; #endif #ifdef RET_DOQUERYINFO - case 'Q': // info query interface - flExit = 1, retval = RET_DOQUERYINFO; - break; + case 'Q': // info query interface + flExit = 1, retval = RET_DOQUERYINFO; + break; #endif #ifdef RET_DOSYSOPEDIT - case 'E': - flExit = 1, retval = RET_DOSYSOPEDIT; - break; + case 'E': + flExit = 1, retval = RET_DOSYSOPEDIT; + break; #endif #ifdef RET_DOCHESSREPLAY - case 'z': - flExit = 1, retval = RET_DOCHESSREPLAY; - break; + case 'z': + flExit = 1, retval = RET_DOCHESSREPLAY; + break; #endif #ifdef RET_COPY2TMP - case Ctrl('T'): - flExit = 1, retval = RET_COPY2TMP; - break; + case Ctrl('T'): + flExit = 1, retval = RET_COPY2TMP; + break; #endif #ifdef RET_SELECTBRD - case 's': - flExit = 1, retval = RET_SELECTBRD; - break; + case 's': + flExit = 1, retval = RET_SELECTBRD; + break; #endif - /* ------------------ EXITING KEYS ------------------ */ - case 'A': - flExit = 1, retval = AUTHOR_PREV; - break; - case 'a': - flExit = 1, retval = AUTHOR_NEXT; - break; - case 'F': case 'f': - flExit = 1, retval = READ_NEXT; - break; - case 'B': case 'b': - flExit = 1, retval = READ_PREV; - break; - case KEY_LEFT: - flExit = 1, retval = FULLUPDATE; - break; - case 'q': - flExit = 1, retval = FULLUPDATE; - break; - - /* from Kaede, thread reading */ - case ']': - case '+': - flExit = 1, retval = RELATE_NEXT; - break; - case '[': - case '-': - flExit = 1, retval = RELATE_PREV; - break; - case '=': - flExit = 1, retval = RELATE_FIRST; - break; - /* ------------------ NAVIGATION KEYS ------------------ */ - /* Simple Navigation */ - case 'k': case 'K': - mf_backward(1); - break; - case 'j': case 'J': - PMORE_UINAV_FORWARDLINE(); - break; - - case Ctrl('F'): - case KEY_PGDN: - PMORE_UINAV_FORWARDPAGE(); - break; - case Ctrl('B'): - case KEY_PGUP: - mf_backward(MFNAV_PAGE); - break; - - case '0': - case 'g': - case KEY_HOME: - mf_goTop(); - break; - case '$': - case 'G': - case KEY_END: - mf_goBottom(); + /* ------------------ EXITING KEYS ------------------ */ + case 'A': + flExit = 1, retval = AUTHOR_PREV; + break; + case 'a': + flExit = 1, retval = AUTHOR_NEXT; + break; + case 'F': case 'f': + flExit = 1, retval = READ_NEXT; + break; + case 'B': case 'b': + flExit = 1, retval = READ_PREV; + break; + case KEY_LEFT: + flExit = 1, retval = FULLUPDATE; + break; + case 'q': + flExit = 1, retval = FULLUPDATE; + break; + + /* from Kaede, thread reading */ + case ']': + case '+': + flExit = 1, retval = RELATE_NEXT; + break; + case '[': + case '-': + flExit = 1, retval = RELATE_PREV; + break; + case '=': + flExit = 1, retval = RELATE_FIRST; + break; + /* ------------------ NAVIGATION KEYS ------------------ */ + /* Simple Navigation */ + case 'k': case 'K': + mf_backward(1); + break; + case 'j': case 'J': + PMORE_UINAV_FORWARDLINE(); + break; + + case Ctrl('F'): + case KEY_PGDN: + PMORE_UINAV_FORWARDPAGE(); + break; + case Ctrl('B'): + case KEY_PGUP: + mf_backward(MFNAV_PAGE); + break; + + case '0': + case 'g': + case KEY_HOME: + mf_goTop(); + break; + case '$': + case 'G': + case KEY_END: + mf_goBottom(); #ifdef PMORE_ACCURATE_WRAPEND - /* allright. in design of pmore, - * it's possible that when user navigates to file end, - * a wrapped line made nav not 100%. - */ - mf_display(); - invalidate = 0; - - if(!mf_viewedAll()) - { - /* one more try. */ - mf_goBottom(); - invalidate = 1; - } + /* allright. in design of pmore, + * it's possible that when user navigates to file end, + * a wrapped line made nav not 100%. + */ + mf_display(); + invalidate = 0; + + if(!mf_viewedAll()) + { + /* one more try. */ + mf_goBottom(); + invalidate = 1; + } #endif - break; - - /* Compound Navigation */ - case '.': - if(mf.xpos == 0) - mf.xpos ++; - mf.xpos ++; - break; - case ',': - if(mf.xpos > 0) - mf.xpos --; - break; - case '\t': - case '>': - //if(mf.xpos == 0 || mf.trunclines) - mf.xpos = (mf.xpos/8+1)*8; - break; - /* acronym form shift-tab, ^[[Z */ - /* however some terminals does not send that. */ - case KEY_STAB: - case '<': - mf.xpos = (mf.xpos/8-1)*8; - if(mf.xpos < 0) mf.xpos = 0; - break; - case '\r': - case '\n': - case KEY_DOWN: - if (mf_viewedAll() || - (promptend == 2 && (ch == '\r' || ch == '\n'))) - flExit = 1, retval = READ_NEXT; - else - PMORE_UINAV_FORWARDLINE(); - break; - - case ' ': - if (mf_viewedAll()) - flExit = 1, retval = READ_NEXT; - else - PMORE_UINAV_FORWARDPAGE(); - break; - case KEY_RIGHT: - if(mf_viewedAll()) - promptend = 0, flExit = 1, retval = 0; - else - { - /* if mf.xpos > 0, widenav mode. */ - /* because we have other keys to do so, - * disable it now. - */ - /* - if(mf.trunclines > 0) - { - if(mf.xpos == 0) - mf.xpos++; - mf.xpos++; - } - else if (mf.xpos == 0) - */ - PMORE_UINAV_FORWARDPAGE(); - } - break; - - case KEY_UP: - if(mf_viewedNone()) - flExit = 1, retval = READ_PREV; - else - mf_backward(1); - break; - case Ctrl('H'): - if(mf_viewedNone()) - flExit = 1, retval = READ_PREV; - else - mf_backward(MFNAV_PAGE); - break; - - case 't': - if (mf_viewedAll()) - flExit = 1, retval = RELATE_NEXT; - else - PMORE_UINAV_FORWARDPAGE(); - break; - /* ------------------ SEARCH KEYS ------------------ */ - case '/': - { - char sbuf[81] = ""; - char ans[4] = "n"; - - if(sr.search_str) { - free(sr.search_str); - sr.search_str = NULL; - } - - getdata(b_lines - 1, 0, PMORE_MSG_SEARCH_KEYWORD, sbuf, - 40, DOECHO); - - if (sbuf[0]) { - if (getdata(b_lines - 1, 0, "°Ï¤À¤j¤p¼g(Y/N/Q)? [N] ", - ans, sizeof(ans), LCECHO) && *ans == 'y') - sr.cmpfunc = strncmp; - else if (*ans == 'q') - sbuf[0] = 0; - else - sr.cmpfunc = strncasecmp; - } - sr.len = strlen(sbuf); - if(sr.len) sr.search_str = (unsigned char*)strdup(sbuf); - mf_search(MFSEARCH_FORWARD); - MFDISP_DIRTY(); - } - break; - case 'n': - mf_search(MFSEARCH_FORWARD); - break; - case 'N': - mf_search(MFSEARCH_BACKWARD); - break; - /* ------------------ SPECIAL KEYS ------------------ */ - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - case ';': case ':': - { - char buf[16] = ""; - int i = 0; - int pageMode = (ch != ':'); - if (ch >= '1' && ch <= '9') - buf[0] = ch, buf[1] = 0; - - pmore_clrtoeol(b_lines-1, 0); - getdata_buf(b_lines-1, 0, - (pageMode ? - "¸õ¦Ü¦¹¶(Yn§ï«ü©w¦æ¼Æ½Ð¦bµ²§À¥[.): " : - "¸õ¦Ü¦¹¦æ: "), - buf, 8, DOECHO); - if(buf[0]) { - i = atoi(buf); - if(buf[strlen(buf)-1] == '.') - pageMode = 0; - if(i-- > 0) - mf_goto(i * (pageMode ? MFNAV_PAGE : 1)); - } - MFDISP_DIRTY(); - } - break; - - case 'h': case 'H': case KEY_F1: - case '?': - // help - show_help(pmore_help); - MFDISP_DIRTY(); - break; + break; + + /* Compound Navigation */ + case '.': + if(mf.xpos == 0) + mf.xpos ++; + mf.xpos ++; + break; + case ',': + if(mf.xpos > 0) + mf.xpos --; + break; + case '\t': + case '>': + //if(mf.xpos == 0 || mf.trunclines) + mf.xpos = (mf.xpos/8+1)*8; + break; + /* acronym form shift-tab, ^[[Z */ + /* however some terminals does not send that. */ + case KEY_STAB: + case '<': + mf.xpos = (mf.xpos/8-1)*8; + if(mf.xpos < 0) mf.xpos = 0; + break; + case '\r': + case '\n': + case KEY_DOWN: + if (mf_viewedAll() || + (promptend == 2 && (ch == '\r' || ch == '\n'))) + flExit = 1, retval = READ_NEXT; + else + PMORE_UINAV_FORWARDLINE(); + break; + + case ' ': + if (mf_viewedAll()) + flExit = 1, retval = READ_NEXT; + else + PMORE_UINAV_FORWARDPAGE(); + break; + case KEY_RIGHT: + if(mf_viewedAll()) + promptend = 0, flExit = 1, retval = 0; + else + { + /* if mf.xpos > 0, widenav mode. */ + /* because we have other keys to do so, + * disable it now. + */ + /* + if(mf.trunclines > 0) + { + if(mf.xpos == 0) + mf.xpos++; + mf.xpos++; + } + else if (mf.xpos == 0) + */ + PMORE_UINAV_FORWARDPAGE(); + } + break; + + case KEY_UP: + if(mf_viewedNone()) + flExit = 1, retval = READ_PREV; + else + mf_backward(1); + break; + case Ctrl('H'): + if(mf_viewedNone()) + flExit = 1, retval = READ_PREV; + else + mf_backward(MFNAV_PAGE); + break; + + case 't': + if (mf_viewedAll()) + flExit = 1, retval = RELATE_NEXT; + else + PMORE_UINAV_FORWARDPAGE(); + break; + /* ------------------ SEARCH KEYS ------------------ */ + case '/': + { + char sbuf[81] = ""; + char ans[4] = "n"; + + if(sr.search_str) { + free(sr.search_str); + sr.search_str = NULL; + } + + getdata(b_lines - 1, 0, PMORE_MSG_SEARCH_KEYWORD, sbuf, + 40, DOECHO); + + if (sbuf[0]) { + if (getdata(b_lines - 1, 0, "°Ï¤À¤j¤p¼g(Y/N/Q)? [N] ", + ans, sizeof(ans), LCECHO) && *ans == 'y') + sr.cmpfunc = strncmp; + else if (*ans == 'q') + sbuf[0] = 0; + else + sr.cmpfunc = strncasecmp; + } + sr.len = strlen(sbuf); + if(sr.len) sr.search_str = (unsigned char*)strdup(sbuf); + mf_search(MFSEARCH_FORWARD); + MFDISP_DIRTY(); + } + break; + case 'n': + mf_search(MFSEARCH_FORWARD); + break; + case 'N': + mf_search(MFSEARCH_BACKWARD); + break; + /* ------------------ SPECIAL KEYS ------------------ */ + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + case ';': case ':': + { + char buf[16] = ""; + int i = 0; + int pageMode = (ch != ':'); + if (ch >= '1' && ch <= '9') + buf[0] = ch, buf[1] = 0; + + pmore_clrtoeol(b_lines-1, 0); + getdata_buf(b_lines-1, 0, + (pageMode ? + "¸õ¦Ü¦¹¶(Yn§ï«ü©w¦æ¼Æ½Ð¦bµ²§À¥[.): " : + "¸õ¦Ü¦¹¦æ: "), + buf, 8, DOECHO); + if(buf[0]) { + i = atoi(buf); + if(buf[strlen(buf)-1] == '.') + pageMode = 0; + if(i-- > 0) + mf_goto(i * (pageMode ? MFNAV_PAGE : 1)); + } + MFDISP_DIRTY(); + } + break; + + case 'h': case 'H': case KEY_F1: + case '?': + // help + show_help(pmore_help); + MFDISP_DIRTY(); + break; #ifdef PMORE_NOTIFY_NEWPREF - //let's be backward compatible! - case 'l': - case 'w': - case 'W': - case '|': - vmsg("³oÓ«öÁä¤w¾ã¦X¶i·sªº³]©w (o) ¤F"); - break; + //let's be backward compatible! + case 'l': + case 'w': + case 'W': + case '|': + vmsg("³oÓ«öÁä¤w¾ã¦X¶i·sªº³]©w (o) ¤F"); + break; #endif // PMORE_NOTIFY_NEWPREF - case '\\': // everyone loves backslash, let's keep it. - pmore_QuickRawModePref(); - MFDISP_DIRTY(); - break; + case '\\': // everyone loves backslash, let's keep it. + pmore_QuickRawModePref(); + MFDISP_DIRTY(); + break; - case 'o': - pmore_Preference(); - MFDISP_DIRTY(); - break; + case 'o': + pmore_Preference(); + MFDISP_DIRTY(); + break; #if defined(USE_BBSLUA) && defined(RET_DOBBSLUA) - case 'P': - vmsg("«D±`©êºp¡ABBS-Lua ªº¼öÁä¤w§ï¬° L ¡A½Ð§ï«ö L"); - break; - - case 'L': - case 'l': - flExit = 1, retval = RET_DOBBSLUA; - break; + case 'P': + vmsg("«D±`©êºp¡ABBS-Lua ªº¼öÁä¤w§ï¬° L ¡A½Ð§ï«ö L"); + break; + + case 'L': + case 'l': + flExit = 1, retval = RET_DOBBSLUA; + break; #endif #ifdef PMORE_USE_ASCII_MOVIE - case 'p': - /* play ascii movie again - */ - if(mfmovie.mode == MFDISP_MOVIE_YES) - { - RESET_MOVIE(); - mfmovie.mode = MFDISP_MOVIE_PLAYING; - mf_determinemaxdisps(0, 0); // display until last line - /* it is said that it's better not to go top. */ - // mf_goTop(); - mf_movieNextFrame(); - MFDISP_DIRTY(); - } - else if (mfmovie.mode == MFDISP_MOVIE_NO) - { - static char buf[10]="1"; - //move(b_lines-1, 0); - - /* - * TODO scan current page to confirm if this is a new style movie - */ - pmore_clrtoeol(b_lines-1, 0); - getdata_buf(b_lines - 1, 0, - PMORE_MSG_MOVIE_PLAYOLD_GETTIME, - buf, 8, LCECHO); - - if(buf[0]) - { - float nf = 0; - nf = atof(buf); // sscanf(buf, "%f", &nf); - RESET_MOVIE(); - - mfmovie.mode = MFDISP_MOVIE_PLAYING_OLD; - mf_float2tv(nf, &mfmovie.frameclk); - mfmovie.compat24 = 0; - /* are we really going to start? check termsize! */ - if (t_lines != 24) - { - char ans[4]; - pmore_clrtoeol(b_lines-1, 0); - getdata(b_lines - 1, 0, - PMORE_MSG_MOVIE_PLAYOLD_AS24L, - ans, 3, LCECHO); - if(ans[0] == 'n') - mfmovie.compat24 = 0; - else - mfmovie.compat24 = 1; - } - mf_determinemaxdisps(0, 0); // display until last line - MFDISP_DIRTY(); - } - } - break; + case 'p': + /* play ascii movie again + */ + if(mfmovie.mode == MFDISP_MOVIE_YES) + { + RESET_MOVIE(); + mfmovie.mode = MFDISP_MOVIE_PLAYING; + mf_determinemaxdisps(0, 0); // display until last line + /* it is said that it's better not to go top. */ + // mf_goTop(); + mf_movieNextFrame(); + MFDISP_DIRTY(); + } + else if (mfmovie.mode == MFDISP_MOVIE_NO) + { + static char buf[10]="1"; + //move(b_lines-1, 0); + + /* + * TODO scan current page to confirm if this is a new style movie + */ + pmore_clrtoeol(b_lines-1, 0); + getdata_buf(b_lines - 1, 0, + PMORE_MSG_MOVIE_PLAYOLD_GETTIME, + buf, 8, LCECHO); + + if(buf[0]) + { + float nf = 0; + nf = atof(buf); // sscanf(buf, "%f", &nf); + RESET_MOVIE(); + + mfmovie.mode = MFDISP_MOVIE_PLAYING_OLD; + mf_float2tv(nf, &mfmovie.frameclk); + mfmovie.compat24 = 0; + /* are we really going to start? check termsize! */ + if (t_lines != 24) + { + char ans[4]; + pmore_clrtoeol(b_lines-1, 0); + getdata(b_lines - 1, 0, + PMORE_MSG_MOVIE_PLAYOLD_AS24L, + ans, 3, LCECHO); + if(ans[0] == 'n') + mfmovie.compat24 = 0; + else + mfmovie.compat24 = 1; + } + mf_determinemaxdisps(0, 0); // display until last line + MFDISP_DIRTY(); + } + } + break; #endif #ifdef DEBUG - case 'd': - debug = !debug; - MFDISP_DIRTY(); - break; + case 'd': + debug = !debug; + MFDISP_DIRTY(); + break; #endif - } - /* DO NOT DO ANYTHING HERE. NOT SAFE RIGHT NOW. */ + } + /* DO NOT DO ANYTHING HERE. NOT SAFE RIGHT NOW. */ } mf_detach(); if (retval == 0 && promptend) { - pressanykey(); - clear(); + pressanykey(); + clear(); } else - outs(reset_color); + outs(reset_color); REENTRANT_RESTORE(); return retval; @@ -2480,10 +2480,10 @@ pmore(char *fpath, int promptend) static void pmore_prefEntry( - int isel, - const char *key, int szKey, - const char *text,int szText, - const char* options) + int isel, + const char *key, int szKey, + const char *text,int szText, + const char* options) { int i = 23; // print key/text @@ -2502,41 +2502,41 @@ pmore_prefEntry( i = 0; while (*options) { - if (*options == '\t') - { - // blank option, skip it. - i++, options++; - continue; - } - - if (i > 0) - outs(ANSI_COLOR(1;30) " |" ANSI_RESET); //OPTATTR_BAR " | " ANSI_RESET); - - // test if option has hotkey - if (*options && *options != '\t' && - *(options+1) && *(options+1) == '.') - { - // found hotkey - outs(ANSI_COLOR(1;31)); //OPTATTR_NORMAL_KEY); - outc(*options); - outs(ANSI_RESET); - options +=2; - } - - if (i == isel) - { - outs(ANSI_COLOR(1;36) "*");// OPTATTR_SELECTED); - } - else - outc(' '); - - while (*options && *options != '\t') - outc(*options++); - - outs(ANSI_RESET); - - if (*options) - i++, options ++; + if (*options == '\t') + { + // blank option, skip it. + i++, options++; + continue; + } + + if (i > 0) + outs(ANSI_COLOR(1;30) " |" ANSI_RESET); //OPTATTR_BAR " | " ANSI_RESET); + + // test if option has hotkey + if (*options && *options != '\t' && + *(options+1) && *(options+1) == '.') + { + // found hotkey + outs(ANSI_COLOR(1;31)); //OPTATTR_NORMAL_KEY); + outc(*options); + outs(ANSI_RESET); + options +=2; + } + + if (i == isel) + { + outs(ANSI_COLOR(1;36) "*");// OPTATTR_SELECTED); + } + else + outc(' '); + + while (*options && *options != '\t') + outc(*options++); + + outs(ANSI_RESET); + + if (*options) + i++, options ++; } outc('\n'); } @@ -2548,18 +2548,18 @@ pmore_PromptBar(const char *caption, int shadow) if (shadow) { - outs(ANSI_COLOR(0;1;30)); - for(i = 0; i+2 < t_columns ; i+=2) - outs("¢b"); - outs(ANSI_RESET "\n"); + outs(ANSI_COLOR(0;1;30)); + for(i = 0; i+2 < t_columns ; i+=2) + outs("¢b"); + outs(ANSI_RESET "\n"); } else - i = t_columns -2; + i = t_columns -2; outs(ANSI_COLOR(7)); outs(caption); for(i -= strlen(caption); i > 0; i--) - outs(" "); + outs(" "); outs(ANSI_RESET "\n"); } @@ -2574,38 +2574,38 @@ pmore_QuickRawModePref() while(1) { - move(ystart, 0); - clrtobot(); - pmore_PromptBar(PMORE_MSG_PREF_TITLE_QRAW, 0); - - // list options - pmore_prefEntry(bpref.rawmode, - "\\", 1, "¦â±mÅã¥Ü¤è¦¡:", -1, - "1.¹w³]®æ¦¡¤Æ¤º®e\t2.ì©lANSI±±¨î½X\t3.¯Â¤å¦r"); - - switch(vmsg("½Ð½Õ¾ã³]©w (1-3 ¥iª½±µ¿ï©w¡A\\¥i¤Á´«) ©Î¨ä¥¦¥ô·NÁäµ²§ô¡C")) - { - case '\\': - bpref.rawmode = (bpref.rawmode+1) % MFDISP_RAW_MODES; - break; - case '1': - bpref.rawmode = MFDISP_RAW_NA; - return; - case '2': - bpref.rawmode = MFDISP_RAW_NOANSI; - return; - case '3': - bpref.rawmode = MFDISP_RAW_PLAIN; - return; - case KEY_LEFT: - if (bpref.rawmode > 0) bpref.rawmode --; - break; - case KEY_RIGHT: - if (bpref.rawmode < MFDISP_RAW_MODES-1) bpref.rawmode ++; - break; - default: - return; - } + move(ystart, 0); + clrtobot(); + pmore_PromptBar(PMORE_MSG_PREF_TITLE_QRAW, 0); + + // list options + pmore_prefEntry(bpref.rawmode, + "\\", 1, "¦â±mÅã¥Ü¤è¦¡:", -1, + "1.¹w³]®æ¦¡¤Æ¤º®e\t2.ì©lANSI±±¨î½X\t3.¯Â¤å¦r"); + + switch(vmsg("½Ð½Õ¾ã³]©w (1-3 ¥iª½±µ¿ï©w¡A\\¥i¤Á´«) ©Î¨ä¥¦¥ô·NÁäµ²§ô¡C")) + { + case '\\': + bpref.rawmode = (bpref.rawmode+1) % MFDISP_RAW_MODES; + break; + case '1': + bpref.rawmode = MFDISP_RAW_NA; + return; + case '2': + bpref.rawmode = MFDISP_RAW_NOANSI; + return; + case '3': + bpref.rawmode = MFDISP_RAW_PLAIN; + return; + case KEY_LEFT: + if (bpref.rawmode > 0) bpref.rawmode --; + break; + case KEY_RIGHT: + if (bpref.rawmode < MFDISP_RAW_MODES-1) bpref.rawmode ++; + break; + default: + return; + } } } @@ -2622,59 +2622,59 @@ pmore_Preference() while (1) { - move(ystart, 0); - clrtobot(); - pmore_PromptBar(PMORE_MSG_PREF_TITLE, 1); - outs("\n"); - - // list options - pmore_prefEntry(bpref.rawmode, - "\\", 1, "¦â±mÅã¥Ü¤è¦¡:", -1, - "¹w³]®æ¦¡¤Æ¤º®e\tì©lANSI±±¨î½X\t¯Â¤å¦r"); - - pmore_prefEntry(bpref.wrapmode, - "w", 1, "Â_¦æ¤è¦¡:", -1, - "ª½±µºI¦æ\t¦Û°ÊÂ_¦æ"); - - pmore_prefEntry(bpref.wrapindicator, - "m", 1, "Â_¦æ²Å¸¹:", -1, - "¤£Åã¥Ü\tÅã¥Ü"); - - pmore_prefEntry(bpref.separator, - "l", 1, "¤å³¹¼ÐÀY¤À¹j½u:", -1, - "µL\t³æ¦æ\t\t¶Ç²Î¤À¹j½u¥[ªÅ¦æ"); - - pmore_prefEntry(bpref.oldstatusbar, - "t", 1, "¶Ç²Îª¬ºA¦C»PÂ_¦æ¤è¦¡: ", -1, - "°±¥Î\t±Ò¥Î"); - - switch(vmsg("½Ð½Õ¾ã³]©w©Î¨ä¥¦¥ô·NÁäµ²§ô¡C")) - { - case '\\': - case '|': - bpref.rawmode = (bpref.rawmode+1) % MFDISP_RAW_MODES; - break; - case 'w': - bpref.wrapmode = (bpref.wrapmode+1) % MFDISP_WRAP_MODES; - break; - case 'm': - bpref.wrapindicator = !bpref.wrapindicator; - break; - case 'l': - // there's no MFDISP_SEP_WRAP only mode. - if (++bpref.separator == MFDISP_SEP_WRAP) - bpref.separator ++; - bpref.separator %= MFDISP_SEP_MODES; - break; - case 't': - bpref.oldwrapmode = !bpref.oldwrapmode; - bpref.oldstatusbar = !bpref.oldstatusbar; - break; - - default: - // finished settings - return; - } + move(ystart, 0); + clrtobot(); + pmore_PromptBar(PMORE_MSG_PREF_TITLE, 1); + outs("\n"); + + // list options + pmore_prefEntry(bpref.rawmode, + "\\", 1, "¦â±mÅã¥Ü¤è¦¡:", -1, + "¹w³]®æ¦¡¤Æ¤º®e\tì©lANSI±±¨î½X\t¯Â¤å¦r"); + + pmore_prefEntry(bpref.wrapmode, + "w", 1, "Â_¦æ¤è¦¡:", -1, + "ª½±µºI¦æ\t¦Û°ÊÂ_¦æ"); + + pmore_prefEntry(bpref.wrapindicator, + "m", 1, "Â_¦æ²Å¸¹:", -1, + "¤£Åã¥Ü\tÅã¥Ü"); + + pmore_prefEntry(bpref.separator, + "l", 1, "¤å³¹¼ÐÀY¤À¹j½u:", -1, + "µL\t³æ¦æ\t\t¶Ç²Î¤À¹j½u¥[ªÅ¦æ"); + + pmore_prefEntry(bpref.oldstatusbar, + "t", 1, "¶Ç²Îª¬ºA¦C»PÂ_¦æ¤è¦¡: ", -1, + "°±¥Î\t±Ò¥Î"); + + switch(vmsg("½Ð½Õ¾ã³]©w©Î¨ä¥¦¥ô·NÁäµ²§ô¡C")) + { + case '\\': + case '|': + bpref.rawmode = (bpref.rawmode+1) % MFDISP_RAW_MODES; + break; + case 'w': + bpref.wrapmode = (bpref.wrapmode+1) % MFDISP_WRAP_MODES; + break; + case 'm': + bpref.wrapindicator = !bpref.wrapindicator; + break; + case 'l': + // there's no MFDISP_SEP_WRAP only mode. + if (++bpref.separator == MFDISP_SEP_WRAP) + bpref.separator ++; + bpref.separator %= MFDISP_SEP_MODES; + break; + case 't': + bpref.oldwrapmode = !bpref.oldwrapmode; + bpref.oldstatusbar = !bpref.oldstatusbar; + break; + + default: + // finished settings + return; + } } } @@ -2693,9 +2693,9 @@ void mf_float2tv(float f, struct timeval *ptv) { if(f < MOVIE_MIN_FRAMECLK) - f = MOVIE_MIN_FRAMECLK; + f = MOVIE_MIN_FRAMECLK; if (f > MOVIE_MAX_FRAMECLK) - f = MOVIE_MAX_FRAMECLK; + f = MOVIE_MAX_FRAMECLK; ptv->tv_sec = (long) f; ptv->tv_usec = (f - (long)f) * MOVIE_SECOND_U; @@ -2709,12 +2709,12 @@ mf_str2float(unsigned char *p, unsigned char *end, float *pf) /* process time */ while ( p < end && - cbuf < sizeof(buf)-1 && - (isdigit(*p) || *p == '.' || *p == '+' || *p == '-')) - buf[cbuf++] = *p++; + cbuf < sizeof(buf)-1 && + (isdigit(*p) || *p == '.' || *p == '+' || *p == '-')) + buf[cbuf++] = *p++; if (!cbuf) - return 0; + return 0; buf[cbuf] = 0; *pf = atof(buf); @@ -2735,36 +2735,36 @@ pmore_wait_key(struct timeval *ptv, int dorefresh) int c = 0; if (dorefresh) - refresh(); + refresh(); do { - // if already something in queue, - // detemine if ok to break. - while ( num_in_buf() > 0) - { - if (!mf_movieMaskedInput((c = igetch()))) - return c; - } - - // wait for real user interaction - FD_ZERO(&readfds); - FD_SET(0, &readfds); + // if already something in queue, + // detemine if ok to break. + while ( num_in_buf() > 0) + { + if (!mf_movieMaskedInput((c = igetch()))) + return c; + } + + // wait for real user interaction + FD_ZERO(&readfds); + FD_SET(0, &readfds); #ifdef STATINC - STATINC(STAT_SYSSELECT); + STATINC(STAT_SYSSELECT); #endif - sel = select(1, &readfds, NULL, NULL, ptv); + sel = select(1, &readfds, NULL, NULL, ptv); - // if select() stopped by other interrupt, - // do it again. - if (sel < 0 && errno == EINTR) - continue; + // if select() stopped by other interrupt, + // do it again. + if (sel < 0 && errno == EINTR) + continue; - // if (sel > 0), try to read. - // note: there may be more in queue. - // will be processed at next loop. - if (sel > 0 && !mf_movieMaskedInput((c = igetch()))) - return c; + // if (sel > 0), try to read. + // note: there may be more in queue. + // will be processed at next loop. + if (sel > 0 && !mf_movieMaskedInput((c = igetch()))) + return c; } while (sel > 0); @@ -2774,7 +2774,7 @@ pmore_wait_key(struct timeval *ptv, int dorefresh) // sync clock(now) if timeout. if (sel == 0) - syncnow(); + syncnow(); return (sel == 0) ? 0 : 1; } @@ -2789,32 +2789,32 @@ mf_moviePromptPlaying(int type) if (override_msg) { - // we must warn user about something... - move(type ? b_lines-2 : b_lines-1, 0); // clrtoeol? - outs(ANSI_RESET); - if (override_attr) outs(override_attr); - w -= strlen(override_msg); - outs(override_msg); - while(w-- > 0) outc(' '); - - outs(ANSI_RESET ANSI_CLRTOEND); - RESET_OVERRIDE_MSG(); - w = t_columns -1; + // we must warn user about something... + move(type ? b_lines-2 : b_lines-1, 0); // clrtoeol? + outs(ANSI_RESET); + if (override_attr) outs(override_attr); + w -= strlen(override_msg); + outs(override_msg); + while(w-- > 0) outc(' '); + + outs(ANSI_RESET ANSI_CLRTOEND); + RESET_OVERRIDE_MSG(); + w = t_columns -1; } move(type ? b_lines-1 : b_lines, 0); // clrtoeol? if (type) { - outs(ANSI_RESET ANSI_COLOR(1;34;47)); - s = " >> ½Ð¿é¤J¿ï¶µ: (¤¬°Ê¦¡°Êµe¼½©ñ¤¤¡A¥i«ö q ©Î Ctrl-C ¤¤Â_)"; + outs(ANSI_RESET ANSI_COLOR(1;34;47)); + s = " >> ½Ð¿é¤J¿ï¶µ: (¤¬°Ê¦¡°Êµe¼½©ñ¤¤¡A¥i«ö q ©Î Ctrl-C ¤¤Â_)"; } else if (mfmovie.interactive) { - outs(ANSI_RESET ANSI_COLOR(1;34;47)); - s = PMORE_MSG_MOVIE_INTERACTION_PLAYING; + outs(ANSI_RESET ANSI_COLOR(1;34;47)); + s = PMORE_MSG_MOVIE_INTERACTION_PLAYING; } else { - outs(ANSI_RESET ANSI_COLOR(1;30;47)); + outs(ANSI_RESET ANSI_COLOR(1;30;47)); } w -= strlen(s); outs(s); @@ -2822,8 +2822,8 @@ mf_moviePromptPlaying(int type) while(w-- > 0) outc(' '); outs(ANSI_RESET ANSI_CLRTOEND); if (type) { - move(b_lines, 0); - clrtoeol(); + move(b_lines, 0); + clrtoeol(); } return 1; @@ -2832,81 +2832,81 @@ mf_moviePromptPlaying(int type) // return = printed characters int mf_moviePromptOptions( - int isel, int maxsel, - int key, - unsigned char *text, unsigned int szText) + int isel, int maxsel, + int key, + unsigned char *text, unsigned int szText) { unsigned char *s = text; int printlen = 0; // determine if we need separator if (maxsel) { - outs(OPTATTR_BAR "|" ); - printlen += 1; + outs(OPTATTR_BAR "|" ); + printlen += 1; } // highlight if is selected if (isel == maxsel) - outs(OPTATTR_SELECTED_KEY); + outs(OPTATTR_SELECTED_KEY); else - outs(OPTATTR_NORMAL_KEY); + outs(OPTATTR_NORMAL_KEY); outc(' '); printlen ++; if (key > ' ' && key < 0x80) // isprint(key)) { - outc(key); - printlen += 1; + outc(key); + printlen += 1; } else { - // named keys - printlen += 2; - - if (key == KEY_UP) outs("¡ô"); - else if (key == KEY_LEFT) outs("¡ö"); - else if (key == KEY_DOWN) outs("¡õ"); - else if (key == KEY_RIGHT) outs("¡÷"); - else if (key == KEY_PGUP) { outs("PgUp"); printlen += 2; } - else if (key == KEY_PGDN) { outs("PgDn"); printlen += 2; } - else if (key == KEY_HOME) { outs("Home"); printlen += 2; } - else if (key == KEY_END) { outs("End"); printlen ++; } - else if (key == KEY_INS) { outs("Ins"); printlen ++; } - else if (key == KEY_DEL) { outs("Del"); printlen ++; } - else if (key == '\b') { outs("¡öBS"); printlen += 2; } - // else if (key == MOVIE_KEY_ANY) // same as default - else printlen -= 2; + // named keys + printlen += 2; + + if (key == KEY_UP) outs("¡ô"); + else if (key == KEY_LEFT) outs("¡ö"); + else if (key == KEY_DOWN) outs("¡õ"); + else if (key == KEY_RIGHT) outs("¡÷"); + else if (key == KEY_PGUP) { outs("PgUp"); printlen += 2; } + else if (key == KEY_PGDN) { outs("PgDn"); printlen += 2; } + else if (key == KEY_HOME) { outs("Home"); printlen += 2; } + else if (key == KEY_END) { outs("End"); printlen ++; } + else if (key == KEY_INS) { outs("Ins"); printlen ++; } + else if (key == KEY_DEL) { outs("Del"); printlen ++; } + else if (key == '\b') { outs("¡öBS"); printlen += 2; } + // else if (key == MOVIE_KEY_ANY) // same as default + else printlen -= 2; } // check text: we don't allow special char. if (text && szText && text[0]) { - while (s < text + szText && *s > ' ') - { - s++; - } - szText = s - text; + while (s < text + szText && *s > ' ') + { + s++; + } + szText = s - text; } else { - // default option text - text = (unsigned char*)"¡¸"; - szText = ustrlen(text); + // default option text + text = (unsigned char*)"¡¸"; + szText = ustrlen(text); } if (szText) { - if (isel == maxsel) - outs(OPTATTR_SELECTED); - else - outs(OPTATTR_NORMAL); - outs_n((char*)text, szText); - printlen += szText; + if (isel == maxsel) + outs(OPTATTR_SELECTED); + else + outs(OPTATTR_NORMAL); + outs_n((char*)text, szText); + printlen += szText; } outc(' '); printlen ++; // un-highlight if (isel == maxsel) - outs(OPTATTR_NORMAL); + outs(OPTATTR_NORMAL); return printlen; } @@ -2916,23 +2916,23 @@ mf_movieNamedKey(int c) { switch (c) { - case 'u': return KEY_UP; - case 'd': return KEY_DOWN; - case 'l': return KEY_LEFT; - case 'r': return KEY_RIGHT; - - case 'b': return '\b'; - - case 'H': return KEY_HOME; - case 'E': return KEY_END; - case 'I': return KEY_INS; - case 'D': return KEY_DEL; - case 'P': return KEY_PGUP; - case 'N': return KEY_PGDN; - - case 'a': return MOVIE_KEY_ANY; - default: - break; + case 'u': return KEY_UP; + case 'd': return KEY_DOWN; + case 'l': return KEY_LEFT; + case 'r': return KEY_RIGHT; + + case 'b': return '\b'; + + case 'H': return KEY_HOME; + case 'E': return KEY_END; + case 'I': return KEY_INS; + case 'D': return KEY_DEL; + case 'P': return KEY_PGUP; + case 'N': return KEY_PGDN; + + case 'a': return MOVIE_KEY_ANY; + default: + break; } return 0; } @@ -2940,7 +2940,7 @@ mf_movieNamedKey(int c) int mf_movieIsSystemBreak(int c) { return (c == 'q' || c == 'Q' || c == Ctrl('C')) - ? 1 : 0; + ? 1 : 0; } int @@ -2949,32 +2949,32 @@ mf_movieMaskedInput(int c) unsigned char *p = mfmovie.optkeys; if (!p) - return 0; + return 0; // some keys cannot be masked if (mf_movieIsSystemBreak(c)) - return 0; + return 0; // treat BS and DEL as same one if (c == MOVIE_KEY_BS2) - c = '\b'; + c = '\b'; // general look up while (p < mf.end && *p && *p != '\n' && *p != '#') { - if (*p == '@' && mf.end - p > 1 - && isalnum(*(p+1))) // named key - { - p++; - - // special: 'a' masks all - if (*p == 'a' || mf_movieNamedKey(*p) == c) - return 1; - } else { - if ((int)*p == c) - return 1; - } - p++; + if (*p == '@' && mf.end - p > 1 + && isalnum(*(p+1))) // named key + { + p++; + + // special: 'a' masks all + if (*p == 'a' || mf_movieNamedKey(*p) == c) + return 1; + } else { + if ((int)*p == c) + return 1; + } + p++; } return 0; } @@ -2988,36 +2988,36 @@ mf_movieFrameHeader(unsigned char *p, unsigned char *end) static char *patHeader = "==" ESC_STR "[30;40m^L"; static char *patHeader2= ESC_STR "[30;40m^L"; // patHeader + 2; // "==" // static char *patHeader3= ESC_STR "[m^L"; - static size_t szPatHeader = 12; // strlen(patHeader); - static size_t szPatHeader2 = 10; // strlen(patHeader2); + static size_t szPatHeader = 12; // strlen(patHeader); + static size_t szPatHeader2 = 10; // strlen(patHeader2); // static size_t szPatHeader3 = 5; // strlen(patHeader3); size_t sz = end - p; if (sz < 1) return NULL; - if(*p == 12) // ^L - return p+1; + if(*p == 12) // ^L + return p+1; if (sz < 2) return NULL; if( *p == '^' && - *(p+1) == 'L') - return p+2; + *(p+1) == 'L') + return p+2; // Add more frame headers /* // *[m seems not so common, skip. if (sz < szPatHeader3) return NULL; if (memcmp(p, patHeader3, szPatHeader3) == 0) - return p + szPatHeader3; - */ + return p + szPatHeader3; + */ if (sz < szPatHeader2) return NULL; if (memcmp(p, patHeader2, szPatHeader2) == 0) - return p + szPatHeader2; + return p + szPatHeader2; if (sz < szPatHeader) return NULL; if (memcmp(p, patHeader, szPatHeader) == 0) - return p + szPatHeader; + return p + szPatHeader; return NULL; } @@ -3030,7 +3030,7 @@ mf_movieGotoNamedFrame(const unsigned char *name, const unsigned char *end) // resolve name first while (p < end && isalnum(*p)) - p++; + p++; sz = p - name; if (sz < 1) return 0; @@ -3041,22 +3041,22 @@ mf_movieGotoNamedFrame(const unsigned char *name, const unsigned char *end) do { - if ((p = mf_movieFrameHeader(mf.disps, mf.end)) == NULL || - *p != ':') - continue; + if ((p = mf_movieFrameHeader(mf.disps, mf.end)) == NULL || + *p != ':') + continue; - // got some frame. let's check the name - p++; - if (mf.end - p < sz) - continue; + // got some frame. let's check the name + p++; + if (mf.end - p < sz) + continue; - // check: target of p must end. - if (mf.end -p > sz && - isalnum(*(p+sz))) - continue; + // check: target of p must end. + if (mf.end -p > sz && + isalnum(*(p+sz))) + continue; - if (memcmp(p, name, sz) == 0) - return 1; + if (memcmp(p, name, sz) == 0) + return 1; } while (mf_forward(1) > 0); return 0; @@ -3066,65 +3066,65 @@ int mf_movieGotoFrame(int fno, int relative) { if (!relative) - mf_goTop(); + mf_goTop(); else if (fno > 0) - mf_forward(1); + mf_forward(1); // for absolute, fno = 1..N if (fno > 0) { - // move forward - do { - while (mf_movieFrameHeader(mf.disps, mf.end) == NULL) - { - if (mf_forward(1) < 1) - return 0; - } - // found frame. - if (--fno > 0) - mf_forward(1); - } while (fno > 0); + // move forward + do { + while (mf_movieFrameHeader(mf.disps, mf.end) == NULL) + { + if (mf_forward(1) < 1) + return 0; + } + // found frame. + if (--fno > 0) + mf_forward(1); + } while (fno > 0); } else { - // backward - // XXX check if we reached head? - while (fno < 0) - { - do { - if (mf_backward(1) < 1) - return 0; - } while (mf_movieFrameHeader(mf.disps, mf.end) == NULL); - fno ++; - } + // backward + // XXX check if we reached head? + while (fno < 0) + { + do { + if (mf_backward(1) < 1) + return 0; + } while (mf_movieFrameHeader(mf.disps, mf.end) == NULL); + fno ++; + } } return 1; } int mf_parseOffsetCmd( - unsigned char *s, unsigned char *end, - int base) + unsigned char *s, unsigned char *end, + int base) { // return is always > 0, or base. int v = 0; if (s >= end) - return base; + return base; v = atoi((char*)s); if (*s == '+' || *s == '-') { - // relative format - v = base + v; + // relative format + v = base + v; } else if (isdigit(*s)) { - // absolute format + // absolute format } else { - // error format? - v = 0; + // error format? + v = 0; } if (v <= 0) - v = base; + v = base; return v; } @@ -3141,58 +3141,58 @@ mf_movieExecuteOffsetCmd(unsigned char *s, unsigned char *end) switch(*s) { - case 'p': - // by page - curr = (mf.lineno / MFDISP_PAGE) + 1; - newno = mf_parseOffsetCmd(s+1, end, curr); + case 'p': + // by page + curr = (mf.lineno / MFDISP_PAGE) + 1; + newno = mf_parseOffsetCmd(s+1, end, curr); #ifdef DEBUG - vmsgf("page: %d -> %d\n", curr, newno); + vmsgf("page: %d -> %d\n", curr, newno); #endif // DEBUG - // prevent endless loop - if (newno == curr) - return 0; + // prevent endless loop + if (newno == curr) + return 0; - return mf_goto((newno -1) * MFDISP_PAGE); + return mf_goto((newno -1) * MFDISP_PAGE); - case 'l': - // by lines - curr = mf.lineno + 1; - newno = mf_parseOffsetCmd(s+1, end, curr); + case 'l': + // by lines + curr = mf.lineno + 1; + newno = mf_parseOffsetCmd(s+1, end, curr); #ifdef DEBUG - vmsgf("line: %d -> %d\n", curr, newno); + vmsgf("line: %d -> %d\n", curr, newno); #endif // DEBUG - // prevent endless loop - if (newno == curr) - return 0; - - return mf_goto(newno-1); - - case 'f': - // by frame [optimized] - if (++s >= end) - return 0; - - curr = 0; - newno = atoi((char*)s); - if (*s == '+' || *s == '-') // relative - { - curr = 1; - if (newno == 0) - return 0; - } else { - // newno starts from 1 - if (newno <= 0) - return 0; - } - return mf_movieGotoFrame(newno, curr); - - case ':': - // by names - return mf_movieGotoNamedFrame(s+1, end); - - default: - // not supported yet - break; + // prevent endless loop + if (newno == curr) + return 0; + + return mf_goto(newno-1); + + case 'f': + // by frame [optimized] + if (++s >= end) + return 0; + + curr = 0; + newno = atoi((char*)s); + if (*s == '+' || *s == '-') // relative + { + curr = 1; + if (newno == 0) + return 0; + } else { + // newno starts from 1 + if (newno <= 0) + return 0; + } + return mf_movieGotoFrame(newno, curr); + + case ':': + // by names + return mf_movieGotoNamedFrame(s+1, end); + + default: + // not supported yet + break; } return 0; } @@ -3224,226 +3224,226 @@ mf_movieOptionHandler(unsigned char *opt, unsigned char *end) // set up timer (opt points to optional time now) do { - p = opt; - while ( p < end && - (isdigit(*p) || *p == '+' || *p == '-' || *p == '.') ) - p++; - - // if no number, abort. - if (p == opt || (p < end && *p != '#')) break; - - // p looks like valid timer now - if (mf_str2float(opt, p, &optclk)) - { - // conversion failed. - if (optclk == 0) - optclk = -1.0f; - } - - // point opt to new var after #. - opt = p + 1; - break; + p = opt; + while ( p < end && + (isdigit(*p) || *p == '+' || *p == '-' || *p == '.') ) + p++; + + // if no number, abort. + if (p == opt || (p < end && *p != '#')) break; + + // p looks like valid timer now + if (mf_str2float(opt, p, &optclk)) + { + // conversion failed. + if (optclk == 0) + optclk = -1.0f; + } + + // point opt to new var after #. + opt = p + 1; + break; } while (1); // UI Selection do { - // do c test here because we need parser to help us - // finding the selection - if (c == '\r' || c == '\n' || c == ' ') - { - selected = 1; - } - - newOpt = 1; - promptlen = 0; - - // parse (key,frame,text) - for ( p = opt, ient = 0, maxsel = 0, - key = '0'; // default command - p < end && *p != '\n'; p++) - { - if (newOpt) - { - // prepare for next loop - pkey = p; - cmd = text = NULL; - szCmd = szText = 0; - ient = 0; - newOpt = 0; - } - - // calculation of fields - if (*p == ',' || *p == '#') - { - switch (++ient) - { - // case 0 is already processed. - case 1: - cmd = p+1; - break; - - case 2: - text = p+1; - szCmd = p - cmd; - break; - - case 3: - szText = p - text; - - default: - // unknown parameters - break; - } - } - - // ready to parse one option - if (*p == '#') - { - newOpt = 1; - - // first, fix pointers - if (szCmd == 0 || *cmd == ',' || *cmd == '#') - { cmd = NULL; szCmd = 0; } - - // quick abort if option is invalid. - if (!cmd) - continue; - - if (szText == 0 || *text == ',' || *text == '#') - { text = NULL; szText = 0; } - - // assign key - if (*pkey == ',' || *pkey == '#') - key++; - else - { - // named key? - int nk = 0; - - // handle special case @a (all) here - - if (*pkey == '@' && - ++ pkey < end && - (nk = mf_movieNamedKey(*pkey))) - { - key = nk; - } else { - key = *pkey; - } - // warning: pkey may be changed after this. - } - - // calculation complete. - - // print option - if (!hideOpts && maxsel == 0 && text == NULL) - { - hideOpts = 1; - mf_moviePromptPlaying(0); - // prevent more hideOpt test - } - - if (!hideOpts) - { - // print header - if (maxsel == 0) - { - pmore_clrtoeol(b_lines-1, 0); - mf_moviePromptPlaying(1); - } - - promptlen += mf_moviePromptOptions( - isel, maxsel, key, - text, szText); - } - - // handle selection - if (c == key || - (key == MOVIE_KEY_ANY && c != 0)) - { - // hotkey pressed - selected = 1; - isel = maxsel; - } - - maxsel ++; - - // parse complete. - // test if this item is selected. - if (selected && isel == maxsel - 1) - break; - } - } - - if (selected || maxsel == 0) - break; - - // finish the selection bar - if (!hideOpts && maxsel > 0) - { - int iw = 0; - for (iw = 0; iw + promptlen < t_columns-1; iw++) - outc(' '); - outs(ANSI_RESET ANSI_CLRTOEND); - } - - // wait for input - if (optclk > 0) - { - // timed interaction - - // disable optkeys to allow masked input - unsigned char *tmpopt = mfmovie.optkeys; - mfmovie.optkeys = NULL; - - mf_float2tv(optclk, &tv); - c = pmore_wait_key(&tv, 1); - mfmovie.optkeys = tmpopt; - - // if timeout, drop. - if (!c) - return 0; - } else { - // infinite wait - c = igetch(); - } - - // parse keyboard input - if (mf_movieIsSystemBreak(c)) - { - // cannot be masked, - // also force stop of playback - STOP_MOVIE(); - vmsg(PMORE_MSG_MOVIE_INTERACTION_STOPPED); - return 0; - } - - // treat BS and DEL as same one - if (c == MOVIE_KEY_BS2) - c = '\b'; - - // standard navigation keys. - if (mf_movieMaskedInput(c)) - continue; - - // these keys can be masked - if (c == KEY_LEFT || c == KEY_UP) - { - if (isel > 0) isel --; - } - else if (c == KEY_RIGHT || c == KEY_TAB || c == KEY_DOWN) - { - if (isel < maxsel-1) isel ++; - } - else if (c == KEY_HOME) - { - isel = 0; - } - else if (c == KEY_END) - { - isel = maxsel -1; - } + // do c test here because we need parser to help us + // finding the selection + if (c == '\r' || c == '\n' || c == ' ') + { + selected = 1; + } + + newOpt = 1; + promptlen = 0; + + // parse (key,frame,text) + for ( p = opt, ient = 0, maxsel = 0, + key = '0'; // default command + p < end && *p != '\n'; p++) + { + if (newOpt) + { + // prepare for next loop + pkey = p; + cmd = text = NULL; + szCmd = szText = 0; + ient = 0; + newOpt = 0; + } + + // calculation of fields + if (*p == ',' || *p == '#') + { + switch (++ient) + { + // case 0 is already processed. + case 1: + cmd = p+1; + break; + + case 2: + text = p+1; + szCmd = p - cmd; + break; + + case 3: + szText = p - text; + + default: + // unknown parameters + break; + } + } + + // ready to parse one option + if (*p == '#') + { + newOpt = 1; + + // first, fix pointers + if (szCmd == 0 || *cmd == ',' || *cmd == '#') + { cmd = NULL; szCmd = 0; } + + // quick abort if option is invalid. + if (!cmd) + continue; + + if (szText == 0 || *text == ',' || *text == '#') + { text = NULL; szText = 0; } + + // assign key + if (*pkey == ',' || *pkey == '#') + key++; + else + { + // named key? + int nk = 0; + + // handle special case @a (all) here + + if (*pkey == '@' && + ++ pkey < end && + (nk = mf_movieNamedKey(*pkey))) + { + key = nk; + } else { + key = *pkey; + } + // warning: pkey may be changed after this. + } + + // calculation complete. + + // print option + if (!hideOpts && maxsel == 0 && text == NULL) + { + hideOpts = 1; + mf_moviePromptPlaying(0); + // prevent more hideOpt test + } + + if (!hideOpts) + { + // print header + if (maxsel == 0) + { + pmore_clrtoeol(b_lines-1, 0); + mf_moviePromptPlaying(1); + } + + promptlen += mf_moviePromptOptions( + isel, maxsel, key, + text, szText); + } + + // handle selection + if (c == key || + (key == MOVIE_KEY_ANY && c != 0)) + { + // hotkey pressed + selected = 1; + isel = maxsel; + } + + maxsel ++; + + // parse complete. + // test if this item is selected. + if (selected && isel == maxsel - 1) + break; + } + } + + if (selected || maxsel == 0) + break; + + // finish the selection bar + if (!hideOpts && maxsel > 0) + { + int iw = 0; + for (iw = 0; iw + promptlen < t_columns-1; iw++) + outc(' '); + outs(ANSI_RESET ANSI_CLRTOEND); + } + + // wait for input + if (optclk > 0) + { + // timed interaction + + // disable optkeys to allow masked input + unsigned char *tmpopt = mfmovie.optkeys; + mfmovie.optkeys = NULL; + + mf_float2tv(optclk, &tv); + c = pmore_wait_key(&tv, 1); + mfmovie.optkeys = tmpopt; + + // if timeout, drop. + if (!c) + return 0; + } else { + // infinite wait + c = igetch(); + } + + // parse keyboard input + if (mf_movieIsSystemBreak(c)) + { + // cannot be masked, + // also force stop of playback + STOP_MOVIE(); + vmsg(PMORE_MSG_MOVIE_INTERACTION_STOPPED); + return 0; + } + + // treat BS and DEL as same one + if (c == MOVIE_KEY_BS2) + c = '\b'; + + // standard navigation keys. + if (mf_movieMaskedInput(c)) + continue; + + // these keys can be masked + if (c == KEY_LEFT || c == KEY_UP) + { + if (isel > 0) isel --; + } + else if (c == KEY_RIGHT || c == KEY_TAB || c == KEY_DOWN) + { + if (isel < maxsel-1) isel ++; + } + else if (c == KEY_HOME) + { + isel = 0; + } + else if (c == KEY_END) + { + isel = maxsel -1; + } } while ( !selected ); @@ -3458,7 +3458,7 @@ mf_movieOptionHandler(unsigned char *opt, unsigned char *end) // Execute Selection if (!cmd || !szCmd) - return 0; + return 0; return mf_movieExecuteOffsetCmd(cmd, cmd+szCmd); } @@ -3474,44 +3474,44 @@ int mf_movieSyncFrame() { if (mfmovie.pause) { - int c = 0; - mfmovie.pause = 0; - c = vmsg(PMORE_MSG_MOVIE_PAUSE); - if (mf_movieIsSystemBreak(c)) - return 0; - return 1; + int c = 0; + mfmovie.pause = 0; + c = vmsg(PMORE_MSG_MOVIE_PAUSE); + if (mf_movieIsSystemBreak(c)) + return 0; + return 1; } else if (mfmovie.options) { - unsigned char *opt = mfmovie.options; - mfmovie.options = NULL; - mf_movieOptionHandler(opt, mf.end); - return 1; + unsigned char *opt = mfmovie.options; + mfmovie.options = NULL; + mf_movieOptionHandler(opt, mf.end); + return 1; } else if (mfmovie.synctime.tv_sec > 0) { - /* synchronize world timeline model */ - struct timeval dv; - gettimeofday(&dv, NULL); - dv.tv_sec = mfmovie.synctime.tv_sec - dv.tv_sec; - if(dv.tv_sec < 0) - return 1; - dv.tv_usec = mfmovie.synctime.tv_usec - dv.tv_usec; - if(dv.tv_usec < 0) { - dv.tv_sec --; - dv.tv_usec += MOVIE_SECOND_U; - } - if(dv.tv_sec < 0) - return 1; - - return !pmore_wait_key(&dv, 0); + /* synchronize world timeline model */ + struct timeval dv; + gettimeofday(&dv, NULL); + dv.tv_sec = mfmovie.synctime.tv_sec - dv.tv_sec; + if(dv.tv_sec < 0) + return 1; + dv.tv_usec = mfmovie.synctime.tv_usec - dv.tv_usec; + if(dv.tv_usec < 0) { + dv.tv_sec --; + dv.tv_usec += MOVIE_SECOND_U; + } + if(dv.tv_sec < 0) + return 1; + + return !pmore_wait_key(&dv, 0); } else { - /* synchronize each frame clock model */ - /* because Linux will change the timeval passed to select, - * let's use a temp value here. - */ - struct timeval dv = mfmovie.frameclk; - return !pmore_wait_key(&dv, 0); + /* synchronize each frame clock model */ + /* because Linux will change the timeval passed to select, + * let's use a temp value here. + */ + struct timeval dv = mfmovie.frameclk; + return !pmore_wait_key(&dv, 0); } } @@ -3524,146 +3524,146 @@ mf_movieProcessCommand(unsigned char *p, unsigned char *end) { for (; p < end && *p != '\n'; p++) { - if (*p == 'S') { - // SYNCHRONIZATION - gettimeofday(&mfmovie.synctime, NULL); - // S can take other commands - } - else if (*p == 'E') - { - // END - STOP_MOVIE(); - // MFDISP_SKIPCURLINE(); - MOVIECMD_SKIP_ALL(p,end); - return p; - } - else if (*p == 'P') - { - // PAUSE - mfmovie.pause = 1; - // MFDISP_SKIPCURLINE(); - MOVIECMD_SKIP_ALL(p,end); - return p; + if (*p == 'S') { + // SYNCHRONIZATION + gettimeofday(&mfmovie.synctime, NULL); + // S can take other commands + } + else if (*p == 'E') + { + // END + STOP_MOVIE(); + // MFDISP_SKIPCURLINE(); + MOVIECMD_SKIP_ALL(p,end); + return p; + } + else if (*p == 'P') + { + // PAUSE + mfmovie.pause = 1; + // MFDISP_SKIPCURLINE(); + MOVIECMD_SKIP_ALL(p,end); + return p; - } - else if (*p == 'G') - { - // GOTO - // Gt+-n,t+-n,t+-n (random select one) - // jump +-n of type(l,p,f) - - // random select, if multiple - unsigned char *pe = p; - unsigned int igs = 0; - - for (pe = p ; pe < end && *pe && - *pe > ' ' && *pe < 0x80 - ; pe ++) - if (*pe == ',') igs++; - - if (igs) - { - // make random - igs = random() % (igs+1); - - for (pe = p ; igs > 0 && pe < end && *pe && - *pe > ' ' && *pe < 0x80 - ; pe ++) - if (*pe == ',') igs--; - - if (pe != p) - p = pe-1; - } - - mf_movieExecuteOffsetCmd(p+1, end); - MOVIECMD_SKIP_ALL(p,end); - return p; - } - else if (*p == ':') - { - // NAMED - // :name: - // name allows alnum only - p++; - // TODO check isalnum p? - - // :name can accept trailing commands - while (p < end && *p != '\n' && *p != ':') - p++; - - if (*p == ':') p++; - - // continue will increase p - p--; - continue; - } - else if (*p == 'K') - { - // Reserve Key for interactive usage. - // Currently only K#...# format is supported. - if (p+2 < end && *(p+1) == '#') - { - p += 2; - mfmovie.optkeys = p; - mfmovie.interactive = 1; - - // K#..# can accept trailing commands - while (p < end && *p != '\n' && *p != '#') - p++; - - // if empty, set optkeys to NULL? - if (mfmovie.optkeys == p) - mfmovie.optkeys = NULL; - - if (*p == '#') p++; - - // continue will increase p - p--; - continue; - } - MOVIECMD_SKIP_ALL(p,end); - return p; - } - else if (*p == '#') - { - // OPTIONS - // #key1,frame1,text1#key2,frame2,text2# - mfmovie.options = p+1; - mfmovie.interactive = 1; - // MFDISP_SKIPCURLINE(); - MOVIECMD_SKIP_ALL(p,end); - return p; - } - else if (*p == 'O') - { - // OLD compatible mode - // = -> compat24 - // - -> ? - // == -> ? - p++; - if (p >= end) - return end; - if (*p == '=') - { - mfmovie.mode = MFDISP_MOVIE_PLAYING_OLD; - mfmovie.compat24 = 1; - p++; - } - // MFDISP_SKIPCURLINE(); - return p+1; - } - else if (*p == 'L') - { - // LOOP - // Lm,n - // m times to backward n - break; - } - else - { - // end of known control codes - break; - } + } + else if (*p == 'G') + { + // GOTO + // Gt+-n,t+-n,t+-n (random select one) + // jump +-n of type(l,p,f) + + // random select, if multiple + unsigned char *pe = p; + unsigned int igs = 0; + + for (pe = p ; pe < end && *pe && + *pe > ' ' && *pe < 0x80 + ; pe ++) + if (*pe == ',') igs++; + + if (igs) + { + // make random + igs = random() % (igs+1); + + for (pe = p ; igs > 0 && pe < end && *pe && + *pe > ' ' && *pe < 0x80 + ; pe ++) + if (*pe == ',') igs--; + + if (pe != p) + p = pe-1; + } + + mf_movieExecuteOffsetCmd(p+1, end); + MOVIECMD_SKIP_ALL(p,end); + return p; + } + else if (*p == ':') + { + // NAMED + // :name: + // name allows alnum only + p++; + // TODO check isalnum p? + + // :name can accept trailing commands + while (p < end && *p != '\n' && *p != ':') + p++; + + if (*p == ':') p++; + + // continue will increase p + p--; + continue; + } + else if (*p == 'K') + { + // Reserve Key for interactive usage. + // Currently only K#...# format is supported. + if (p+2 < end && *(p+1) == '#') + { + p += 2; + mfmovie.optkeys = p; + mfmovie.interactive = 1; + + // K#..# can accept trailing commands + while (p < end && *p != '\n' && *p != '#') + p++; + + // if empty, set optkeys to NULL? + if (mfmovie.optkeys == p) + mfmovie.optkeys = NULL; + + if (*p == '#') p++; + + // continue will increase p + p--; + continue; + } + MOVIECMD_SKIP_ALL(p,end); + return p; + } + else if (*p == '#') + { + // OPTIONS + // #key1,frame1,text1#key2,frame2,text2# + mfmovie.options = p+1; + mfmovie.interactive = 1; + // MFDISP_SKIPCURLINE(); + MOVIECMD_SKIP_ALL(p,end); + return p; + } + else if (*p == 'O') + { + // OLD compatible mode + // = -> compat24 + // - -> ? + // == -> ? + p++; + if (p >= end) + return end; + if (*p == '=') + { + mfmovie.mode = MFDISP_MOVIE_PLAYING_OLD; + mfmovie.compat24 = 1; + p++; + } + // MFDISP_SKIPCURLINE(); + return p+1; + } + else if (*p == 'L') + { + // LOOP + // Lm,n + // m times to backward n + break; + } + else + { + // end of known control codes + break; + } } return p; } @@ -3673,60 +3673,60 @@ mf_movieNextFrame() { while (1) { - unsigned char *p = mf_movieFrameHeader(mf.disps, mf.end); - - if(p) - { - float nf = 0; - unsigned char *odisps = mf.disps; - - /* process leading */ - p = mf_movieProcessCommand(p, mf.end); - - // disps may change after commands - if (mf.disps != odisps) - { - // commands changing location must - // support at least one frame pause - // to allow user break - struct timeval tv; - mf_float2tv(MOVIE_MIN_FRAMECLK, &tv); - - if (pmore_wait_key(&tv, 0)) - { - STOP_MOVIE(); - return 0; - } - continue; - } - - /* process time */ - if (mf_str2float(p, mf.end, &nf)) - { - mf_float2tv(nf, &mfmovie.frameclk); - } - - if(mfmovie.synctime.tv_sec > 0) - { - mfmovie.synctime.tv_usec += mfmovie.frameclk.tv_usec; - mfmovie.synctime.tv_sec += mfmovie.frameclk.tv_sec; - mfmovie.synctime.tv_sec += mfmovie.synctime.tv_usec / MOVIE_SECOND_U; - mfmovie.synctime.tv_usec %= MOVIE_SECOND_U; - } - - if (mfmovie.mode != MFDISP_MOVIE_PLAYING_OLD) - mf_forward(1); - - return 1; - } - - if (mf_forward(1) <= 0) - break; + unsigned char *p = mf_movieFrameHeader(mf.disps, mf.end); + + if(p) + { + float nf = 0; + unsigned char *odisps = mf.disps; + + /* process leading */ + p = mf_movieProcessCommand(p, mf.end); + + // disps may change after commands + if (mf.disps != odisps) + { + // commands changing location must + // support at least one frame pause + // to allow user break + struct timeval tv; + mf_float2tv(MOVIE_MIN_FRAMECLK, &tv); + + if (pmore_wait_key(&tv, 0)) + { + STOP_MOVIE(); + return 0; + } + continue; + } + + /* process time */ + if (mf_str2float(p, mf.end, &nf)) + { + mf_float2tv(nf, &mfmovie.frameclk); + } + + if(mfmovie.synctime.tv_sec > 0) + { + mfmovie.synctime.tv_usec += mfmovie.frameclk.tv_usec; + mfmovie.synctime.tv_sec += mfmovie.frameclk.tv_sec; + mfmovie.synctime.tv_sec += mfmovie.synctime.tv_usec / MOVIE_SECOND_U; + mfmovie.synctime.tv_usec %= MOVIE_SECOND_U; + } + + if (mfmovie.mode != MFDISP_MOVIE_PLAYING_OLD) + mf_forward(1); + + return 1; + } + + if (mf_forward(1) <= 0) + break; } return 0; } #endif -/* vim:sw=4:ts=8:nofoldenable +/* vim:sw=4:ts=8:expandtab:nofoldenable */ |