/*
 * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <ctype.h>
#include <fcntl.h>
#include <libtsm.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include "dbus.h"
#include "fb.h"
#include "font.h"
#include "image.h"
#include "input.h"
#include "main.h"
#include "shl_pty.h"
#include "term.h"
#include "util.h"

unsigned int term_num_terminals = 4;
static terminal_t* terminals[TERM_MAX_TERMINALS];
static uint32_t current_terminal = 0;

struct term {
	struct tsm_screen* screen;
	struct tsm_vte* vte;
	struct shl_pty* pty;
	int pty_bridge;
	int pid;
	tsm_age_t age;
	int w_in_char, h_in_char;
};

struct _terminal_t {
	unsigned vt;
	bool active;
	bool input_enable;
	uint32_t background;
	bool background_valid;
	fb_t* fb;
	struct term* term;
	char** exec;
};


static char* interactive_cmd_line[] = {
	"/sbin/agetty",
	"-",
	"9600",
	"xterm",
	NULL
};

static bool in_background = false;
static bool hotplug_occured = false;


static void __attribute__ ((noreturn)) term_run_child(terminal_t* terminal)
{
	/* XXX figure out how to fix "top" for xterm-256color */
	setenv("TERM", "xterm", 1);
	if (terminal->exec) {
		execve(terminal->exec[0], terminal->exec, environ);
		exit(1);
	} else {
		while (1)
			sleep(1000000);
	}
}

static int term_draw_cell(struct tsm_screen* screen, uint32_t id,
			  const uint32_t* ch, size_t len,
			  unsigned int cwidth, unsigned int posx,
			  unsigned int posy,
			  const struct tsm_screen_attr* attr,
			  tsm_age_t age, void* data)
{
	terminal_t* terminal = (terminal_t*)data;
	uint32_t front_color, back_color;
	uint8_t br, bb, bg;
	uint32_t luminance;

	if (age && terminal->term->age && age <= terminal->term->age)
		return 0;

	if (terminal->background_valid) {
		br = (terminal->background >> 16) & 0xFF;
		bg = (terminal->background >> 8) & 0xFF;
		bb = (terminal->background) & 0xFF;
		luminance = (3 * br + bb + 4 * bg) >> 3;

		/*
		 * FIXME: black is chosen on a dark background, but it uses the
		 * default color for light backgrounds
		 */
		if (luminance > 128) {
			front_color = 0;
			back_color = terminal->background;
		} else {
			front_color = (attr->fr << 16) | (attr->fg << 8) | attr->fb;
			back_color = terminal->background;
		}
	} else {
			front_color = (attr->fr << 16) | (attr->fg << 8) | attr->fb;
			back_color = (attr->br << 16) | (attr->bg << 8) | attr->bb;
	}

	if (attr->inverse) {
		uint32_t tmp = front_color;
		front_color = back_color;
		back_color = tmp;
	}

	if (len)
		font_render(terminal->fb, posx, posy, *ch,
					front_color, back_color);
	else
		font_fillchar(terminal->fb, posx, posy,
						front_color, back_color);

	return 0;
}

static void term_redraw(terminal_t* terminal)
{
	if (fb_lock(terminal->fb)) {
		terminal->term->age =
			tsm_screen_draw(terminal->term->screen, term_draw_cell, terminal);
		fb_unlock(terminal->fb);
	}
}

void term_key_event(terminal_t* terminal, uint32_t keysym, int32_t unicode)
{
	if (!terminal->input_enable)
		return;

	if (tsm_vte_handle_keyboard(terminal->term->vte, keysym, 0, 0, unicode))
		tsm_screen_sb_reset(terminal->term->screen);

	term_redraw(terminal);
}

static void term_read_cb(struct shl_pty* pty, char* u8, size_t len, void* data)
{
	terminal_t* terminal = (terminal_t*)data;

	tsm_vte_input(terminal->term->vte, u8, len);

	term_redraw(terminal);
}

static void term_write_cb(struct tsm_vte* vte, const char* u8, size_t len,
				void* data)
{
	struct term* term = data;
	int r;

	r = shl_pty_write(term->pty, u8, len);
	if (r < 0)
		LOG(ERROR, "OOM in pty-write (%d)", r);

	shl_pty_dispatch(term->pty);
}

static void term_esc_show_image(terminal_t* terminal, char* params)
{
	char* tok;
	image_t* image;
	int status;

	image = image_create();
	if (!image) {
		LOG(ERROR, "Out of memory when creating an image.\n");
		return;
	}
	for (tok = strtok(params, ";"); tok; tok = strtok(NULL, ";")) {
		if (strncmp("file=", tok, 5) == 0) {
			image_set_filename(image, tok + 5);
		} else if (strncmp("location=", tok, 9) == 0) {
			uint32_t x, y;
			if (sscanf(tok + 9, "%u,%u", &x, &y) != 2) {
				LOG(ERROR, "Error parsing image location.\n");
				goto done;
			}
			image_set_location(image, x, y);
		} else if (strncmp("offset=", tok, 7) == 0) {
			int32_t x, y;
			if (sscanf(tok + 7, "%d,%d", &x, &y) != 2) {
				LOG(ERROR, "Error parsing image offset.\n");
				goto done;
			}
			image_set_offset(image, x, y);
		} else if (strncmp("scale=", tok, 6) == 0) {
			uint32_t s;
			if (sscanf(tok + 6, "%u", &s) != 1) {
				LOG(ERROR, "Error parsing image scale.\n");
				goto done;
			}
			if (s == 0)
				s = image_get_auto_scale(term_getfb(terminal));
			image_set_scale(image, s);
		}
	}

	status = image_load_image_from_file(image);
	if (status != 0) {
		LOG(WARNING, "Term ESC image_load_image_from_file %s failed: %d:%s.",
	        image_get_filename(image), status, strerror(status));
	} else {
		term_show_image(terminal, image);
	}
done:
	image_destroy(image);
}

static void term_esc_draw_box(terminal_t* terminal, char* params)
{
	char* tok;
	uint32_t color = 0;
	uint32_t w = 1;
	uint32_t h = 1;
	uint32_t locx, locy;
	bool use_location = false;
	int32_t offx, offy;
	bool use_offset = false;
	uint32_t scale = 1;
	fb_stepper_t s;
	int32_t startx, starty;

	for (tok = strtok(params, ";"); tok; tok = strtok(NULL, ";")) {
		if (strncmp("color=", tok, 6) == 0) {
			color = strtoul(tok + 6, NULL, 0);
		} else if (strncmp("size=", tok, 5) == 0) {
			if (sscanf(tok + 5, "%u,%u", &w, &h) != 2) {
				LOG(ERROR, "Error parsing box size.\n");
				goto done;
			}
		} else if (strncmp("location=", tok, 9) == 0) {
			if (sscanf(tok + 9, "%u,%u", &locx, &locy) != 2) {
				LOG(ERROR, "Error parsing box location.\n");
				goto done;
			}
			use_location = true;
		} else if (strncmp("offset=", tok, 7) == 0) {
			if (sscanf(tok + 7, "%d,%d", &offx, &offy) != 2) {
				LOG(ERROR, "Error parsing box offset.\n");
				goto done;
			}
			use_offset = true;
		} else if (strncmp("scale=", tok, 6) == 0) {
			if (sscanf(tok + 6, "%u", &scale) != 1) {
				LOG(ERROR, "Error parsing box scale.\n");
				goto done;
			}
			if (scale == 0)
				scale = image_get_auto_scale(term_getfb(terminal));
		}
	}

	w *= scale;
	h *= scale;
	offx *= scale;
	offy *= scale;

	if (!fb_lock(terminal->fb))
		goto done;

	if (use_offset && use_location) {
		LOG(WARNING, "Box offset and location set, using location.");
		use_offset = false;
	}

	if (use_location) {
		startx = locx;
		starty = locy;
	} else {
		startx = (fb_getwidth(terminal->fb) - w)/2;
		starty = (fb_getheight(terminal->fb) - h)/2;
	}

	if (use_offset) {
		startx += offx;
		starty += offy;
	}

	if (!fb_stepper_init(&s, terminal->fb, startx, starty, w, h))
		goto done_fb;

	do {
		do {
		} while (fb_stepper_step_x(&s, color));
	} while (fb_stepper_step_y(&s));

done_fb:
	fb_unlock(terminal->fb);
done:
	;
}

static void term_esc_input(terminal_t* terminal, char* params)
{
	if (strcmp(params, "1") == 0 ||
	    strcasecmp(params, "on") == 0 ||
	    strcasecmp(params, "true") == 0)
		term_input_enable(terminal, true);
	else if (strcmp(params, "0") == 0 ||
		 strcasecmp(params, "off") == 0 ||
		 strcasecmp(params, "false") == 0)
		term_input_enable(terminal, false);
	else
		LOG(ERROR, "Invalid parameter for input escape.\n");
}

/*
 * Assume all one or two digit sequences followed by ; are xterm OSC escapes.
 */
static bool is_xterm_osc(char *osc)
{
	if (isdigit(osc[0])) {
		if (osc[1] == ';')
			return true;
		if (isdigit(osc[1]) && osc[2] == ';')
			return true;
	}
	return false;
}

static void term_osc_cb(struct tsm_vte *vte, const uint32_t *osc_string,
			size_t osc_len, void *data)
{
	terminal_t* terminal = (terminal_t*)data;
	size_t i;
	char *osc;

	for (i = 0; i < osc_len; i++)
		if (osc_string[i] >= 128)
			return; /* we only want to deal with ASCII */

	osc = malloc(osc_len + 1);
	if (!osc) {
		LOG(WARNING, "Out of memory when processing OSC.\n");
		return;
	}

	for (i = 0; i < osc_len; i++)
		osc[i] = (char)osc_string[i];
	osc[i] = '\0';

	if (strncmp(osc, "image:", 6) == 0)
		term_esc_show_image(terminal, osc + 6);
	else if (strncmp(osc, "box:", 4) == 0)
		term_esc_draw_box(terminal, osc + 4);
	else if (strncmp(osc, "input:", 6) == 0)
		term_esc_input(terminal, osc + 6);
	else if (is_xterm_osc(osc))
		; /* Ignore it. */
	else
		LOG(WARNING, "Unknown OSC escape sequence \"%s\", ignoring.", osc);

	free(osc);
}

#ifdef __clang__
__attribute__((__format__ (__printf__, 7, 0)))
#endif
static void log_tsm(void* data, const char* file, int line, const char* fn,
		    const char* subs, unsigned int sev, const char* format,
		    va_list args)
{
	char buffer[KMSG_LINE_MAX];
	int len = snprintf(buffer, KMSG_LINE_MAX, "<%i>frecon[%d]: %s: ", sev,
	                   getpid(), subs);
	if (len < 0)
		return;
	if (len < KMSG_LINE_MAX - 1)
		vsnprintf(buffer+len, KMSG_LINE_MAX - len, format, args);
	fprintf(stderr, "%s\n", buffer);
}

static int term_resize(terminal_t* term, int scaling)
{
	uint32_t char_width, char_height;
	int status;

	if (!scaling)
		scaling = fb_getscaling(term->fb);

	font_init(scaling);
	font_get_size(&char_width, &char_height);

	term->term->w_in_char = fb_getwidth(term->fb) / char_width;
	term->term->h_in_char = fb_getheight(term->fb) / char_height;

	status = tsm_screen_resize(term->term->screen,
				   term->term->w_in_char, term->term->h_in_char);
	if (status < 0) {
		font_free();
		return -1;
	}

	status = shl_pty_resize(term->term->pty, term->term->w_in_char,
				term->term->h_in_char);
	if (status < 0) {
		font_free();
		return -1;
	}

	return 0;
}

void term_set_num_terminals(unsigned new_num)
{
	if (new_num < 1)
		term_num_terminals = 1;
	else if (new_num > TERM_MAX_TERMINALS)
		term_num_terminals = TERM_MAX_TERMINALS;
	else
		term_num_terminals = new_num;
}

static bool term_is_interactive(unsigned int vt)
{
	if (command_flags.no_login)
		return false;

	if (vt == TERM_SPLASH_TERMINAL)
		return command_flags.enable_vt1;

	return true;
}

/*
 * Set the area not covered by any characters, possibly existing on the right
 * side and bottom of the screen, to the background color.
 */
static void term_clear_border(terminal_t* terminal)
{
	fb_stepper_t s;
	uint32_t char_width, char_height;
	font_get_size(&char_width, &char_height);

	if (!fb_lock(terminal->fb))
		return;

	if (fb_stepper_init(&s, terminal->fb,
			    terminal->term->w_in_char * char_width, 0,
			    fb_getwidth(terminal->fb) - terminal->term->w_in_char * char_width, terminal->term->h_in_char * char_height)) {
		do {
			do {
			} while (fb_stepper_step_x(&s, terminal->background));
		} while (fb_stepper_step_y(&s));
	}

	if (fb_stepper_init(&s, terminal->fb,
			    0, terminal->term->h_in_char * char_height,
			    fb_getwidth(terminal->fb), fb_getheight(terminal->fb) - terminal->term->h_in_char * char_height)) {
		do {
			do {
			} while (fb_stepper_step_x(&s, terminal->background));
		} while (fb_stepper_step_y(&s));
	}

	fb_unlock(terminal->fb);
}

terminal_t* term_init(unsigned vt, int pts_fd)
{
	const int scrollback_size = 200;
	int status;
	terminal_t* new_terminal;
	bool interactive = term_is_interactive(vt);

	new_terminal = (terminal_t*)calloc(1, sizeof(*new_terminal));
	if (!new_terminal)
		return NULL;

	new_terminal->vt = vt;
	new_terminal->background_valid = false;
	new_terminal->input_enable = true;

	new_terminal->fb = fb_init();

	if (!new_terminal->fb) {
		LOG(ERROR, "Failed to create fb on VT%u.", vt);
		term_close(new_terminal);
		return NULL;
	}

	new_terminal->term = (struct term*)calloc(1, sizeof(*new_terminal->term));
	if (!new_terminal->term) {
		term_close(new_terminal);
		return NULL;
	}

	if (interactive)
		new_terminal->exec = interactive_cmd_line;
	else
		new_terminal->exec = NULL;

	status = tsm_screen_new(&new_terminal->term->screen,
			log_tsm, new_terminal->term);
	if (status < 0) {
		LOG(ERROR, "Failed to create new screen on VT%u.", vt);
		term_close(new_terminal);
		return NULL;
	}

	tsm_screen_set_max_sb(new_terminal->term->screen, scrollback_size);

	status = tsm_vte_new(&new_terminal->term->vte, new_terminal->term->screen,
			term_write_cb, new_terminal->term, log_tsm, new_terminal->term);

	if (status < 0) {
		LOG(ERROR, "Failed to create new VT%u.", vt);
		term_close(new_terminal);
		return NULL;
	}

	if (command_flags.enable_osc)
		tsm_vte_set_osc_cb(new_terminal->term->vte, term_osc_cb, (void *)new_terminal);

	new_terminal->term->pty_bridge = shl_pty_bridge_new();
	if (new_terminal->term->pty_bridge < 0) {
		LOG(ERROR, "Failed to create pty bridge on VT%u.", vt);
		term_close(new_terminal);
		return NULL;
	}

	status = shl_pty_open(&new_terminal->term->pty,
			term_read_cb, new_terminal, 1, 1, pts_fd);

	if (status < 0) {
		LOG(ERROR, "Failed to open pty on VT%u.", vt);
		term_close(new_terminal);
		return NULL;
	} else if (status == 0) {
		term_run_child(new_terminal);
		exit(1);
	}

	status = mkdir(FRECON_RUN_DIR, S_IRWXU);
	if (status == 0 || (status < 0 && errno == EEXIST)) {
		char path[32];
		snprintf(path, sizeof(path), FRECON_VT_PATH, vt);
		unlink(path); /* In case it already exists. Ignore return codes. */
		if (symlink(ptsname(shl_pty_get_fd(new_terminal->term->pty)), path) < 0)
			LOG(ERROR, "Failed to symlink pts name %s to %s, %d:%s",
			    path,
			    ptsname(shl_pty_get_fd(new_terminal->term->pty)),
			    errno, strerror(errno));
	}

	status = shl_pty_bridge_add(new_terminal->term->pty_bridge, new_terminal->term->pty);
	if (status) {
		LOG(ERROR, "Failed to add pty bridge on VT%u.", vt);
		term_close(new_terminal);
		return NULL;
	}

	new_terminal->term->pid = shl_pty_get_child(new_terminal->term->pty);

	status = term_resize(new_terminal, 0);

	if (status < 0) {
		LOG(ERROR, "Failed to resize VT%u.", vt);
		term_close(new_terminal);
		return NULL;
	}

	return new_terminal;
}

void term_activate(terminal_t* terminal)
{
	term_set_current_to(terminal);
	terminal->active = true;
	fb_setmode(terminal->fb);
	term_redraw(terminal);
}

void term_deactivate(terminal_t* terminal)
{
	if (!terminal->active)
		return;

	terminal->active = false;
}

void term_close(terminal_t* term)
{
	char path[32];
	if (!term)
		return;

	snprintf(path, sizeof(path), FRECON_VT_PATH, term->vt);
	unlink(path);

	if (term->fb) {
		fb_close(term->fb);
		term->fb = NULL;
	}

	if (term->term) {
		if (term->term->pty) {
			if (term->term->pty_bridge >= 0) {
				shl_pty_bridge_remove(term->term->pty_bridge, term->term->pty);
				shl_pty_bridge_free(term->term->pty_bridge);
				term->term->pty_bridge = -1;
			}
			shl_pty_close(term->term->pty);
			term->term->pty = NULL;
		}
		free(term->term);
		term->term = NULL;
	}

	font_free();
	free(term);
}

bool term_is_child_done(terminal_t* terminal)
{
	int status;
	int ret;
	ret = waitpid(terminal->term->pid, &status, WNOHANG);

	if ((ret == -1) && (errno == ECHILD)) {
		return false;
	}
	return ret != 0;
}

void term_page_up(terminal_t* terminal)
{
	tsm_screen_sb_page_up(terminal->term->screen, 1);
	term_redraw(terminal);
}

void term_page_down(terminal_t* terminal)
{
	tsm_screen_sb_page_down(terminal->term->screen, 1);
	term_redraw(terminal);
}

void term_line_up(terminal_t* terminal)
{
	tsm_screen_sb_up(terminal->term->screen, 1);
	term_redraw(terminal);
}

void term_line_down(terminal_t* terminal)
{
	tsm_screen_sb_down(terminal->term->screen, 1);
	term_redraw(terminal);
}

bool term_is_valid(terminal_t* terminal)
{
	return ((terminal != NULL) && (terminal->term != NULL));
}

int term_fd(terminal_t* terminal)
{
	if (term_is_valid(terminal))
		return terminal->term->pty_bridge;
	else
		return -1;
}

void term_dispatch_io(terminal_t* terminal, fd_set* read_set)
{
	if (term_is_valid(terminal))
		if (FD_ISSET(terminal->term->pty_bridge, read_set))
			shl_pty_bridge_dispatch(terminal->term->pty_bridge, 0);
}

bool term_exception(terminal_t* terminal, fd_set* exception_set)
{
	if (term_is_valid(terminal)) {
		if (terminal->term->pty_bridge >= 0) {
			return FD_ISSET(terminal->term->pty_bridge,
					exception_set);
		}
	}

	return false;
}

bool term_is_active(terminal_t* terminal)
{
	if (term_is_valid(terminal))
		return terminal->active;

	return false;
}

void term_add_fds(terminal_t* terminal, fd_set* read_set, fd_set* exception_set, int* maxfd)
{
	if (term_is_valid(terminal)) {
		if (terminal->term->pty_bridge >= 0) {
			*maxfd = MAX(*maxfd, terminal->term->pty_bridge);
			FD_SET(terminal->term->pty_bridge, read_set);
			FD_SET(terminal->term->pty_bridge, exception_set);
		}
	}
}

const char* term_get_ptsname(terminal_t* terminal)
{
	return ptsname(shl_pty_get_fd(terminal->term->pty));
}

void term_set_background(terminal_t* terminal, uint32_t bg)
{
	terminal->background = bg;
	terminal->background_valid = true;
}

int term_show_image(terminal_t* terminal, image_t* image)
{
	return image_show(image, terminal->fb);
}

void term_write_message(terminal_t* terminal, char* message)
{
	FILE* fp;

	fp = fopen(term_get_ptsname(terminal), "w");
	if (fp) {
		fputs(message, fp);
		fclose(fp);
	}
}

static void term_hide_cursor(terminal_t* terminal)
{
	term_write_message(terminal, "\033[?25l");
}

__attribute__ ((unused))
static void term_show_cursor(terminal_t* terminal)
{
	term_write_message(terminal, "\033[?25h");
}

fb_t* term_getfb(terminal_t* terminal)
{
	return terminal->fb;
}

terminal_t* term_get_terminal(int num)
{
	return terminals[num];
}

void term_set_terminal(int num, terminal_t* terminal)
{
	terminals[num] = terminal;
}

int term_create_splash_term(int pts_fd)
{
	terminal_t* terminal = term_init(TERM_SPLASH_TERMINAL, pts_fd);
	
	if (!terminal) {
		LOG(ERROR, "Could not create splash term.");
		return -1;
	}
	term_set_terminal(TERM_SPLASH_TERMINAL, terminal);

	// Hide the cursor on the splash screen
	term_hide_cursor(terminal);
	return 0;
}

void term_destroy_splash_term(void)
{
	terminal_t *terminal;
	if (command_flags.enable_vt1) {
		return;
	}
	terminal = term_get_terminal(TERM_SPLASH_TERMINAL);
	term_set_terminal(TERM_SPLASH_TERMINAL, NULL);
	term_close(terminal);
}

void term_set_current(uint32_t t)
{
	if (t >= TERM_MAX_TERMINALS)
		LOG(ERROR, "set_current: larger than array size");
	else
	if (t >= term_num_terminals)
		LOG(ERROR, "set_current: larger than num terminals");
	else
		current_terminal = t;
}

uint32_t term_get_current(void)
{
	return current_terminal;
}

terminal_t *term_get_current_terminal(void)
{
	return terminals[current_terminal];
}

void term_set_current_terminal(terminal_t* terminal)
{
	terminals[current_terminal] = terminal;
}

void term_set_current_to(terminal_t* terminal)
{
	if (!terminal) {
		if (terminals[current_terminal])
			term_close(terminals[current_terminal]);
		terminals[current_terminal] = NULL;
		current_terminal = 0;
		return;
	}

	for (unsigned i = 0; i < term_num_terminals; i++) {
		if (terminal == terminals[i]) {
			current_terminal = i;
			return;
		}
	}
	LOG(ERROR, "set_current_to: terminal not in array");
}

int term_switch_to(unsigned int vt)
{
	terminal_t *terminal;
	if (vt == term_get_current()) {
		terminal = term_get_current_terminal();
		if (term_is_valid(terminal)) {
			if (!term_is_active(terminal))
				term_activate(terminal);
			return vt;
		}
	}

	if (vt >= term_num_terminals)
		return -EINVAL;

	terminal = term_get_current_terminal();
	if (term_is_active(terminal))
		term_deactivate(terminal);

	if (vt == TERM_SPLASH_TERMINAL
	    && !term_get_terminal(TERM_SPLASH_TERMINAL)
	    && !command_flags.enable_vt1) {
		term_set_current(vt);
		/* Splash term is already gone, returning to Chrome. */
		term_background(false);
		return vt;
	}

	term_foreground();

	term_set_current(vt);
	terminal = term_get_current_terminal();
	if (!terminal) {
		/* No terminal where we are switching to, create new one. */
		term_set_current_terminal(term_init(vt, -1));
		terminal = term_get_current_terminal();
		if (!term_is_valid(terminal)) {
			LOG(ERROR, "Term init failed VT%u.", vt);
			return -1;
		}
		term_activate(terminal);
	} else {
		term_activate(terminal);
	}

	return vt;
}

void term_monitor_hotplug(void)
{
	unsigned int t;

	if (in_background) {
		hotplug_occured = true;
		return;
	}

	if (!drm_rescan())
		return;

	for (t = 0; t < term_num_terminals; t++) {
		if (!terminals[t])
			continue;
		if (!terminals[t]->fb)
			continue;
		fb_buffer_destroy(terminals[t]->fb);
		font_free();
	}

	for (t = 0; t < term_num_terminals; t++) {
		if (!terminals[t])
			continue;
		if (!terminals[t]->fb)
			continue;
		fb_buffer_init(terminals[t]->fb);
		term_resize(terminals[t], 0);
		if (current_terminal == t && terminals[t]->active)
			fb_setmode(terminals[t]->fb);
		terminals[t]->term->age = 0;
		term_redraw(terminals[t]);
	}
}

void term_redrm(terminal_t* terminal)
{
	fb_buffer_destroy(terminal->fb);
	font_free();
	fb_buffer_init(terminal->fb);
	term_resize(terminal, 0);
	terminal->term->age = 0;
	term_redraw(terminal);
}

void term_clear(terminal_t* terminal)
{
	term_clear_border(terminal);
	tsm_screen_erase_screen(terminal->term->screen, false);
	term_redraw(terminal);
}

void term_zoom(bool zoom_in)
{
	int scaling = font_get_scaling();
	if (zoom_in && scaling < 4)
		scaling++;
	else if (!zoom_in && scaling > 1)
		scaling--;
	else
		return;

	unsigned int t;
	for (t = 0; t < term_num_terminals; t++) {
		if (terminals[t])
			font_free();
	}
	for (t = 0; t < term_num_terminals; t++) {
		terminal_t* term = terminals[t];
		if (term) {
			term_resize(term, scaling);
			term->term->age = 0;
			term_redraw(term);
		}
	}
}

/*
 * Put frecon in background. Give up DRM master.
 * onetry - if true, do not retry to notify Chrome multiple times. For use at
 * time when Chrome may be not around yet to receive the message.
 */
void term_background(bool onetry)
{
	int retry = onetry ? 1 : 5;
	if (in_background)
		return;
	in_background = true;
	drm_dropmaster(NULL);
	while (!dbus_take_display_ownership() && retry--) {
		if (onetry)
			break;
		LOG(ERROR, "Chrome failed to take display ownership. %s",
		    retry ? "Trying again." : "Giving up, Chrome is probably dead.");
		if (retry > 0)
			usleep(500 * 1000);
	}
}

void term_foreground(void)
{
	int ret;
	int retry = 5;

	if (!in_background)
		return;
	in_background = false;

	/* LOG(INFO, "TIMING: Console switch time start."); */ /* Keep around for timing it in the future. */
	while (!dbus_release_display_ownership() && retry--) {
		LOG(ERROR, "Chrome did not release master. %s",
		    retry ? "Trying again." : "Frecon will steal master.");
		if (retry > 0)
			usleep(500 * 1000);
	}

	/* LOG(INFO, "TIMING: Console switch setmaster."); */
	ret = drm_setmaster(NULL);
	if (ret < 0)
		LOG(ERROR, "Could not set master when switching to foreground %m.");

	if (hotplug_occured) {
		hotplug_occured = false;
		term_monitor_hotplug();
	}
}

void term_suspend_done(void* ignore)
{
	term_monitor_hotplug();
}

void term_input_enable(terminal_t* terminal, bool input_enable)
{
	terminal->input_enable = input_enable;
}
