/* Copyright 1996 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
  Purpose: provide a menu for simple cosmetic alterations to a Text
           Arthur version.
  Author: WRS
  History:
    25 August 87 -- started
    25-Feb-88: WRS: converted to C, new trace usage.
    02-Mar-88: WRS: dbox form removed.
 *  13-Dec-89: WRS: msgs literal text put back in.
    12-Feb-90: IDJ: added menu entry to set max size of work area
    13-Feb-90: IDJ: limited work area width to 256 chars (you get 'echos' of text
                    appearing if width is much bigger - probably another display bug)
    16-Feb-90: IDJ: changed limit to 192 chars (display bugs start > 196 chars)
    02-Dec-90: IDJ: changed Wrap to Window wrap
    08-Apr-91: PJC: added facility to use new font manager menus
    07-Jun-91: IDJ: no font change when just click on font name
    14-Jun-91: IDJ: changed font menu to what it used to be, and made edit read
                    new fonts every menu open (so we can catch new fonts loaded)
*/

#define BOOL int
#define TRUE 1
#define FALSE 0

#define NewFontMenu TRUE

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "h.txt"
#include "h.os"
#include "h.wimp"
#include "h.wimpt"
#include "h.menu"
#include "h.EditIntern.txtar"
#include "h.dbox"
#include "h.event"
#include "h.EditIntern.txtoptmenu"
#include "h.visdelay"
#include "h.font"
#include "h.trace"
#include "h.werr"
#include "h.colourmenu"
#include "h.msgs"
#include "h.txtwin"
#include "h.verintern.messages"

void txtoptmenu_fontdbox(txt text);

#define MenuDescByteSize sizeof(wimp_menuhdr)
#define MenuItemByteSize sizeof(wimp_menuitem)


#define MFont 1
#define MFontSize 2
#define MFontHeight 3
#define MLeading 4
#define MMargin 5
#define MInvert 6
#define MWrap 7
#define MForeground 8
#define MBackground 9
#ifdef BIG_WINDOWS
#define MWorkArea 10
#endif

static menu tmsize; /* the size menu */
static menu tmheight; /* height menu */
static menu tmleading; /* leading menu */
static menu tmmargin; /* margin menu */
#ifdef BIG_WINDOWS
static menu tmworkarea; /* window width in chars */
#endif
static char leadingbuf[10];
static char marginbuf[10];
#ifdef BIG_WINDOWS
static char widthbuf[10];
#endif

#if NewFontMenu

static wimp_menustr *font_menu = 0;
static char *font_hit = 0;
static int padding3;
static int padding4;

static wimp_menustr* txtoptmenu__fontmenu(void) {
#if FALSE
  if (font_menu == 0) {
#endif

   /* always rebuild the font menu */
   wimpt_complain(font_makemenu(&font_menu, NULL, fontmenu_WithSystemFont));


#if FALSE
  }
#endif
  return(font_menu);
}

#else

static menu font_menu = 0;
static int font_menu_size = 1;
static char **fonts = 0;
static int font_array_size = 0;

static menu txtoptmenu__fontmenu(void) {
  if (font_menu == 0) {
    char a[99];
    int i = 0;

    fonts = malloc(4 * sizeof(*fonts)); /* room for 4 fonts */
    if (fonts == 0) werr(TRUE, msgs_lookup(MSGS_txt52));
    font_array_size = 4;
    font_menu = menu_new(
      msgs_lookup(MSGS_txt53),
      msgs_lookup(MSGS_txt54));
    while (1) {
      font_list(&a[0], &i);
      tracef1("found font '%s'.\n", (int) &a[0]);
      if (i == -1) break;
      if (++font_menu_size >= font_array_size) {
        /* copy the fonts array to one twice the size */
        char **newfonts = malloc(2 * font_array_size * sizeof(*fonts));
        int i;
        if (newfonts == 0) werr(TRUE, msgs_lookup(MSGS_txt52));
        for (i = 0; i < font_array_size; i++) newfonts[i] = fonts[i];
        fonts = newfonts;
        font_array_size = font_array_size * 2;
      };
      fonts[font_menu_size] = malloc(1 + strlen(&a[0]));
      if (fonts[font_menu_size] == 0) werr(TRUE, msgs_lookup(MSGS_txt52));
      strcpy(fonts[font_menu_size], &a[0]);
      menu_extend(font_menu, &a[0]);
    };
  };
  return font_menu;
}
#endif

static int sizes[] = {8, 10, 12, 14, 20};

static void txtoptmenu__setfontmenuflags(txtar_options *current) {
  int i;
#if NewFontMenu
  if (current->fixfont) {
    wimpt_complain(font_makemenu(&font_menu, (char *)1, fontmenu_WithSystemFont));
  } else {
    wimpt_complain(font_makemenu(&font_menu, current->fontname, fontmenu_WithSystemFont));
  }
#else
  menu_setflags(font_menu, 1, current->fixfont, FALSE);
  for (i = 2; i <= font_menu_size; i++) {
    menu_setflags(font_menu, i,
      (!current->fixfont) & (strcmp(current->fontname, fonts[i]) == 0),
      FALSE);
  };
#endif
#if FALSE
  menu_setflags(tmsize, 1, current->fontwidth == 8, FALSE);
  menu_setflags(tmsize, 2, current->fontwidth == 10, FALSE);
  menu_setflags(tmsize, 3, current->fontwidth == 12, FALSE);
  menu_setflags(tmsize, 4, current->fontwidth == 14, FALSE);
  menu_setflags(tmsize, 5, current->fontwidth == 20, FALSE);
#else
  for (i = 1; i <= 5; i++) {
    menu_setflags(tmsize, i, current->fontwidth == sizes[i-1], FALSE);
    menu_setflags(tmheight, i, current->fontheight == sizes[i-1], FALSE);
  };
#endif
}

/* -------- Colour Menu. -------- */

static menu txtoptmenu_makecolourmenu()
{
return colourmenu_make(msgs_lookup(MSGS_txt55), FALSE);
}

/* -------- Entire Menu. -------- */

static menu tm = 0;
static menu tm3;
static menu tm4;

static void txtoptmenu__makevaluemenu(menu m) {
wimp_menuhdr *sizemenu;
wimp_menuitem *sizeitem;

sizemenu = (wimp_menuhdr*) menu_syshandle(m);
sizemenu->width = 160;
  /* fix because of long entry messing things up. */
  /* >>>> change when size-of-system-font becomes available. */
sizeitem = (wimp_menuitem*) (sizemenu+1); /* points at first item. */
sizeitem += 5; /* point at last item. */
sizeitem->data.indirecttext.buffer[0] = 0;
sizeitem->data.indirecttext.validstring = "a0-9";
sizeitem->data.indirecttext.bufflen = 3; /* >>> new, to prevent huge numbers. */
sizeitem->flags |= wimp_MWRITABLE;
sizeitem->iconflags &= ~(wimp_IBTYPE * 0xF); /* clear button type field */
sizeitem->iconflags |= (wimp_IBTYPE * wimp_BWRITABLE); /* and set writable */
}

static void txtoptmenu__makeoriginal(void)
{

#if FALSE
tm = menu_new(
      "Display",
      "Font,Font size,Font height,Line spacing,Margin,Invert,Window wrap,Foreground,Background");
#else
#ifdef BIG_WINDOWS
tm = menu_new(
  msgs_lookup(MSGS_txt62),
  msgs_lookup(MSGS_txt63));
#else
tm = menu_new(
  msgs_lookup(MSGS_txt62),
  msgs_lookup(MSGS_txt63));
#endif
#endif

#ifndef NewFontMenu
menu_submenu(tm, MFont, txtoptmenu__fontmenu());
#endif

#if FALSE
tmsize = menu_new("Font size", "8,10,12,14,20,morethan12chars");
tmheight = menu_new("Font height", "8,10,12,14,20,morethan12chars");
#else
tmsize = menu_new(
  msgs_lookup(MSGS_txt56),
  msgs_lookup(MSGS_txt57));
tmheight = menu_new(
  msgs_lookup(MSGS_txt58),
  msgs_lookup(MSGS_txt59));
#endif

tmleading = menu_new(msgs_lookup(MSGS_txt60), msgs_lookup(MSGS_txt72));
menu_make_writeable(tmleading, 1, leadingbuf, 3, "a0-9\\-");
menu_submenu(tm, MLeading, tmleading);

tmmargin = menu_new(msgs_lookup(MSGS_txt61),msgs_lookup(MSGS_txt72));
menu_make_writeable(tmmargin, 1, marginbuf, 3, "a0-9");
menu_submenu(tm, MMargin, tmmargin);

#ifdef BIG_WINDOWS
tmworkarea = menu_new(msgs_lookup("txt71"), "foofoofoo");
menu_make_writeable(tmworkarea, 1, widthbuf, 4, "a0-9");
menu_submenu(tm, MWorkArea, tmworkarea);
#endif

/* The final option (a writable menu entry) is so large that he's forced
to make it indirect. */
txtoptmenu__makevaluemenu(tmsize);
txtoptmenu__makevaluemenu(tmheight);
menu_submenu(tm, MFontSize, tmsize);
menu_submenu(tm, MFontHeight, tmheight);

tm3 = txtoptmenu_makecolourmenu();
menu_submenu(tm, MForeground, tm3);

tm4 = txtoptmenu_makecolourmenu();
menu_submenu(tm, MBackground, tm4);
}

static void txtoptmenu__setflags(txt t) {
  txtar_options o;
  int i;

  txtar_getoptions(t, &o);
/*  menu_setflags(tm, MFont, ! o.fixfont, FALSE); */
  menu_setflags(tm, MWrap, o.wraptowindow, FALSE);
  for (i = 1; i <= 16; i++) {
    menu_setflags(tm3, i, i - 1 == o.forecolour, FALSE);
    menu_setflags(tm4, i, i - 1 == o.backcolour, FALSE);
  };
  menu_setflags(tm, MFontSize, FALSE, o.fixfont);
  menu_setflags(tm, MFontHeight, FALSE, o.fixfont);
  txtoptmenu__setfontmenuflags(&o);
  sprintf(leadingbuf, "%i", o.leading);
  sprintf(marginbuf, "%i", o.margin);
#ifdef BIG_WINDOWS
  menu_setflags(tm, MWorkArea, o.big_windows, FALSE);
  sprintf(widthbuf, "%i", o.big_window_size);
#endif
}

static int getint(char *a, int dft) {
  int n = 0;
  while (1) {
    int ch = *a++;
    tracef1("found char %i.\n", ch);
    if (ch == 0) return n;
    if (ch >= '0' && ch <= '9') {
      n = n * 10 + ch - '0';
    } else {
      return dft;
    };
  };
}

static int txtoptmenu__fontmenuvalue(menu m, int item, int dft) {
  wimp_menuhdr *sizemenu;
  wimp_menuitem *sizeitem;

  switch (item) {
    default: return dft;
    case 1: return 8;
    case 2: return 10;
    case 3: return 12;
    case 4: return 14;
    case 5: return 20;
    case 6:
      tracef0("writable font size menu entry.\n");
      sizemenu = (wimp_menuhdr*) menu_syshandle(m);
      sizeitem = (wimp_menuitem*) (sizemenu+1); /* points at first item. */
      sizeitem += 5; /* point at last item. */
    return getint(sizeitem->data.indirecttext.buffer, dft);
  };
}

menu txtoptmenu_make(txt t) {
  if (tm == 0) txtoptmenu__makeoriginal();
#if NewFontMenu
 /* need to "magic" the font menu into the structure */
 { wimp_menuhdr *foo = (wimp_menuhdr*) menu_syshandle(tm);
   wimp_menuitem *item = (wimp_menuitem*) (foo+1);

   item += MFont-1;
   item->submenu = txtoptmenu__fontmenu();
 }
#endif
  txtoptmenu__setflags(t);
  return tm;
}

void txtoptmenu_eventproc(txt t, char *s)
{

txtar_options o;
unsigned i;

if (s[0] == 0) {
  /* do nothing */
} else {
  txtar_getoptions(t, &o);

  if (s[0] == MFont) {
#if FALSE
    o.fixfont = FALSE;
    if (s[1] == 0) {
      /* He just clicked "font": go back to last one. */
    } else {
    }
#else
    if (s[1] == 1) {
      o.fixfont = TRUE;
    } else if (s[1] > 1) {
#if NewFontMenu
      /* we can't just copy the string 'cos it isn't linear any more */
      /* need to translate RISC_OSLib menu hits back into wimp menu hits */
      /* this is done by copying the chars back into ints, decrementing as we go */
      int selection[20];
      int i = 0;
      do {
       i++;
       selection[i-1] = s[i] - 1;
      } while (s[i] != 0);
      /* now get the string */
      wimpt_complain(font_decodemenu(font_menu, selection, &font_hit));
      o.fixfont = FALSE;
      strcpy(o.fontname, font_hit);
#else
      o.fixfont = FALSE;
      strcpy(o.fontname, fonts[s[1]]);
#endif
    };
    o.leading = 0; /* zeroed on any font change. */
#endif
  } else if (s[0] == MFontSize) {
    o.fixfont = FALSE;
    o.fontwidth = txtoptmenu__fontmenuvalue(tmsize, s[1], o.fontwidth);
    o.fontheight = o.fontwidth;
  } else if (s[0] == MFontHeight) {
    o.fixfont = FALSE;
    o.fontheight = txtoptmenu__fontmenuvalue(tmheight, s[1], o.fontheight);
  } else if (s[0] == MLeading) {
    if (leadingbuf[0] == '-') {
      o.leading = - getint(&leadingbuf[1], 0);
    } else {
      o.leading = getint(leadingbuf, 0);
    };
  } else if (s[0] == MMargin) {
    o.margin = getint(marginbuf, 0);
#ifdef BIG_WINDOWS
  } else if (s[0] == MWorkArea) {
    txtwin_setcurrentwindow(t);
    if (s[1] == 0)
      o.big_windows = !o.big_windows;
    else
    { int i = getint(widthbuf, 0);
      if (i <= 0)
         i = 1;
      else if (i >= 192)
         i = 192;
      o.big_windows = TRUE;
      o.big_window_size = i;
    }
#endif
  } else if (s[0] == MWrap) /* invert wrap bit */
     o.wraptowindow = !o.wraptowindow;

  else if (s[0] == MInvert) /* swap fore and back */

          {
          i = o.forecolour;
          o.forecolour = o.backcolour;
          o.backcolour = i;
          }

  else { /* foreground, background. */
#if FALSE
    o.fixfont = TRUE;
#endif
    if (s[1] == 0)  /* he just clicked in main menu */
      ;    /* colours are fine */
    else if (s[0] == MForeground) {
      o.forecolour = s[1] - 1;
    } else if (s[0] == MBackground) {
      o.backcolour = s[1] - 1;
    };
  };

  txtar_setoptions(t, &o);

  }
}

/* If he's displaying in a font, he can go direct to the foreground colour
menu to set black-on-white or white-on-black. */

void txtoptmenu_init(void) {
  (void) txtoptmenu__fontmenu(); /* create the font menu */
}

/* end */