예제 #1
0
static void do_edit(struct hexedit *buf, int c)
{
	uint8_t *byte;

	if (buf->cursor_offset == buf->len) {
		hexedit_resize_buffer(buf, buf->len + 1);
	}

	byte = buf->data + buf->cursor_offset;

	if (buf->cursor_x >= ASCII_COL) {
		*byte = (uint8_t)c;

		mvwprintw(buf->win, buf->cursor_y,
			  offset_to_hex_col(buf->cursor_line_offset), "%X", c);
		if (!isprint(c)) {
			c = '.';
		}
		mvwaddch(buf->win, buf->cursor_y,
			 ASCII_COL + buf->cursor_line_offset, c);
		if (buf->cursor_x + 1 != ASCII_COL_END) {
			cursor_right(buf);
		} else {
			cursor_down(buf);
		}
	} else {
		if (!isxdigit(c)) {
			return;
		}
		c = toupper(c);
		waddch(buf->win, c);

		if (isdigit(c)) {
			c = c - '0';
		} else {
			c = c - 'A' + 10;
		}
		if (buf->nibble == 0) {
			*byte = (*byte & 0x0f) | c << 4;
		} else {
			*byte = (*byte & 0xf0) | c;
		}

		c = *byte;
		if (!isprint(c)) {
			c = '.';
		}
		mvwaddch(buf->win, buf->cursor_y,
			 ASCII_COL + buf->cursor_line_offset, c);

		if (buf->cursor_x + 1 != HEX_COL2_END) {
			cursor_right(buf);
		} else {
			cursor_down(buf);
		}
	}

	hexedit_refresh(buf);
}
예제 #2
0
void terminal::print_search_line(std::string str, int pos) const{
  restore_cursor_pos();
  erase_line();
  fprintf(stderr,">%s", str.c_str());
  restore_cursor_pos();
  cursor_right(1+pos);
}
예제 #3
0
void hexedit_driver(struct hexedit *buf, int c)
{
	switch (c) {
	case HE_CURSOR_UP:
		cursor_up(buf);
		break;
	case HE_CURSOR_DOWN:
		cursor_down(buf);
		break;
	case HE_CURSOR_LEFT:
		cursor_left(buf);
		break;
	case HE_CURSOR_RIGHT:
		cursor_right(buf);
		break;
	case HE_CURSOR_PGUP:
		break;
	case HE_CURSOR_PGDN:
		break;
	case HE_BACKSPACE:
		do_backspace(buf);
		break;
	case HE_DELETE:
		do_delete(buf);
		break;
	default:
		do_edit(buf, c & 0xff);
		break;
	}

	hexedit_set_cursor(buf);
}
예제 #4
0
void compose_handle_keypress(uint8_t key) {
  if (state_ == COMPOSE_STATE_WRITING) {
    switch (key) {
      case KBACK:
        del_char();
        compose_draw();
        break;
      case '<':
        cursor_left();
        compose_draw();
        break;
      case '>':
        cursor_right();
        compose_draw();
        break;
      case ' ':
      case ',':
        add_char(key);
        compose_draw();
        break;
      case KALT:
        alt_on_ = !alt_on_;
        compose_draw();
        break;
      case KSPK:
        if (alt_on_) {
          add_char('0');
          compose_draw();
        }
        break;
      case '\n':
        state_ = COMPOSE_STATE_CONFIRM;
        compose_draw();
      default:
        if (key >= 'A' && key <= 'Z') {
          add_char(key);
          compose_draw();
        }
        break;
    }
  } else if (state_ == COMPOSE_STATE_CONFIRM) {
    switch (key) {
      case 'Y':
        state_ = COMPOSE_STATE_SENDING;
        compose_draw();
        send_message();
        break;
      case 'N':
        state_ = COMPOSE_STATE_WRITING;
        compose_draw();
        break;
    }
  }
}
예제 #5
0
파일: hexview.c 프로젝트: opalmirror/cefive
int hexview_dpad_right(HexView* prView) {
    HexPad* prPad = NULL;
    if (prView == NULL) {
        return HEXVIEW_NULLPTR;
    }
    prPad = get_hexpad(prView);
    if (prPad->visible == 1) {
        if (hexpad_cursor_right(prPad) < 0) {
            return HEXVIEW_FAILURE;
        }
        return HEXVIEW_SUCCESS;
    }
    if (cursor_right(prView) < 0) {
        return HEXVIEW_FAILURE;
    }
    return HEXVIEW_SUCCESS;
}
예제 #6
0
int optionspanel_dpad_right(OptionsPanel* prPanel) {
    HexPad* prPad = NULL;
    
    if (prPanel == NULL) {
        return OPTIONSPANEL_NULLPTR;
    }
    prPad = get_hexpad(prPanel);
    if (prPad->visible == 1) {
        if (hexpad_cursor_right(prPad) < 0) {
            return OPTIONSPANEL_FAILURE;
        }
        return OPTIONSPANEL_SUCCESS;
    }
    if (cursor_right(prPanel) < 0) {
        return OPTIONSPANEL_FAILURE;
    }
    return OPTIONSPANEL_SUCCESS;
}
예제 #7
0
void
ShellContent::handleSpec(const InputEvent & e) { 
    // fprintf(stderr, "bleep\n");
    switch ( e.key ) { 
    case KEY_LEFTARROW : 
        cursor_left();
        break;
    case KEY_RIGHTARROW :
        cursor_right();
        break;
    case KEY_UPARROW : 
        hist_up();
        break;
    case KEY_DOWNARROW :
        hist_down();
        break;
    }
}
예제 #8
0
파일: normal_loop.c 프로젝트: poiiii/vic
int goto_line_end()
{
    unsigned int actual_column = 0;
    unsigned int length = 0;
    length = (unsigned int) strlen((const char *) get_line(cur_file, cur_line + cur_top - 1));
//    length = (length == 0) ? 1 : length;
    actual_column = cur_left + cur_column - 1;
    if (length > actual_column)
    {
        for (int i = 0; i < length - actual_column; i++)
        {
            cursor_right();
        }
    }
    else
    {
        for (int i = 0; i < actual_column - length; i++)
        {
            cursor_left();
        }
    }
    return 0;
}
예제 #9
0
파일: CW.C 프로젝트: kytulendu/TW
int main( int argc, char *argv[] ) {
	/* (x,y) position of edit window. x column, y line -> (0,0) at upper left on screen */
	unsigned int xCursorPos = 0;
	unsigned int yCursorPos = 0;

	unsigned int curmenu = 0x1100;
	int i;

	cwsetup( argc, argv );

	writestatus( 0 );
	writetab( );

	splashscreen( );

	/* Main program loop */
	do {
		dispstrhgc( "   ", wind.col, 2, NORMALATTR );
		i = pulled_down_menu( &curmenu, &xCursorPos, &yCursorPos );
		if ( filename[0] != '\0' ) {
			switch ( i ) {
			case RETKEY:
				keymain = menu_to_key( curmenu );
				break;

			case ESCKEY:
				waitkbd( wind.col + xCursorPos, wind.row + yCursorPos );		/* Show blinking cursor */
				keymain = readkbd( );		/* If keypressed Get it */
				break;

			default:
				keymain = i;
				break;
			}

			while ( keymain != ESCKEY ) {
				if ( ( keymain & 0xff ) >= 32 ) {
					keymain = changekey( keymain );
					if ( insertmode ) {
						if ( !insert_char( keymain, &xCursorPos, &yCursorPos ) ) {
							linetoolong( );
						}
					} else {
						if ( !ovrwrite_char( keymain, &xCursorPos, &yCursorPos ) ) {
							linetoolong( );
						}
					}
					refreshline( xCursorPos, yCursorPos );
				} else {	/*  Function Key  */
					switch ( keymain ) {
					case PGUPKEY:
					case CNTRL_R:
						page_up( );
						break;

					case PGDNKEY:
					case CNTRL_C:
						page_down( );
						break;

					case UPKEY:
					case CNTRL_E:
						cursor_up( );
						break;

					case DNKEY:
					case CNTRL_X:
						cursor_down( yCursorPos );
						break;

					case LEKEY:
					case CNTRL_S:
						cursor_left( &xCursorPos );
						break;

					case 0x2301:
						gobeginblk( &xCursorPos );
						break;

					case 0x2401:
						goendblk( &xCursorPos );
						break;

					case RIKEY:
					case CNTRL_D:
						cursor_right( &xCursorPos, yCursorPos );
						break;

					case CNTRL_W:
						scroll_up( );
						break;

					case CNTRL_Z:
						scroll_down( );
						break;

					case CHOMEKEY:
						top_of_page( );
						break;

					case CPGUPKEY:
						topfile( &xCursorPos );
						break;

					case CENDKEY:
						bottom_of_page( );
						break;

					case CPGDNKEY:
						endfile( &xCursorPos );
						break;

					case DELKEY:
					case CNTRL_G:
						delete_char( xCursorPos );
						refreshline( xCursorPos, yCursorPos );
						changeflag = YES;
						break;

					case CNTRL_T:
						delete_word( xCursorPos );
						refreshline( xCursorPos, yCursorPos );
						changeflag = YES;
						break;

					case CNTRL_Y:
						delete_line( );
						changeflag = YES;
						break;

					case CNTRL_M:
					case RETKEY:
						if ( insertmode == NO ) {
							returnkey( &xCursorPos, yCursorPos );
						} else {
							ret_with_ins( &xCursorPos, yCursorPos );
							changeflag = YES;
						}
						break;

					case BSKEY:
					case CNTRL_H:
						backspace( &xCursorPos );
						yCursorPos = findrow( );
						refreshline( 0, yCursorPos );
						changeflag = YES;
						break;

					case INSKEY:
					case CNTRL_V:
						insertmode = !insertmode;
						writeinsmode( );
						break;

					case CNTRL_N:
						insert_ret( &xCursorPos );
						break;

					case F10KEY:
						thaimode = !thaimode;
						writelanguage( );
						break;

					case F1KEY:
						fontused = 0x00;
						writeattr( );
						break;

					case F2KEY:
						fontused = fontused | ITALICATTR;
						writeattr( );
						break;

					case F3KEY:
						fontused = fontused | ONELINEATTR;
						fontused = fontused & 0x7f;
						writeattr( );
						break;

					case F4KEY:
						fontused = fontused | TWOLINEATTR;
						fontused = fontused & 0xfe;
						writeattr( );
						break;

					case F5KEY:
						fontused = fontused | BOLDATTR;
						writeattr( );
						break;

					case F6KEY:
						fontused = fontused | ENLARGEATTR;
						writeattr( );
						break;

					case F7KEY:
						fontused = fontused | SUPERATTR;
						if ( ( fontused & SUBATTR ) == SUBATTR ) {
							fontused = fontused ^ SUBATTR;
						}
						writeattr( );
						break;

					case F8KEY:
						fontused = fontused | SUBATTR;
						if ( ( fontused & SUPERATTR ) == SUPERATTR ) {
							fontused = fontused ^ SUPERATTR;
						}
						writeattr( );
						break;

					case F9KEY:
						manualwrap( &xCursorPos, &yCursorPos );
						break;

					case ALTM:
						editmacro( );
						break;

					case TABKEY:
					case CNTRL_I:
						movetotab( &xCursorPos, yCursorPos );
						break;

					case CNTRL_K:
						blockcommand( &xCursorPos );
						break;

					case 0x1401:
						blkcmd( 'p', &xCursorPos );
						break;
					case 0x6101:
						blkcmd( 'b', &xCursorPos );
						break;
					case 0x6201:
						blkcmd( 'k', &xCursorPos );
						break;
					case 0x6301:
						blkcmd( 'c', &xCursorPos );
						break;
					case 0x6401:
						blkcmd( 'y', &xCursorPos );
						break;
					case 0x6501:
						blkcmd( 'v', &xCursorPos );
						break;
					case 0x6601:
						blkcmd( 'r', &xCursorPos );
						break;
					case 0x6701:
						blkcmd( 'w', &xCursorPos );
						break;
					case 0x6801:
						blkcmd( 'h', &xCursorPos );
						break;

					case CNTRL_O:
						onscreen( xCursorPos, yCursorPos );
						break;

					case 0x7101:
						doonscrn( 'l', xCursorPos, yCursorPos );
						break;
					case 0x7201:
						doonscrn( 'r', xCursorPos, yCursorPos );
						break;
					case 0x7301:
						doonscrn( 'i', xCursorPos, yCursorPos );
						break;
					case 0x7401:
						doonscrn( 'n', xCursorPos, yCursorPos );
						break;
					case 0x7501:
						doonscrn( 'c', xCursorPos, yCursorPos );
						break;
					case 0x7601:
						doonscrn( 'p', xCursorPos, yCursorPos );
						break;
					case 0x7701:
						doonscrn( 'x', xCursorPos, yCursorPos );
						break;

					case CNTRL_Q:
						quick( &xCursorPos, &yCursorPos );
						break;

					case 0x3501:
						deltoendline( xCursorPos, yCursorPos );
						break;

					case 0x8111:
						inscntrl( CNTRL_W, xCursorPos, yCursorPos );
						break;
					case 0x8211:
						inscntrl( CNTRL_S, xCursorPos, yCursorPos );
						break;
					case 0x8311:
						inscntrl( CNTRL_R, xCursorPos, yCursorPos );
						break;
					case 0x8411:
						inscntrl( CNTRL_B, xCursorPos, yCursorPos );
						break;
					case 0x8511:
						inscntrl( CNTRL_E, xCursorPos, yCursorPos );
						break;
					case 0x8611:
						inscntrl( CNTRL_T, xCursorPos, yCursorPos );
						break;
					case 0x8711:
						inscntrl( CNTRL_V, xCursorPos, yCursorPos );
						break;

					case CNTRL_P:
						printcntrl( xCursorPos, yCursorPos );
						break;

					case HOMEKEY:
						home( &xCursorPos );
						break;

					case ENDKEY:
						endline( &xCursorPos );
						break;

					case CLEKEY:
					case CNTRL_A:
						backword( &xCursorPos );
						break;

					case CRIKEY:
					case CNTRL_F:
						nextword( &xCursorPos, yCursorPos );
						break;

					case CNTRL_L:
						if ( source[0] != '\0' ) {
							if ( replaceflag == NO ) {
								if ( searchfwd( &xCursorPos, &yCursorPos ) == NO ) {
									wordnotfound( );
								}
							} else {
								if ( searchreplace( &xCursorPos, &yCursorPos ) == NO ) {
									wordnotfound( );
								}
							}
						}
						break;

					case CNTRL_B:
						reform( );
						break;

					case ALTP:
						gotopage( );
						break;

					case CNTRL_J:
					case ALTL:
						gotoline( );
						break;

					case 0x5101:
						searching( &xCursorPos, &yCursorPos );
						break;

					case 0x5201:
						replacing( &xCursorPos, &yCursorPos );
						break;

					case 0x8501:
						loadtoline( curline->text );
						refreshline( 0, yCursorPos );
						break;

					case CF1KEY:
						insertmacro( &macro[0][0], &xCursorPos, &yCursorPos );
						break;
					case CF2KEY:
						insertmacro( &macro[1][0], &xCursorPos, &yCursorPos );
						break;
					case CF3KEY:
						insertmacro( &macro[2][0], &xCursorPos, &yCursorPos );
						break;
					case CF4KEY:
						insertmacro( &macro[3][0], &xCursorPos, &yCursorPos );
						break;
					case CF5KEY:
						insertmacro( &macro[4][0], &xCursorPos, &yCursorPos );
						break;
					case CF6KEY:
						insertmacro( &macro[5][0], &xCursorPos, &yCursorPos );
						break;
					case CF7KEY:
						insertmacro( &macro[6][0], &xCursorPos, &yCursorPos );
						break;
					case CF8KEY:
						insertmacro( &macro[7][0], &xCursorPos, &yCursorPos );
						break;
					case CF9KEY:
						insertmacro( &macro[8][0], &xCursorPos, &yCursorPos );
						break;
					case CF10KEY:
						insertmacro( &macro[9][0], &xCursorPos, &yCursorPos );
						break;

					case AF2KEY:
						inscntrl( ITALICCODE, xCursorPos, yCursorPos );
						break;
					case AF3KEY:
						inscntrl( ONELINECODE, xCursorPos, yCursorPos );
						break;
					case AF4KEY:
						inscntrl( TWOLINECODE, xCursorPos, yCursorPos );
						break;
					case AF5KEY:
						inscntrl( BOLDCODE, xCursorPos, yCursorPos );
						break;
					case AF6KEY:
						inscntrl( ENLARGECODE, xCursorPos, yCursorPos );
						break;
					case AF7KEY:
						inscntrl( SUPERCODE, xCursorPos, yCursorPos );
						break;
					case AF8KEY:
						inscntrl( SUBCODE, xCursorPos, yCursorPos );
						break;

#ifdef WANT_TO_USE_GRAPH
					case ALTG:
						insertgraph( );
						break;
					case ALTD:
						deletegraph( );
						break;
#endif

					case ALTX:
						quitprog = YES;
						keymain = ESCKEY;
						break;

					default:
						if ( ( alt_char_map( keymain ) ) != -1 ) {
							keymain = alt_char_map( keymain );
							if ( insertmode ) {
								if ( !insert_char( keymain, &xCursorPos, &yCursorPos ) ) {
									linetoolong( );
								}
							} else {
								if ( !ovrwrite_char( keymain, &xCursorPos, &yCursorPos ) ) {
									linetoolong( );
								}
							}
							refreshline( xCursorPos, yCursorPos );
						}
						break;
					} /* switch ( keymain ) */
				}
				adjustcol( &xCursorPos );
				while ( ( yCursorPos = findrow( ) ) > ( wind.width - 1 ) ) {
					storeline( curline );
					curline = curline->previous;
					loadtoline( curline->text );
					lineno--;
				}
				if ( !keypressed( ) ) {
					if ( !pagecomplete ) {
						showpage( );
					}
					if ( !keypressed( ) ) {
						writecolno( firstcol + xCursorPos );
						dispstrhgc( "   ", wind.col, 2, NORMALATTR );
						if ( !keypressed( ) ) {
							writepageline( );
						}
					}
				}
				if ( quitprog != YES ) {
					waitkbd( wind.col + xCursorPos, wind.row + yCursorPos );
					keymain = readkbd( );
					dispkey( keymain );
				}
			}	/* while */
		} else {	/* if filename[0] != '\0' */
			errorsound( );
		}
	} while ( !quitprog );

	if ( changeflag ) {

		blockmsg( 5 );
		dispstrhgc( "ÂѧäÁèä´é¨Ñ´à¡çºá¿éÁ¢éÍÁÙÅ µéͧ¡ÒèѴà¡çºËÃ×ÍäÁè (Y/N)?", ( 16 + center_factor ) + 7, 5, REVERSEATTR );

		keymain = 0;
		while ( ( keymain != 'n' ) && ( keymain != 'N' )
			&& ( keymain != 'y' ) && ( keymain != 'Y' ) ) {
			keymain = ebioskey( 0 ) & 0xff;
			if ( ( keymain == 'y' ) || ( keymain == 'Y' ) ) {
				writeblk( filename, sentinel->next, 0, sentinel->previous, MAXCOL );
			}
		}
	}
	settext( );

	return 0;
}
예제 #10
0
void sbbs_t::ctrl_a(char x)
{
	char	tmp1[128],atr=curatr;
	struct	tm tm;

	if(x && (uchar)x<=CTRL_Z) {    /* Ctrl-A through Ctrl-Z for users with MF only */
		if(!(useron.flags1&FLAG(x+64)))
			console^=(CON_ECHO_OFF);
		return; 
	}
	if((uchar)x>0x7f) {
		cursor_right((uchar)x-0x7f);
		return; 
	}
	switch(toupper(x)) {
		case '!':   /* level 10 or higher */
			if(useron.level<10)
				console^=CON_ECHO_OFF;
			break;
		case '@':   /* level 20 or higher */
			if(useron.level<20)
				console^=CON_ECHO_OFF;
			break;
		case '#':   /* level 30 or higher */
			if(useron.level<30)
				console^=CON_ECHO_OFF;
			break;
		case '$':   /* level 40 or higher */
			if(useron.level<40)
				console^=CON_ECHO_OFF;
			break;
		case '%':   /* level 50 or higher */
			if(useron.level<50)
				console^=CON_ECHO_OFF;
			break;
		case '^':   /* level 60 or higher */
			if(useron.level<60)
				console^=CON_ECHO_OFF;
			break;
		case '&':   /* level 70 or higher */
			if(useron.level<70)
				console^=CON_ECHO_OFF;
			break;
		case '*':   /* level 80 or higher */
			if(useron.level<80)
				console^=CON_ECHO_OFF;
			break;
		case '(':   /* level 90 or higher */
			if(useron.level<90)
				console^=CON_ECHO_OFF;
			break;
		case ')':   /* turn echo back on */
			console&=~CON_ECHO_OFF;
			break;
		case '+':	/* push current attribte */
			if(attr_sp<(int)sizeof(attr_stack))
				attr_stack[attr_sp++]=curatr;
			break;
		case '-':	/* pop current attribute OR optimized "normal" */
			if(attr_sp>0)
				attr(attr_stack[--attr_sp]);
			else									/* turn off all attributes if */
				if(atr&(HIGH|BLINK|BG_LIGHTGRAY))	/* high intensity, blink or */
					attr(LIGHTGRAY);				/* background bits are set */
			break;
		case '_':								/* turn off all attributes if */
			if(atr&(BLINK|BG_LIGHTGRAY))		/* blink or background is set */
				attr(LIGHTGRAY);
			break;
		case 'P':	/* Pause */
			pause();
			break;
		case 'Q':   /* Pause reset */
			lncntr=0;
			break;
		case 'T':   /* Time */
			now=time(NULL);
			localtime_r(&now,&tm);
			if(cfg.sys_misc&SM_MILITARY)
				bprintf("%02u:%02u:%02u"
					,tm.tm_hour, tm.tm_min, tm.tm_sec);
			else
				bprintf("%02d:%02d %s"
					,tm.tm_hour==0 ? 12
					: tm.tm_hour>12 ? tm.tm_hour-12
					: tm.tm_hour, tm.tm_min, tm.tm_hour>11 ? "pm":"am");
			break;
		case 'D':   /* Date */
			now=time(NULL);
			bputs(unixtodstr(&cfg,(time32_t)now,tmp1));
			break;
		case ',':   /* Delay 1/10 sec */
			mswait(100);
			break;
		case ';':   /* Delay 1/2 sec */
			mswait(500);
			break;
		case '.':   /* Delay 2 secs */
			mswait(2000);
			break;
		case 'S':   /* Synchronize */
			ASYNC;
			break;
		case 'L':	/* CLS (form feed) */
			CLS;
			break;
		case '>':   /* CLREOL */
			cleartoeol();
			break;
		case '<':   /* Non-destructive backspace */
			outchar(BS);
			break;
		case '[':   /* Carriage return */
			outchar(CR);
			break;
		case ']':   /* Line feed */
			outchar(LF);
			break;
		case 'A':   /* Ctrl-A */
			outchar(CTRL_A);
			break;
		case 'H': 	/* High intensity */
			atr|=HIGH;
			attr(atr);
			break;
		case 'I':	/* Blink */
			atr|=BLINK;
			attr(atr);
			break;
		case 'N': 	/* Normal */
			attr(LIGHTGRAY);
			break;
		case 'R':
			atr=(atr&0xf8)|RED;
			attr(atr);
			break;
		case 'G':
			atr=(atr&0xf8)|GREEN;
			attr(atr);
			break;
		case 'B':
			atr=(atr&0xf8)|BLUE;
			attr(atr);
			break;
		case 'W':	/* White */
			atr=(atr&0xf8)|LIGHTGRAY;
			attr(atr);
			break;
		case 'C':
			atr=(atr&0xf8)|CYAN;
			attr(atr);
			break;
		case 'M':
			atr=(atr&0xf8)|MAGENTA;
			attr(atr);
			break;
		case 'Y':   /* Yellow */
			atr=(atr&0xf8)|BROWN;
			attr(atr);
			break;
		case 'K':	/* Black */
			atr=(atr&0xf8)|BLACK;
			attr(atr);
			break;
		case '0':	/* Black Background */
			atr=(atr&0x8f);
			attr(atr);
			break;
		case '1':	/* Red Background */
			atr=(atr&0x8f)|(uchar)BG_RED;
			attr(atr);
			break;
		case '2':	/* Green Background */
			atr=(atr&0x8f)|(uchar)BG_GREEN;
			attr(atr);
			break;
		case '3':	/* Yellow Background */
			atr=(atr&0x8f)|(uchar)BG_BROWN;
			attr(atr);
			break;
		case '4':	/* Blue Background */
			atr=(atr&0x8f)|(uchar)BG_BLUE;
			attr(atr);
			break;
		case '5':	/* Magenta Background */
			atr=(atr&0x8f)|(uchar)BG_MAGENTA;
			attr(atr);
			break;
		case '6':	/* Cyan Background */
			atr=(atr&0x8f)|(uchar)BG_CYAN;
			attr(atr);
			break;
		case '7':	/* White Background */
			atr=(atr&0x8f)|(uchar)BG_LIGHTGRAY;
			attr(atr);
			break; 
	}
}
예제 #11
0
파일: screentest.c 프로젝트: ruhler/focus
void test(bool* result)
{
    SCREEN_Screen scr;

    scr = screen(80, 25);
    update(result, tposeq("initial cursor", mkpos(0, 0), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(5, 10));
    update(result, tposeq("cursor_address", mkpos(5, 10), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(12, 5));
    carriage_return(&scr);
    update(result, tposeq("carriage_return", mkpos(0, 5), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(12, 5));
    newline(&scr);
    update(result, tposeq("newline", mkpos(0, 6), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(10, 6));
    tab(&scr);
    update(result, tposeq("tab", mkpos(16, 6), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(1, 6));
    column_address(&scr, 16);
    update(result, tposeq("column_address", mkpos(16, 6), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(16, 6));
    row_address(&scr, 12);
    update(result, tposeq("row_address", mkpos(16, 12), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(15, 6));
    cursor_down(&scr);
    update(result, tposeq("cursor_down", mkpos(15, 7), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(15, 6));
    cursor_home(&scr);
    update(result, tposeq("cursor_home", mkpos(0, 0), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(6, 8));
    cursor_left(&scr);
    update(result, tposeq("cursor_left", mkpos(5, 8), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(6, 8));
    cursor_right(&scr);
    update(result, tposeq("cursor_right", mkpos(7, 8), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(6, 8));
    cursor_to_ll(&scr);
    update(result, tposeq("cursor_to_ll", mkpos(0, 24), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(6, 8));
    cursor_up(&scr);
    update(result, tposeq("cursor_up", mkpos(6, 7), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(26, 9));
    parm_left_cursor(&scr, 23);
    update(result, tposeq("parm_left_cursor", mkpos(3, 9), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(3, 9));
    parm_right_cursor(&scr, 23);
    update(result, tposeq("parm_right_cursor", mkpos(26, 9), cursor(&scr)));

    scr = screen(80, 25);
    cursor_address(&scr, mkpos(26, 4));
    parm_down_cursor(&scr, 11);
    update(result, tposeq("parm_down_cursor", mkpos(26, 15), cursor(&scr)));

    scr = screen(6, 4);
    cursor_address(&scr, mkpos(2, 3));
    put_char(&scr, 'a');
    SCREEN_Cell want_0 = {'a', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("put_char puts", want_0, cellat(&scr, mkpos(2,3))));

    scr = screen(6, 4);
    cursor_address(&scr, mkpos(2, 3));
    put_char(&scr, 'a');
    update(result, tposeq("put_char moves", mkpos(3, 3), cursor(&scr)));

    scr = screen(6, 4);
    cursor_address(&scr, mkpos(5, 1));
    put_char(&scr, 'a');
    update(result, tposeq("put_char am", mkpos(0, 2), cursor(&scr)));

    scr = screen(6, 4);
    put_chars(&scr, "abcdefGHIJKLmno");
    SCREEN_Cell want_1 = {'J', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("put_char multiple", want_1, cellat(&scr, mkpos(3,1))));

    scr = screen(6, 4);
    put_chars(&scr, "abcdefGHIJKLmno");
    clear_screen(&scr);
    update(result, tposeq("clear_screen homes", mkpos(0, 0), cursor(&scr)));

    scr = screen(6, 4);
    put_chars(&scr, "abcdefGHIJKLmno");
    clear_screen(&scr);
    SCREEN_Cell want_2 = {' ', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("clear_screen clears", want_2, cellat(&scr, mkpos(3,1))));

    scr = screen(6, 4);
    cursor_address(&scr, mkpos(0, 3));
    put_chars(&scr, "abcdefGHIJKLmno");
    SCREEN_Cell want_3 = {'J', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("put_char scrolls at end", want_3, cellat(&scr, mkpos(3,2))));

    scr = screen(6, 3);
    put_chars(&scr, "abcdefGHIJKLmno");
    cursor_home(&scr);
    clr_eos(&scr);
    SCREEN_Cell want_4 = {' ', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("put_char scrolls at end", want_4, cellat(&scr, mkpos(4,1))));
    
    scr = screen(6, 4);
    cursor_down(&scr);
    put_chars(&scr, "abcdefGHIJKLmno");
    cursor_address(&scr, mkpos(0, 3));
    newline(&scr);
    SCREEN_Cell want_5 = {'K', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("newline at bottom scrolls", want_5, cellat(&scr, mkpos(4,1))));

    scr = screen(6, 4);
    put_chars(&scr, "abcdefGHIJKLmno");
    cursor_address(&scr, mkpos(0, 0));
    insert_line(&scr);
    SCREEN_Cell want_6 = {' ', SCREEN_COLOR_WHITE, SCREEN_COLOR_BLACK, {false, false}};
    update(result, tcelleq("insert_line clears full line", want_6, cellat(&scr, mkpos(5,0))));

    scr = screen(24, 4);
    cursor_address(&scr, mkpos(20, 1));
    tab(&scr);
    update(result, tposeq("tab at eol", mkpos(0, 2), cursor(&scr)));
}
예제 #12
0
파일: vt52.c 프로젝트: klamonte/qodem
/**
 * Push one byte through the VT52 emulator.
 *
 * @param from_modem one byte from the remote side.
 * @param to_screen if the return is Q_EMUL_FSM_ONE_CHAR or
 * Q_EMUL_FSM_MANY_CHARS, then to_screen will have a character to display on
 * the screen.
 * @return one of the Q_EMULATION_STATUS constants.  See emulation.h.
 */
Q_EMULATION_STATUS vt52(const unsigned char from_modem, wchar_t * to_screen) {
    static unsigned char *count;
    static attr_t attributes;
    int new_row;
    int new_col;
    unsigned char from_modem2;

    /*
     * The VT52 spec only supports 7-bit ASCII. Strip the high bit off every
     * character.
     */
    from_modem2 = from_modem & 0x7F;

    DLOG(("STATE: %d CHAR: 0x%02x '%c'\n", scan_state, from_modem2,
          from_modem2));

vt52_start:

    switch (scan_state) {

    case SCAN_NONE:
        /*
         * ESC
         */
        if (from_modem2 == C_ESC) {
            save_char(from_modem2, to_screen);
            scan_state = SCAN_ESC;
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        /*
         * Only a few control chars to handle here.  CR and LF are in
         * emulation.c .
         */
        if (from_modem2 == 0x05) {

            DLOG(("Enquire\n"));

            /*
             * ENQ - transmit the answerback message.
             */
            qodem_write(q_child_tty_fd, get_option(Q_OPTION_ENQ_ANSWERBACK),
                        strlen(get_option(Q_OPTION_ENQ_ANSWERBACK)), Q_TRUE);
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 0x08) {

            DLOG(("Backspace\n"));

            /*
             * Backspace.
             */
            cursor_left(1, Q_FALSE);
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 0x09) {

            DLOG(("Tab\n"));

            /*
             * Tab.
             */
            while (q_status.cursor_x < 80) {
                cursor_right(1, Q_FALSE);
                if (q_status.cursor_x % 8 == 0) {
                    break;
                }
            }

            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 0x7F) {

            DLOG(("Del\n"));

            /*
             * Del - consume but do nothing.
             */
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        /*
         * Any other control characters.
         */
        if (iscntrl(from_modem2)) {
            /*
             * Consume but do nothing.
             */
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        /*
         * This is a printable character.
         */
        *to_screen = map_character(from_modem2);
        return Q_EMUL_FSM_ONE_CHAR;

    case SCAN_Y_1:
        save_char(from_modem2, to_screen);
        scan_state = SCAN_Y_2;
        return Q_EMUL_FSM_NO_CHAR_YET;

    case SCAN_Y_2:
        /*
         * q_emul_buffer[0] = ESC
         * q_emul_buffer[1] = 'Y'
         */
        new_row = q_emul_buffer[2] - 32;
        new_col = from_modem2 - 32;
        if (new_row < 0) {
            new_row = 0;
        }
        if (new_col < 0) {
            new_col = 0;
        }

        DLOG(("Cursor position: %d %d\n", new_row, new_col));

        cursor_position(new_row, new_col);
        clear_state(to_screen);
        return Q_EMUL_FSM_NO_CHAR_YET;

    case SCAN_ESC:

        if (from_modem2 == 'A') {

            DLOG(("Cursor up\n"));

            cursor_up(1, Q_FALSE);
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'B') {

            DLOG(("Cursor down\n"));

            cursor_down(1, Q_FALSE);
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'C') {

            DLOG(("Cursor right\n"));

            cursor_right(1, Q_FALSE);
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'D') {

            DLOG(("Cursor left\n"));

            cursor_left(1, Q_FALSE);
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'E') {

            DLOG(("Erase entire screen\n"));

            /*
             * Cursor position to (0,0) and erase entire screen.
             */
            cursor_formfeed();
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'F') {

            DLOG(("Graphics mode ON\n"));

            graphics_mode = Q_TRUE;
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'G') {

            DLOG(("Graphics mode OFF\n"));

            graphics_mode = Q_FALSE;
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'H') {

            DLOG(("Cursor home\n"));

            cursor_position(0, 0);
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'I') {

            DLOG(("Reverse linefeed\n"));

            /*
             * Move up one column, inserting a line if already at the top.
             */
            if (q_status.cursor_y == 0) {
                scroll_down(1);
            } else {
                cursor_up(1, Q_FALSE);
            }

            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'J') {

            DLOG(("Erase to end of screen\n"));

            /*
             * Erase from here to end of screen.
             */
            erase_screen(q_status.cursor_y, q_status.cursor_x,
                         HEIGHT - STATUS_HEIGHT - 1, WIDTH - 1, Q_FALSE);

            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'K') {

            DLOG(("Erase to end of line\n"));

            /*
             * Erase from here to end of line.
             */
            erase_line(q_status.cursor_x, q_scrollback_current->length,
                       Q_FALSE);

            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'Y') {
            /*
             * Cursor position.
             */
            save_char(from_modem2, to_screen);
            scan_state = SCAN_Y_1;
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'Z') {

            DLOG(("DECID\n"));

            /*
             * Identify
             */

            /*
             * Note the VT100 and above will send <ESC>/Z, but the DECScope
             * manual claims the VT52 will send <ESC>/K if it does not have
             * an "integral electrolytic copier" (an internal printer that
             * used wet paper).
             */
            qodem_write(q_child_tty_fd, "\033/K", 3, Q_TRUE);

            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == '=') {

            DLOG(("Alternate keypad ON\n"));

            q_vt52_alternate_keypad_mode = Q_TRUE;
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == '>') {

            DLOG(("Alternate keypad OFF\n"));

            q_vt52_alternate_keypad_mode = Q_FALSE;
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == '[') {
            if (q_status.vt52_color == Q_TRUE) {
                /*
                 * Fall into SCAN_CSI only if VT52_COLOR is enabled.
                 */
                save_char(from_modem2, to_screen);
                scan_state = SCAN_CSI;
                return Q_EMUL_FSM_NO_CHAR_YET;
            }

            DLOG(("Hold screen mode ON\n"));

            q_status.hold_screen_mode = Q_TRUE;
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == '\\') {

            DLOG(("Hold screen mode OFF\n"));

            q_status.hold_screen_mode = Q_FALSE;
            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        break;

    case SCAN_CSI:
        /*
         * We are only going to support CSI Pn [ ; Pn ... ] m a.k.a. ANSI
         * Select Graphics Rendition.  We can see only a digit or 'm'.
         */
        if (q_isdigit(from_modem2)) {
            /*
             * Save the position for the counter.
             */
            count = q_emul_buffer + q_emul_buffer_n;
            save_char(from_modem2, to_screen);
            scan_state = SCAN_CSI_PARAM;
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'm') {
            /*
             * ESC [ m mean ESC [ 0 m, all attributes off.
             */

            DLOG(("ANSI SGR: reset\n"));

            q_current_color =
                Q_A_NORMAL | scrollback_full_attr(Q_COLOR_CONSOLE_TEXT);

            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        /*
         * This means we entered HOLD SCREEN mode.
         */

        DLOG(("Hold screen mode ON\n"));

        q_status.hold_screen_mode = Q_TRUE;

        /*
         * Reprocess the character from the top.
         */
        clear_state(to_screen);
        goto vt52_start;

    case SCAN_CSI_PARAM:
        /*
         * Following through on the SGR code, we are now looking only for a
         * digit, semicolon, or 'm'
         *
         */
        if ((q_isdigit(from_modem2)) || (from_modem2 == ';')) {
            save_char(from_modem2, to_screen);
            scan_state = SCAN_CSI_PARAM;
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        if (from_modem2 == 'm') {

            DLOG(("ANSI SGR: change text attributes\n"));

            /*
             * Text attributes.
             */
            if (ansi_color(&attributes, &count) == Q_TRUE) {
                q_current_color = attributes;
            } else {
                break;
            }

            clear_state(to_screen);
            return Q_EMUL_FSM_NO_CHAR_YET;
        }

        break;
    }

    /*
     * This point means we got most, but not all, of a sequence.
     */
    q_emul_buffer[q_emul_buffer_n] = from_modem2;
    q_emul_buffer_n++;
    *to_screen = q_emul_buffer[q_emul_buffer_i];
    q_emul_buffer_i++;
    scan_state = SCAN_NONE;

    /*
     * Special case: one character returns Q_EMUL_FSM_ONE_CHAR.
     */
    if (q_emul_buffer_n == 1) {
        q_emul_buffer_i = 0;
        q_emul_buffer_n = 0;
        return Q_EMUL_FSM_ONE_CHAR;
    }

    return Q_EMUL_FSM_MANY_CHARS;
}
예제 #13
0
static void do_sleep(int seconds)
{
	time_t target;
	int delta;

	if (!ncurses_initialized()) {
		sleep(seconds);
		return;
	}
	target = time(NULL) + seconds;
	delta = seconds;
	do {
		int c;
		usleep(6000);
		halfdelay(delta * 10);

		c = getch();
		switch (c) {
		case KEY_BTAB:
			show_prev_tab();
			break;
		case '\t':
			show_next_tab(); 
			break;
		case KEY_RIGHT:
			cursor_right(); 
			break;
		case KEY_LEFT:
			cursor_left(); 
			break;
		case KEY_NPAGE:
		case KEY_DOWN:
			cursor_down();
			break;
		case KEY_PPAGE:
		case KEY_UP:
			cursor_up();
			break;
		case ' ':
		case '\n':
			cursor_enter();
			break;
		case 's':
			if (set_refresh_timeout())
				return;
			break;
		case 'r':
			window_refresh();
			return;
		case KEY_EXIT:
		case 'q':
		case 27:	// Escape
			leave_powertop = 1;
			return;
		}

		delta = target - time(NULL);
		if (delta <= 0)
			break;

	} while (1);
}
예제 #14
0
파일: normal_loop.c 프로젝트: poiiii/vic
int normal_mode_process(int key_down)
{
#ifdef __VIC_POSIX
    int second_key_down = 0;
#endif

    char t[100];
    sprintf(t, "%x", key_down);
    print_log(t);

    switch (key_down)
    {
        case '\x1b':  //Esc
#ifdef __VIC_POSIX
            second_key_down = getchar();
            switch (second_key_down)    //double stroke Esc to return to normal mode.
            {
                case '\x5b':
                    second_key_down = getchar();
                    switch (second_key_down)
                    {
                        case '\x41':     //up
                            cursor_up();
                            break;

                        case '\x42':     //down
                            cursor_down();
                            break;

                        case '\x43':     //right
                            cursor_right();
                            break;

                        case '\x44':     //left
                            cursor_left();
                            break;

                        default:
                            break;
                    }
                    break;

                default:
                    break;
            }
#endif

#ifdef __VIC_WIN

#endif
            break;

#ifdef __VIC_WIN

            /*
        case '\xe0':    //first(or last maybe?) ascii of arrow keys.
        case '\x00':
            switch (getch())
            {
                case '\x48':    //up
                    cursor_up();
                    break;

                case '\x50':    //down
                    cursor_down();
                    break;

                case '\x4b':    //left
                    cursor_left();
                    break;

                case '\x4d':    //right
                    cursor_right();
                    break;

                default:
                    break;
            }
            break;
             */

        case '\x48':    //up
            cursor_up();
            break;

        case '\x50':    //down
            cursor_down();
            break;

        case '\x4b':    //left
            cursor_left();
            break;

        case '\x4d':    //right
            cursor_right();
            break;
#endif

        case '!':   //quit directly.
            enable_display_back();
            set_cursor_pos(console_columns, console_lines);
            exit(0);
            break;

        case '1':   //New File.
        case 'n':
            if (changed_flag == UNCHANGED || changed_flag == UNSAVED)
            {
                enable_display_back();
                set_cursor_pos(console_columns, console_lines);
            }
            else
            {
                changed_flag = UNSAVED;
            }
            break;

        case 'q':   //quit, is saved should be checked.
            if (changed_flag == UNCHANGED || changed_flag == UNSAVED)
            {
                enable_display_back();
                set_cursor_pos(console_columns, console_lines);
                exit(0);
            }
            else
            {
                changed_flag = UNSAVED;
            }
            break;

            //belows hjkl for cursor moving.
            //aiming to disable moving cursor outside the file part.
        case 'h':
            cursor_left();
            break;

        case 'l':
            cursor_right();
            break;

        case 'j':
            cursor_down();
            break;

        case 'k':
            cursor_up();
            break;

        case 'w':   //word forward.
        {
            int position = cur_left + cur_column - 1;
            int counter = 0;
            char *cur = get_line(cur_file, cur_top + cur_line - 1)->text;
            cur += cur_left + cur_column - 2;   //to be checked.
            if (is_word_start(cur))
            {
                position++;
                counter++;
                cur++;
            }
            for (; position < get_length(get_line(cur_file, cur_line + cur_top - 1)); position++, counter++)
            {
                if (is_word_start(cur++))
                {
                    break;
                }
            }
            for (; counter > 0; counter--)
            {
                cursor_right();
            }
        }
            break;

        case 'b':   //word backward.
        {
            int position = cur_left + cur_column - 1;
            int counter = 0;
            char *cur = get_line(cur_file, cur_top + cur_line - 1)->text;
            cur += cur_left + cur_column - 2;   //to be checked.
            if (is_word_start(cur))
            {
                position--;
                counter++;
                cur--;
            }
            for (; position > 0; position--, counter++)
            {
                if (is_word_start(cur--))
                {
                    break;
                }
            }
            for (; counter > 0; counter--)
            {
                cursor_left();
            }
        }
            break;

        case 'e':   //word-end forward.
        {
            int position = cur_left + cur_column - 1;
            int counter = 0;
            char *cur = get_line(cur_file, cur_top + cur_line - 1)->text;
            cur += cur_left + cur_column - 2;   //to be checked.
            if (is_word_end(cur))
            {
                position++;
                counter++;
                cur++;
            }
            for (; position < get_length(get_line(cur_file, cur_line + cur_top - 1)); position++, counter++)
            {
                if (is_word_end(cur++))
                {
                    break;
                }
            }
            for (; counter > 0; counter--)
            {
                cursor_right();
            }
        }
            break;

        case 'i':   //insert.
            mode_flag = INSERT_MODE;
            break;

        case 'a':   //append.
            cursor_right();
            mode_flag = INSERT_MODE;
            break;

        case 'd':   //delete a word.
        {
            v_line *this_line = get_line(cur_file, cur_top + cur_line - 1);
            unsigned int word_len = 0;
            unsigned int start_index = cur_left + cur_column - 2;
            unsigned int end_index = judge_word(this_line, start_index + 1);
            word_len = end_index - start_index + 1;
            for (int i = 0; i < end_index - start_index + 1; i++)
            {
                del_char(this_line, cur_left + cur_column - 2);
            }
            if (word_len != 0)
            {
                changed_flag = CHANGED;
            }
        }
            break;

        case 'x':   //delete a single char.
            del_char(get_line(cur_file, cur_top + cur_line - 1), cur_left + cur_column - 2);
            changed_flag = CHANGED;
            break;

        case 'o':   //open new line.
            insert_empty_line(cur_file, cur_top + cur_line - 1);
            cursor_down();
            mode_flag = INSERT_MODE;
            break;

        case '$':
            goto_line_end();
            break;

        case '^':   //goto first char of line.
            goto_line_actual_start();
            break;

        case '0':   //goto fixed first column.
            goto_line_start();
            break;

        case '3':
        case ':':   //bottom line command mode.
            //Now I wanna use this as open file command.
            if (changed_flag == CHANGED)
            {
                changed_flag = UNSAVED;
                break;
            }
            mode_flag = BOTTOMLINE_MODE;
            bottomline_sub_mode = BOTTOM_LINE_FILENAME_OPEN;
            break;

        case '/':    //bottom line and search.
            break;

        case '2':
        case 's':
            if (strlen(cur_file_name) == 0)
            {
                mode_flag = BOTTOMLINE_MODE;
                bottomline_sub_mode = BOTTOM_LINE_FILENAME_SAVE;
            }
            else
            {
                v_save_file(cur_file_name, cur_file);
                changed_flag = UNCHANGED;
            }
            break;

#ifdef __VIC_WIN
        case '\x00':
        case '\xe0':
#endif
        default:
            break;
    }
    return 0;
}
예제 #15
0
파일: vt100.c 프로젝트: ErisBlastar/osfree
// you may want to have a look into /usr/src/linux/drivers/char/console.c
void parse_character(termstate_t * term, l4_uint8_t c)
{
    int i;

    // these must be handled independetly of state
    switch (c)
    {
    case 0: // ignore
        return;
    case 7: // bell
        // todo: impl. me
        return;
    case 8: // backspace
        if (term->cur_x > 0)
            term->cur_x--;
        return;
    case 9: // tab
        cursor_tab(term);
        return;
    case 10: // newline (lf)
    case 11: // ?
    case 12: // ?
        cursor_nl(term);
        return;
    case 13: // do a cr here, maybe a smart one (+ lf)
        cursor_cr(term);
        return;
    case 27: // ESC
        term->esc_state = ESesc;
        return;
    }

    // now check for the state-dependant characters
    switch (term->esc_state)
    {
    case ESnormal:
        // normal character
        if ((c >= 0x20 && c <= 0x7e) || (c >= 0xa1 && c <= 0xfe))
        {
            if (term->insert_mode == VT100_INSMODE_REPLACE)
            {
                set_char(term, c);
                //vt100_redraw_xy(term, term->cur_x, term->cur_y);
                cursor_next(term);
            }
            else // VT100_INSMODE_INSERT
            {
                insert_char(term, c);
                //vt100_redraw(term);
            }
            return;
        }
//        switch (c)
//        {
//        }
        break;
    case ESesc: // normal ESC found
        term->esc_state = ESnormal;
        switch (c)
        {
        case '[':
            term->esc_state = ESsquare;
            return;
        case 'D':  // lf
            cursor_lf(term);
            //vt100_redraw(term);
            return;
        case 'E':  // cr + lf
            cursor_nl(term);
            //vt100_redraw(term);
            return;
        case 'H':  // set tab at current position
            set_tab( term, term->cur_x );
            return;
        case 'M':
            rev_scroll(term);
            //vt100_redraw(term);
            return;
        case '7':  // save cursor position and attributes
            term->cur_stored_x    = term->cur_x;
            term->cur_stored_y    = term->cur_y;
            term->cur_stored_attr = term->attrib_mode;
            return;
        case '8':  // restore saved cursor position and attributes
            term->cur_x         = term->cur_stored_x;
            term->cur_y         = term->cur_stored_y;
            term->attrib_mode   = term->cur_stored_attr;
            return;
        case '#':
            term->esc_state = EShash;
            return;
        case 'c':  // reset vt to default settings
            init_termstate(term, term->w, term->phys_h, term->virt_h);
            return;
        }
    case ESsquare:
        for(i = 0; i < NUM_PAR; i++)
            term->par[i] = 0;
        term->used_par = 0;
        term->esc_state = ESgetpars;
        term->ques = (c=='?');
        if (term->ques)
            return;
        // fall-through
    case ESgetpars:
        if (c == ';' && term->used_par < NUM_PAR - 1)
        {
            term->used_par++;
            return;
        }
        else if (c >= '0' && c <= '9')
        {
            term->par[term->used_par] *= 10;
            term->par[term->used_par] += c - '0';
            return;
        } else term->esc_state = ESgotpars;
        // fall-through
    case ESgotpars:
        term->esc_state = ESnormal;
        switch (c)
        {
        case 'h':
            if (term->ques)
            {
                // handle question commands ending with h
                for (i = 0; i <= term->used_par; i++)
                {
                    switch( term->par[i] )
                    {
                    case  5: // activate inverse screen
                        if (set_mode(term, 1))
                            //vt100_redraw(term);
                        break;
                    case  6: // origin mode = scroll region
                        term->origin_mode = VT100_ORIGIN_SCROLL;
                        break;
                    case  7: // autowrap mode on
                        term->autowrap   = 1;
                        break;
                    case  8: // autorepeat on
                        term->autorepeat = 1;
                        break;
                    case 25: // activate cursor
                        term->cursor_vis = 1; return;
                    default:
                        break;
                    }
                }
                return;
            }
            else // handle commands without question mark
            {
                for(i = 0; i <= term->used_par; i++)
                {
                    switch( term->par[i] )
                    {
                    case 4: // insert mode on
                        term->insert_mode = VT100_INSMODE_INSERT;
                        break;
                    case 12: // echo on
                        term->echo = 1;
                        break;
                    case 20: // line feed mode
                        term->newline = 1;
                        break;
                    default: break;
                    }
                }
                return;
            }
        case 'l':
            if (term->ques)
            {
                for(i = 0; i <= term->used_par; i++)
                {
                    // handle question commands ending with l
                    switch( term->par[i] )
                    {
                    case  3: // set 80 column mode, clear screen
                        // todo: impl. resize and use it here
                        break;
                    case  5: // deactivate inverse screen
                        if(set_mode(term, 0))
                            //vt100_redraw(term);
                        break;
                    case  6: // origin mode = whole screen
                        term->origin_mode = VT100_ORIGIN_GLOBAL;
                    case  7: // autowrap mode off
                        term->autowrap = 0;
                        break;
                    case  8: // autorepeat off
                        term->autorepeat = 0;
                        break;
                    case 25: // deactivate cursor
                        term->cursor_vis = 0; return;
                    default: break;
                    }
                    return;
                }
            }
            else // handle commands without question mark
            {
                for( i=0; i <= term->used_par; i++ )
                {
                    switch( term->par[i] )
                    {
                    case 4: // insert mode off
                        term->insert_mode = VT100_INSMODE_REPLACE;
                        break;
                    case 12: // echo off
                        term->echo = 0;
                        break;
                    case 20: // carriage return mode
                        term->newline = 0;
                        break;
                    default:
                        break;
                    }
                    return;
                }
            }
        }
        if (term->ques)
        {
            term->ques = 0;
            return;
        }
        switch (c)
        {
        case 'F':  // CR + up
            term->cur_x     = 0;
            // fall through
        case 'A':  // up
            if (! term->par[0])
                term->par[0]++;
            cursor_up(term);
            return;
        case 'E':  // CR + down
            term->cur_x     = 0;
            // fall through
        case 'B':  // down
            if (! term->par[0])
                term->par[0]++;
            cursor_down(term);
            return;
        case 'C':  // right
            // no parameter -> set parameter to default (=1)
            if (! term->par[0])
                term->par[0]++;
            cursor_right(term);
            return;
        case 'D':  // left
            if (! term->par[0])
                term->par[0]++;
            cursor_left(term);
            return;
        case 'G':  // cursor position horizontal absolute
            if ( (term->par[0] > 0) &&
                 (term->par[0] < term->w) )
                term->cur_x = term->par[0];
            return;
        case 'H':  // absolute position (x,y)
        case 'f':  // f is the same as H (correct me, if I'm wrong)
            // well it is the same in the Linux kernel, in theorie the
            // 'f' commands depend on the PUM (Position unit mode),
            // which can be characters (seems to be default) or inch
            if (term->par[0] > 0)  // convert to (0, 0) based coords
                term->par[0]--;
            if (term->par[1] > 0)
                term->par[1]--;
            cursor_move_abs(term, term->par[1], term->par[0]);
            return;
        case 'I':  // insert tabs ('\t', term->par[0] times)
            if (!term->par[0])
                term->par[0]++;
            for (i=0;i<term->par[0];i++)
                cursor_tab(term);
            return;
        case 'J':
            switch(term->par[0])
            {
            case 0:  // kill to end of screen
                clean_to_eos(term);
                //vt100_redraw(term);
                return;
            case 1:  // kill from start of screen
                clean_from_sos(term);
                //vt100_redraw(term);
                return;
            case 2:  // kill whole screen
                clean_screen(term, ' ');
                //vt100_redraw(term);
                return;
            }
        case 'K':  // kill to end of line
            switch(term->par[0])
            {
            case 0: // clean to end of line
                clean_to_eol(term);
                //vt100_redraw(term);
                return;
            case 1: // clean from start of line
                clean_from_sol(term);
                return;
            case 2: // erase whole line
                clean_line(term, term->cur_y);
                return;
            }
        case 'L':  // insert lines
            if (!term->par[0])
                term->par[0] = 1;
            for (i=0; i<term->par[0]; i++)
                insert_line(term);
            //vt100_redraw(term);
            return;
        case 'M':  // erase lines
            if (!term->par[0])
                term->par[0] = 1;
            for (i=0; i<term->par[0]; i++)
                erase_line(term);
            //vt100_redraw(term);
            return;
        case 'c':  // we were asked to identify the terminal type
            identify(term);
            return;
        case 'g':  // erase tab(s)
            switch(term->par[0])
            {
                case 0:  remove_tab( term, term->cur_x );
                         break;
                case 3:  clear_tabs( term );
                         break;
                default: break;
            }
            return;
        case 'm':
            csi_m(term);
            return;
        case 'r':  // set scrolling region
            if (term->par[0] == 0)
                term->par[0]++;
            if (term->par[1] == 0)
                term->par[1] = term->phys_h;
            /* Minimum allowed region is 2 lines */
            if (term->par[0] < term->par[1] &&
                term->par[1] <= term->phys_h)
            {
                term->scroll_top = term->par[0] - 1;
                term->scroll_bottom = term->par[1]; // this line is excluded
                // if in origin mode, make sure that the cursor is placed
                // inside the scrolling region immediately
                if (term->origin_mode == VT100_ORIGIN_SCROLL)
                {
                    term->cur_x = 0;
                    term->cur_y = term->scroll_top;
                }
            }
            return;
        }
    case EShash:
        term->esc_state = ESnormal;
        switch(c)
        {
        case '8':  // fill the screen with 'E'
            clean_screen(term, 'E');
            //vt100_redraw(term);
            break;
        }
        break;
    }
}
예제 #16
0
파일: amiga.c 프로젝트: DavidKinder/Level9
L9BOOL os_input (char *ibuff, int size)
{
  int c, pos = 0;
  int inputting = 1;
  unsigned long saved_pen;
  UWORD qualifier;

  *ibuff = '\0';
  cursor (*ibuff);
  saved_pen = RastPort->FgPen;
  SetAPen (RastPort, 2);

  while (inputting)
  {
    set_window (1, TextLength (RastPort, ibuff + pos, strlen (ibuff + pos)));
    c = get_key (&qualifier, *(ibuff + pos), 1);
    set_window (0, 0);

    switch (c)
    {
    case -1:
      cursor (*(ibuff + pos));
      SetAPen (RastPort, 1);
      MoreCount = 0;
      return 0;

    case -2:
      cursor (*(ibuff + pos));
      cursor_right (ibuff, &pos);
      strcpy(ibuff,"save");
      SetAPen (RastPort, 1);
      MoreCount = 0;
      return 1;

    case -3:
      cursor (*(ibuff + pos));
      cursor_right (ibuff, &pos);
      strcpy(ibuff,"#restore");
      SetAPen (RastPort, 1);
      MoreCount = 0;
      return 1;

    case 13:
      if (strlen (ibuff) > 0)
      {
	cursor (*(ibuff + pos));
	cursor_right (ibuff, &pos);
	SetAPen (RastPort, 1);
	store_hist (ibuff);
	MoreCount = 0;
	return 1;
      }
      break;

    case 264:
      redraw_line (ibuff, &pos, size);
      break;

    case 127:
      if (pos > 0)
      {
	int deleted;

	cursor (*(ibuff + pos));
	deleted = *(ibuff + pos - 1);
	memmove (ibuff + pos - 1, ibuff + pos, strlen (ibuff) - pos + 1);
	move_text (-char_len (deleted), Window->Width - Window->BorderRight);
	Move (RastPort, RastPort->cp_x - char_len (deleted), RastPort->cp_y);
	pos--;
	cursor (*(ibuff + pos));
      }
      break;

    case 260:
      if (pos < strlen (ibuff))
      {
	int deleted;

	cursor (*(ibuff + pos));
	deleted = *(ibuff + pos);
	memmove (ibuff + pos, ibuff + pos + 1, strlen (ibuff) - pos);
	Move (RastPort, RastPort->cp_x + char_len (deleted), RastPort->cp_y);
	move_text (-char_len (deleted), Window->Width - Window->BorderRight);
	Move (RastPort, RastPort->cp_x - char_len (deleted), RastPort->cp_y);
	cursor (*(ibuff + pos));
      }
      break;

    case 131:
      if (pos > 0)
      {
	if (qualifier & QUALIFIER_SHIFT)
	{
	  cursor (*(ibuff + pos));
	  cursor_left (ibuff, &pos);
	  cursor (*(ibuff + pos));
	}
	else
	{
	  cursor (*(ibuff + pos--));
	  Move (RastPort, RastPort->cp_x - char_len (*(ibuff + pos)), RastPort->cp_y);
	  cursor (*(ibuff + pos));
	}
      }
      break;

    case 132:
      if (pos < strlen (ibuff))
      {
	if (qualifier & QUALIFIER_SHIFT)
	{
	  cursor (*(ibuff + pos));
	  cursor_right (ibuff, &pos);
	  cursor (*(ibuff + pos));
	}
	else
	{
	  cursor (*(ibuff + pos));
	  Move (RastPort, RastPort->cp_x + char_len (*(ibuff + pos)), RastPort->cp_y);
	  pos++;
	  cursor (*(ibuff + pos));
	}
      }
      break;

    case 129:
      if (qualifier & QUALIFIER_SHIFT)
      {
	HistoryPosition = 0;
	while ((*(History + HistoryPosition) == 0) && (HistoryPosition < HISTORY_LINES))
	  HistoryPosition++;
	into_buffer (ibuff, HistoryPosition == HISTORY_LINES ?
	  (unsigned char *) "" : *(History + HistoryPosition), &pos, size);
      }
      else
      {
	if ((HistoryPosition > 0) && (*(History + HistoryPosition - 1) != 0))
	{
	  HistoryPosition--;
	  into_buffer (ibuff, *(History + HistoryPosition), &pos, size);
	}
      }
      break;

    case 130:
      if (qualifier & QUALIFIER_SHIFT)
      {
	HistoryPosition = HISTORY_LINES;
	into_buffer (ibuff, "", &pos, size);
      }
      else
      {
	if ((HistoryPosition < HISTORY_LINES - 1) && (*(History + HistoryPosition + 1) != 0))
	{
	  HistoryPosition++;
	  into_buffer (ibuff, HistoryPosition == HISTORY_LINES ?
	    (unsigned char *) "" : *(History + HistoryPosition), &pos, size);
	}
	else
	{
	  HistoryPosition = HISTORY_LINES;
	  into_buffer (ibuff, "", &pos, size);
	}
      }
      break;

    default:
      if (c >= 32 && c <= 127)
      {
	if ((strlen (ibuff) < size) && (fit_text (ibuff + pos, c)))
	{
	  memmove (ibuff + pos + 1, ibuff + pos, strlen (ibuff) - pos + 1);
	  *(ibuff + pos) = c;

	  pos++;
	  cursor (*(ibuff + pos));
	  move_text (char_len (c), Window->Width - Window->BorderRight);
	  os_printchar (c);
	  cursor (*(ibuff + pos));
	}
      }
      break;
    }
  }
}
예제 #17
0
파일: outputter.c 프로젝트: ruhler/focus
void outputter(SCREEN_Screen* scr, int terminator, GetCharFunction getf)
{
    while (1) {
        unsigned char c = getf();
        if (c == terminator) {
            return;
        }

        switch (c) {
            case '\a': break;   // TODO: alert?
            case '\t': tab(scr); break;
            case '\n': cursor_down(scr); break;
            case '\b': cursor_left(scr); break;
            case '\r': carriage_return(scr); break;
            case 0x1b: 
            {
                c = getf();
                switch (c) {
                    case '[':
                    {
                        int x;
                        if (getnum(getf, &x, &c)) {
                            if (x == 1 && c == 'K') {
                                clr_bol(scr);
                            } else {
                                switch (c) {
                                    case 'm': mode(scr, x); break;
                                    case 'A': parm_up_cursor(scr, x); break;
                                    case 'B': parm_down_cursor(scr, x); break;
                                    case 'C': parm_right_cursor(scr, x); break;
                                    case 'D': parm_left_cursor(scr, x); break;
                                    case 'G': column_address(scr, (x-1)); break;
                                    case 'L': parm_insert_line(scr, x); break;
                                    case 'M': parm_delete_line(scr, x); break;
                                    case 'P': parm_dch(scr, x); break;
                                    case 'S': parm_index(scr, x); break;
                                    case 'T': parm_rindex(scr, x); break;
                                    case 'X': erase_chars(scr, x); break;
                                    case '@': parm_ich(scr, x); break;
                                    case 'd': row_address(scr, (x-1)); break;
                                    case ';':
                                    {
                                        int y;
                                        if (getnum(getf, &y, &c)) {
                                            switch (c) {
                                                case 'm':
                                                    mode(scr, x);
                                                    mode(scr, y);
                                                    break;

                                                case 'H': cursor_address(scr, mkpos(y-1, x-1)); break;
                                                default: 
                                                    fprintf(stderr, "unhandled: ESC[%i;%i%c\n", x, y, c);
                                                    break;
                                            }
                                        } else {
                                            fprintf(stderr, "unhandled: ESC[%i;%c\n", x, c);
                                        }
                                    } break;

                                    default:
                                        fprintf(stderr, "unahndled: ESC[%i%c\n", x, c);
                                        break;
                                }
                            }
                        } else {
                            switch (c) {
                                case '@': insert_character(scr); break;
                                case 'A': cursor_up(scr); break;
                                case 'B': cursor_down(scr); break;
                                case 'C': cursor_right(scr); break;
                                case 'D': cursor_left(scr); break;
                                case 'H': cursor_home(scr); break;
                                case 'I': tab(scr); break;
                                case 'J': clr_eos(scr); break;
                                case 'K': clr_eol(scr); break;
                                case 'L': insert_line(scr); break;
                                case 'M': delete_line(scr); break;
                                case 'P': delete_character(scr); break;
                                case 'm': exit_attribute_mode(scr); break;
                                default:
                                    fprintf(stderr, "unhandled: ESC[%c\n", c);
                                    break;
                            }
                        }

                    } break;

                    case 'M':
                        scroll_reverse(scr);
                        break;

                    default:
                        fprintf(stderr, "unhandled: ESC%c\n", c);
                        break;
                }
            } break;

            default:
            {
                wchar_t wc;
                if ((c & 0x80) == 0x00) {
                    wc = c;
                } else if ((c & 0xE0) == 0xC0) {
                    char c1 = 0x1F & c;
                    char c2 = 0x3F & getf();
                    wc = (c1 << 6) | c2;
                } else if ((c & 0xF0) == 0xE0) {
                    char c1 = 0x0F & c;
                    char c2 = 0x3F & getf();
                    char c3 = 0x3F & getf();
                    wc = (c1 << 12) | (c2 << 6) | c3;
                } else if ((c & 0xF8) == 0xF0) {
                    char c1 = 0x07 & c;
                    char c2 = 0x3F & getf();
                    char c3 = 0x3F & getf();
                    char c4 = 0x3F & getf();
                    wc = (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
                } else if ((c & 0xFC) == 0xF8) {
                    char c1 = 0x03 & c;
                    char c2 = 0x3F & getf();
                    char c3 = 0x3F & getf();
                    char c4 = 0x3F & getf();
                    char c5 = 0x3F & getf();
                    wc = (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | c5;
                } else if ((c & 0xFE) == 0xFC) {
                    char c1 = 0x01 & c;
                    char c2 = 0x3F & getf();
                    char c3 = 0x3F & getf();
                    char c4 = 0x3F & getf();
                    char c5 = 0x3F & getf();
                    char c6 = 0x3F & getf();
                    wc = (c1 << 30) | (c2 << 24) | (c3 << 18) | (c4 << 12) | (c5 < 6) | c6;
                } else {
                    fprintf(stderr, "bad utf-8 sequence: c=0x%02x\n", c);
                    wc = '\0';
                }

                put_char(scr, wc);
            } break;
        }
    }
}
예제 #18
0
파일: dev.c 프로젝트: Turingwy/turinux
void kbd_handler(regs_pt *regs)
{
    static int max_len;
    static int cur_len;
    if(input.s == 1)
    {
        max_len = 0;
        cur_len = 0;
        input.s = 2;
    } 

    if(input.s != 2)
        return;
    
    int ch = kbdgetc();
    if(!ch)
        return;
    switch(ch)
    {
        case KEY_LF:
            if(cur_len > 0) {
                cursor_left();
                cur_len--;
            }
            return;
        case KEY_RT:
            if(cur_len < max_len) {
                cursor_right();
                cur_len++;
            }
            return;
        case '\b':
            if(cur_len <= 0)
                return;
            cur_len--;
            max_len--;
            for(int i = (input.r+cur_len)%256; i != input.w; i=(i+1)%256)
            {
                input.buf[i] = input.buf[(i+1)%256];
            }
            input.w=(input.w-1)%256;
            for(int i = cur_len; i < max_len; i++)
                    cursor_right();
            flush_input(max_len+1, max_len, &input.buf[input.r]);
            for(int i = cur_len; i < max_len; i++)
                    cursor_left();
            return;
        case '\n':
            input.w=(input.w+1)%256;
            for(int i = cur_len; i < max_len; i++)
                    cursor_right();
            putchar_normal('\n');
            wakeup(&input.r);
            return;
    }

    // queue is full.
    if((input.w + 1)%256 == input.r)
    {
        wakeup(&input.r);
        return;
    }
        
    int i;
    for(i = input.w; i != (input.r+cur_len)%256; i=(i-1)%256)
        input.buf[i] = input.buf[(i-1)%256];
    input.buf[i] = ch;

    max_len++;
    cur_len++;
    for(i = cur_len-1; i < max_len-1; i++)
        cursor_right();
    flush_input(max_len-1, max_len, &input.buf[input.r]);
    for(i = cur_len; i < max_len; i++)
        cursor_left();
    input.w=(input.w+1)%256;
    input.w%=256;

}
예제 #19
0
const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen)
{
	char*	tp;
	uint	i;
	uint	ugrp;
	uint	usub;
	long	l;
    stats_t stats;
    node_t  node;
	struct	tm tm;

	str[0]=0;

	if(!strcmp(sp,"VER"))
		return(VERSION);

	if(!strcmp(sp,"REV")) {
		safe_snprintf(str,maxlen,"%c",REVISION);
		return(str);
	}

	if(!strcmp(sp,"FULL_VER")) {
		safe_snprintf(str,maxlen,"%s%c%s",VERSION,REVISION,beta_version);
		truncsp(str);
#if defined(_DEBUG)
		strcat(str," Debug");
#endif
		return(str);
	}

	if(!strcmp(sp,"VER_NOTICE"))
		return(VERSION_NOTICE);

	if(!strcmp(sp,"OS_VER"))
		return(os_version(str));

#ifdef JAVASCRIPT
	if(!strcmp(sp,"JS_VER"))
		return((char *)JS_GetImplementationVersion());
#endif

	if(!strcmp(sp,"PLATFORM"))
		return(PLATFORM_DESC);

	if(!strcmp(sp,"COPYRIGHT"))
		return(COPYRIGHT_NOTICE);

	if(!strcmp(sp,"COMPILER")) {
		DESCRIBE_COMPILER(str);
		return(str);
	}

	if(!strcmp(sp,"UPTIME")) {
		extern volatile time_t uptime;
		time_t up=time(NULL)-uptime;
		if(up<0)
			up=0;
		char   days[64]="";
		if((up/(24*60*60))>=2) {
	        sprintf(days,"%lu days ",(ulong)(up/(24L*60L*60L)));
			up%=(24*60*60);
		}
		safe_snprintf(str,maxlen,"%s%lu:%02lu"
	        ,days
			,(ulong)(up/(60L*60L))
			,(ulong)((up/60L)%60L)
			);
		return(str);
	}

	if(!strcmp(sp,"SERVED")) {
		extern volatile ulong served;
		safe_snprintf(str,maxlen,"%lu",served);
		return(str);
	}

	if(!strcmp(sp,"SOCKET_LIB"))
		return(socklib_version(str,SOCKLIB_DESC));

	if(!strcmp(sp,"MSG_LIB")) {
		safe_snprintf(str,maxlen,"SMBLIB %s",smb_lib_ver());
		return(str);
	}

	if(!strcmp(sp,"BBS") || !strcmp(sp,"BOARDNAME"))
		return(cfg.sys_name);

	if(!strcmp(sp,"BAUD") || !strcmp(sp,"BPS")) {
		safe_snprintf(str,maxlen,"%lu",cur_rate);
		return(str);
	}

	if(!strcmp(sp,"CONN"))
		return(connection);

	if(!strcmp(sp,"SYSOP"))
		return(cfg.sys_op);

	if(!strcmp(sp,"LOCATION"))
		return(cfg.sys_location);

	if(!strcmp(sp,"NODE")) {
		safe_snprintf(str,maxlen,"%u",cfg.node_num);
		return(str);
	}

	if(!strcmp(sp,"TNODE")) {
		safe_snprintf(str,maxlen,"%u",cfg.sys_nodes);
		return(str);
	}

	if(!strcmp(sp,"INETADDR"))
		return(cfg.sys_inetaddr);

	if(!strcmp(sp,"HOSTNAME"))
		return(startup->host_name);

	if(!strcmp(sp,"FIDOADDR")) {
		if(cfg.total_faddrs)
			return(smb_faddrtoa(&cfg.faddr[0],str));
		return(nulstr);
	}

	if(!strcmp(sp,"EMAILADDR"))
		return(usermailaddr(&cfg, str
			,cfg.inetmail_misc&NMAIL_ALIAS ? useron.alias : useron.name));

	if(!strcmp(sp,"QWKID"))
		return(cfg.sys_id);

	if(!strcmp(sp,"TIME") || !strcmp(sp,"SYSTIME")) {
		now=time(NULL);
		memset(&tm,0,sizeof(tm));
		localtime_r(&now,&tm);
		if(cfg.sys_misc&SM_MILITARY)
			safe_snprintf(str,maxlen,"%02d:%02d:%02d"
		        	,tm.tm_hour,tm.tm_min,tm.tm_sec);
		else
			safe_snprintf(str,maxlen,"%02d:%02d %s"
				,tm.tm_hour==0 ? 12
				: tm.tm_hour>12 ? tm.tm_hour-12
				: tm.tm_hour, tm.tm_min, tm.tm_hour>11 ? "pm":"am");
		return(str);
	}

	if(!strcmp(sp,"TIMEZONE"))
		return(smb_zonestr(sys_timezone(&cfg),str));

	if(!strcmp(sp,"DATE") || !strcmp(sp,"SYSDATE")) {
		return(unixtodstr(&cfg,time32(NULL),str));
	}

	if(!strcmp(sp,"DATETIME"))
		return(timestr(time(NULL)));

	if(!strcmp(sp,"TMSG")) {
		l=0;
		for(i=0;i<cfg.total_subs;i++)
			l+=getposts(&cfg,i); 		/* l=total posts */
		safe_snprintf(str,maxlen,"%lu",l);
		return(str);
	}

	if(!strcmp(sp,"TUSER")) {
		safe_snprintf(str,maxlen,"%u",total_users(&cfg));
		return(str);
	}

	if(!strcmp(sp,"TFILE")) {
		l=0;
		for(i=0;i<cfg.total_dirs;i++)
			l+=getfiles(&cfg,i);
		safe_snprintf(str,maxlen,"%lu",l);
		return(str);
	}

	if(!strcmp(sp,"TCALLS") || !strcmp(sp,"NUMCALLS")) {
		getstats(&cfg,0,&stats);
		safe_snprintf(str,maxlen,"%lu",stats.logons);
		return(str);
	}

	if(!strcmp(sp,"PREVON") || !strcmp(sp,"LASTCALLERNODE")
		|| !strcmp(sp,"LASTCALLERSYSTEM"))
		return(lastuseron);

	if(!strcmp(sp,"CLS")) {
		CLS;
		return(nulstr);
	}

	if(!strcmp(sp,"PAUSE") || !strcmp(sp,"MORE")) {
		pause();
		return(nulstr);
	}

	if(!strcmp(sp,"RESETPAUSE")) {
		lncntr=0;
		return(nulstr);
	}

	if(!strcmp(sp,"NOPAUSE") || !strcmp(sp,"POFF")) {
		sys_status^=SS_PAUSEOFF;
		return(nulstr);
	}

	if(!strcmp(sp,"PON") || !strcmp(sp,"AUTOMORE")) {
		sys_status^=SS_PAUSEON;
		return(nulstr);
	}

	/* NOSTOP */

	/* STOP */

	if(!strcmp(sp,"BELL") || !strcmp(sp,"BEEP"))
		return("\a");

	if(!strcmp(sp,"EVENT")) {
		if(event_time==0)
			return("<none>");
		return(timestr(event_time));
	}

	/* LASTCALL */

	if(!strncmp(sp,"NODE",4)) {
		i=atoi(sp+4);
		if(i && i<=cfg.sys_nodes) {
			getnodedat(i,&node,0);
			printnodedat(i,&node);
		}
		return(nulstr);
	}

	if(!strcmp(sp,"WHO")) {
		whos_online(true);
		return(nulstr);
	}

	/* User Codes */

	if(!strcmp(sp,"USER") || !strcmp(sp,"ALIAS") || !strcmp(sp,"NAME"))
		return(useron.alias);

	if(!strcmp(sp,"FIRST")) {
		safe_snprintf(str,maxlen,"%s",useron.alias);
		tp=strchr(str,' ');
		if(tp) *tp=0;
		return(str);
	}

	if(!strcmp(sp,"USERNUM")) {
		safe_snprintf(str,maxlen,"%u",useron.number);
		return(str);
	}

	if(!strcmp(sp,"PHONE") || !strcmp(sp,"HOMEPHONE")
		|| !strcmp(sp,"DATAPHONE") || !strcmp(sp,"DATA"))
		return(useron.phone);

	if(!strcmp(sp,"ADDR1"))
		return(useron.address);

	if(!strcmp(sp,"FROM"))
		return(useron.location);

	if(!strcmp(sp,"CITY")) {
		safe_snprintf(str,maxlen,"%s",useron.location);
		char* p=strchr(str,',');
		if(p) {
			*p=0;
			return(str);
		}
		return(nulstr);
	}

	if(!strcmp(sp,"STATE")) {
		char* p=strchr(useron.location,',');
		if(p) {
			p++;
			if(*p==' ')
				p++;
			return(p);
		}
		return(nulstr);
	}

	if(!strcmp(sp,"CPU"))
		return(useron.comp);

	if(!strcmp(sp,"HOST"))
		return(client_name);

	if(!strcmp(sp,"BDATE"))
		return(useron.birth);

	if(!strcmp(sp,"AGE")) {
		safe_snprintf(str,maxlen,"%u",getage(&cfg,useron.birth));
		return(str);
	}

	if(!strcmp(sp,"CALLS") || !strcmp(sp,"NUMTIMESON")) {
		safe_snprintf(str,maxlen,"%u",useron.logons);
		return(str);
	}

	if(!strcmp(sp,"MEMO"))
		return(unixtodstr(&cfg,useron.pwmod,str));

	if(!strcmp(sp,"SEC") || !strcmp(sp,"SECURITY")) {
		safe_snprintf(str,maxlen,"%u",useron.level);
		return(str);
	}

	if(!strcmp(sp,"SINCE"))
		return(unixtodstr(&cfg,useron.firston,str));

	if(!strcmp(sp,"TIMEON") || !strcmp(sp,"TIMEUSED")) {
		now=time(NULL);
		safe_snprintf(str,maxlen,"%lu",(ulong)(now-logontime)/60L);
		return(str);
	}

	if(!strcmp(sp,"TUSED")) {              /* Synchronet only */
		now=time(NULL);
		return(sectostr((uint)(now-logontime),str)+1);
	}

	if(!strcmp(sp,"TLEFT")) {              /* Synchronet only */
		gettimeleft();
		return(sectostr(timeleft,str)+1);
	}

	if(!strcmp(sp,"TPERD"))                /* Synchronet only */
		return(sectostr(cfg.level_timeperday[useron.level],str)+1);

	if(!strcmp(sp,"TPERC"))                /* Synchronet only */
		return(sectostr(cfg.level_timepercall[useron.level],str)+1);

	if(!strcmp(sp,"TIMELIMIT")) {
		safe_snprintf(str,maxlen,"%u",cfg.level_timepercall[useron.level]);
		return(str);
	}

	if(!strcmp(sp,"MINLEFT") || !strcmp(sp,"LEFT") || !strcmp(sp,"TIMELEFT")) {
		gettimeleft();
		safe_snprintf(str,maxlen,"%lu",timeleft/60);
		return(str);
	}

	if(!strcmp(sp,"LASTON"))
		return(timestr(useron.laston));

	if(!strcmp(sp,"LASTDATEON"))
		return(unixtodstr(&cfg,useron.laston,str));

	if(!strcmp(sp,"LASTTIMEON")) {
		memset(&tm,0,sizeof(tm));
		localtime32(&useron.laston,&tm);
		if(cfg.sys_misc&SM_MILITARY)
			safe_snprintf(str,maxlen,"%02d:%02d:%02d"
				,tm.tm_hour, tm.tm_min, tm.tm_sec);
		else
			safe_snprintf(str,maxlen,"%02d:%02d %s"
				,tm.tm_hour==0 ? 12
				: tm.tm_hour>12 ? tm.tm_hour-12
				: tm.tm_hour, tm.tm_min, tm.tm_hour>11 ? "pm":"am");
		return(str);
	}

	if(!strcmp(sp,"MSGLEFT") || !strcmp(sp,"MSGSLEFT")) {
		safe_snprintf(str,maxlen,"%u",useron.posts);
		return(str);
	}

	if(!strcmp(sp,"MSGREAD")) {
		safe_snprintf(str,maxlen,"%lu",posts_read);
		return(str);
	}

	if(!strcmp(sp,"FREESPACE")) {
		safe_snprintf(str,maxlen,"%lu",getfreediskspace(cfg.temp_dir,0));
		return(str);
	}

	if(!strcmp(sp,"FREESPACEK")) {
		safe_snprintf(str,maxlen,"%lu",getfreediskspace(cfg.temp_dir,1024));
		return(str);
	}

	if(!strcmp(sp,"UPBYTES")) {
		safe_snprintf(str,maxlen,"%lu",useron.ulb);
		return(str);
	}

	if(!strcmp(sp,"UPK")) {
		safe_snprintf(str,maxlen,"%lu",useron.ulb/1024L);
		return(str);
	}

	if(!strcmp(sp,"UPS") || !strcmp(sp,"UPFILES")) {
		safe_snprintf(str,maxlen,"%u",useron.uls);
		return(str);
	}

	if(!strcmp(sp,"DLBYTES")) {
		safe_snprintf(str,maxlen,"%lu",useron.dlb);
		return(str);
	}

	if(!strcmp(sp,"DOWNK")) {
		safe_snprintf(str,maxlen,"%lu",useron.dlb/1024L);
		return(str);
	}

	if(!strcmp(sp,"DOWNS") || !strcmp(sp,"DLFILES")) {
		safe_snprintf(str,maxlen,"%u",useron.dls);
		return(str);
	}

	if(!strcmp(sp,"LASTNEW"))
		return(unixtodstr(&cfg,(time32_t)ns_time,str));

	if(!strcmp(sp,"NEWFILETIME"))
		return(timestr(ns_time));

	/* MAXDL */

	if(!strcmp(sp,"MAXDK") || !strcmp(sp,"DLKLIMIT") || !strcmp(sp,"KBLIMIT")) {
		safe_snprintf(str,maxlen,"%lu",cfg.level_freecdtperday[useron.level]/1024L);
		return(str);
	}

	if(!strcmp(sp,"DAYBYTES")) {    /* amt of free cdts used today */
		safe_snprintf(str,maxlen,"%lu",cfg.level_freecdtperday[useron.level]-useron.freecdt);
		return(str);
	}

	if(!strcmp(sp,"BYTELIMIT")) {
		safe_snprintf(str,maxlen,"%lu",cfg.level_freecdtperday[useron.level]);
		return(str);
	}

	if(!strcmp(sp,"KBLEFT")) {
		safe_snprintf(str,maxlen,"%lu",(useron.cdt+useron.freecdt)/1024L);
		return(str);
	}

	if(!strcmp(sp,"BYTESLEFT")) {
		safe_snprintf(str,maxlen,"%lu",useron.cdt+useron.freecdt);
		return(str);
	}

	if(!strcmp(sp,"CONF")) {
		safe_snprintf(str,maxlen,"%s %s"
			,usrgrps ? cfg.grp[usrgrp[curgrp]]->sname :nulstr
			,usrgrps ? cfg.sub[usrsub[curgrp][cursub[curgrp]]]->sname : nulstr);
		return(str);
	}

	if(!strcmp(sp,"CONFNUM")) {
		safe_snprintf(str,maxlen,"%u %u",curgrp+1,cursub[curgrp]+1);
		return(str);
	}

	if(!strcmp(sp,"NUMDIR")) {
		safe_snprintf(str,maxlen,"%u %u",usrlibs ? curlib+1 : 0,usrlibs ? curdir[curlib]+1 : 0);
		return(str);
	}

	if(!strcmp(sp,"EXDATE") || !strcmp(sp,"EXPDATE"))
		return(unixtodstr(&cfg,useron.expire,str));

	if(!strcmp(sp,"EXPDAYS")) {
		now=time(NULL);
		l=(long)(useron.expire-now);
		if(l<0)
			l=0;
		safe_snprintf(str,maxlen,"%lu",l/(1440L*60L));
		return(str);
	}

	if(!strcmp(sp,"MEMO1"))
		return(useron.note);

	if(!strcmp(sp,"MEMO2") || !strcmp(sp,"COMPANY"))
		return(useron.name);

	if(!strcmp(sp,"ZIP"))
		return(useron.zipcode);

	if(!strcmp(sp,"HANGUP")) {
		hangup();
		return(nulstr);
	}

	/* Synchronet Specific */

	if(!strncmp(sp,"SETSTR:",7)) {
		strcpy(main_csi.str,sp+7);
		return(nulstr);
	}

	if(!strncmp(sp,"EXEC:",5)) {
		exec_bin(sp+5,&main_csi);
		return(nulstr);
	}

	if(!strncmp(sp,"EXEC_XTRN:",10)) {
		for(i=0;i<cfg.total_xtrns;i++)
			if(!stricmp(cfg.xtrn[i]->code,sp+10))
				break;
		if(i<cfg.total_xtrns)
			exec_xtrn(i);
		return(nulstr);
	}

	if(!strncmp(sp,"MENU:",5)) {
		menu(sp+5);
		return(nulstr);
	}

	if(!strncmp(sp,"TYPE:",5)) {
		printfile(cmdstr(sp+5,nulstr,nulstr,str),0);
		return(nulstr);
	}

	if(!strncmp(sp,"INCLUDE:",8)) {
		printfile(cmdstr(sp+8,nulstr,nulstr,str),P_NOCRLF|P_SAVEATR);
		return(nulstr);
	}

	if(!strcmp(sp,"QUESTION"))
		return(question);

	if(!strcmp(sp,"HANDLE"))
		return(useron.handle);

	if(!strcmp(sp,"CID") || !strcmp(sp,"IP"))
		return(cid);

	if(!strcmp(sp,"LOCAL-IP"))
		return(local_addr);

	if(!strcmp(sp,"CRLF"))
		return("\r\n");

	if(!strcmp(sp,"PUSHXY")) {
		ansi_save();
		return(nulstr);
	}

	if(!strcmp(sp,"POPXY")) {
		ansi_restore();
		return(nulstr);
	}

	if(!strncmp(sp,"UP:",3)) {
		cursor_up(atoi(sp+3));
		return(str);
	}

	if(!strncmp(sp,"DOWN:",5)) {
		cursor_down(atoi(sp+5));
		return(str);
	}

	if(!strncmp(sp,"LEFT:",5)) {
		cursor_left(atoi(sp+5));
		return(str);
	}

	if(!strncmp(sp,"RIGHT:",6)) {
		cursor_right(atoi(sp+6));
		return(str);
	}

	if(!strncmp(sp,"GOTOXY:",7)) {
		tp=strchr(sp,',');
		if(tp!=NULL) {
			tp++;
			ansi_gotoxy(atoi(sp+7),atoi(tp));
		}
		return(nulstr);
	}

	if(!strcmp(sp,"GRP")) {
		if(SMB_IS_OPEN(&smb)) {
			if(smb.subnum==INVALID_SUB)
				return("Local");
			if(smb.subnum<cfg.total_subs)
				return(cfg.grp[cfg.sub[smb.subnum]->grp]->sname);
		}
		return(usrgrps ? cfg.grp[usrgrp[curgrp]]->sname : nulstr);
	}

	if(!strcmp(sp,"GRPL")) {
		if(SMB_IS_OPEN(&smb)) {
			if(smb.subnum==INVALID_SUB)
				return("Local");
			if(smb.subnum<cfg.total_subs)
				return(cfg.grp[cfg.sub[smb.subnum]->grp]->lname);
		}
		return(usrgrps ? cfg.grp[usrgrp[curgrp]]->lname : nulstr);
	}

	if(!strcmp(sp,"GN")) {
		if(SMB_IS_OPEN(&smb))
			ugrp=getusrgrp(smb.subnum);
		else
			ugrp=usrgrps ? curgrp+1 : 0;
		safe_snprintf(str,maxlen,"%u",ugrp);
		return(str);
	}

	if(!strcmp(sp,"GL")) {
		if(SMB_IS_OPEN(&smb))
			ugrp=getusrgrp(smb.subnum);
		else
			ugrp=usrgrps ? curgrp+1 : 0;
		safe_snprintf(str,maxlen,"%-4u",ugrp);
		return(str);
	}

	if(!strcmp(sp,"GR")) {
		if(SMB_IS_OPEN(&smb))
			ugrp=getusrgrp(smb.subnum);
		else
			ugrp=usrgrps ? curgrp+1 : 0;
		safe_snprintf(str,maxlen,"%4u",ugrp);
		return(str);
	}

	if(!strcmp(sp,"SUB")) {
		if(SMB_IS_OPEN(&smb)) {
			if(smb.subnum==INVALID_SUB)
				return("Mail");
			else if(smb.subnum<cfg.total_subs)
				return(cfg.sub[smb.subnum]->sname);
		}
		return(usrgrps ? cfg.sub[usrsub[curgrp][cursub[curgrp]]]->sname : nulstr);
	}

	if(!strcmp(sp,"SUBL")) {
		if(SMB_IS_OPEN(&smb)) {
			if(smb.subnum==INVALID_SUB)
				return("Mail");
			else if(smb.subnum<cfg.total_subs)
				return(cfg.sub[smb.subnum]->lname);
		}
		return(usrgrps  ? cfg.sub[usrsub[curgrp][cursub[curgrp]]]->lname : nulstr);
	}

	if(!strcmp(sp,"SN")) {
		if(SMB_IS_OPEN(&smb))
			usub=getusrsub(smb.subnum);
		else
			usub=usrgrps ? cursub[curgrp]+1 : 0;
		safe_snprintf(str,maxlen,"%u",usub);
		return(str);
	}

	if(!strcmp(sp,"SL")) {
		if(SMB_IS_OPEN(&smb))
			usub=getusrsub(smb.subnum);
		else
			usub=usrgrps ? cursub[curgrp]+1 : 0;
		safe_snprintf(str,maxlen,"%-4u",usub);
		return(str);
	}

	if(!strcmp(sp,"SR")) {
		if(SMB_IS_OPEN(&smb))
			usub=getusrsub(smb.subnum);
		else
			usub=usrgrps ? cursub[curgrp]+1 : 0;
		safe_snprintf(str,maxlen,"%4u",usub);
		return(str);
	}

	if(!strcmp(sp,"LIB"))
		return(usrlibs ? cfg.lib[usrlib[curlib]]->sname : nulstr);

	if(!strcmp(sp,"LIBL"))
		return(usrlibs ? cfg.lib[usrlib[curlib]]->lname : nulstr);

	if(!strcmp(sp,"LN")) {
		safe_snprintf(str,maxlen,"%u",usrlibs ? curlib+1 : 0);
		return(str);
	}

	if(!strcmp(sp,"LL")) {
		safe_snprintf(str,maxlen,"%-4u",usrlibs ? curlib+1 : 0);
		return(str);
	}

	if(!strcmp(sp,"LR")) {
		safe_snprintf(str,maxlen,"%4u",usrlibs  ? curlib+1 : 0);
		return(str);
	}

	if(!strcmp(sp,"DIR"))
		return(usrlibs ? cfg.dir[usrdir[curlib][curdir[curlib]]]->sname :nulstr);

	if(!strcmp(sp,"DIRL"))
		return(usrlibs ? cfg.dir[usrdir[curlib][curdir[curlib]]]->lname : nulstr);

	if(!strcmp(sp,"DN")) {
		safe_snprintf(str,maxlen,"%u",usrlibs ? curdir[curlib]+1 : 0);
		return(str);
	}

	if(!strcmp(sp,"DL")) {
		safe_snprintf(str,maxlen,"%-4u",usrlibs ? curdir[curlib]+1 : 0);
		return(str);
	}

	if(!strcmp(sp,"DR")) {
		safe_snprintf(str,maxlen,"%4u",usrlibs ? curdir[curlib]+1 : 0);
		return(str);
	}

	if(!strcmp(sp,"NOACCESS")) {
		if(noaccess_str==text[NoAccessTime])
			safe_snprintf(str,maxlen,noaccess_str,noaccess_val/60,noaccess_val%60);
		else if(noaccess_str==text[NoAccessDay])
			safe_snprintf(str,maxlen,noaccess_str,wday[noaccess_val]);
		else
			safe_snprintf(str,maxlen,noaccess_str,noaccess_val);
		return(str);
	}

	if(!strcmp(sp,"LAST")) {
		tp=strrchr(useron.alias,' ');
		if(tp) tp++;
		else tp=useron.alias;
		return(tp);
	}

	if(!strcmp(sp,"REAL") || !strcmp(sp,"FIRSTREAL")) {
		safe_snprintf(str,maxlen,"%s",useron.name);
		tp=strchr(str,' ');
		if(tp) *tp=0;
		return(str);
	}

	if(!strcmp(sp,"LASTREAL")) {
		tp=strrchr(useron.name,' ');
		if(tp) tp++;
		else tp=useron.name;
		return(tp);
	}

	if(!strcmp(sp,"MAILW")) {
		safe_snprintf(str,maxlen,"%u",getmail(&cfg,useron.number,0));
		return(str);
	}

	if(!strcmp(sp,"MAILP")) {
		safe_snprintf(str,maxlen,"%u",getmail(&cfg,useron.number,1));
		return(str);
	}

	if(!strncmp(sp,"MAILW:",6)) {
		safe_snprintf(str,maxlen,"%u",getmail(&cfg,atoi(sp+6),0));
		return(str);
	}

	if(!strncmp(sp,"MAILP:",6)) {
		safe_snprintf(str,maxlen,"%u",getmail(&cfg,atoi(sp+6),1));
		return(str);
	}

	if(!strcmp(sp,"MSGREPLY")) {
		safe_snprintf(str,maxlen,"%c",cfg.sys_misc&SM_RA_EMU ? 'R' : 'A');
		return(str);
	}

	if(!strcmp(sp,"MSGREREAD")) {
		safe_snprintf(str,maxlen,"%c",cfg.sys_misc&SM_RA_EMU ? 'A' : 'R');
		return(str);
	}

	if(!strncmp(sp,"STATS.",6)) {
		getstats(&cfg,0,&stats);
		sp+=6;
		if(!strcmp(sp,"LOGONS"))
			safe_snprintf(str,maxlen,"%lu",stats.logons);
		else if(!strcmp(sp,"LTODAY"))
			safe_snprintf(str,maxlen,"%lu",stats.ltoday);
		else if(!strcmp(sp,"TIMEON"))
			safe_snprintf(str,maxlen,"%lu",stats.timeon);
		else if(!strcmp(sp,"TTODAY"))
			safe_snprintf(str,maxlen,"%lu",stats.ttoday);
		else if(!strcmp(sp,"ULS"))
			safe_snprintf(str,maxlen,"%lu",stats.uls);
		else if(!strcmp(sp,"ULB"))
			safe_snprintf(str,maxlen,"%lu",stats.ulb);
		else if(!strcmp(sp,"DLS"))
			safe_snprintf(str,maxlen,"%lu",stats.dls);
		else if(!strcmp(sp,"DLB"))
			safe_snprintf(str,maxlen,"%lu",stats.dlb);
		else if(!strcmp(sp,"PTODAY"))
			safe_snprintf(str,maxlen,"%lu",stats.ptoday);
		else if(!strcmp(sp,"ETODAY"))
			safe_snprintf(str,maxlen,"%lu",stats.etoday);
		else if(!strcmp(sp,"FTODAY"))
			safe_snprintf(str,maxlen,"%lu",stats.ftoday);
		else if(!strcmp(sp,"NUSERS"))
			safe_snprintf(str,maxlen,"%u",stats.nusers);
		return(str);
	}

	/* Message header codes */
	if(!strcmp(sp,"MSG_TO") && current_msg!=NULL) {
		if(current_msg->to==NULL)
			return(nulstr);
		if(current_msg->to_ext!=NULL)
			safe_snprintf(str,maxlen,"%s #%s",current_msg->to,current_msg->to_ext);
		else if(current_msg->to_net.type!=NET_NONE) {
			char tmp[128];
			safe_snprintf(str,maxlen,"%s (%s)",current_msg->to
				,smb_netaddrstr(&current_msg->to_net,tmp));
		} else
			return(current_msg->to);
		return(str);
	}
	if(!strcmp(sp,"MSG_TO_NAME") && current_msg!=NULL)
		return(current_msg->to==NULL ? nulstr : current_msg->to);
	if(!strcmp(sp,"MSG_TO_EXT") && current_msg!=NULL) {
		if(current_msg->to_ext==NULL)
			return(nulstr);
		return(current_msg->to_ext);
	}
	if(!strcmp(sp,"MSG_TO_NET") && current_msg!=NULL)
		return(smb_netaddrstr(&current_msg->to_net,str));
	if(!strcmp(sp,"MSG_FROM") && current_msg!=NULL) {
		if(current_msg->from==NULL)
			return(nulstr);
		if(current_msg->hdr.attr&MSG_ANONYMOUS && !SYSOP)
			return(text[Anonymous]);
		if(current_msg->from_ext!=NULL)
			safe_snprintf(str,maxlen,"%s #%s",current_msg->from,current_msg->from_ext);
		else if(current_msg->from_net.type!=NET_NONE) {
			char tmp[128];
			safe_snprintf(str,maxlen,"%s (%s)",current_msg->from
				,smb_netaddrstr(&current_msg->from_net,tmp));
		} else
			return(current_msg->from);
		return(str);
	}
	if(!strcmp(sp,"MSG_FROM_NAME") && current_msg!=NULL) {
		if(current_msg->from==NULL)
			return(nulstr);
		if(current_msg->hdr.attr&MSG_ANONYMOUS && !SYSOP)
			return(text[Anonymous]);
		return(current_msg->from);
	}
	if(!strcmp(sp,"MSG_FROM_EXT") && current_msg!=NULL) {
		if(!(current_msg->hdr.attr&MSG_ANONYMOUS) || SYSOP)
			if(current_msg->from_ext!=NULL)
				return(current_msg->from_ext);
		return(nulstr);
	}
	if(!strcmp(sp,"MSG_FROM_NET") && current_msg!=NULL) {
		if(current_msg->from_net.type!=NET_NONE
			&& (!(current_msg->hdr.attr&MSG_ANONYMOUS) || SYSOP))
			return(smb_netaddrstr(&current_msg->from_net,str));
		return(nulstr);
	}
	if(!strcmp(sp,"MSG_SUBJECT") && current_msg!=NULL)
		return(current_msg->subj==NULL ? nulstr : current_msg->subj);
	if(!strcmp(sp,"MSG_DATE") && current_msg!=NULL)
		return(timestr(current_msg->hdr.when_written.time));
	if(!strcmp(sp,"MSG_TIMEZONE") && current_msg!=NULL)
		return(smb_zonestr(current_msg->hdr.when_written.zone,NULL));
	if(!strcmp(sp,"MSG_ATTR") && current_msg!=NULL) {
		safe_snprintf(str,maxlen,"%s%s%s%s%s%s%s%s%s%s%s"
			,current_msg->hdr.attr&MSG_PRIVATE		? "Private  "   :nulstr
			,current_msg->hdr.attr&MSG_READ			? "Read  "      :nulstr
			,current_msg->hdr.attr&MSG_DELETE		? "Deleted  "   :nulstr
			,current_msg->hdr.attr&MSG_KILLREAD		? "Kill  "      :nulstr
			,current_msg->hdr.attr&MSG_ANONYMOUS	? "Anonymous  " :nulstr
			,current_msg->hdr.attr&MSG_LOCKED		? "Locked  "    :nulstr
			,current_msg->hdr.attr&MSG_PERMANENT	? "Permanent  " :nulstr
			,current_msg->hdr.attr&MSG_MODERATED	? "Moderated  " :nulstr
			,current_msg->hdr.attr&MSG_VALIDATED	? "Validated  " :nulstr
			,current_msg->hdr.attr&MSG_REPLIED		? "Replied  "	:nulstr
			,current_msg->hdr.attr&MSG_NOREPLY		? "NoReply  "	:nulstr
			);
		return(str);
	}
	if(!strcmp(sp,"MSG_ID") && current_msg!=NULL)
		return(current_msg->id==NULL ? nulstr : current_msg->id);
	if(!strcmp(sp,"MSG_REPLY_ID") && current_msg!=NULL)
		return(current_msg->reply_id==NULL ? nulstr : current_msg->reply_id);
	if(!strcmp(sp,"MSG_NUM") && current_msg!=NULL) {
		safe_snprintf(str,maxlen,"%lu",current_msg->hdr.number);
		return(str);
	}

	if(!strcmp(sp,"SMB_AREA")) {
		if(smb.subnum!=INVALID_SUB && smb.subnum<cfg.total_subs)
			safe_snprintf(str,maxlen,"%s %s"
				,cfg.grp[cfg.sub[smb.subnum]->grp]->sname
				,cfg.sub[smb.subnum]->sname);
		return(str);
	}
	if(!strcmp(sp,"SMB_AREA_DESC")) {
		if(smb.subnum!=INVALID_SUB && smb.subnum<cfg.total_subs)
			safe_snprintf(str,maxlen,"%s %s"
				,cfg.grp[cfg.sub[smb.subnum]->grp]->lname
				,cfg.sub[smb.subnum]->lname);
		return(str);
	}
	if(!strcmp(sp,"SMB_GROUP")) {
		if(smb.subnum!=INVALID_SUB && smb.subnum<cfg.total_subs)
			return(cfg.grp[cfg.sub[smb.subnum]->grp]->sname);
		return(nulstr);
	}
	if(!strcmp(sp,"SMB_GROUP_DESC")) {
		if(smb.subnum!=INVALID_SUB && smb.subnum<cfg.total_subs)
			return(cfg.grp[cfg.sub[smb.subnum]->grp]->lname);
		return(nulstr);
	}
	if(!strcmp(sp,"SMB_GROUP_NUM")) {
		if(smb.subnum!=INVALID_SUB && smb.subnum<cfg.total_subs)
			safe_snprintf(str,maxlen,"%u",getusrgrp(smb.subnum));
		return(str);
	}
	if(!strcmp(sp,"SMB_SUB")) {
		if(smb.subnum==INVALID_SUB)
			return("Mail");
		else if(smb.subnum<cfg.total_subs)
			return(cfg.sub[smb.subnum]->sname);
		return(nulstr);
	}
	if(!strcmp(sp,"SMB_SUB_DESC")) {
		if(smb.subnum==INVALID_SUB)
			return("Mail");
		else if(smb.subnum<cfg.total_subs)
			return(cfg.sub[smb.subnum]->lname);
		return(nulstr);
	}
	if(!strcmp(sp,"SMB_SUB_CODE")) {
		if(smb.subnum==INVALID_SUB)
			return("MAIL");
		else if(smb.subnum<cfg.total_subs)
			return(cfg.sub[smb.subnum]->code);
		return(nulstr);
	}
	if(!strcmp(sp,"SMB_SUB_NUM")) {
		if(smb.subnum!=INVALID_SUB && smb.subnum<cfg.total_subs)
			safe_snprintf(str,maxlen,"%u",getusrsub(smb.subnum));
		return(str);
	}
	if(!strcmp(sp,"SMB_MSGS")) {
		safe_snprintf(str,maxlen,"%ld",smb.msgs);
		return(str);
	}
	if(!strcmp(sp,"SMB_CURMSG")) {
		safe_snprintf(str,maxlen,"%ld",smb.curmsg+1);
		return(str);
	}
	if(!strcmp(sp,"SMB_LAST_MSG")) {
		safe_snprintf(str,maxlen,"%lu",smb.status.last_msg);
		return(str);
	}
	if(!strcmp(sp,"SMB_MAX_MSGS")) {
		safe_snprintf(str,maxlen,"%lu",smb.status.max_msgs);
		return(str);
	}
	if(!strcmp(sp,"SMB_MAX_CRCS")) {
		safe_snprintf(str,maxlen,"%lu",smb.status.max_crcs);
		return(str);
	}
	if(!strcmp(sp,"SMB_MAX_AGE")) {
		safe_snprintf(str,maxlen,"%hu",smb.status.max_age);
		return(str);
	}
	if(!strcmp(sp,"SMB_TOTAL_MSGS")) {
		safe_snprintf(str,maxlen,"%lu",smb.status.total_msgs);
		return(str);
	}

	return(NULL);
}