CLI Multi-screen Code

Added code to support switching between text screens and new layout of CLI screen.
This commit is contained in:
Peter Weingartner 2022-04-08 20:07:59 -04:00
parent 50797494e6
commit 17b4d77c2d
10 changed files with 13035 additions and 12615 deletions

View file

@ -4,6 +4,7 @@
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "log.h"
@ -85,6 +86,12 @@ extern short cmd_screen(short channel, int argc, const char * argv[]);
/** The channel to use for interactions */
short g_current_channel = 0;
/** Flag to indicate that the current working directory has changed */
short g_cwd_changed = 0;
/** The number of text screens on this machine */
short g_num_screens = 0;
/** The history of previous commands issued */
char cli_history[MAX_HISTORY_DEPTH][MAX_COMMAND_SIZE];
@ -672,6 +679,86 @@ short cli_process_line(short channel, const char * command_line) {
}
}
void cli_draw_window(short channel, const char * status, short is_active) {
const char * title_header = "Foenix/MCP - ";
unsigned char foreground, background;
char buffer[128];
t_point cursor;
t_rect region, old_region, full_region;
short i = 0, j;
// Save the current region and cursor location
sys_txt_get_xy(channel, &cursor);
sys_txt_get_region(channel, &old_region);
sys_txt_get_color(channel, &foreground, &background);
// Return to the full region and get its dimensions
region.origin.x = 0;
region.origin.y = 0;
region.size.width = 0;
region.size.height = 0;
sys_txt_set_region(channel, &region);
sys_txt_get_region(channel, &full_region);
// Display the titlebar
i = 0;
sys_txt_set_xy(channel, 0, 0);
if (is_active) {
sys_txt_set_color(channel, background, foreground);
}
for (j = 0; j < strlen(title_header); j++) {
buffer[i++] = title_header[j];
}
for (j = 0; j < strlen(status); j++) {
buffer[i++] = status[j];
}
while (i < full_region.size.width) {
if (is_active) {
buffer[i++] = ' ';
} else {
buffer[i++] = 0xB0;
}
}
buffer[i++] = 0;
print(channel, buffer);
// Restore the region and cursor location
sys_txt_set_color(channel, foreground, background);
sys_txt_set_region(channel, &old_region);
sys_txt_set_xy(channel, cursor.x, cursor.y);
}
/**
* Initialize the text screen (set up regions, windows, etc.)
*/
void cli_setup_screen(short channel, const char * path, short is_active) {
t_rect full_region, command_region;
// Get the size of the screen
full_region.origin.x = 0;
full_region.origin.y = 0;
full_region.size.width = 0;
full_region.size.height = 0;
sys_txt_set_region(channel, &full_region);
sys_txt_get_region(channel, &full_region);
// Clear the screen
print(channel, "\x1b[2J\x1b[H");
// Figure out the size of the command box and its region
command_region.origin.x = 0;
command_region.origin.y = 1;
command_region.size.width = full_region.size.width;
command_region.size.height = full_region.size.height - 1;
// Restrict the region to the command panel
sys_txt_set_region(channel, &command_region);
// Draw the window
cli_draw_window(channel, path, is_active);
print(channel, "\x1b[2J\x1b[1;2H");
}
//
// Enter the CLI's read-eval-print loop
//
@ -680,7 +767,10 @@ short cli_repl(short channel, const char * init_cwd) {
char cwd_buffer[MAX_PATH_LEN];
short result = 0;
short i = 0;
t_point cursor;
short old_channel;
old_channel = channel;
g_current_channel = channel;
if (init_cwd != 0) {
@ -692,14 +782,41 @@ short cli_repl(short channel, const char * init_cwd) {
}
}
while (1) {
sys_chan_write(g_current_channel, "\n", 1);
// TODO: write the current directory to the status line
// if(sys_fsys_get_cwd(cwd_buffer, MAX_PATH_LEN) == 0) {
// sys_chan_write(channel, cwd_buffer, strlen(cwd_buffer));
// }
sys_chan_write(g_current_channel, "\x10 ", 2); // Print our prompt
// Set up the screen(s)
cli_setup_screen(channel, init_cwd, 1); // Initialize our main main screen
if (g_num_screens > 1) {
for (i = 0; i < g_num_screens; i++) { // Set up each screen we aren't using
if (i != channel) {
cli_setup_screen(i, init_cwd, 0);
}
}
}
g_cwd_changed = 1;
cursor.x = 0;
cursor.y = 0;
while (1) {
// Refresh window if the current working directory has changed
if (g_cwd_changed || (old_channel != g_current_channel)) {
g_cwd_changed = 0;
// Get and display the new working directory
if (sys_fsys_get_cwd(cwd_buffer, MAX_PATH_LEN) == 0) {
// char message[80];
// sprintf(message, "%d", strlen(cwd_buffer));
print(0, "");
if (old_channel != g_current_channel) {
// If channel has changed, deactivate old channel
cli_draw_window(old_channel, cwd_buffer, 0);
old_channel = g_current_channel;
}
cli_draw_window(g_current_channel, cwd_buffer, 1);
}
}
sys_chan_write(g_current_channel, "\x10 ", 2); // Print our prompt
result = cli_readline(g_current_channel, command_line);
switch (result) {
case -1:
@ -720,11 +837,12 @@ short cli_repl(short channel, const char * init_cwd) {
strcpy(cli_history[0], command_line);
break;
}
// sys_chan_readline(channel, command_line, MAX_COMMAND_SIZE); // Attempt to read line
sys_chan_write(g_current_channel, "\n", 1);
print(g_current_channel, "\n");
cli_process_line(g_current_channel, command_line);
print(g_current_channel, "\n");
sys_txt_get_xy(channel, &cursor);
}
return 0;
@ -865,6 +983,13 @@ long cli_eval_number(const char * arg) {
return cli_eval_dec(arg);
}
/**
* Indicate that the current working directory has changed
*/
void cli_flag_cwd() {
g_cwd_changed = 1;
}
//
// Initialize the CLI
//
@ -872,6 +997,7 @@ long cli_eval_number(const char * arg) {
// 0 on success, negative number on error
//
short cli_init() {
t_sys_info info;
short i;
// Clear out the command history
@ -879,6 +1005,10 @@ short cli_init() {
cli_history[i][0] = 0;
}
// Figure out how many screens we have
sys_get_info(&info);
g_num_screens = info.screens;
cli_set_init();
return 0;
}

View file

@ -68,4 +68,9 @@ extern void cli_channel_set(short channel);
*/
extern short cli_channel_get();
/**
* Indicate that the current working directory has changed
*/
extern void cli_flag_cwd();
#endif

View file

@ -239,6 +239,7 @@ short cmd_cd(short screen, int argc, const char * argv[]) {
err_print(screen, "Unable to change directory", result);
return result;
} else {
cli_flag_cwd();
print(screen, "Changed to: ");
print(screen, argv[1]);
print(screen, "\n");

View file

@ -274,8 +274,8 @@ void txt_a2560k_b_set_cursor(short enable, short rate, char c) {
*
* @return 0 on success, any other number means the region was invalid
*/
short txt_a2560k_b_set_region(p_rect region) {
if ((region == 0) || (region->size.width == 0) || (region->size.height == 0)) {
short txt_a2560k_b_set_region(p_rect region) {
if ((region->size.width == 0) || (region->size.height == 0)) {
/* Set the region to the default (full screen) */
a2560k_b_region.origin.x = 0;
a2560k_b_region.origin.y = 0;
@ -289,6 +289,22 @@ short txt_a2560k_b_set_region(p_rect region) {
a2560k_b_region.size.height = region->size.height;
}
return 0;
}
/**
* get the current region
*
* @param region pointer to a t_rect describing the rectangular region (using character cells for size and size)
*
* @return 0 on success, any other number means the region was invalid
*/
short txt_a2560k_b_get_region(p_rect region) {
region->origin.x = a2560k_b_region.origin.x;
region->origin.y = a2560k_b_region.origin.y;
region->size.width = a2560k_b_region.size.width;
region->size.height = a2560k_b_region.size.height;
return 0;
}
@ -303,6 +319,18 @@ short txt_a2560k_b_set_color(unsigned char foreground, unsigned char background)
return 0;
}
/**
* Get the default foreground and background colors for printing
*
* @param pointer to the foreground the Text LUT index of the new current foreground color (0 - 15)
* @param pointer to the background the Text LUT index of the new current background color (0 - 15)
*/
short txt_a2560k_b_get_color(unsigned char * foreground, unsigned char * background) {
*foreground = (a2560k_b_color & 0xf0) >> 4;
*background = a2560k_b_color & 0x0f;
return 0;
}
/**
* Scroll the text in the current region
@ -595,7 +623,9 @@ short txt_a2560k_b_install() {
device.set_font = txt_a2560k_b_set_font;
device.set_cursor = txt_a2560k_b_set_cursor;
device.set_region = txt_a2560k_b_set_region;
device.get_region = txt_a2560k_b_get_region
device.set_color = txt_a2560k_b_set_color;
device.get_color = txt_a2560k_b_get_color;
device.set_xy = txt_a2560k_b_set_xy;
device.get_xy = txt_a2560k_b_get_xy;
device.put = txt_a2560k_b_put;

View file

@ -4,6 +4,8 @@
* Uniform routines to manage the text screens
*/
#include "types.h"
#ifndef __TXT_SCREEN_H
#define __TXT_SCREEN_H
@ -15,36 +17,6 @@
#define TXT_MODE_TILE 0x0008 /**< The bit to enable tile graphics mode */
#define TXT_MODE_SLEEP 0x0010 /**< The bit to put the monitor to sleep by disabling sync */
/**
* @struct s_extent
*
* An extent or size of a rectangular area
*/
typedef struct s_extent {
short width; /**< The width of the region */
short height; /**< The height of the region */
} t_extent, *p_extent;
/**
* @struct s_point
*
* A point on a plane
*/
typedef struct s_point {
short x; /**< The column of the point */
short y; /**< The row of the point */
} t_point, *p_point;
/**
* @struct s_rect
*
* A rectangle on the screen
*/
typedef struct s_rect {
t_point origin; /**< The upper-left corner of the rectangle */
t_extent size; /**< The size of the rectangle */
} t_rect, *p_rect;
/**
* @struct s_txt_capabilities
*

File diff suppressed because it is too large Load diff

View file

@ -716,4 +716,68 @@ extern short sys_kbd_layout(const char * tables);
*/
extern short sys_proc_run(const char * path, int argc, char * argv[]);
//
// Text screen calls
//
/**
* Set the position of the cursor to (x, y) relative to the current region
* If the (x, y) coordinate is outside the region, it will be clipped to the region.
* If y is greater than the height of the region, the region will scroll until that relative
* position would be within view.
*
* @param screen the number of the text device
* @param x the column for the cursor
* @param y the row for the cursor
*/
extern void sys_txt_set_xy(short screen, short x, short y);
/**
* Get the position of the cursor (x, y) relative to the current region
*
* @param screen the number of the text device
* @param position pointer to a t_point record to fill out
*/
extern void sys_txt_get_xy(short screen, p_point position);
/**
* Get the current region.
*
* @param screen the number of the text device
* @param region pointer to a t_rect describing the rectangular region (using character cells for size and size)
*
* @return 0 on success, any other number means the region was invalid
*/
extern short sys_txt_get_region(short screen, p_rect region);
/**
* Set a region to restrict further character display, scrolling, etc.
* Note that a region of zero size will reset the region to the full size of the screen.
*
* @param screen the number of the text device
* @param region pointer to a t_rect describing the rectangular region (using character cells for size and size)
*
* @return 0 on success, any other number means the region was invalid
*/
extern short sys_txt_set_region(short screen, p_rect region);
/**
* Set the default foreground and background colors for printing
*
* @param screen the number of the text device
* @param foreground the Text LUT index of the new current foreground color (0 - 15)
* @param background the Text LUT index of the new current background color (0 - 15)
*/
extern void sys_txt_set_color(short screen, unsigned char foreground, unsigned char background);
/*
* Get the foreground and background color for printing
*
* Inputs:
* screen = the screen number 0 for channel A, 1 for channel B
* foreground = pointer to the foreground color number
* background = pointer to the background color number
*/
extern void sys_txt_get_color(short screen, unsigned char * foreground, unsigned char * background);
#endif

View file

@ -8,14 +8,35 @@
#include <stdint.h>
#include <stdbool.h>
/*
* Function types
/**
* @struct s_extent
*
* An extent or size of a rectangular area
*/
typedef struct s_extent {
short width; /**< The width of the region */
short height; /**< The height of the region */
} t_extent, *p_extent;
/*
* Integer types in their standard sizes, signed and unsigned.
/**
* @struct s_point
*
* A point on a plane
*/
typedef struct s_point {
short x; /**< The column of the point */
short y; /**< The row of the point */
} t_point, *p_point;
/**
* @struct s_rect
*
* A rectangle on the screen
*/
typedef struct s_rect {
t_point origin; /**< The upper-left corner of the rectangle */
t_extent size; /**< The size of the rectangle */
} t_rect, *p_rect;
//
// A color (BGR)

17256
src/mapfile

File diff suppressed because it is too large Load diff

View file

@ -694,3 +694,79 @@ short sys_kbd_layout(const char * tables) {
short sys_proc_run(const char * path, int argc, char * argv[]) {
return syscall(KFN_RUN, path, argc, argv);
}
//
// Text system calls
//
/**
* Set the position of the cursor to (x, y) relative to the current region
* If the (x, y) coordinate is outside the region, it will be clipped to the region.
* If y is greater than the height of the region, the region will scroll until that relative
* position would be within view.
*
* @param screen the number of the text device
* @param x the column for the cursor
* @param y the row for the cursor
*/
void sys_txt_set_xy(short screen, short x, short y) {
syscall(KFN_TXT_SET_XY, screen, x, y);
}
/**
* Get the position of the cursor (x, y) relative to the current region
*
* @param screen the number of the text device
* @param position pointer to a t_point record to fill out
*/
void sys_txt_get_xy(short screen, p_point position) {
syscall(KFN_TXT_GET_XY, screen, position);
}
/**
* Get the current region.
*
* @param screen the number of the text device
* @param region pointer to a t_rect describing the rectangular region (using character cells for size and size)
*
* @return 0 on success, any other number means the region was invalid
*/
short sys_txt_get_region(short screen, p_rect region) {
syscall(KFN_TXT_GET_REGION, screen, region);
}
/**
* Set a region to restrict further character display, scrolling, etc.
* Note that a region of zero size will reset the region to the full size of the screen.
*
* @param screen the number of the text device
* @param region pointer to a t_rect describing the rectangular region (using character cells for size and size)
*
* @return 0 on success, any other number means the region was invalid
*/
short sys_txt_set_region(short screen, p_rect region) {
syscall(KFN_TXT_SET_REGION, screen, region);
}
/**
* Set the default foreground and background colors for printing
*
* @param screen the number of the text device
* @param foreground the Text LUT index of the new current foreground color (0 - 15)
* @param background the Text LUT index of the new current background color (0 - 15)
*/
short sys_txt_set_color(short screen, unsigned char foreground, unsigned char background) {
return syscall(KFN_TXT_SET_COLOR, screen, foreground, background);
}
/*
* Get the foreground and background color for printing
*
* Inputs:
* screen = the screen number 0 for channel A, 1 for channel B
* foreground = pointer to the foreground color number
* background = pointer to the background color number
*/
void sys_txt_get_color(short screen, unsigned char * foreground, unsigned char * background) {
syscall(KFN_TXT_GET_COLOR, screen, foreground, background);
}