/* 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.
 */
/*
 * Title: txt.c
 * Purpose: Text display object.
 * Author: WRS
 * History:
 *   16 July 87 -- started
 *   30-Nov-87: WRS: converted into C.
 *   02-Mar-88: WRS: convertion complete.
 *   08-May-91: ECN: #ifndefed out unused ROM functions
 */

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

#include <stdlib.h>
#include <stdarg.h>
#include "h.txt"
#include "h.EditIntern.txtundo"
#include "h.EditIntern.txt1"
#include "h.EditIntern.txt3"
#include "h.EditIntern.txtar"
#include "h.werr"
#include "h.trace"

/* The type txt__str is actually provided by module txt1 */
/* ----------------------------------------------------- */

/* Module Structure of text implementation:
   =======================================
There are three key modules. There are recursive dependencies so that
the Texts module itself does not betray its implementation.

txt:    does the lock grabbing (if necessary), then calls txt1
        (buffer manipulation) or procedures installed by the window
        implementation (probably txt2).
        System-independent, uncontrovertial.
        h.txt is the only public part of this whole thing.
txt1:   the horrid but system-independent buffer manipulation
        and display calls.
        h.txt1 also has the main internal data structures declared.
        calls window procedures for system-dependent display primitives.
txt2:   the system-dependent stuff, installs window procedures in the
        text object. Other implementations are possible.
        Calls txt1 for editing operations provoked by user events.

*/
txt txt_new(char *title)
{
  txt t;

  t = malloc(sizeof(txt1_str));
  if (t == 0) {
    tracef0("txt_new fails.\n");
    return 0;
  };
  t->oaction = txt_EXTEND;
  t->charoptionset = txt_DISPLAY + txt_CARET;
  if (! txt1_inittextbuffer(t)) {
    free(t);
    return 0;
  };
  t->inbufhead = 0;
  t->inbuftail = 0;
  t->eventproc = (txt_event_proc) 0;
  t->eventprochandle = 0;
  t->eventnest = 0;
  t->disposepending = FALSE;
  txt3_inittxt(t); /* cannot fail. */
  if (! txtar_initwindow(t, title)) {
    txt1_disposetextbuffer(t);
    free(t);
    return 0;
  };
  t->undostate = txtundo_new();
  if (t->undostate == 0) {
    txt3_disposeallwindows(t);
    txt1_disposetextbuffer(t);
    free(t);
    return 0;
  };
  return t;
}

void txt_show(txt t)
{
  while (txt3_foreachwindow(t)) {
    t->w->doshow(t);
  }
}

void txt_hide(txt t)
{
  while (txt3_foreachwindow(t)) {
    t->w->dohide(t);
  }
}

void txt_settitle(txt t, char* title)
{
  while (txt3_foreachwindow(t)) {
    t->w->dosettitle(t, title);
  }
}

void txt_dispose(txt *t)
{
  if ((*t)->eventnest == 0) {
    txt1_disposetextbuffer(*t);
    txt3_disposeallwindows(*t);
    txtundo_dispose(&((*t)->undostate));
    free(*t);
  } else {
    (*t)->disposepending = TRUE;
  };
}

/* -------- General control operations. -------- */

#ifndef UROM
int txt_bufsize(txt t)
{
  return txt1_dobufsize(t);
}
#endif

#ifndef UROM
BOOL txt_setbufsize(txt t, int size)
{
  return txt1_dosetbufsize(t, size);
}
#endif

#if FALSE
txt_overflowaction txt_oaction(txt t)
{
  return txt1_dooaction(t);
}

void txt_setoaction(txt t, txt_overflowaction o)
{
  txt1_dosetoaction(t, o);
}
#endif

txt_charoption txt_charoptions(txt t)
{
  return t->charoptionset;
}

void txt_setcharoptions(txt t, txt_charoption affect, txt_charoption values)
{
  txt1_dosetcharoptions(t, affect, values);
}

void txt_setdisplayok(txt t) {
  txt1_dosetdisplayok(t);
}

int txt_lastref(txt t)
{
  return t->last_ref;
}

void txt_setlastref(txt t, int newvalue)
{
  t->last_ref = newvalue;
}

/* -------- Operations on the array of characters. -------- */

txt_index txt_dot(txt t)
{
  return txt1_dodot(t);
}

txt_index txt_size(txt t) /* max value that dot can take */
{
  return txt1_dosize(t);
}

void txt_setdot(txt t, txt_index i)
{
  txt1_dosetdot(t, i);
}

void txt_movedot(txt t, int by)
{
  txt1_domovedot(t, by);
}

void txt_insertchar(txt t, char c)
{
  txt1_doinsertchar(t, c);
}

void txt_insertstring(txt t, char* s)
{
  txt1_doinsertstring(t, s);
}

void txt_delete(txt t, int n)
{
  txt1_dodelete(t, n);
}

void txt_replacechars(txt t, int ntodelete, char* chars, int n)
{
  txt1_doreplacechars(t, ntodelete, chars, n);
}

char txt_charatdot(txt t)
{
  return txt1_docharatdot(t);
}

char txt_charat(txt t, txt_index i)
{
  return txt1_docharat(t, i);
}

#ifndef UROM
void txt_charsatdot(txt t, char/*out*/ *buffer, int /*inout*/ *n)
{
  txt1_docharsatdot(t, buffer, n);
}
#endif

void txt_replaceatend(txt t, int ntodelete, char *buffer, int n)
{
  txt1_doreplaceatend(t, ntodelete, buffer, n);
}

/* -------- Layout-dependent Operations. -------- */

void txt_movevertical(txt t, int by, int caretstill)
{
  txt1_domovevertical(t, by, caretstill);
}

void txt_movehorizontal(txt t, int by)
{
  txt1_domovehorizontal(t, by);
}

int txt_visiblelinecount(txt t)
{
  return t->w->dovisiblelinecount(t);
}

#ifndef UROM
int txt_visiblecolcount(txt t)
{
  return t->w->dovisiblecolcount(t);
}
#endif

/* -------- Operations on Markers. -------- */

void txt_newmarker(txt t, txt_marker* m)
{
  txt1_donewmarker(t, (txt1_imarker*) m);
}

void txt_movemarker(txt t, txt_marker* m, txt_index to)
{
  txt1_domovemarker(t, (txt1_imarker*) m, to);
}

void txt_movedottomarker(txt t, txt_marker* m)
{
  txt1_domovedottomarker(t, (txt1_imarker*) m);
}

txt_index txt_indexofmarker(txt t, txt_marker* m)
{
  return txt1_doindexofmarker(t, (txt1_imarker*) m);
}

void txt_disposemarker(txt t, txt_marker* m)
{
  txt1_dodisposemarker(t, (txt1_imarker*) m);
}

/* -------- Operations on the selection. -------- */

BOOL txt_selectset(txt t)
{
  return txt1_doselectset(t);
}

txt_index txt_selectstart(txt t)
{
  return txt1_doselectstart(t);
}

txt_index txt_selectend(txt t)
{
  return txt1_doselectend(t);
}

void txt_setselect(txt t, txt_index start, txt_index end)
{
  txt1_dosetselect(t, start, end);
}

/* -------- Input from the user -------- */

txt_eventcode txt_get(txt t)
{
  return t->w->doget(t);
}

#ifndef UROM
int txt_queue(txt t)
{
  return t->w->doqueue(t);
}
#endif

void txt_unget(txt t, txt_eventcode code)
{
  t->w->dounget(t, code);
}

void txt_eventhandler(txt t, txt_event_proc e, void* handle)
{
  t->eventproc = e;
  t->eventprochandle = handle;
}

void txt_readeventhandler(txt t, txt_event_proc *proc, void **handle)
{
  *proc = t->eventproc;
  *handle = t->eventprochandle;
}

/* -------- Direct Access to the array of characters. -------- */

void txt_arrayseg(txt t, txt_index at, char **a, int *n)
{
  txt1_doarraysegment(t, at, a, n);
}

/* -------- System hook. -------- */

int txt_syshandle(txt t)
{
  return t->w->dosyshandle(t);
}

void txt_init(void)
{
  return;   /* @@@ Do nothing for the moment (maybe one day) */
}

/* -------- STUBS FOR M2. -------- */

#if FALSE
/* -------- Modula-2 equivalents. -------- */

txt Texts_New(char *title);

void Texts_Show(txt t);
void Texts_Hide(txt t);

void Texts_SetTitle(txt t, char* title);

void Texts_Dispose(txt *t);

/* -------- General control operations. -------- */

int Texts_BufSize(txt t);

int Texts_SetBufSize(txt t, int s);

txt_overflowaction Texts_OAction(txt);
void Texts_SetOAction(txt t, txt_overflowaction);

txt_charoption Texts_CharOptions(txt);
void Texts_SetCharOptions(txt t, txt_charoption affect, txt_charoption values);

/* -------- Operations on the array of characters. -------- */

txt_index Texts_Dot(txt);
txt_index Texts_Size(txt); /* max value that dot can take */
void Texts_SetDot(txt t, txt_index);
void Texts_MoveDot(txt t, int by);

void Texts_InsertChar(txt t, char);
void Texts_InsertString(txt t, char*);

void Texts_Delete(txt t, int);

void Texts_ReplaceChars(txt t, int ntodelete, char*, int n);

char Texts_CharAtDot(txt);
char Texts_CharAt(txt t, txt_index);
void Texts_CharsAtDot(txt t, char*/*out*/ buffer, int* /*inout*/ n);

/* -------- Layout-dependent Operations. -------- */

void Texts_MoveVertical(txt t, int by, int caretstill);

void Texts_MoveHorizontal(txt t, int by);

int Texts_VisibleLineCount(txt);

int Texts_VisibleColCount(txt);

/* -------- Operations on Markers. -------- */

void Texts_NewMarker(txt t, txt_marker*);

void Texts_MoveMarker(txt t, txt_marker*, txt_index to);

void Texts_MoveDotToMarker(txt t, txt_marker*);

txt_index Texts_IndexOfMarker(txt t, txt_marker*);

void Texts_DisposeMarker(txt t, txt_marker*);

/* -------- Operations on the selection. -------- */

int Texts_SelectSet(txt); /* returns 1 or 0 */
txt_index Texts_SelectStart(txt);
txt_index Texts_SelectEnd(txt);
void Texts_SetSelect(txt t, txt_index start, txt_index end);

/* -------- Input from the user -------- */

txt_eventcode Texts_Get(txt);

int Texts_Queue(txt);

void Texts_EventHandler(txt t, void(e)(txt,void*), void*);

/* -------- Direct Access to the array of characters. -------- */

void Texts_ArraySegment(txt t, txt_index at, char **a, int *n);

/* -------- System hook. -------- */

int Texts_SysHandle(txt);

/* end */


/*************************************/

txt txt_new(char *title)
{
  return(Texts_New(title));
}

void txt_show(txt t)
{
  Texts_Show(t);
}

void txt_hide(txt t)
{
  Texts_Hide(t);
}

void txt_settitle(txt t, char* title)
{
  Texts_SetTitle(t, title);
}

void txt_dispose(txt *t)
{
  Texts_Dispose(t);
}

/* -------- General control operations. -------- */

int txt_bufsize(txt t)
{
  return Texts_BufSize(t);
}

int txt_setbufsize(txt t, int size)
{
  return Texts_SetBufSize(t, size);
}

txt_overflowaction txt_oaction(txt t)
{
  return Texts_OAction(t);
}
void txt_setoaction(txt t, txt_overflowaction o)
{
  Texts_SetOAction(t, o);
}

txt_charoption txt_charoptions(txt t)
{
  return Texts_CharOptions(t);
}
void txt_setcharoptions(txt t, txt_charoption affect, txt_charoption values)
{
  Texts_SetCharOptions(t, affect, values);
}

/* -------- Operations on the array of characters. -------- */

txt_index txt_dot(txt t)
{
  return Texts_Dot(t);
}
txt_index txt_size(txt t) /* max value that dot can take */
{
  return Texts_Size(t);
}
void txt_setdot(txt t, txt_index i)
{
  Texts_SetDot(t, i);
}
void txt_movedot(txt t, int by)
{
  Texts_MoveDot(t, by);
}

void txt_insertchar(txt t, char c)
{
  Texts_InsertChar(t, c);
}
void txt_insertstring(txt t, char* s)
{
  Texts_InsertString(t, s);
}

void txt_delete(txt t, int n)
{
  Texts_Delete(t, n);
}

void txt_replacechars(txt t, int ntodelete, char* chars, int n)
{
  Texts_ReplaceChars(t, ntodelete, chars, n);
}

char txt_charatdot(txt t)
{
  return Texts_CharAtDot(t);
}
char txt_charat(txt t, txt_index i)
{
  return Texts_CharAt(t, i);
}
void txt_charsatdot(txt t, char/*out*/ *buffer, int /*inout*/ *n)
{
  Texts_CharsAtDot(t, buffer, n);
}

/* -------- Layout-dependent Operations. -------- */

void txt_movevertical(txt t, int by, int caretstill)
{
  Texts_MoveVertical(t,  by, caretstill);
}

void txt_movehorizontal(txt t, int by)
{
  Texts_MoveHorizontal(t, by);
}

int txt_visiblelinecount(txt t)
{
  return Texts_VisibleLineCount(t);
}

int txt_visiblecolcount(txt t)
{
  return Texts_VisibleColCount(t);
}

/* -------- Operations on Markers. -------- */

void txt_newmarker(txt t, txt_marker* m)
{
  Texts_NewMarker(t, m);
}

void txt_movemarker(txt t, txt_marker* m, txt_index to)
{
  Texts_MoveMarker(t, m, to);
}

void txt_movedottomarker(txt t, txt_marker* m)
{
  Texts_MoveDotToMarker(t, m);
}

txt_index txt_indexofmarker(txt t, txt_marker* m)
{
  return Texts_IndexOfMarker(t, m);
}

void txt_disposemarker(txt t, txt_marker* m)
{
  Texts_DisposeMarker(t, m);
}

/* -------- Operations on the selection. -------- */

int txt_selectset(txt t) /* returns 1 or 0 */
{
  return Texts_SelectSet(t);
}

txt_index txt_selectstart(txt t)
{
  return Texts_SelectStart(t);
}
txt_index txt_selectend(txt t)
{
  return Texts_SelectEnd(t);
}
void txt_setselect(txt t, txt_index start, txt_index end)
{
  Texts_SetSelect(t, start, end);
}

/* -------- Input from the user -------- */

txt_eventcode txt_get(txt t)
{
  return Texts_Get(t);
}

int txt_queue(txt t)
{
  return Texts_Queue(t);
}

void txt_eventhandler(txt t, void(e)(txt,void*), void* handle)
{
  Texts_EventHandler(t, e, handle);
}

/* -------- Direct Access to the array of characters. -------- */

void txt_arrayseg(txt t, txt_index at, char **a, int *n)
{
  Texts_ArraySegment(t, at, a, n);
}

/* -------- System hook. -------- */

int txt_syshandle(txt t)
{
  return Texts_SysHandle(t);
}


#endif
/* end */