예제 #1
0
void vo_show_progress(int sizeM)
{
    video_set_cursor((video_get_rows() / 4) * 3, (video_get_colums() - 22)/ 2);
    video_printf("=====================\n");
    video_set_cursor((video_get_rows() / 4) * 3 + 1, (video_get_colums() - 22)/ 2);
    video_printf(">>> Written %4dM <<<\n", sizeM);
    video_set_cursor((video_get_rows() / 4) * 3 + 2, (video_get_colums() - 22)/ 2);
    video_printf("=====================\n");
    video_set_cursor(video_get_rows() - 1, 0);

    dprintf(CRITICAL,"... Written %dM\n", sizeM);
}
예제 #2
0
void video_putc(char ch)
{
    switch(ch)
    {
    case '\n':
	cursor_col = 0;
	cursor_row += 1;
	break;
    case '\r':
	cursor_col = 0;
	break;
    case '\b':
	if (cursor_col) cursor_col--;
	else return;
	break;
    case '\t':
	cursor_col = (cursor_col/8+1)*8;
	break;
    default:
	video_write_char(ch);
	cursor_col++;
	if (cursor_col > VIDEO_COLS-1)
	{
	    cursor_row++;
	    cursor_col=0;
	}
    }

    if (cursor_row > VIDEO_ROWS-1)
	video_scroll(1);
    video_set_cursor(cursor_row, cursor_col);
}
예제 #3
0
static void kdump_ui(struct mrdump_control_block *mrdump_cblock)
{
    video_clean_screen();
    video_set_cursor(0, 0);

    mrdump_status_error("Unknown error\n");
    voprintf_info("Kdump triggerd by '%s'\n", mrdump_mode2string(mrdump_cblock->crash_record.reboot_mode));

    struct aee_timer elapse_time;
    aee_timer_init(&elapse_time);

    uint32_t total_dump_size = memory_size();
    
    aee_timer_start(&elapse_time);
    switch (mrdump_cblock->machdesc.output_device) {
    case MRDUMP_DEV_NULL:
        kdump_null_output(mrdump_cblock, total_dump_size);
        break;
#if 0
    case MRDUMP_DEV_SDCARD:
        kdump_sdcard_output(mrdump_cblock, total_dump_size);
        break;
#endif
    case MRDUMP_DEV_EMMC:
        kdump_emmc_output(mrdump_cblock, total_dump_size);
        break;

    default:
        voprintf_error("Unknown device id %d\n", mrdump_cblock->machdesc.output_device);
    }

    aee_timer_stop(&elapse_time);
    
    voprintf_info("Reset count down %d ...\n", MRDUMP_DELAY_TIME);
    mtk_wdt_restart();

    int timeout = MRDUMP_DELAY_TIME;
    while(timeout-- >= 0) {
        mdelay(1000);
        mtk_wdt_restart();
	voprintf_info("\rsec %d", timeout);
    }
    aee_mrdump_flush_cblock();

    video_clean_screen();
    video_set_cursor(0, 0);
}
static void init_display_xy()
{
#if defined(DISPLAY_INFO_ON_LCM)
	video_clean_screen();
	video_set_cursor(video_get_rows()/2, 0);
	//video_set_cursor(1, 0);
#endif
}
예제 #5
0
/* Do any target specific intialization needed before entering fastboot mode */
void target_fastboot_init(void)
{
//                               
	#if defined (FASTBOOT_USERDEBUG) /* jjm_l10 */
	mt_disp_show_black_screen();
	video_clean_screen();
	video_set_cursor(video_get_rows()/4, 0);
	video_printf("[Fastboot Mode Entered!]\n");
	#endif
//                               
}
예제 #6
0
void video_bios_print_string(char *s, int x, int y, int attr, int count)
{
    int cattr = current_attr;
    if (attr != -1) current_attr = attr;
    video_set_cursor(x,y);
    while (count)
    {
	char c = *s++;
	if (attr == -1) current_attr = *s++;
	video_putc(c);
	count--;
    }
}
예제 #7
0
void fastboot_boot_menu(void)
{
          const char* title_msg = "Select Boot Mode:\n[VOLUME_UP to select.  VOLUME_DOWN is OK.]\n\n";
          video_clean_screen();
          video_set_cursor(video_get_rows()/2, 0);
          video_printf(title_msg);
          video_printf("[Recovery    Mode]             \n");
#ifdef MTK_FASTBOOT_SUPPORT
          video_printf("[Fastboot    Mode]         <<==\n");
#endif
          video_printf("[Normal      Boot]             \n");
#ifndef USER_BUILD
          video_printf("[Normal      Boot +ftrace]    \n");
          video_printf("[Normal      slub debug off]     \n");
#endif
          video_printf(" => FASTBOOT mode...\n");
}
예제 #8
0
void lock_warranty(void)
{
  const char* title_msg = "lock bootloader?\n\n";
  video_clean_screen();
  video_set_cursor(video_get_rows()/2, 0);
  video_printf(title_msg);
  video_printf("If you lock the bootloader,you will need to install official operating\n");
  video_printf("system software on this phone.\n\n");


  video_printf("To prevent unauthorized access to your personal data,locking the bootloader\n");
  video_printf("will also delete all personal data from your phone(a \"factory data reset\").\n\n");

  video_printf("Press the Volume UP/Down buttons to select Yes or No. \n\n");
  video_printf("Yes (Volume UP):Lock bootloader.\n\n");
  video_printf("No (Volume Down):Do not lock bootloader.\n\n");
}
예제 #9
0
void video_clear(void)
{
    unsigned short *fbb = (unsigned short *)0xFD0B8000;
    int i,j;
    unsigned short val = 0x2000 | current_attr;

    for (i=0; i<video_rows(); i++)
    {
	for (j=0; j<video_cols(); j++)
	{
	    *fbb++ = val;
	}
    }
    video_set_cursor(0,0);
    cursor_row = 0;
    cursor_col = 0;
}
예제 #10
0
void unlock_warranty(void)
{
  const char* title_msg = "Unlock bootloader?\n\n";
  video_clean_screen();
  video_set_cursor(video_get_rows()/2, 0);
  video_printf(title_msg);
  video_printf("If you unlock the bootloader,you will be able to install custom operating\n");
  video_printf("system software on this phone.\n\n");

  video_printf("A custom OS is not subject to the same testing as the original OS, and can\n");
  video_printf("cause your phone and installed applications to stop working properly.\n\n");

  video_printf("To prevent unauthorized access to your personal data,unlocking the bootloader\n");
  video_printf("will also delete all personal data from your phone(a \"factory data reset\").\n\n");

  video_printf("Press the Volume UP/Down buttons to select Yes or No. \n\n");
  video_printf("Yes (Volume UP):Unlock(may void warranty).\n\n");
  video_printf("No (Volume Down):Do not unlock bootloader.\n\n");

}
예제 #11
0
void input_init() {
	// Initialize input
	Input(emulator).AutoSelectController(0);
	Input(emulator).AutoSelectController(1);
	video_set_cursor();
}
예제 #12
0
void boot_mode_menu_select()
{
          int select = 0;  // 0=recovery mode, 1=fastboot.  2=normal boot 3=normal boot + ftrace.4=slub debug off
          const char* title_msg = "Select Boot Mode:\n[VOLUME_UP to select.  VOLUME_DOWN is OK.]\n\n";
          video_clean_screen();
          video_set_cursor(video_get_rows()/2, 0);
          video_printf(title_msg);
          video_printf("[Recovery    Mode]         <<==\n");
#ifdef MTK_FASTBOOT_SUPPORT
          video_printf("[Fastboot    Mode]             \n");
#endif
          video_printf("[Normal      Boot]             \n");
#ifndef USER_BUILD
          video_printf("[Normal      Boot +ftrace]    \n");
          video_printf("[Normal      slub debug off]     \n");
#endif
          while(1)
          {
             if(mtk_detect_key(MT65XX_MENU_SELECT_KEY))//VOL_UP
             {
                    g_boot_menu = true;
                    switch(select) {

                        case 0:
#ifdef MTK_FASTBOOT_SUPPORT
                            select = 1;

                            video_set_cursor(video_get_rows()/2, 0);
                            video_printf(title_msg);
                            video_printf("[Recovery    Mode]             \n");
                            video_printf("[Fastboot    Mode]         <<==\n");
                            video_printf("[Normal      Boot]             \n");
#ifndef USER_BUILD
                            video_printf("[Normal      Boot +ftrace]     \n");
                            video_printf("[Normal      slub debug off]     \n");
#endif
                        break;
#endif
                        case 1:
                            select = 2;

                            video_set_cursor(video_get_rows()/2, 0);
                            video_printf(title_msg);
                            video_printf("[Recovery    Mode]             \n");
#ifdef MTK_FASTBOOT_SUPPORT
                            video_printf("[Fastboot    Mode]             \n");
#endif
                            video_printf("[Normal      Boot]         <<==\n");
#ifndef USER_BUILD
                            video_printf("[Normal      Boot +ftrace]     \n");
                            video_printf("[Normal      slub debug off]     \n");
#endif
                        break;

                        case 2:
#ifdef USER_BUILD
                            select = 0;
#else
                            select = 3;
#endif
    
                            video_set_cursor(video_get_rows()/2, 0);
                            video_printf(title_msg);
#ifdef USER_BUILD
                            video_printf("[Recovery    Mode]         <<==\n");
#ifdef MTK_FASTBOOT_SUPPORT
                            video_printf("[Fastboot    Mode]             \n");
#endif
                            video_printf("[Normal      Boot]             \n");
#else
                            video_printf("[Recovery    Mode]             \n");
#ifdef MTK_FASTBOOT_SUPPORT
                            video_printf("[Fastboot    Mode]             \n");
#endif
                            video_printf("[Normal      Boot]             \n");
                            video_printf("[Normal      Boot +ftrace] <<==\n");
                            video_printf("[Normal      slub debug off]     \n");
#endif
                        break;

#ifndef USER_BUILD
                        case 3:
                            select = 4;
                            video_set_cursor(video_get_rows()/2, 0);
                            video_printf(title_msg);
                            video_printf("[Recovery    Mode]             \n");
#ifdef MTK_FASTBOOT_SUPPORT
                            video_printf("[Fastboot    Mode]             \n");
#endif
                            video_printf("[Normal      Boot]             \n");
                            video_printf("[Normal      Boot +ftrace]     \n");
                            video_printf("[Normal      slub debug off] <<==\n");
                            
                        break;
#endif


#ifndef USER_BUILD
                        case 4:
                            select = 0;
                            video_set_cursor(video_get_rows()/2, 0);
                            video_printf(title_msg);
                            video_printf("[Recovery    Mode]         <<==\n");
#ifdef MTK_FASTBOOT_SUPPORT
                            video_printf("[Fastboot    Mode]             \n");
#endif
                            video_printf("[Normal      Boot]             \n");
                            video_printf("[Normal      Boot +ftrace]     \n");
                            video_printf("[Normal      slub debug off]     \n");                            
                        break;
#endif

                        default: 
                        break;
                    }
                    dprintf(CRITICAL,  "[VOL_UP]Key Detect, current select:%d\n", select);
                    mdelay(300);
             }
             else if(mtk_detect_key(MT65XX_MENU_OK_KEY))//VOL_DOWN,
             {
                 //use for OK
                 break;
             }
             else
             {
                //pass
             }
          }
          if(select == 0)
          {
               g_boot_mode = RECOVERY_BOOT;
          }
          else if(select == 1)
          {
                g_boot_mode = FASTBOOT;
          }
          else if(select == 2)
          {
                g_boot_mode = NORMAL_BOOT;
          }
          else if(select == 3)
          {
                sprintf(g_CMDLINE, "%s trace_buf_size=11m boot_time_ftrace", g_CMDLINE);
                g_boot_mode = NORMAL_BOOT;
          }
          else if (select == 4)
          {
                sprintf(g_CMDLINE, "%s slub_debug=-", g_CMDLINE);
                g_boot_mode = NORMAL_BOOT;
          }
          else{
                //pass
          }
          video_printf("\n");
          return;
}
예제 #13
0
// check the boot mode : (1) meta mode or (2) recovery mode ...
void boot_mode_select(void)
{
//Ivan    
    ulong begin;
    
    if (meta_detection())
    {
      return;
    }

#if defined (HAVE_LK_TEXT_MENU)
    if(Check_RTC_PDN1_bit13())
    {
      printf("[FASTBOOT] reboot to boot loader\n");
      g_boot_mode = FASTBOOT;
      Set_Clr_RTC_PDN1_bit13(false);
   	  return;
    }
//Ivan
#ifdef MENU_BOOT_ENABLE
    boot_mode_dkey_check();
    if (g_boot_mode == MENU_BOOT)
    {
	    /* clean console screen */
	video_clean_screen();
//	mt65xx_disp_fill_rect(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT, 0x0);

	video_set_cursor(2,0);
	video_printf("Recovery Mode: Volume Up\r\n");
	video_set_cursor(4,0);
	video_printf("Factory Mode: Volume Down\r\n");
//	mt65xx_disp_update(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT);
	mt65xx_backlight_on();
	video_set_cursor(49,0);

	while (mt65XX_get_key() != 0xFFFF);
	printf(" > Key release!!!\n");
        mdelay(500);
	
//Ivan added 
	mtk_wdt_restart();
	begin = get_timer(0);
	
	while (g_boot_mode == MENU_BOOT)
	{
	    if (factory_detection())
	    {
		video_clean_screen();
		return;
	    }
	    if(boot_menu_detection())//recovery, fastboot, normal boot.
	    {
		video_clean_screen();
		return;
	    }
//Ivan add 20s time limit
	    if (get_timer(begin) < 20000)
		mtk_wdt_restart();
	}

//	video_clean_screen();
//	mt65xx_disp_fill_rect(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT, 0x0);
//	mt65xx_disp_update(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT);
//	video_set_cursor(49,0);
//	mt65xx_disp_wait_idle();
    }

    if(Check_RTC_Recovery_Mode())
    {	
	    g_boot_mode = RECOVERY_BOOT;
    }

    recovery_check_command_trigger();
    
#else  //MENU_BOOT_ENABLE
    
    if (factory_detection())
    {
      return;
    }
    if(boot_menu_detection())//recovery, fastboot, normal boot.
    {
        return;
    }
    recovery_detection();
#endif //MENU_BOOT_ENABLE
#else	//HAVE_LK_TEXT_MENU
#ifdef MTK_FASTBOOT_SUPPORT
    if(fastboot_trigger())
    {
      return;
    }
#endif	//MTK_FASTBOOT_SUPPORT
    if (factory_detection())
    {
      return;
    }
    if(recovery_detection())
    {
      //**************************************
  		//* CHECK IMAGE
  		//**************************************
  		if(DRV_Reg32(0x40002300)==0xE92D4800)
  		{
  		  printf(" > do recovery_check\n");
  			//jump(0x40002300);
  		}
  		else
  		{
  		  printf(" > bypass recovery_check\n");
  		}
    	return;
    }
#endif
#ifdef MTK_KERNEL_POWER_OFF_CHARGING
	if(kernel_power_off_charging_detection())
	{
		printf(" < Kernel Power Off Charging Detection Ok> \n");
		return;
	}
	else
	{
		printf("< Kernel Enter Normal Boot > \n");
	}
#endif
}
예제 #14
0
파일: input.cpp 프로젝트: TaylanUB/nestopia
void input_init() {
    // Initialize input

    char controller[32];

    for (int i = 0; i < NUMGAMEPADS; i++) {
        Input(emulator).AutoSelectController(i);

        switch(Input(emulator).GetConnectedController(i)) {
        case Input::UNCONNECTED:
            snprintf(controller, sizeof(controller), "%s", "Unconnected");
            break;
        case Input::PAD1:
        case Input::PAD2:
        case Input::PAD3:
        case Input::PAD4:
            snprintf(controller, sizeof(controller), "%s", "Standard Pad");
            break;
        case Input::ZAPPER:
            snprintf(controller, sizeof(controller), "%s", "Zapper");
            break;
        case Input::PADDLE:
            snprintf(controller, sizeof(controller), "%s", "Arkanoid Paddle");
            break;
        case Input::POWERPAD:
            snprintf(controller, sizeof(controller), "%s", "Power Pad");
            break;
        case Input::POWERGLOVE:
            snprintf(controller, sizeof(controller), "%s", "Power Glove");
            break;
        case Input::MOUSE:
            snprintf(controller, sizeof(controller), "%s", "Mouse");
            break;
        case Input::ROB:
            snprintf(controller, sizeof(controller), "%s", "R.O.B.");
            break;
        case Input::FAMILYTRAINER:
            snprintf(controller, sizeof(controller), "%s", "Family Trainer");
            break;
        case Input::FAMILYKEYBOARD:
            snprintf(controller, sizeof(controller), "%s", "Family Keyboard");
            break;
        case Input::SUBORKEYBOARD:
            snprintf(controller, sizeof(controller), "%s", "Subor Keyboard");
            break;
        case Input::DOREMIKKOKEYBOARD:
            snprintf(controller, sizeof(controller), "%s", "Doremikko Keyboard");
            break;
        case Input::HORITRACK:
            snprintf(controller, sizeof(controller), "%s", "Hori Track");
            break;
        case Input::PACHINKO:
            snprintf(controller, sizeof(controller), "%s", "Pachinko");
            break;
        case Input::OEKAKIDSTABLET:
            snprintf(controller, sizeof(controller), "%s", "Oeka Kids Tablet");
            break;
        case Input::KONAMIHYPERSHOT:
            snprintf(controller, sizeof(controller), "%s", "Konami Hypershot");
            break;
        case Input::BANDAIHYPERSHOT:
            snprintf(controller, sizeof(controller), "%s", "Bandai Hypershot");
            break;
        case Input::CRAZYCLIMBER:
            snprintf(controller, sizeof(controller), "%s", "Crazy Climber");
            break;
        case Input::MAHJONG:
            snprintf(controller, sizeof(controller), "%s", "Mahjong");
            break;
        case Input::EXCITINGBOXING:
            snprintf(controller, sizeof(controller), "%s", "Exciting Boxing");
            break;
        case Input::TOPRIDER:
            snprintf(controller, sizeof(controller), "%s", "Top Rider");
            break;
        case Input::POKKUNMOGURAA:
            snprintf(controller, sizeof(controller), "%s", "Pokkun Moguraa");
            break;
        case Input::PARTYTAP:
            snprintf(controller, sizeof(controller), "%s", "PartyTap");
            break;
        case Input::TURBOFILE:
            snprintf(controller, sizeof(controller), "%s", "Turbo File");
            break;
        case Input::BARCODEWORLD:
            snprintf(controller, sizeof(controller), "%s", "Barcode World");
            break;
        default:
            snprintf(controller, sizeof(controller), "%s", "Unknown");
            break;
        }

        fprintf(stderr, "Port %d: %s\n", i + 1, controller);
    }

    video_set_cursor();
}
예제 #15
0
void boot_mode_menu_select()
{
	int select = 0;  // 0=recovery mode, 1=fastboot.  2=normal boot 3=normal boot + ftrace.4=slub debug off
	const char* title_msg = "Select Boot Mode:\n[VOLUME_UP to select.  VOLUME_DOWN is OK.]\n\n";
	mt65xx_backlight_on();
	video_clean_screen();
	video_set_cursor(video_get_rows()/2, 0);
	video_printf(title_msg);
	video_printf("[Recovery    Mode]         <<==\n");
#ifdef MTK_FASTBOOT_SUPPORT
	video_printf("[Fastboot    Mode]             \n");
#endif
	video_printf("[Normal      Boot]             \n");
#if !defined(USER_BUILD) || defined(MTK_BUILD_ROOT)
	video_printf("[Normal      Boot +ftrace]    \n");
	video_printf("[Normal      slub debug off]     \n");
#endif
	while (1) {
		if (mtk_detect_key(MT65XX_MENU_SELECT_KEY)) { //VOL_UP
			g_boot_menu = true;
			switch (select) {

				case 0:
#ifdef MTK_FASTBOOT_SUPPORT
					select = 1;

					video_set_cursor(video_get_rows()/2, 0);
					video_printf(title_msg);
					video_printf("[Recovery    Mode]             \n");
					video_printf("[Fastboot    Mode]         <<==\n");
					video_printf("[Normal      Boot]             \n");
#if !defined(USER_BUILD) || defined(MTK_BUILD_ROOT)
					video_printf("[Normal      Boot +ftrace]     \n");
					video_printf("[Normal      slub debug off]     \n");
#endif
					break;
#endif
				case 1:
					select = 2;

					video_set_cursor(video_get_rows()/2, 0);
					video_printf(title_msg);
					video_printf("[Recovery    Mode]             \n");
#ifdef MTK_FASTBOOT_SUPPORT
					video_printf("[Fastboot    Mode]             \n");
#endif
					video_printf("[Normal      Boot]         <<==\n");
#if !defined(USER_BUILD) || defined(MTK_BUILD_ROOT)
					video_printf("[Normal      Boot +ftrace]     \n");
					video_printf("[Normal      slub debug off]     \n");
#endif
					break;

				case 2:
#if defined(USER_BUILD) && !defined(MTK_BUILD_ROOT)
					select = 0;
#else
					select = 3;
#endif

					video_set_cursor(video_get_rows()/2, 0);
					video_printf(title_msg);
#if defined(USER_BUILD) && !defined(MTK_BUILD_ROOT)
					video_printf("[Recovery    Mode]         <<==\n");
#ifdef MTK_FASTBOOT_SUPPORT
					video_printf("[Fastboot    Mode]             \n");
#endif
					video_printf("[Normal      Boot]             \n");
#else
					video_printf("[Recovery    Mode]             \n");
#ifdef MTK_FASTBOOT_SUPPORT
					video_printf("[Fastboot    Mode]             \n");
#endif
					video_printf("[Normal      Boot]             \n");
					video_printf("[Normal      Boot +ftrace] <<==\n");
					video_printf("[Normal      slub debug off]     \n");
#endif
					break;

#if !defined(USER_BUILD) || defined(MTK_BUILD_ROOT)
				case 3:
					select = 4;
					video_set_cursor(video_get_rows()/2, 0);
					video_printf(title_msg);
					video_printf("[Recovery    Mode]             \n");
#ifdef MTK_FASTBOOT_SUPPORT
					video_printf("[Fastboot    Mode]             \n");
#endif
					video_printf("[Normal      Boot]             \n");
					video_printf("[Normal      Boot +ftrace]     \n");
					video_printf("[Normal      slub debug off] <<==\n");

					break;
#endif


#if !defined(USER_BUILD) || defined(MTK_BUILD_ROOT)
				case 4:
					select = 0;
					video_set_cursor(video_get_rows()/2, 0);
					video_printf(title_msg);
					video_printf("[Recovery    Mode]         <<==\n");
#ifdef MTK_FASTBOOT_SUPPORT
					video_printf("[Fastboot    Mode]             \n");
#endif
					video_printf("[Normal      Boot]             \n");
					video_printf("[Normal      Boot +ftrace]     \n");
					video_printf("[Normal      slub debug off]     \n");
					break;
#endif

				default:
					break;
			}
			dprintf(0,  "[VOL_UP]Key Detect, current select:%d\n", select);
			mdelay(300);
		} else if (mtk_detect_key(MT65XX_MENU_OK_KEY)) { //VOL_DOWN,
			//use for OK
			break;
		} else {
			//pass
		}
	}
	if (select == 0) {
		g_boot_mode = RECOVERY_BOOT;
	} else if (select == 1) {
		g_boot_mode = FASTBOOT;
	} else if (select == 2) {
		g_boot_mode = NORMAL_BOOT;
	} else if (select == 3) {
                cmdline_append("boot_trace");
		g_boot_mode = NORMAL_BOOT;
	} else if (select == 4) {
		cmdline_append("slub_debug=-");
		g_boot_mode = NORMAL_BOOT;
	} else {
		//pass
	}

	video_set_cursor(video_get_rows()/2 +8, 0);
	return;
}
예제 #16
0
파일: ef.c 프로젝트: OS2World/LIB-libfly
void editor (char *filename, int startpos)
{
    int stop    = FALSE; // exit main loop?
    int fline   = 0;     // no. of first displayed line
    int cline   = 0;     // no. of line with cursor
    int shift   = 0;     // shift to the right
    int ccol    = 0;     // column of the cursor position in the file window

    int        k, i, ndisp, rc, reply;
    char       *p, buf[1024];

    if (editor_open_file (filename) < 0) return;
    cline = min1 (startpos, nl-1);
    fline = max1 (0, cline - video_vsize()/2);

    // enter the loop
    while (1)
    {
        if (stop)
        {
            rc = 0;
            if (changed)
            {
                rc = -1;
                reply = fly_ask (0, "   Save file `%s'?   ", " Yes \n No \n Cancel ", filename);
                if (reply == 1) rc = editor_save_file (filename);
                if (reply == 2) rc = 0;
                if (reply == 3) stop = FALSE;
            }
            if (rc == 0) break;
        }
        
        ndisp = video_vsize()-1;
        // draw the screen
        for (i=0; i<ndisp; i++)
        {
            video_put_n_cell (' ', _BackWhite+_Black, video_hsize(), i, 0);
            if (i+fline < nl)
                editor_display_line (i, fline+i, shift);
        }
        video_put_n_cell (' ', _BackBlue+_White, video_hsize(), video_vsize()-1, 0);
        snprintf1 (buf, sizeof(buf), "L%d:C%d:S%d %c %s%s", cline, ccol, shift, fl_sym.v,
                 changed ? "*" : "", filename);
        video_put (buf, video_vsize()-1, 0);
        video_set_cursor (cline-fline, ccol-shift);
        video_update (0);

        // get a keyboard/mouse event and process it
        k = getmessage (-1);
        if (IS_KEY(k))
        {
            switch (k)
            {
                // Navigation keys
                
            case _Up:
            case _Down:
            case _PgUp:
            case _PgDn:
                fly_scroll_it (k, &fline, &cline, nl, video_vsize()-1);
                break;

            case _Right:
                ccol++;
                if (ccol-shift > video_hsize()-1) shift = ccol-video_hsize()+1;
                break;

            case _Left:
                ccol = max1 (ccol-1, 0);
                if (ccol < shift) shift = ccol;
                break;

            case _Home:
                ccol = 0; shift = 0;
                break;

            case _End:
                ccol = strlen(lines[cline]);
                if (ccol-shift > video_hsize()-1) shift = ccol-video_hsize()+1;
                break;

            case _CtrlHome:
                fline = 0; cline = 0; ccol = 0; shift = 0; break;

            case _CtrlEnd:
                fline = max1 (0, nl-video_vsize()+1);
                cline = min1 (fline+video_vsize()-1, nl-1);
                shift = 0;
                ccol = 0;
                break;

                // Action keys

            case _CtrlY:
                put_clipboard (lines[cline]);
                free (lines[cline]);
                for (i=cline; i<nl-1; i++)
                    lines[i] = lines[i+1];
                nl--;
                changed = TRUE;
                break;

            case _ShiftInsert:
            case _CtrlV:
                p = get_clipboard ();
                if (p == NULL || *p == '\0') break;
                if (nl == na)
                {
                    na *= 2;
                    lines = realloc (lines, sizeof(char *) * na);
                }
                for (i=nl-1; i>cline; i--)
                    lines[i+1] = lines[i];
                lines[cline+1] = p;
                ccol = 0;
                shift = 0;
                cline++;
                if (cline-fline == video_vsize()-1) fline++;
                nl++;
                changed = TRUE;
                break;

            case _BackSpace:
                if (ccol == 0)
                {
                    // ccol == 0: glue this line to the previous
                    if (cline == 0) break;
                    p = malloc (strlen (lines[cline])+strlen(lines[cline-1])+1);
                    strcpy (p, lines[cline-1]);
                    strcat (p, lines[cline]);
                    ccol = strlen (lines[cline-1]);
                    if (ccol-shift > video_hsize()-1) shift = ccol-video_hsize()+1;
                    free (lines[cline-1]);
                    free (lines[cline]);
                    lines[cline-1] = p;
                    for (i=cline; i<nl-1; i++)
                        lines[i] = lines[i+1];
                    cline--;
                    nl--;
                }
                else
                {
                    // ccol != 0: delete char at ccol-1, move cursor left
                    str_delete (lines[cline], lines[cline]+ccol-1);
                    ccol--;
                    if (ccol < shift) shift = ccol;
                }
                changed = TRUE;
                break;

            case _Enter:
                if (nl == na)
                {
                    na *= 2;
                    lines = realloc (lines, sizeof(char *) * na);
                }
                for (i=nl-1; i>cline; i--)
                    lines[i+1] = lines[i];
                if (ccol < strlen (lines[cline]))
                {
                    lines[cline+1] = strdup (lines[cline]+ccol);
                    lines[cline][ccol] = '\0';
                }
                else
                {
                    lines[cline+1] = strdup ("");
                }
                ccol = 0;
                shift = 0;
                cline++;
                if (cline-fline == video_vsize()-1) fline++;
                nl++;
                changed = TRUE;
                break;

            case _Delete:
                if (ccol >= strlen (lines[cline]))
                {
                    // glue previous line to this one
                    if (cline == nl-1) break;
                    p = malloc (ccol+strlen(lines[cline+1])+1);
                    strcpy (p, lines[cline]);
                    memset (p+strlen(lines[cline]), ' ', ccol-strlen(lines[cline]));
                    strcpy (p+ccol, lines[cline+1]);
                    free (lines[cline]);
                    free (lines[cline+1]);
                    lines[cline] = p;
                    for (i=cline+1; i<nl-1; i++)
                        lines[i] = lines[i+1];
                    nl--;
                }
                else
                {
                    // ccol != 0: delete char at ccol-1, move cursor left
                    str_delete (lines[cline], lines[cline]+ccol);
                }
                changed = TRUE;
                break;

            case _F2:
                rc = editor_save_file (filename);
                if (rc == 0) changed = FALSE;
                break;
                
            case _Esc:
            case _F10:
                stop = TRUE; break;

                // character keys
                
            default:
                if (k >= ' ' && k <= 255)
                {
                    str_insert_at (cline, k, ccol);
                    ccol++;
                    changed = TRUE;
                }
            }
        }
        else if (IS_MOUSE(k))
        {
        }
        else if (IS_SYSTEM(k))
        {
            switch (SYS_TYPE(k))
            {
            case SYSTEM_QUIT:
                stop = TRUE; break;
            }
        }
    }

    if (nl != 0 && lines != NULL)
        for (i=0; i<nl; i++)
            free (lines[i]);
    if (na != 0 && lines != NULL) free (lines);
    na = 0;
    lines = NULL;
}