summaryrefslogtreecommitdiffstats
path: root/src/gui_riscos.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2004-06-13 20:20:40 +0000
committerBram Moolenaar <Bram@vim.org>2004-06-13 20:20:40 +0000
commit071d4279d6ab81b7187b48f3a0fc61e587b6db6c (patch)
tree221cbe3c40e043163c06f61c52a7ba2eb41e12ce /src/gui_riscos.c
parentb4210b3bc14e2918f153a7307530fbe6eba659e1 (diff)
updated for version 7.0001v7.0001
Diffstat (limited to 'src/gui_riscos.c')
-rw-r--r--src/gui_riscos.c3547
1 files changed, 3547 insertions, 0 deletions
diff --git a/src/gui_riscos.c b/src/gui_riscos.c
new file mode 100644
index 0000000000..b823a79f87
--- /dev/null
+++ b/src/gui_riscos.c
@@ -0,0 +1,3547 @@
+/* vi:set ts=8 sts=4 sw=4:
+ *
+ * VIM - Vi IMproved by Bram Moolenaar
+ *
+ * Do ":help uganda" in Vim to read copying and usage conditions.
+ * Do ":help credits" in Vim to see a list of people who contributed.
+ * See README.txt for an overview of the Vim source code.
+ */
+
+#include "vim.h"
+#include <string.h>
+
+/*
+ * gui_riscos.c
+ *
+ * Thomas Leonard <tal197@ecs.soton.ac.uk>
+ * Updated by Andy Wingate <andy@sparse.net>
+ */
+
+extern int time_of_last_poll;
+
+int task_handle = 0; /* Zero means we are not yet a Wimp task */
+int child_handle = 0; /* Task handle of our child process (zero if none). */
+int *wimp_menu = (int *) -1; /* Pointer to a Wimp menu structure (or -1) */
+int save_window = -1; /* Save As window handle */
+
+int *redraw_block = NULL; /* NULL means not in a redraw loop. */
+int ro_return_early = FALSE; /* Break out of gui_mch_wait_for_chars() */
+
+int leaf_ref = 0; /* Wimp message number - send via Wimp$Scrap */
+char_u *leaf_name = NULL; /* Leaf name from DataSave */
+
+int default_columns = 120; /* These values are used if the --rows and --columns */
+int default_rows = 32; /* options aren't used on startup. */
+
+#define DRAG_FALSE 0
+#define DRAG_SELECTION 1
+#define DRAG_RESIZE_WINDOW 2
+int ro_dragging = DRAG_FALSE;
+int drag_button;
+int drag_modifiers;
+int drag_x_offset;
+int drag_y_offset;
+
+int nested_wimp = FALSE; /* Bool - can we use the new wimp? */
+
+int changed_mode = FALSE;
+int x_eigen_factor;
+int y_eigen_factor;
+
+/* If ro_current_font is non-zero then use the outline font with that handle,
+ * otherwise, if zap_redraw is TRUE then use ZapRedraw, otherwise use the
+ * system font.
+ *
+ * If zap_redraw is TRUE then zap_file[] contains valid Zap font file
+ * pointers (or NULLs).
+ */
+int ro_current_font = 0; /* 0 is system font, or ZapRedraw */
+int font_x_offset = 0; /* Where to position each char in its box */
+int font_y_offset = 0;
+
+int zap_redraw = FALSE;
+int double_height = FALSE; /* Plot each line twice? */
+
+#define grgb(r,g,b) ((b<<16) + (g<<8) + (r))
+#define UNUSED_COLOUR (gui.back_pixel)
+
+#define RO_LOAD_CLIPBOARD -2 /* Internal handle for DataSave message. */
+
+/* Changes by John Kortink, 22-23 July 1998
+ *
+ * Stuff to make redraw a lot faster. Almost all of it is right here below,
+ * elsewhere changes are marked with 'JK230798'. Apart from a small change in
+ * 'gui.c' all changes are limited to this file, 'gui_riscos.c'. The change in
+ * 'gui.c' is to make Vim stop being 'smart' not redrawing characters that are
+ * 'already there' (i.e. from the previous line, by coincidence). This caused a
+ * lot more calls to the redraw code, which we want to avoid because a few nice
+ * big strings at a time is a lot faster than a truckload of small ones. ('Dear
+ * Bram ...').
+ */
+
+/* The ZapRedraw structure */
+
+static struct
+{
+ int r_flags;
+ int r_minx;
+ int r_miny;
+ int r_maxx;
+ int r_maxy;
+ int r_screen;
+ int r_bpl;
+ int r_bpp;
+ int r_charw;
+ int r_charh;
+ char *r_caddr;
+ int r_cbpl;
+ int r_cbpc;
+ int r_linesp;
+ int r_data;
+ int r_scrollx;
+ int r_scrolly;
+ int *r_palette;
+ int r_for;
+ int r_bac;
+ char *r_workarea;
+ int r_magx;
+ int r_magy;
+ int r_xsize;
+ int r_ysize;
+ int r_mode;
+}
+zap_redraw_block;
+
+/* Other globals */
+
+static int zap_redraw_initialised = FALSE;
+static int zap_redraw_update_colours;
+static int zap_redraw_colours[2];
+static int zap_redraw_palette[16];
+
+/* Holds the current Zap font file(s).
+ * The font is recreated from this block on a mode change.
+ * When using zap, element ZAP_NORMAL is always valid, but
+ * the others can be NULL.
+ */
+
+#define ZAP_NORMAL 0
+#define ZAP_BOLD 1
+#define ZAP_ITALIC 2
+#define ZAP_BITALIC 3
+#define ZAP_STYLES 4
+
+/* Zap font file format data */
+static char *zap_file[ZAP_STYLES] = {NULL, NULL, NULL, NULL};
+
+/* r_caddr format for current mode */
+static char *zap_caddr[ZAP_STYLES] = {NULL, NULL, NULL, NULL};
+
+static void ro_remove_menu(int *menu);
+
+/*
+ * Initialise all the ZapRedraw stuff.
+ * Call this when changing font and after each mode change.
+ * zap_redraw_bitmap must contain a valid Zap font file (possibly
+ * created from the system font).
+ *
+ * Return FAIL to revert to system font (if we can't use ZapRedraw).
+ */
+ int
+ro_zap_redraw_initialise()
+{
+ int bytes_per_bitmap_char;
+ int first, last;
+ int i;
+
+ /* Can't have initialisers for struct members :-(, ok, this way then ... */
+ if (!zap_redraw_initialised)
+ {
+ zap_redraw_block.r_workarea = NULL;
+ zap_redraw_initialised = TRUE;
+ }
+
+ /* We redraw in DSA mode */
+ zap_redraw_block.r_flags = 0x0;
+
+ /* Let ZapRedraw get the screen address for us */
+ zap_redraw_block.r_screen = 0;
+
+ /* Read the font width and height from the font file header.
+ * Assume that all styles are the same size.
+ * ZAP_NORMAL is always present.
+ */
+ zap_redraw_block.r_charw = ((int *) zap_file[ZAP_NORMAL])[2];
+ zap_redraw_block.r_charh = ((int *) zap_file[ZAP_NORMAL])[3];
+
+ /* We have no linespacing */
+ zap_redraw_block.r_linesp = 0;
+
+ /* Fix foreground = colour 1 */
+ zap_redraw_block.r_for = 1;
+
+ /* Fix background = colour 0 */
+ zap_redraw_block.r_bac = 0;
+
+ /* Colour mask buffer */
+ zap_redraw_block.r_palette = zap_redraw_palette;
+
+ /* Allocate local workspace (for the few calls following here) */
+ if (zap_redraw_block.r_workarea != NULL)
+ free(zap_redraw_block.r_workarea);
+ zap_redraw_block.r_workarea = (char*) malloc(128);
+ if (!zap_redraw_block.r_workarea)
+ return FAIL; /* Out of memory */
+
+ /* Fill in VDU variables */
+ if (xswi(ZapRedraw_ReadVduVars, 0, &zap_redraw_block) & v_flag)
+ return FAIL; /* Can't find ZapRedraw module - use VDU instead */
+
+ /* Determine cbpl and cbpc */
+ swi(ZapRedraw_CachedCharSize, zap_redraw_block.r_bpp, 0,
+ zap_redraw_block.r_charw, zap_redraw_block.r_charh);
+ zap_redraw_block.r_cbpl = r2;
+ zap_redraw_block.r_cbpc = r3;
+
+ /* Allocate general workspace (for the calls outside) */
+ if (zap_redraw_block.r_workarea != NULL)
+ free(zap_redraw_block.r_workarea);
+ zap_redraw_block.r_workarea = (char*) malloc(128 + zap_redraw_block.r_cbpl);
+ if (!zap_redraw_block.r_workarea)
+ return FAIL; /* Out of memory */
+
+ /* Now convert the 1 bpp character data ready for the current mode */
+
+ bytes_per_bitmap_char = (zap_redraw_block.r_charw * zap_redraw_block.r_charh + 7) / 8;
+
+ /* Convert the fonts from 1bpp to a format suitable for the
+ * current mode.
+ */
+ for (i = 0; i < ZAP_STYLES; i++)
+ {
+ first = ((int *) zap_file[i])[4];
+ last = ((int *) zap_file[i])[5];
+
+ if (last > 255)
+ last = 255; /* Don't convert cursors (overwrites memory!) */
+
+ /* Allocate the font cache */
+ vim_free(zap_caddr[i]);
+ if (zap_file[i])
+ zap_caddr[i] = (char*) malloc(zap_redraw_block.r_cbpc * 256);
+ else
+ zap_caddr[i] = NULL; /* No file for this style */
+
+ if (zap_caddr[i])
+ {
+ zap_redraw_block.r_caddr = zap_caddr[i];
+
+ swi(ZapRedraw_ConvertBitmap, 0, &zap_redraw_block,
+ first, last, /* Range of characters to convert */
+ zap_file[i] + 0x20 /* Addr of first char provided by font */
+ - first * bytes_per_bitmap_char);
+ }
+ }
+
+ if (!zap_caddr[ZAP_NORMAL])
+ {
+ zap_redraw = FALSE; /* Out of memory */
+ return FAIL;
+ }
+
+ /* Next time we need them, we have to update the colour masks */
+ zap_redraw_update_colours = TRUE;
+
+ return OK;
+}
+
+/*
+ * Redraw a string at OS coordinates <x,y> (top-left, x inclusive, y exclusive).
+ * Graphics clip window is window[0..3] as in R1+28..40 of Wimp_RedrawWindow.
+ * Returns (possibly modified) flags.
+ */
+ int
+ro_zap_redraw_draw_string(x, y, string, length, flags, clip)
+ int x;
+ int y;
+ char *string;
+ int length;
+ int flags; /* DRAW_TRANSP, DRAW_BOLD, DRAW_UNDERL, DRAW_ITALIC */
+ int *clip;
+{
+ char redraw_data[1024];
+ int clip_minx;
+ int clip_miny;
+ int clip_maxx;
+ int clip_maxy;
+ int os_xshift = zap_redraw_block.r_magx;
+ int os_yshift = zap_redraw_block.r_magy;
+
+ if (flags & DRAW_TRANSP)
+ return flags; /* We don't do transparent plotting yet. */
+
+ if (flags & DRAW_BOLD)
+ {
+ if (flags & DRAW_ITALIC && zap_caddr[ZAP_BITALIC])
+ zap_redraw_block.r_caddr = zap_caddr[ZAP_BITALIC];
+ else
+ zap_redraw_block.r_caddr = zap_caddr[ZAP_BOLD];
+ }
+ else
+ {
+ if (flags & DRAW_ITALIC)
+ zap_redraw_block.r_caddr = zap_caddr[ZAP_ITALIC];
+ else
+ zap_redraw_block.r_caddr = zap_caddr[ZAP_NORMAL];
+ }
+ if (!zap_redraw_block.r_caddr)
+ {
+ zap_redraw_block.r_caddr = zap_caddr[ZAP_NORMAL];
+ flags |= DRAW_UNDERL; /* Style missing - we can always underline */
+ }
+
+ /* Set the vertical scaling flag */
+ if (double_height)
+ zap_redraw_block.r_flags = 1 << 1;
+ else
+ zap_redraw_block.r_flags = 0;
+
+ /* Update the colour masks (if needed) */
+ if (zap_redraw_update_colours)
+ {
+ swi(ZapRedraw_CreatePalette, 2,
+ &zap_redraw_block,
+ zap_redraw_colours,
+ zap_redraw_block.r_palette, 2);
+ zap_redraw_update_colours = FALSE;
+ }
+
+ /* Target rectangle in ZapRedraw rectangle coordinates (pixels, Y-min/max reversed !!!) */
+ zap_redraw_block.r_minx = x >> os_xshift; /* inclusive */
+ zap_redraw_block.r_miny = zap_redraw_block.r_ysize - (y >> os_yshift); /* inclusive */
+ zap_redraw_block.r_maxx = (x + length * gui.char_width) >> os_xshift; /* exclusive */
+ zap_redraw_block.r_maxy = zap_redraw_block.r_ysize - ((y - gui.char_height) >> os_yshift);
+ /* exclusive */
+
+ /* Clip rectangle in ZapRedraw rectangle coordinates (pixels, Y-min/max reversed !!!) */
+ clip_minx = clip[0] >> os_xshift; /* inclusive */
+ clip_miny = zap_redraw_block.r_ysize - (clip[3] >> os_yshift); /* inclusive */
+ clip_maxx = clip[2] >> os_xshift; /* exclusive */
+ clip_maxy = zap_redraw_block.r_ysize - (clip[1] >> os_yshift); /* exclusive */
+
+ /* Clip target rectangle against the current graphics window */
+ if (zap_redraw_block.r_minx < clip_minx)
+ {
+ zap_redraw_block.r_scrollx = clip_minx - zap_redraw_block.r_minx;
+ zap_redraw_block.r_minx = clip_minx;
+ }
+ else
+ zap_redraw_block.r_scrollx = 0;
+ if (zap_redraw_block.r_miny < clip_miny)
+ {
+ zap_redraw_block.r_scrolly = clip_miny - zap_redraw_block.r_miny;
+ zap_redraw_block.r_miny = clip_miny;
+ }
+ else
+ zap_redraw_block.r_scrolly = 0;
+ if (zap_redraw_block.r_maxx > clip_maxx)
+ zap_redraw_block.r_maxx = clip_maxx;
+ if (zap_redraw_block.r_maxy > clip_maxy)
+ zap_redraw_block.r_maxy = clip_maxy;
+
+ /* Fill in the character data structure */
+ if (length > (sizeof(redraw_data) - 2 * 4 - 2))
+ length = sizeof(redraw_data) - 2 * 4 - 2;
+ ((int*) redraw_data)[0] = 2 * 4;
+ ((int*) redraw_data)[1] = 0;
+ strncpy(redraw_data + 2 * 4, string, length);
+ redraw_data[2 * 4 + length + 0] = '\0';
+ redraw_data[2 * 4 + length + 1] = '\x2';
+ zap_redraw_block.r_data = (int) redraw_data;
+
+ /* Perform the draw */
+ swi(ZapRedraw_RedrawArea, 0, &zap_redraw_block);
+
+ return flags;
+}
+
+/*
+ * Okay that was it from me, back to Thomas ...
+ */
+
+/*
+ * Parse the GUI related command-line arguments. Any arguments used are
+ * deleted from argv, and *argc is decremented accordingly. This is called
+ * when vim is started, whether or not the GUI has been started.
+ */
+ void
+gui_mch_prepare(int *argc, char **argv)
+{
+ int arg = 1;
+
+ while (arg < *argc - 1)
+ {
+ if (strcmp(argv[arg], "--rows") == 0 || strcmp(argv[arg], "--columns") == 0)
+ {
+ int value;
+
+ value = atoi(argv[arg + 1]);
+
+ if (argv[arg][2] == 'r')
+ default_rows = value;
+ else
+ default_columns = value;
+
+ /* Delete argument from argv[]. (hope this is read/write!) */
+
+ *argc -= 2;
+ if (*argc > arg)
+ mch_memmove(&argv[arg], &argv[arg + 2], (*argc - arg)
+ * sizeof(char *));
+ }
+ else
+ arg++;
+ }
+}
+
+/* Fatal error on initialisation - report it and die. */
+ void
+ro_die(error)
+ char_u *error; /* RISC OS error block */
+{
+ swi(Wimp_ReportError, error, 5, "GVim");
+ exit(EXIT_FAILURE);
+}
+
+/* Find the sizes of the window tools:
+ *
+ * Create a test window.
+ * Find inner and outer sizes.
+ * Find the difference.
+ * Delete window.
+ *
+ * While we're here, find the eigen values too.
+ */
+ void
+ro_measure_tools()
+{
+ int block[10];
+ int vdu[] = { 4, 5, -1};
+ int test_window[] =
+ {
+ -100, -100, /* Visible area : min X,Y */
+ -50, -50, /* max X,Y */
+ 0, 0, /* Scroll offsets */
+ -1, /* Window in front */
+ 0xd0800150, /* Window flags */
+ 0xff070207, /* Colours */
+ 0x000c0103, /* More colours */
+ 0, -0x4000, /* Workarea extent */
+ 0x4000, 0, /* max X,Y */
+ 0x00000000, /* No title */
+ 0 << 12, /* No workarea button type */
+ 1, /* Wimp sprite area */
+ 0x00010001, /* Minimum width, height */
+ 0, 0, 0, /* Title data (none) */
+ 0 /* No icons */
+ };
+ int inner_max_x, inner_min_y;
+
+ swi(Wimp_CreateWindow, 0, test_window);
+
+ block[0] = r0;
+ /* Open the window (and read state).
+ * GetWindowOutline needs it too if the wimp isn't nested.
+ */
+ swi(Wimp_OpenWindow, 0, block);
+ inner_max_x = block[3];
+ inner_min_y = block[2];
+
+ swi(Wimp_GetWindowOutline, 0, block);
+
+ gui.scrollbar_width = block[3] - inner_max_x;
+ gui.scrollbar_height = inner_min_y - block[2];
+
+ swi(Wimp_DeleteWindow, 0, block);
+
+ /* Read the size of one pixel. */
+ swi(OS_ReadVduVariables, vdu, vdu);
+ x_eigen_factor = vdu[0];
+ y_eigen_factor = vdu[1];
+}
+
+/* Load a template from the current templates file.
+ * Create the window and return its handle.
+ */
+ int
+ro_load_template(str_name, title, title_size)
+ char_u *str_name; /* Identifier of window in file (max 12 chars) */
+ char_u **title; /* If not NULL then return pointer to title here */
+ int *title_size; /* If not NULL then return the title length here */
+{
+ int *window;
+ char *data;
+ int name[4];
+
+ strcpy( (char *) name, str_name);
+
+ /* Find how big we must make the buffers */
+
+ if (xswi(Wimp_LoadTemplate, 0, 0, 0, 0, -1, name, 0) & v_flag)
+ ro_die( (char *) r0);
+
+ window = malloc(r1); /* Don't print text messages from alloc() */
+ data = malloc(r2);
+ if (window == NULL || data == NULL)
+ ro_die("\0\0\0\0Out of memory - Can't load templates");
+
+ /* Load the template into the buffers */
+
+ swi(Wimp_LoadTemplate, 0,
+ window, /* Temp block */
+ data, /* Icon data */
+ data + r2 + 1, /* End of icon data */
+ -1, /* No fonts */
+ name, 0); /* First match */
+ if (r6 == 0)
+ ro_die("\0\0\0\0Can't find window in Templates file");
+
+ /* Create the window */
+
+ if (xswi(Wimp_CreateWindow, 0, window) & v_flag)
+ ro_die( (char *) r0);
+
+ if (title)
+ *title = (char_u *) window[18];
+ if (title_size)
+ *title_size = window[20];
+
+ free(window); /* Free temp block */
+ return r0; /* Return the window handle */
+}
+
+/*
+ * Check if the GUI can be started. Called before gvimrc is sourced.
+ * Return OK or FAIL.
+ */
+ int
+gui_mch_init_check()
+{
+ return OK; /* TODO: GUI can always be started? */
+}
+
+/*
+ * Initialise the RISC OS GUI.
+ * Create all the windows.
+ * Returns OK for success, FAIL when the GUI can't be started.
+ */
+ int
+gui_mch_init()
+{
+ int messages[] = {
+ 1, 2, 3, 4, /* DataSave, DataSaveAck, DataLoad, DataLoadAck */
+ 8, /* PreQuit */
+ 0xf, /* ClaimEntity (for clipboard) */
+ 0x10, /* DataRequest (for clipboard) */
+ 0x400c1, /* Mode change */
+ 0x400c3, /* TaskCloseDown */
+ 0x400c9, /* MenusDeleted */
+ 0x808c1, /* TW_Output */
+ 0x808c2, /* TW_Ego */
+ 0x808c3, /* TW_Morio */
+ 0x808c4, /* TW_Morite */
+ 0}; /* End-of-list. */
+
+
+ /* There may have been some errors reported in the
+ * command window before we get here. Wait if so.
+ */
+ swi(Wimp_ReadSysInfo, 3);
+ if (r0 == 0)
+ swi(Wimp_CommandWindow, 0); /* Window opened - close with prompt */
+
+ if (xswi(Wimp_Initialise, 310, 0x4b534154, "GVim", messages) & v_flag)
+ return FAIL;
+ nested_wimp = r0 >= 397;
+ task_handle = r1;
+
+ /* Load the templates. */
+
+ if (xswi(Wimp_OpenTemplate, 0, "Vim:Templates") & v_flag)
+ ro_die( (char *) r0);
+
+ gui.window_handle = ro_load_template("editor",
+ &gui.window_title,
+ &gui.window_title_size);
+
+ save_window = ro_load_template("save", NULL, NULL);
+
+ swi(Wimp_CloseTemplate);
+
+ /* Set default foreground and background colours. */
+
+ gui.norm_pixel = gui.def_norm_pixel;
+ gui.back_pixel = gui.def_back_pixel;
+
+ /* Get the colours from the "Normal" and "Menu" group (set in syntax.c or
+ * in a vimrc file) */
+
+ set_normal_colors();
+
+ /*
+ * Check that none of the colors are the same as the background color
+ */
+
+ gui_check_colors();
+
+ /* Get the colours for the highlight groups (gui_check_colors() might have
+ * changed them) */
+
+ highlight_gui_started(); /* re-init colours and fonts */
+
+ /* Set geometry based on values read on initialisation. */
+
+ gui.num_cols = Columns = default_columns;
+ gui.num_rows = Rows = default_rows;
+
+ /* Get some information about our environment. */
+
+ ro_measure_tools();
+
+ return OK;
+}
+
+/*
+ * Called when the foreground or background colour has been changed.
+ */
+ void
+gui_mch_new_colors()
+{
+}
+
+/*
+ * Open the GUI window which was created by a call to gui_mch_init().
+ */
+ int
+gui_mch_open(void)
+{
+ int block[10];
+
+ block[0] = gui.window_handle;
+ swi(Wimp_GetWindowState, 0, block);
+ block[7] = -1; /* Open at the top of the stack */
+ swi(Wimp_OpenWindow, 0, block);
+
+ /* Give the new window the input focus */
+ swi(Wimp_SetCaretPosition, gui.window_handle, -1, 0, 0, -1, -1);
+
+ if (gui_win_x != -1 && gui_win_y != -1)
+ gui_mch_set_winpos(gui_win_x, gui_win_y);
+
+ return OK;
+}
+
+ void
+gui_mch_exit(int rc)
+{
+ int block[64];
+
+ /* Close window. Stops us from getting troublesome events
+ * if we take a while to die.
+ */
+ block[0] = gui.window_handle;
+ swi(Wimp_CloseWindow, 0, block);
+
+ if (child_handle)
+ {
+ /* We still have a sub-task running - kill it */
+ block[0] = 20;
+ block[3] = 0;
+ block[4] = 0; /* Quit */
+ if ((xswi(Wimp_SendMessage, 17, block, child_handle) & v_flag) == 0)
+ {
+ /* Idle until child dies. */
+ while (child_handle)
+ {
+ process_event(wimp_poll(1, block), block);
+ }
+ }
+ }
+
+ exit(rc);
+}
+
+/*
+ * Get the position of the top left corner of the window.
+ */
+ int
+gui_mch_get_winpos(int *x, int *y)
+{
+ /* TODO */
+ return FAIL;
+}
+
+/*
+ * Set the position of the top left corner of the window to the given
+ * coordinates.
+ */
+ void
+gui_mch_set_winpos(int x, int y)
+{
+ /* TODO */
+}
+
+ void
+gui_mch_set_shellsize(width, height, min_width, min_height, base_width, base_height)
+ int width; /* In OS units */
+ int height;
+ int min_width; /* Smallest permissable window size (ignored) */
+ int min_height;
+ int base_width; /* Space for scroll bars, etc */
+ int base_height;
+{
+ int s_width, s_height;
+ int block[] = {
+ gui.window_handle,
+ 0,
+ -height + 1,
+ width,
+ 1};
+
+ gui_mch_get_screen_dimensions(&s_width, &s_height);
+ s_width -= base_width;
+ s_height -= base_height; /* Underestimate - ignores titlebar */
+
+ swi(Wimp_GetWindowState, 0, block);
+ block[3] = block[1] + width;
+ block[2] = block[4] - height;
+ if (block[3] > s_width)
+ {
+ block[3] = s_width;
+ block[1] = block[3] - width;
+ }
+ if (block[2] < gui.scrollbar_height)
+ {
+ block[2] = gui.scrollbar_height;
+ block[4] = block[2] + height;
+ }
+ swi(Wimp_OpenWindow, 0, block);
+ swi(Wimp_ForceRedraw, gui.window_handle, 0, -height, width, 0);
+}
+
+ void
+gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
+{
+ int block[] = {4, 5, 11, 12, -1};
+
+ swi(OS_ReadVduVariables, block, block);
+ *screen_w = (block[2] + 1) << block[0];
+ *screen_h = (block[3] + 1) << block[1];
+}
+
+/* Take a font name with options and return a font handle, or
+ * zero for failure.
+ * Replace extension with 'Bold' or 'Italic' depending on modifiers.
+ */
+ int
+ro_get_font(fullname, weight)
+ char_u *fullname;
+ int weight; /* Initial weights:
+ * BIT MEANING
+ * 0 bold
+ * 1 italic
+ */
+{
+ char_u *arg;
+ char_u font[41];
+ int width = -1;
+ int height = -1;
+ int name_len;
+ int i;
+ char_u c;
+
+ for (i = 0; i < 39;)
+ {
+ c = fullname[i];
+ if (c == ':' || c == NUL || c == '.')
+ break;
+ font[i++] = c;
+ }
+
+ /* find the first modifier, NULL if none */
+ arg = strchr(fullname + i, ':');
+
+ while (arg)
+ {
+ switch (*++arg)
+ {
+ case 'h':
+ height = strtol(arg + 1, (char **) &arg, 10);
+ break;
+ case 'w':
+ width = strtol(arg + 1, (char **) &arg, 10);
+ break;
+ case 'b':
+ weight |= 1;
+ break;
+ case 'i':
+ weight |= 2;
+ break;
+ default:
+ return 0;
+ }
+ arg = strchr(arg, ':');
+ }
+
+ if ((weight & 1) && i < 35)
+ {
+ /* Bold goes instead of given suffix */
+ strncpy(font + i, ".Bold", 5);
+ i += 5;
+ }
+ else
+ {
+ /* Copy rest of name unless we are using Bold */
+ while (i < 39)
+ {
+ c = fullname[i];
+ if (c == ':' || c == NUL)
+ break;
+ font[i++] = c;
+ }
+ }
+ if ((weight & 2) && i < 32)
+ {
+ strncpy(font + i, ".Oblique", 8);
+ i += 8;
+ }
+
+ font[i] = 0;
+
+ if (height < 1 && width < 1)
+ height = width = 10; /* Default to 10pt */
+ else if (height < 1)
+ height = width;
+ else if (width < 1)
+ width = height;
+
+ if (xswi(Font_FindFont, 0, font, width << 4, height << 4, 0, 0) & v_flag)
+ return NOFONT; /* Can't find font */
+
+ return r0;
+}
+
+/* Load a file into allocated memory and check it is valid.
+ * Return a pointer to the allocated block on success.
+ */
+ char *
+zap_load_file(name, style)
+ char_u *name; /* Name of directory containing styles */
+ char_u *style; /* Name of style within directory */
+{
+ char_u fname[256];
+ char_u *file;
+
+ if (strlen(name) + strlen(style) > 254)
+ return NULL; /* Names too long */
+
+ sprintf(fname, "%s.%s", name, style);
+
+ /* Load the named font in 1bpp format. */
+ if (xswi(OS_File, 13, fname, 0, 0, "VimFonts:") & v_flag || r0 != 1)
+ return NULL; /* Error reading file info, or not a file */
+
+ /* Allocate enough memory to load the whole file */
+ file = (char *) alloc(r4);
+ if (!file)
+ return NULL; /* Out of memory */
+
+ if (xswi(OS_File, 12, fname, file, 0, "VimFonts:") & v_flag)
+ return NULL; /* Unable to load file */
+
+ if (strncmp(file, "ZapFont\015", 8) == 0)
+ return file; /* Loaded OK! */
+
+ free(file);
+ return NULL; /* Not a valid font file */
+}
+
+/* Load and convert the named font.
+ * If name is NULL or a null string then convert the system font.
+ * Return OK on success; FAIL and we revert to using the VDU drivers.
+ *
+ * 'name' is the name of a directory.
+ * Tries to load 'name.0', 'name.B', 'name.I' and 'name.IB'.
+ */
+ int
+zap_load_font(name)
+ char_u *name;
+{
+ int i;
+
+ /* Free the existing font files, if any */
+ for (i = 0; i < ZAP_STYLES; i++)
+ {
+ vim_free(zap_file[i]);
+ zap_file[i] = NULL;
+ }
+
+ if (name && *name == '!')
+ {
+ name++;
+ double_height = TRUE;
+ }
+ else
+ double_height = FALSE;
+
+ if (name && *name)
+ {
+ zap_file[ZAP_NORMAL] = zap_load_file(name, "0");
+ if (!zap_file[ZAP_NORMAL])
+ return FAIL; /* Can't load the 'normal' style - error */
+
+ zap_file[ZAP_BOLD] = zap_load_file(name, "B");
+ zap_file[ZAP_ITALIC] = zap_load_file(name, "I");
+ zap_file[ZAP_BITALIC] = zap_load_file(name, "IB");
+ }
+ else
+ {
+ int *header;
+ char workarea[16];
+ char *old_wa;
+
+ /* Allocate memory for system font (8 x 8 x 256 bits, plus header) */
+ header = (int *) alloc(0x20 + 8 * 256);
+ if (header == NULL)
+ return FAIL;
+ zap_file[ZAP_NORMAL] = (char *) header;
+
+ /* Store details about the system font */
+ header[2] = 8; /* Width */
+ header[3] = 8; /* Height */
+ header[4] = 0; /* First char */
+ header[5] = 255; /* Last char */
+ header[6] = header[7] = 0; /* Reserved */
+
+ /* Get system font bitmap */
+ old_wa = zap_redraw_block.r_workarea;
+ zap_redraw_block.r_workarea = workarea;
+ swi(ZapRedraw_ReadSystemChars, zap_file[ZAP_NORMAL] + 0x20, &zap_redraw_block);
+ zap_redraw_block.r_workarea = old_wa;
+ }
+
+ return ro_zap_redraw_initialise();
+}
+
+/*
+ * Initialise vim to use the font with the given name.
+ * Return FAIL if the font could not be loaded, OK otherwise.
+ */
+ int
+gui_mch_init_font(char_u *font_name, int fontset)
+{
+ int new_handle = 0; /* Use the system font by default */
+
+ if (font_name[0] == '!')
+ {
+ /* Select a ZapRedraw font */
+ if (zap_load_font(font_name + 1))
+ zap_redraw = TRUE;
+ else
+ {
+ EMSG2(_("E610: Can't load Zap font '%s'"), font_name);
+ font_name = "System"; /* Error - use system font */
+ zap_redraw = FALSE;
+ }
+ }
+ else
+ {
+ zap_redraw = FALSE;
+
+ if (font_name)
+ {
+ /* Extract any extra details about the font */
+ new_handle = ro_get_font(font_name, 0);
+ if (!new_handle)
+ return FAIL;
+ }
+ else
+ font_name = "System";
+ }
+
+ /* Free the previous font, if any */
+ gui_mch_free_font(gui.norm_font);
+ gui.norm_font = new_handle;
+ gui.char_ascent = 0;
+
+ if (new_handle)
+ {
+ /* Read details about the chosen font */
+ swi(Font_ReadInfo, new_handle);
+
+ gui.char_width = r3 - r1;
+ gui.char_height = r4 - r2;
+
+ font_x_offset = -r1; /* Where to position each char in its box */
+ font_y_offset = -r4;
+
+ /* Try to load other fonts for bold, italic, and bold-italic */
+ gui_mch_free_font(gui.bold_font);
+ gui.bold_font = ro_get_font(font_name, 1);
+ gui_mch_free_font(gui.ital_font);
+ gui.ital_font = ro_get_font(font_name, 2);
+ gui_mch_free_font(gui.boldital_font);
+ gui.boldital_font = ro_get_font(font_name, 3);
+ }
+ else
+ {
+ /* Use the system font or ZapRedraw. */
+ if (zap_redraw)
+ {
+ gui.char_width = zap_redraw_block.r_charw << zap_redraw_block.r_magx;
+ gui.char_height = zap_redraw_block.r_charh << zap_redraw_block.r_magy;
+ if (double_height)
+ gui.char_height <<= 1;
+ }
+ else
+ {
+ gui.char_width = 16;
+ gui.char_height = 32;
+ }
+
+ gui_mch_free_font(gui.bold_font);
+ gui.bold_font = 0;
+ gui_mch_free_font(gui.ital_font);
+ gui.ital_font = 0;
+ gui_mch_free_font(gui.boldital_font);
+ gui.boldital_font = 0;
+ }
+ hl_set_font_name(font_name);
+
+ must_redraw = CLEAR;
+ return OK;
+}
+
+ int
+gui_mch_adjust_charsize()
+{
+ return FAIL;
+}
+
+/*
+ * Get a font structure for highlighting.
+ */
+ GuiFont
+gui_mch_get_font(name, giveErrorIfMissing)
+ char_u *name;
+ int giveErrorIfMissing;
+{
+ int handle;
+
+ if (!name)
+ return NOFONT; /* System font if no name */
+
+ handle = ro_get_font(name, 0);
+ if (!handle)
+ {
+ if (giveErrorIfMissing)
+ EMSG2(_("E611: Can't use font %s"), name);
+ return NOFONT;
+ }
+
+ return handle;
+}
+
+/*
+ * Set the current text font.
+ */
+ void
+gui_mch_set_font(GuiFont font)
+{
+ ro_current_font = font;
+
+ if (font)
+ {
+ /* Not the system font or ZapRedraw font - select it */
+ swi(Font_SetFont, font);
+ }
+}
+
+#if 0 /* not used */
+/*
+ * Return TRUE if the two fonts given are equivalent.
+ */
+ int
+gui_mch_same_font(GuiFont f1, GuiFont f2)
+{
+ return f1 == f2;
+}
+#endif
+
+/*
+ * If a font is not going to be used, free its structure.
+ */
+ void
+gui_mch_free_font(GuiFont font)
+{
+ if (font)
+ swi(Font_LoseFont, font);
+}
+
+/*
+ * Return the Pixel value (colour) for the given colour name.
+ * Return INVALCOLOR for error.
+ * NB: I've changed Green for now, since it looked really sick
+ */
+ guicolor_T
+gui_mch_get_color(char_u *name)
+{
+ int i;
+ struct colour
+ {
+ char_u *name;
+ guicolor_T value;
+ } colours[] =
+ {
+ { "Red", grgb(255, 0, 0) },
+ { "LightRed", grgb(255, 0, 0) },
+ { "DarkRed", grgb(139, 0, 0) },
+
+ { "Green", grgb(50, 200, 50) },
+ { "LightGreen", grgb(144, 238, 144) },
+ { "DarkGreen", grgb(0, 100, 0) },
+ { "SeaGreen", grgb(46, 139, 87) },
+
+ { "Blue", grgb(0, 0, 255) },
+ { "LightBlue", grgb(173, 216, 230) },
+ { "DarkBlue", grgb(0, 0, 139) },
+ { "SlateBlue", grgb(160, 90, 205) },
+
+ { "Cyan", grgb(0, 255, 255) },
+ { "LightCyan", grgb(224, 255, 255) },
+ { "DarkCyan", grgb(0, 139, 139) },
+
+ { "Magenta", grgb(255, 0, 255) },
+ { "LightMagenta", grgb(255, 224, 255) },
+ { "DarkMagenta", grgb(139, 0, 139) },
+
+ { "Yellow", grgb(255, 255, 0) },
+ { "LightYellow", grgb(255, 255, 224) },
+ { "DarkYellow", grgb(139, 139, 0) },
+ { "Brown", grgb(165, 42, 42) },
+
+ { "Gray", grgb(190, 190, 190) },
+ { "Grey", grgb(190, 190, 190) },
+ { "LightGray", grgb(211, 211, 211) },
+ { "LightGrey", grgb(211, 211, 211) },
+ { "DarkGray", grgb(169, 169, 169) },
+ { "DarkGrey", grgb(169, 169, 169) },
+
+ { "Black", grgb(0, 0, 0) },
+ { "White", grgb(255, 255, 255) },
+
+ { "Orange", grgb(255, 165, 0) },
+ { "Purple", grgb(160, 32, 240) },
+ { "Violet", grgb(238, 130, 238) },
+ {NULL, 0}
+ };
+
+ if (name[0] == '#')
+ {
+ char *end;
+ int c;
+
+ c = strtol(name + 1, &end, 16);
+ return (guicolor_T) ((c >> 16) & 0xff) | (c & 0xff00) | ((c & 0xff) << 16);
+ }
+
+ for (i = 0; colours[i].name != NULL; i++)
+ {
+ if (STRICMP(name, colours[i].name) == 0)
+ return colours[i].value;
+ }
+ if (strnicmp(name, "grey", 4) == 0 || strnicmp(name, "gray", 4) == 0)
+ {
+ int level = (255 * atoi(name + 4)) / 100;
+ return (guicolor_T) grgb(level, level, level);
+ }
+ return INVALCOLOR;
+}
+
+/*
+ * Set the current text colours.
+ * If we are using fonts then set the antialiasing colours too.
+ */
+ void
+gui_mch_set_colors(guicolor_T fg, guicolor_T bg)
+{
+ zap_redraw_colours[0] = bg << 8; /* JK230798, register new background colour */
+ zap_redraw_colours[1] = fg << 8; /* JK230798, register new foreground colour */
+ zap_redraw_update_colours = TRUE; /* JK230798, need update of colour masks */
+
+ swi(ColourTrans_ReturnGCOL, fg << 8);
+ gui.fg_colour = r0;
+ swi(ColourTrans_ReturnGCOL, bg << 8);
+ gui.bg_colour = r0;
+
+ if (ro_current_font)
+ swi(ColourTrans_SetFontColours, 0, bg << 8, fg << 8, 14);
+}
+
+ void
+ro_draw_string(x, y, s, len, flags, clip)
+ int x; /* Top-left coord to plot at (x incl, y excl) */
+ int y; /* (screen coords) */
+ char_u *s; /* String to plot */
+ int len; /* Length of string */
+ int flags; /* DRAW_TRANSP, DRAW_BOLD, DRAW_UNDERL */
+ int* clip; /* JK230798, added clip window */