Commit 99904b10 authored by Robert Sprowson's avatar Robert Sprowson
Browse files

Switch from ArcEdit style model to clipboard cut & paste model

The txt library part of RISC_OSLib was essentially contrary to everything Acorn was telling its developers, to use the global clipboard.
Additionally, support is added for swap case within a selection.
txt.h:
 Add a new charoption type 'txt_READONLY' to inform txt that the buffer is notionally read only, this is used to supress 'Paste' in the selection menu when appropriate.
 Correct some typos in the comments.
txt1.h:
 Kill off modula 2 dummy structure member.
txtar.h:
 Remove unused function export.
txtfile.h:
 Rename basicimport to be consistent with the text version of the same function. We use 'import' to denote RAM transfers and 'insert' to denote file/scrap transfers throughout.
txtmisc.h:
 Redundant internal functions removed.
txtundo.h:
 Add a new undo operation type 't' for swap case, to avoid polluting the undo buffer with an entire copy of the text where only the case changed.
 Kill off modula 2 double pointer requirement.
txtedit.h:
 Unused structure member 'selectctl' removed.
txt.c:
 Kill off modula 2 double pointer requirement.
txtar.c:
 Refactor message despatch with a switch statement so the save/load/open operations are explicitly checked for, in case the application enables other messages.
txtedit.c:
 Adopt MOVERWRITE, been enabled since 1988 so is probably good to keep.
 Dynamically generate the Select menu by first sending a clipboard request, and fading Paste if no reply comes back.
 Implement changed mouse selection logic.
 Implement different hotkeys and caret navigation.
 Implement copy and paste/replace operations.
 Implement swap case operation.
txtfile.c:
 Type corrections and function rename admin.
 Implement copy and paste/replace operation for detokenised BASIC.
txtmisc.c:
 Supporting functions for clipboard added, supporting functions for ArcEdit removed.
txtscrap.c:
 Make sure the caret is visible for programmatical zero sized selections.
txtundo.c:
 Allow suspension of undo during known complex operations, such as import via RAM transmit. This was a longstanding bug where the import buffer was grabbed in ~4k chunks (even if only 1 byte was being transferred) which in turn resulted in a +4000 undo insertion and a -3999 removal, which given the default undo buffer is only 5k would result in it failing the reversibility test, so no undo was possible.
 Now, during a RAM transmit undo is suspended until the total transfer size is known, and only that data is placed in the undo buffer (subject to the same 5k reversibility limit).
 Add new undo type 't' for swap case operation.
rlibdata.s:
 4 new ints and 1 new BOOL, so RlibSpace increases by 5.

Version 5.85. Tagged as 'RISC_OSLib-5_85'
......@@ -11,13 +11,13 @@
GBLS Module_HelpVersion
GBLS Module_ComponentName
GBLS Module_ComponentPath
Module_MajorVersion SETS "5.84"
Module_Version SETA 584
Module_MajorVersion SETS "5.85"
Module_Version SETA 585
Module_MinorVersion SETS ""
Module_Date SETS "03 Apr 2015"
Module_ApplicationDate SETS "03-Apr-15"
Module_ComponentName SETS "RISC_OSLib"
Module_ComponentPath SETS "castle/RiscOS/Sources/Lib/RISC_OSLib"
Module_FullVersion SETS "5.84"
Module_HelpVersion SETS "5.84 (03 Apr 2015)"
Module_FullVersion SETS "5.85"
Module_HelpVersion SETS "5.85 (03 Apr 2015)"
END
/* (5.84)
/* (5.85)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 5.84
#define Module_MajorVersion_CMHG 5.85
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 03 Apr 2015
#define Module_MajorVersion "5.84"
#define Module_Version 584
#define Module_MajorVersion "5.85"
#define Module_Version 585
#define Module_MinorVersion ""
#define Module_Date "03 Apr 2015"
......@@ -18,6 +18,6 @@
#define Module_ComponentName "RISC_OSLib"
#define Module_ComponentPath "castle/RiscOS/Sources/Lib/RISC_OSLib"
#define Module_FullVersion "5.84"
#define Module_HelpVersion "5.84 (03 Apr 2015)"
#define Module_LibraryVersionInfo "5:84"
#define Module_FullVersion "5.85"
#define Module_HelpVersion "5.85 (03 Apr 2015)"
#define Module_LibraryVersionInfo "5:85"
......@@ -191,8 +191,6 @@ typedef struct txt1_window {
typedef struct txt1_str { /* the overall state object for a text */
int dud; /* >>>> for M2 compatibility */
/* The main character array */
char *buf; /* the character buffer */
txt1_bufindex top; /* no of chars in buffer - 1 */
......
......@@ -40,9 +40,6 @@ space. */
/* Some of these are not too Arthur-specific. The general format should be
followed by the matching interface for other systems. */
void txtar_movetoback(txt);
/* Functionality of the move-to-back mouse button. Gives away the cursor. */
void txtar_clone_current_window(txt t);
/* The current primary window on t is a txtar one. Clone it, using the
txt3 facilities, resulting in two windows. They should divide up between
......
......@@ -37,11 +37,11 @@ int txtfile_saverange(txt t, char *filename, typdat ty, txt_index from, txt_inde
/* Save the given range of text, using the given type/date stamp. */
#if BASIC
BOOL txtfile_dobasicimport(txtedit_state *s, int estsize, int detokenise, BOOL strip);
BOOL txtfile_basicimport(txtedit_state *s, BOOL insrep, int detokenise, BOOL strip);
/* import some BASIC into the txt. */
BOOL txtfile_basicinsert(txt t, char *filename, int l, typdat *ty, int detokenise, BOOL strip);
/* import a BASIC file into the txt. */
/* insert a BASIC file into the txt. */
BOOL txtfile_basicsenderproc(txt t, int *maxbuf, txt_index from, txt_index to, int tokenise, int increment);
/* export some BASIC from the txt. */
......
......@@ -14,7 +14,7 @@
*/
/* -> h.txtmisc
* Title: txtmisc.h
* Purpose: Search text for string.
* Purpose: Various facilities.
* Author: AFP
* Status: system-independent
* Requires:
......@@ -92,25 +92,6 @@ void txtmisc_selectpointandline(txt t, txt_index point, txt_index line);
void txtmisc_select3(txt t, txt_index a1, txt_index a2, txt_index a3);
/* Set the selection to contain all of a1-a3. */
/* -------- Operations on Selections -------- */
void txtmisc_clearselection(void);
/* Clear any selection. */
void txtmisc_deleteselection(int parawidth);
void txtmisc_moveselection(txt t, int parawidthsrc, int parawidthdst);
/* The selection is copied to the caret, then deleted at the source. The new
version is now the selection. t contains the Caret, a shared location is used
for the selection. */
void txtmisc_copyselection(txt t, int parawidth);
/* The selection is copied to the caret. The old version is still the
selection. */
int txtmisc_textinsertfromflexistore(txt t, flex_ptr anchor, unsigned n);
/* Return FALSE, with situation unchanged, if out of store. */
/* --------- Wordwrap ------------------------ */
#if WORDWRAP
......
......@@ -37,11 +37,18 @@ void txtundo_separate_major_edits(txt);
units that the user understands, rather than single moves, deletes and
inserts. Adjacent separators, without intermediate edits, will be ignored. */
void txtundo_prevent_undo(txt);
void txtundo_purge_undo(txt);
/* Prevent undoing from going back beyond this point. This is useful if
the text object has been edited by direct access to txt_arraysegment, or if
for any other reason going back beyond this point is not reasonable. */
BOOL txtundo_suspend_undo(txt, BOOL);
/* Temporarily suspend (or resume) puts into the undo buffer. This is useful if
lots of edits are being implicitly being made by calling txt's internal routines
to achieve some overall much more simply expressed edit. The more simple
version can then be inserted manually rather than polluting the undo buffer
with all the intermediate steps. */
typedef enum {
txtundo_MINOR, /* successfully reversed a move/copy/delete */
txtundo_MAJOR, /* encountered a major edit separator */
......@@ -53,12 +60,12 @@ void txtundo_init(txt);
/* Prepare to start a sequence of undo operations. */
txtundo_result txtundo_undo(txt);
/* undo the last insert, move or delete operation. If successful the inverse
operation will be invoked on the text, further adding to the undo buffer. A
pointer to "current position" within the undo buffer is maintained, so that
subsequent calls to undo go further back into history. The pointer is reset
by a call to txtundo_init. No other edits to the text should occur between a
txtundo_init and subsequent undo/redo calls. */
/* undo the last insert, delete, select or move operation. If successful the
inverse operation will be invoked on the text, further adding to the undo
buffer. A pointer to "current position" within the undo buffer is maintained,
so that subsequent calls to undo go further back into history. The pointer is
reset by a call to txtundo_init. No other edits to the text should occur
between a txtundo_init and subsequent undo/redo calls. */
txtundo_result txtundo_redo(txt);
/* Redo an operation caused by undo. The result concerns the operation that
......@@ -85,8 +92,7 @@ typedef struct txtundo__state *txtundo; /* abstract undo buffer state. */
txtundo txtundo_new(void); /* with small undo buffer. Will return
0 if not enough store. */
void txtundo_dispose(txtundo*);
/* >>>> The extra * is for M2-compatibility: it will change. */
void txtundo_dispose(txtundo);
void txtundo_putbytes(txtundo, char*, int);
void txtundo_putnumber(txtundo, int);
......@@ -106,6 +112,8 @@ void txtundo_putcode(txtundo, char);
putnumber index-of-old-start-of-selection
putnumber index-of-old-end-of-selection
putcode 'l'
when toggling the case of the selection:
putcode 't'
This can be done without regard for overflow etc.
Calling txtundo_putcode when not nested within any undo op on that
......
......@@ -122,7 +122,7 @@ void txt_dispose(txt *t)
if ((*t)->eventnest == 0) {
txt1_disposetextbuffer(*t);
txt3_disposeallwindows(*t);
txtundo_dispose(&((*t)->undostate));
txtundo_dispose((*t)->undostate);
free(*t);
} else {
(*t)->disposepending = TRUE;
......
......@@ -1961,7 +1961,6 @@ static void txtar__performredraw(txt t)
#if FALSE
static msgref = 1;
#endif
void txtar_movetoback(txt t)
{
......@@ -1973,6 +1972,7 @@ void txtar_movetoback(txt t)
wimpt_noerr(wimp_open_wind(&state.o));
win_give_away_caret();
}
#endif
#define DELAY_BEFORE_HOURGLASS 200
......@@ -2097,15 +2097,18 @@ static void txtar__textwimpevent(wimp_eventstr *e, void *handle)
case wimp_ESEND:
case wimp_ESENDWANTACK:
{
char *name; /* dud */
int estsize; /* dud */
if (xferrecv_checkinsert(&name) != -1
|| xferrecv_checkimport(&estsize) != -1) {
txtar__docharevent(t, txt_EXTRACODE + akbd_Sh + akbd_Fn + 2);
} else if (e->data.msg.hdr.action == wimp_MHELPREQUEST) {
txtar__docharevent(t, txt_EXTRACODE + akbd_Fn + 1);
} else {
tracef0("strange wimp message arrived at txtar, ignored.\n");
switch (e->data.msg.hdr.action) {
case wimp_MDATASAVE:
case wimp_MDATALOAD:
case wimp_MDATAOPEN:
txtar__docharevent(t, txt_EXTRACODE + akbd_Fn + akbd_Sh + 2);
break;
case wimp_MHELPREQUEST:
txtar__docharevent(t, txt_EXTRACODE + akbd_Fn + 1);
break;
default:
tracef0("strange wimp message arrived at txtar, ignored.\n");
break;
};
};
break;
......@@ -2268,7 +2271,9 @@ static void txtar__doopenevent(txt t, wimp_openstr *o /*in*/)
txtar__sysdata *s = (txtar__sysdata*) t->w->syshandle;
BOOL sizechange;
BOOL move;
#if FALSE
BOOL wasfull = (s->d->info.flags & wimp_WFULL) != 0;
#endif
tracef4("open event: to (%i,%i,%i,%i).\n",
o->box.x0, o->box.y0, o->box.x1, o->box.y1);
......@@ -2748,7 +2753,7 @@ BOOL txtar_initwindow(txt t, char *title)
er = wimp_create_wind(&s->d->info, &s->w);
if (er != 0) {
tracef0("create window failed.\n");
werr(FALSE, &er->errmess[0]);
werr(FALSE, er->errmess);
free(s->d);
free(s);
return FALSE;
......
......@@ -79,22 +79,16 @@
#define PRINT 1
/* 29-Apr-91: IDJ: support for printing */
#define BASIC 1
/* 7-Mar-91: PJC: support for BASIC files wanted */
#define OVERWRITE 1
/* 17-Nov-88: WRS: Overwrite feature - late spec extension. */
#define MOVERWRITE 1
/* 29-Nov-88: WRS: overwrite is on menu tree - no. */
#define FMTTEXT1 1
/* 17-Nov-88: WRS: late spec change - set width of format-text causes
an actual format operation. */
/* User Guide wording does not actually preclude this change: so, in it goes. */
#define TAB1 1
/* 17-Nov-88: WRS: late spec change - tab by columns-of-8, user-settable. */
/* WORDWRAP definition moved to h.EditIntern.txtmisc by NRaine */
#define EDIT2 1
/* 05-Jan-89 WRS: beyond 1.00: wordwrap, tab col, overwrite modes */
#define NEWDELETE 1
......@@ -122,6 +116,7 @@ an actual format operation. */
#include "EditIntern/txtfind.h"
#include "EditIntern/txtmisc.h"
#include "EditIntern/txtundo.h"
#include "EditIntern/txt1.h"
#include "EditIntern/txtar.h" /* >>>> because of TextOptMen, Options */
#include "dboxquery.h"
#include "dboxfile.h"
......@@ -148,8 +143,10 @@ an actual format operation. */
txtedit_state *txtedit_newwithoptions(char *filename, int desired_filetype, txtar_options *o);
void txtedit_splitwindow(void *v);
void txtedit_swapcase(txt);
void txtedit__undomajor(txtedit_state *s);
static void txtedit_deleteselection(void);
static void txtedit_clearselection(txt);
#define txtedit_AMax 20
......@@ -201,18 +198,24 @@ void txtedit__undomajor(txtedit_state *s);
#if PRINT
#define txtedit_MSelSave 1
#define txtedit_MSelPrint 2
#define txtedit_MSelCopy 3
#define txtedit_MSelMove 4
#define txtedit_MSelDelete 5
#define txtedit_MSelClear 6
#define txtedit_MSelIndent 7
#define txtedit_MSelSwapCase 3
#define txtedit_MSelIndent 4
#define txtedit_MSelCut 5
#define txtedit_MSelCopy 6
#define txtedit_MSelPaste 7
#define txtedit_MSelDelete 8
#define txtedit_MSelSelAll 9
#define txtedit_MSelClear 10
#else
#define txtedit_MSelSave 1
#define txtedit_MSelCopy 2
#define txtedit_MSelMove 3
#define txtedit_MSelDelete 4
#define txtedit_MSelClear 5
#define txtedit_MSelIndent 6
#define txtedit_MSelSwapCase 2
#define txtedit_MSelIndent 3
#define txtedit_MSelCut 4
#define txtedit_MSelCopy 5
#define txtedit_MSelPaste 6
#define txtedit_MSelDelete 7
#define txtedit_MSelSelAll 8
#define txtedit_MSelClear 9
#endif /* PRINT */
#define txtedit_MFind 1
......@@ -311,28 +314,16 @@ void txtedit__undomajor(txtedit_state *s);
/* -------- statics. -------- */
#if FALSE
static BOOL lastopts_set = FALSE;
static txtar_options lastopts;
#endif
static void *clipboard_anchor = NULL;
static int clipboard_ref = -1;
static txtedit_state *txtedits = NULL; /* list of them all */
/* -------- -------- */
typedef enum
{
txtedit_SEL = 1, txtedit_EXT = 2, txtedit_CTLSEL = 4, txtedit_NONE = 8
} txtedit_SELACTION;
static menu txtedit_menumaker(void *a);
/* Forward reference. */
void txtedit_copyselection(txtedit_state *s);
static txtedit_state *txtedits = 0; /* list of them all */
{
txtedit_SEL = 1, txtedit_EXT = 2, txtedit_CTLSEL = 4, txtedit_NONE = 8
} txtedit_SELACTION;
/* handlers and handles for update/close/save/shutdown */
static txtedit_update_handler txtedit__update_handler = 0;
......@@ -416,7 +407,7 @@ txtedits = s;
/* Force the creation of the menu tree early on.
This prevents embarassing cases of running out of memory. */
txtedit_menumaker(s);
txtedit_menu(s);
return(s);
......@@ -426,7 +417,7 @@ void txtedit_dispose(txtedit_state *s)
{
if (txtscrap_selectowner() == s->t)
txtscrap_setselect(s->t, 0, 0);
txtscrap_setselect(NULL, 0, 0); /* Relinquish since disposing */
txt_disposemarker(s->t, &(s->selpivot));
txt_dispose(&(s->t));
......@@ -437,12 +428,6 @@ if (txtedits == s) {
} else {
txtedit_state *ptr = txtedits;
while (ptr->next != s) {
#if FALSE
if (ptr == 0) {
/* >>> chasing apparent collapse in findnamedtxt... */
werr(TRUE, "Unexpected internal error te-1-1.");
};
#endif
ptr = ptr->next;
};
ptr->next = s->next;
......@@ -655,6 +640,7 @@ static char filetypebuff[10] = ""; /* new file type */
static void txtedit__menumaker(void *a)
{
txtedit_state *s = (txtedit_state *) a;
menu mt;
txtedit__menu = menu_new(
msgs_lookup(MSGS_txt10),
......@@ -663,24 +649,10 @@ static void txtedit__menumaker(void *a)
m1 = menu_new(
msgs_lookup(MSGS_txt12),
msgs_lookup(MSGS_txt13));
/* In the string above,
\x8b is an up-arrow - provided by the Wimp, utterly non-standard.
I then can't figure out how to stop C complaining about following hex digits!
\x46 is 'F'
\x33 is '3'
\x31 is '1'
*/
#if TRACE
menu_extend(m1, "|trace,no trace");
#endif
{ menu foo = menu_new(msgs_lookup(MSGS_txt13a), "foo");
menu_make_writeable(foo, 1, filetypebuff, 9, "a~.");
menu_submenu(m1, txtedit_MNewType, foo);
}
mt = menu_new(msgs_lookup(MSGS_txt13a), "foo");
menu_make_writeable(mt, 1, filetypebuff, sizeof(filetypebuff)-1, "a~.");
menu_submenu(m1, txtedit_MNewType, mt);
menu_submenu(txtedit__menu, txtedit_MMisc, m1);
m3 = menu_new(
......@@ -691,42 +663,15 @@ static void txtedit__menumaker(void *a)
m4 = menu_new(
msgs_lookup(MSGS_txt16),
msgs_lookup(MSGS_txt17));
m5 = menu_new(msgs_lookup(MSGS_txt18), msgs_lookup(MSGS_txt72));
menu_make_writeable(m5, 1, fwidthbuf, 9, "a0-9");
menu_submenu(m4, txtedit_MFormatText, m5);
mt = menu_new(msgs_lookup(MSGS_txt18), msgs_lookup(MSGS_txt72));
menu_make_writeable(mt, 1, fwidthbuf, sizeof(fwidthbuf)-1, "a0-9");
menu_submenu(m4, txtedit_MFormatText, mt);
menu_submenu(txtedit__menu, txtedit_MEdit, m4);
m5 = txtoptmenu_make(s->t);
menu_submenu(txtedit__menu, txtedit_MDisplay, m5);
}
static void txtedit__menusetflags(void *a) {
txtedit_state *s = (txtedit_state *) a;
BOOL noscrap = txtscrap_selectowner() == 0;
BOOL scrapnothere = txtscrap_selectowner() != s->t;
menu_setflags(m1, txtedit_MOverwrite, s->overwrite, FALSE);
menu_setflags(m1, txtedit_MColTab, ! s->wordtab, FALSE);
menu_setflags(m1, txtedit_MWordwrap, s->wordwrap, FALSE);
#if TRACE
menu_setflags(m1, txtedit_MTrace, trace_is_on(), FALSE);
menu_setflags(m1, txtedit_MNoTrace, ! trace_is_on(), FALSE);
#endif
menu_setflags(m3, txtedit_MSelSave, FALSE, scrapnothere);
#if PRINT
menu_setflags(m3, txtedit_MSelPrint, FALSE, noscrap);
#endif
menu_setflags(m3, txtedit_MSelCopy, FALSE, noscrap);
menu_setflags(m3, txtedit_MSelMove, FALSE, noscrap);
menu_setflags(m3, txtedit_MSelDelete, FALSE, noscrap);
menu_setflags(m3, txtedit_MSelClear, FALSE, noscrap);
menu_setflags(m3, txtedit_MSelIndent, FALSE, noscrap);
(void) txtoptmenu_make(s->t); /* set flags for this. */
}
static void txtedit__help_handler(void *a, char *hit)
{
txtedit_state *s = (txtedit_state *) a;
......@@ -743,25 +688,46 @@ static void txtedit__help_handler(void *a, char *hit)
static menu txtedit_menumaker(void *a) {
txtedit_state *s = (txtedit_state *) a;
char *p = filetypebuff;
BOOL selection = txtscrap_selectowner() != s->t;
/* IDJ: 30-Jul-91: insert current filetype */
if (((unsigned int) s->ty.ld >> 20) == 0xfff)
{
char *p;
os_swi4r(OS_FSControl, 18, 0, 0xfff & (s->ty.ld >> 8), 0, 0,
0, (int*) &filetypebuff[0], (int*) &filetypebuff[4]);
p = filetypebuff;
while (*p > ' ' && p < filetypebuff + 8) p++;
*p = 0;
}
else
filetypebuff[0] = 0;
/* IDJ: 30-Jul-91: insert current filetype */
if (((unsigned int) s->ty.ld >> 20) == 0xfff)
{
os_swi4r(OS_FSControl, 18, 0, 0xfff & (s->ty.ld >> 8), 0,
NULL, NULL, (int*) &filetypebuff[0], (int*) &filetypebuff[4]);
while (*p > ' ' && p < filetypebuff + 8) p++;
}
*p = 0;
txtwin_setcurrentwindow(s->t);
if (txtedit__menu == 0) txtedit__menumaker(a);
txtedit__menusetflags(a);
help_register_handler(txtedit__help_handler, s);
/* Place ticks where required */
menu_setflags(m1, txtedit_MOverwrite, s->overwrite, FALSE);
menu_setflags(m1, txtedit_MColTab, ! s->wordtab, FALSE);
menu_setflags(m1, txtedit_MWordwrap, s->wordwrap, FALSE);
#if TRACE
menu_setflags(m1, txtedit_MTrace, trace_is_on(), FALSE);
menu_setflags(m1, txtedit_MNoTrace, ! trace_is_on(), FALSE);
#endif
/* Shade selection menu as required (except Paste entry, done on menu warning) */
menu_setflags(m3, txtedit_MSelSave, FALSE, selection);
#if PRINT
menu_setflags(m3, txtedit_MSelPrint, FALSE, selection);
#endif
menu_setflags(m3, txtedit_MSelSwapCase, FALSE, selection);
menu_setflags(m3, txtedit_MSelIndent, FALSE, selection);
menu_setflags(m3, txtedit_MSelCopy, FALSE, selection);
menu_setflags(m3, txtedit_MSelCut, FALSE, selection);
menu_setflags(m3, txtedit_MSelDelete, FALSE, selection);
menu_setflags(m3, txtedit_MSelClear, FALSE, selection);
/* Adjust font/colour menu options */
txtoptmenu_make(s->t);
return txtedit__menu;
}
......@@ -880,6 +846,9 @@ tracef1("KeyboardInput of %d chars.\n", count);
txt_setcharoptions(s->t, txt_CARET, 0);
/* Typing replaces selection */
if (txtscrap_selectowner() == s->t) txtedit_deleteselection();
#if OVERWRITE
/* Replace characters, until the next newline in the text. */
{
......@@ -979,12 +948,14 @@ else if ((mflags & txt_MSELECT) != 0)
}
else
{
#if FALSE
s->selectctl = akbd_pollctl();
if (s->selectctl)
{
action = txtedit_CTLSEL;
s->selectrecent = FALSE;
}
#endif
txt_movemarker(s->t, &s->selpivot, at);
}
......@@ -1032,7 +1003,7 @@ else if (action == txtedit_SEL) /* drag or not, don't care */
}
else if (drag)
/* ext or ctl-sel, don't care */
/* ext */
txtscrap_setselect(s->t, txt_indexofmarker(s->t, &s->selpivot), at);
else if (action == txtedit_EXT)
{
......@@ -1077,6 +1048,7 @@ if (!drag)
if ((mflags & txt_MEXACT) != 0)
{
/* Cycle round single->double->triple click */
if (s->seltype == txtedit_CHARSEL)
s->seltype = txtedit_WORDSEL;
else if (s->seltype == txtedit_WORDSEL)
......@@ -1085,7 +1057,12 @@ if (!drag)
s->seltype = txtedit_CHARSEL;
}
else
{
/* For SELECT, cancel any existing selection and start again */
if (mflags & txt_MSELECT) txtedit_clearselection(s->t);
/* and for both SELECT and ADJUST reset the click state machine */
s->seltype = txtedit_CHARSEL;
}
}
tracef1("Mouse selType=%d.\n", s->seltype);
......@@ -1093,9 +1070,6 @@ tracef1("Mouse selType=%d.\n", s->seltype);
if ((mflags & txt_MEXTEND) != 0) action = txtedit_EXT;
else if ((mflags & txt_MSELECT) != 0)
/* Polling Ctl is only done at the beginning of the drag. */
{
action = txtedit_SEL;
......@@ -1114,14 +1088,19 @@ else if ((mflags & txt_MSELECT) != 0)
else
{
s->selectrecent = TRUE;
#if FALSE
/* Polling Ctl is only done at the beginning of the drag. */
s->selectctl = akbd_pollctl();
if (s->selectctl) action = txtedit_CTLSEL;
#endif
if (s->seltype == txtedit_CHARSEL) {
txt_movemarker(s->t, &s->selpivot, at);
} else if (s->seltype == txtedit_WORDSEL) {
txt_movemarker(s->t, &s->selpivot, txtmisc_bow(s->t, at));
txt_setcharoptions(s->t, txt_CARET, 0); /* Hide caret for non zero width sel */
} else { /* s->seltype == txtedit_LINESEL */
txt_movemarker(s->t, &s->selpivot, txtmisc_bol(s->t, at));
txt_setcharoptions(s->t, txt_CARET, 0); /* Hide caret for non zero width sel */
};
}
......@@ -1151,15 +1130,13 @@ else if (action == txtedit_SEL) /* drag or not, don't care */
if (txt_dot(s->t) != at || !drag)
/* not doing it reduces flicker: yuk, tweaky! */
txt_setdot(s->t, at);
if ((txt_charoptions(s->t) & txt_CARET) == 0)
txt_setcharoptions(s->t, txt_CARET, txt_CARET);
}
else if (drag)
/* ext or ctl-sel, don't care */
{
/* ext */
txtscrap_setselect(s->t, txt_indexofmarker(s->t, &s->selpivot), at);
}
else if (action == txtedit_EXT)
{
if (txt_selectset(s->t))
......@@ -1169,16 +1146,17 @@ else if (action == txtedit_EXT)
txt_movemarker(s->t, &s->selpivot, txt_dot(s->t));
txtscrap_setselect(s->t, txt_indexofmarker(s->t, &s->selpivot), at);
}
#if FALSE
else /* action = ctlsel, not drag */
{
txt_movemarker(s->t, &s->selpivot, at);
txtscrap_setselect(s->t, at, at + 1);
}
#endif
}
#endif
#if FALSE
static void txtedit_exchangedotandselect(txtedit_state *s)
{
......@@ -1196,6 +1174,7 @@ if (owner != NULL)
txt_setdot(owner, at);
}
}
#endif
static BOOL escflag = FALSE; /* for escaping from long searches. */
......@@ -2118,7 +2097,7 @@ BOOL loop = TRUE;
char a[100];
txt t = txtscrap_selectowner();
if (t == 0) return;
if (t == NULL) return; /* No selection, no indent then */
if (idbox == 0) {
idbox = dbox_new("indent");
......@@ -2166,6 +2145,31 @@ dbox_hide(idbox);
}
void txtedit_swapcase(txt t)
{
char *a;
int i, segsize, size;
txt_index pos;
t = txtscrap_selectowner();
if (t == NULL) return; /* No selection, no swap then */
pos = txt_selectstart(t);
size = txt_selectend(t) - pos; /* At least 1 */
txt_setcharoptions(t, txt_DISPLAY, 0);
while (size) {
txt_arrayseg(t, pos, &a, &segsize);
if (segsize > size) segsize = size;
for (i = 0; i < segsize; i++) a[i] = isupper(a[i]) ? tolower(a[i])
: toupper(a[i]);
size = size - segsize;
pos = pos + segsize;
}
/* Mark as updated, make a note in the undo buffer */
txt_setcharoptions(t, txt_UPDATED + txt_DISPLAY, txt_UPDATED + txt_DISPLAY);
txtundo_putcode(t->undostate, 't');
}
static void txtedit_goto(txtedit_state *s)
{
......@@ -2197,6 +2201,7 @@ while (1) {
txtmisc_gotoline(s->t, line);
return;
}
txtedit_clearselection(s->t); /* Goto equates to a caret move */
} else {
break;
}
......@@ -2278,9 +2283,17 @@ static BOOL txtedit__validbasicfile(char *filename)
/* PJC: extended so that BASIC files can be detokenised */
void txtedit_doinsertfile(txtedit_state *s, char *filename, BOOL replaceifwasnull) {
BOOL wasnull = 0 == txt_size(s->t);
BOOL result;
int result;
BOOL insrep;
typdat ty;
int size, tsize;
txt_index dot;
/* Insertion replaces selection */
insrep = txtscrap_selectowner() == s->t;
if (insrep) txtedit_deleteselection();
tsize = txt_size(s->t);
dot = txt_dot(s->t);
if (filename[0] != 0) {
#if BASIC
......@@ -2295,7 +2308,7 @@ void txtedit_doinsertfile(txtedit_state *s, char *filename, BOOL replaceifwasnul
file.name = filename;
er = os_file(&file);
if (er) {
werr(FALSE, &er->errmess[0]);
werr(FALSE, er->errmess);
return;
}
if (file.action != 1) {
......@@ -2310,7 +2323,7 @@ void txtedit_doinsertfile(txtedit_state *s, char *filename, BOOL replaceifwasnul
filety = -1;
l = -1;
}
if (filety == 0xFFB && (result = txtedit__validbasicfile(filename))) {
if (filety == 0xffb && (result = txtedit__validbasicfile(filename))) {
if (result == 2) return;
result = txtfile_basicinsert(s->t, filename, l, &ty, txtedit__detokenise, txtedit__strip);
} else {
......@@ -2320,13 +2333,24 @@ void txtedit_doinsertfile(txtedit_state *s, char *filename, BOOL replaceifwasnul
}
#endif
if (result) {
if (wasnull) {
s->ty = ty;
txt_setcharoptions(s->t, txt_UPDATED + txt_DISPLAY, txt_DISPLAY);
txtundo_prevent_undo(s->t);
if (replaceifwasnull) {
strcpy(s->filename, filename);
txtedit_settexttitle(s);
/* Now consider
- the text was empty and has been entirely replaced by the loaded file (tsize == 0, insrep == 0)
- the text had no selection and has been extended by the loaded file (tsize != 0, insrep == 0)
- the text was all selected and has been entirely replaced (tsize == 0, insrep != 0)
- the text was partly selected and the selection has been replaced (tsize != 0, insrep != 0). */
if (insrep) {
size = txt_size(s->t) - tsize;
txt_setdot(s->t, dot);
txtscrap_setselect(s->t, dot, dot + size);
} else {
if (tsize == 0) {
s->ty = ty;
txt_setcharoptions(s->t, txt_UPDATED + txt_DISPLAY, txt_DISPLAY);
txtundo_purge_undo(s->t);
if (replaceifwasnull) {
strcpy(s->filename, filename);
txtedit_settexttitle(s);
};
};
};
};
......@@ -2335,15 +2359,13 @@ void txtedit_doinsertfile(txtedit_state *s, char *filename, BOOL replaceifwasnul
static void txtedit_insertfile(txtedit_state *s)
{
char filename[256];
char filename[256];
tracef0("inserting file.\n");
filename[0] = 0;
dboxfile(msgs_lookup("txt70"), -1, filename, 256);
txtedit_doinsertfile(s, filename, TRUE);
tracef0("inserting file.\n");
filename[0] = 0;
dboxfile(msgs_lookup("txt70"), -1, filename, sizeof(filename));
txtedit_doinsertfile(s, filename, TRUE);
}
/* -------- Saving file and selection. -------- */
......@@ -2549,6 +2571,50 @@ static BOOL txtedit__sendselproc(void *handle, int *maxbuf) {
#endif
}
/* Clipboard helpers for xfersend */
static BOOL txtedit__saveclipproc(char *filename, void *handle) {
os_error *err;
os_filestr file;
char *clip = (char *)clipboard_anchor;
int size = flex_size(&clipboard_anchor);
tracef0("saveclipproc.\n");
file.action = 0; /* Save */
file.name = filename;
file.loadaddr = (int)0xffffff00; /* Text file on 01 Jan 1900 */
file.execaddr = 0;
file.start = (int)&clip[0];
file.end = (int)&clip[size];
err = os_file(&file);
if (err != NULL)
{
werr(FALSE, err->errmess);
return FALSE;
}
tracef0("saveclipproc worked.\n");
return TRUE;
}
static BOOL txtedit__sendclipproc(void *handle, int *maxbuf) {
char *clip = (char *)clipboard_anchor;
int size = flex_size(&clipboard_anchor);
int avail, sent = 0;
tracef0("sendclipproc.\n");
while (sent < size)
{
avail = size - sent;
if (avail > *maxbuf)
avail = *maxbuf; /* MIN(recipient space, unsent clipboard) */
if (!xfersend_sendbuf(&clip[sent], avail)) return FALSE;
sent += avail;
}
return TRUE;
}
/* It's hard to do pipeing to/from the same object: it really
just doesn't work! So, we have to spot this and use the
txtmisc facilities. */
......@@ -2601,10 +2667,10 @@ static BOOL txtedit__import_buffer_processor(char **buffer, int *size) {
BOOL txtedit_doimport(txtedit_state *s, int filetype, int estsize) {
txt t = s->t;
char *buffer;
int size;
int tsize = txt_size(t);
int dot = txt_dot(t); /* in case of error result, to delete all */
int size, tsize;
txt_index dot;
int last;
BOOL insrep, undo;
txt_charoption wasupdated = txt_charoptions(t) & txt_UPDATED;
txtedit__import_s = s;
......@@ -2613,30 +2679,37 @@ BOOL txtedit_doimport(txtedit_state *s, int filetype, int estsize) {
filetype=filetype;
if (withinsaveselect && s == sss) {
txtedit_copyselection(s);
txtedit_settexttitle(s);
txtundo_separate_major_edits(s->t);
os_swi2(0x400D4, 0, -1); /* PJC: force the menu tree to shut */
/* Doing a Selection->Save into yourself is a no-op since the
imported text replaces the selection, and becomes the new selection; just
close the menu. */
wimp_create_menu((wimp_menustr *)-1, 0, 0);
return TRUE;
};
if (withinsaveas && s == sas) {
werr(FALSE, msgs_lookup(MSGS_txt1));
werr(FALSE, msgs_lookup(MSGS_txt1)); /* No saving into yourself */
return FALSE;
};
txt_setcharoptions(t, txt_DISPLAY, 0);
/* Insertion replaces selection */
insrep = txtscrap_selectowner() == s->t;
if (insrep) txtedit_deleteselection();
#if BASIC
if ((filetype == 0xffb) && (txtedit__detokenise != -1)) {
return(txtfile_dobasicimport(s, estsize, txtedit__detokenise, txtedit__strip));
return txtfile_basicimport(s, insrep, txtedit__detokenise, txtedit__strip);
} else {
#endif
txt_setcharoptions(t, txt_DISPLAY, 0);
undo = txtundo_suspend_undo(t, TRUE);
tsize = txt_size(t);
dot = txt_dot(t); /* in case of error result, to delete all */
txt_replacechars(t, 0, NULL, estsize); /* create blanks */
if (txt_size(t) != tsize + estsize) { /* out of space */
txt_delete(t, txt_size(t) - tsize); /* delete blanks */
werr(FALSE, msgs_lookup(MSGS_txt3));
txt_setcharoptions(t, txt_DISPLAY + txt_UPDATED, txt_DISPLAY + wasupdated);
txtedit_settexttitle(s);
txtundo_separate_major_edits(s->t);
txtundo_suspend_undo(t, undo);
return FALSE;
};
txt_arrayseg(t, txt_dot(t), &buffer, &size); /* get pointer to them */
......@@ -2649,21 +2722,33 @@ BOOL txtedit_doimport(txtedit_state *s, int filetype, int estsize) {
txt_delete(t, txt_size(t) - tsize); /* delete everything new */
txt_setcharoptions(s->t, txt_DISPLAY + txt_UPDATED, txt_DISPLAY + wasupdated);
txtedit_settexttitle(s);
txtundo_separate_major_edits(s->t);
txtundo_suspend_undo(t, undo);
return FALSE;
} else {
/* last indicates the number of bytes actually transferred into
the final buffer. Delete any remaining blanks. */
txt_movedot(t, last);
txt_delete(t, txtedit__import_size - last);
/* txt_movedot(t, -last); */
size = txt_size(t) - tsize;
txt_setdot(t, dot);
if (txt_size(t) == tsize) {
txtundo_suspend_undo(t, undo);
txtundo_putnumber(t->undostate, size);
txtundo_putcode(t->undostate, 'd');
if (size == 0) {
/* At the end of the day, nothing has been inserted. Check
that modified flag does not change. */
txt_setcharoptions(s->t, txt_UPDATED, wasupdated);
txt_setcharoptions(t, txt_DISPLAY + txt_UPDATED, txt_DISPLAY + wasupdated);
} else {
/* When insertion replaced a selection, must select the new
insertion in its place. */
if (insrep) {
txtscrap_setselect(t, dot, dot + size);
} else {
txt_movedot(t, size);
txt_show(s->t); /* Force a redraw so caret x/y is recalculated */
}
txt_setcharoptions(t, txt_DISPLAY, txt_DISPLAY);
};
txt_setcharoptions(s->t, txt_DISPLAY, txt_DISPLAY);
txtedit_settexttitle(s);
txtundo_separate_major_edits(s->t);
return TRUE;
......@@ -2673,21 +2758,6 @@ BOOL txtedit_doimport(txtedit_state *s, int filetype, int estsize) {
#endif
}
#if FALSE /* provided by the Wimp now */
static void txtedit_exiteditor(s)
txtedit_state *s;
/* >>>> Should query only if there are any updated windows. */
{
s=s;
if (txtedit_mayquit()) exit(0);
}
#endif
/* -------- Information display. -------- */
/* info about file, template offsets. */
......@@ -2768,43 +2838,121 @@ void txtedit__redomajor(txtedit_state *s, int harmless) {
if (i <= 0) txt_setcharoptions(s->t, txt_DISPLAY, txt_DISPLAY);
}
static void txtedit_moveselection(txt t) {
txtedit_state *from = txtedit__findtxt(txtscrap_selectowner());
#if FALSE
txtmisc_moveselection(
t,
txtedit__parawidth(from),
txtedit__parawidth(txtedit__findtxt(t)));
#else
txtmisc_moveselection(t, 0, 0);
#endif
if (from != NULL) {
txtedit_settexttitle(from);
};
static void txtedit_clearselection(txt t) {
/* Clear any selection, reveal the caret. */
txtscrap_setselect(NULL, 0, 0);
txt_setcharoptions(t, txt_CARET, txt_CARET);
}
void txtedit_copyselection(txtedit_state *s) {
#if FALSE
txtmisc_copyselection(
s->t,
txtedit__parawidth(s));
#else
txtmisc_copyselection(s->t, 0);
#endif
static void txtedit_copyselection(txtedit_state *s) {
txt owner;
owner = txtscrap_selectowner();
if ((owner != NULL) && txt_selectset(s->t)) {
char *a;
size_t n, size;
int segsize;
BOOL success, claim;
size = txt_selectend(owner) - txt_selectstart(owner);
claim = (clipboard_anchor == NULL);
if (claim)
success = flex_alloc((flex_ptr)&clipboard_anchor, size);
else
success = flex_extend((flex_ptr)&clipboard_anchor, size);
if (success) {
/* Copy the selection into the temporary store */
n = 0;
while (n != size) {
txt_arrayseg(owner, txt_selectstart(owner) + n, &a, &segsize);
segsize = (segsize < size - n) ? segsize : size - n;
memcpy((char *)clipboard_anchor + n, a, segsize);
n += segsize;
}
if (claim) {
wimp_msgstr m;
/* Stake my claim of the clipboard */
m.hdr.size = sizeof(wimp_msghdr) + sizeof(wimp_msgclaimentity);
m.hdr.your_ref = 0;
m.hdr.action = wimp_MCLAIMENTITY;
m.data.claimentity.flags = wimp_MCLAIMENTITY_flags_clipboard;
wimpt_noerr(wimp_sendmessage(wimp_ESEND, &m, 0));
}
} else {
werr(FALSE, msgs_lookup(MSGS_txt48)); /* Not enough memory */
}
}
}
static void txtedit_pasteselection(txtedit_state *s) {
wimp_msgstr m;
int *types = m.data.datarequest.types;
/* Ask for the clipboard data */
m.hdr.size = sizeof(wimp_msghdr) + sizeof(wimp_msgdatarequest) + sizeof(int);
m.hdr.your_ref = 0;
m.hdr.action = wimp_MDATAREQUEST;
m.data.datarequest.w = txt_syshandle(s->t); /* As though dropped into that window */
m.data.datarequest.h = s; /* Handle back to state, might be useful */
m.data.datarequest.x =
m.data.datarequest.y = 0;
m.data.datarequest.flags = wimp_MDATAREQUEST_flags_clipboard;
types[0] = 0xfff; /* Our one preferred type */
types[1] = wimp_MDATAREQUEST_types_end;
wimpt_noerr(wimp_sendmessage(wimp_ESENDWANTACK, &m, 0));
clipboard_ref = m.hdr.my_ref; /* Picked by Wimp */
}
/* Distinguish whether this is a test paste or a real one */
static BOOL withinmsel = FALSE;
static int mselx, msely;
static BOOL txtedit_pasteok(txt t, wimp_msgstr *m) {
BOOL faded, istext = m->data.datasave.type == 0xfff;
if (m->hdr.your_ref != clipboard_ref) return TRUE; /* Pass all non replies */
if (withinmsel) {
/* This was a trial paste to see if anything was there, generate and
show the 'Selection' menu instead, then abort the paste silently */
faded = (txt_charoptions(t) & txt_READONLY) || !istext;
menu_setflags(m3, txtedit_MSelPaste, FALSE, faded);
wimp_create_submenu(menu_syshandle(m3), mselx, msely);
withinmsel = FALSE;
return FALSE;
}
return istext;
}
static void txtedit_deleteselection(void) {
txtedit_state *from = txtedit__findtxt(txtscrap_selectowner());
#if FALSE
txtmisc_deleteselection(txtedit__parawidth(from));
#else
txtmisc_deleteselection(0);
#endif
if (from != NULL) {
txt_marker m;
txt owner;
owner = txtscrap_selectowner();
if (owner != NULL && txt_selectset(owner))
{
txt_newmarker(owner, &m);
txt_setdot(owner, txt_selectstart(owner));
txt_delete(owner, txt_selectend(owner) - txt_selectstart(owner));
txtmisc_normalisepara(owner, 0);
txt_movedottomarker(owner, &m);
txt_disposemarker(owner, &m);
txtedit_clearselection(owner);
}
if (from != NULL)
{
txtedit_settexttitle(from);
};
}
}
static void txtedit_infoaboutprogram(void)
{
......@@ -2974,13 +3122,7 @@ BOOL wasupdated = txt_UPDATED & txt_charoptions(s->t);
#else
BOOL wasupdated = ((txt_UPDATED & txt_charoptions(s->t)) != 0);
#endif
/* 14-Dec-89: If the last event was an interactive help one,
provide help instead of doing the hit. This is a bit of a cheat,
but means that txtedit_menuevent can be used by c.message to give
menu interactive help on the task window menu. */
{
wimp_eventstr *e = wimpt_last_event();
wimp_eventstr *e = wimpt_last_event();
if (
(e->e == wimp_ESEND || e->e == wimp_ESENDWANTACK)
......@@ -2988,10 +3130,13 @@ menu interactive help on the task window menu. */
e->data.msg.hdr.action == wimp_MHELPREQUEST
)
{
/* 14-Dec-89: If the last event was an interactive help one,
provide help instead of doing the hit. This is a bit of a cheat,
but means that txtedit_menuevent can be used by c.message to give
menu interactive help on the task window menu. */
txtedit__help_handler(v, cmd);
return;
}
}
if (cmd[0] == txtedit_MEdit
&& (cmd[1] == txtedit_MUndo || cmd[1] == txtedit_MRedo)) {
......@@ -3033,8 +3178,6 @@ case txtedit_MMisc :
txtedit__printstart(s, txt_size(s->t), txtedit__print_wholefile_unknowns);
break;
#endif
#if MOVERWRITE
case txtedit_MOverwrite : s->overwrite = ! s->overwrite;
#ifdef SET_MISC_OPTIONS
{
......@@ -3046,7 +3189,6 @@ case txtedit_MMisc :
#endif
txtedit_settexttitle(s);
break;
#endif
#if TAB1
case txtedit_MColTab : s->wordtab = ! s->wordtab;
#ifdef SET_MISC_OPTIONS
......@@ -3096,19 +3238,31 @@ case txtedit_MFile :
break;
case txtedit_MSel :
switch (cmd[1])
{
case txtedit_MSelSave : if (cmd[2] != 0) txtedit_saveselect(s); break;
case txtedit_MSelSave : if (cmd[2] != 0) {
txtedit_saveselect(s);
} else {
/* This is the top level 'Select' submenu warning. Kick off
an exchange to decide whether the clipboard has text or not. */
withinmsel = TRUE;
mselx = e->data.msg.data.words[1];
msely = e->data.msg.data.words[2];
txtedit_pasteselection(s);
}
break;
#if PRINT
case txtedit_MSelPrint : txtedit__printstart(s, txt_selectend(s->t) - txt_selectstart(s->t),
txtedit__print_selection_unknowns);
break;
#endif
case txtedit_MSelCopy : txtedit_copyselection(s); break;
case txtedit_MSelMove : txtedit_moveselection(s->t); break;
case txtedit_MSelDelete : txtedit_deleteselection(); break;
case txtedit_MSelClear : txtmisc_clearselection(); break;
case txtedit_MSelCopy : txtedit_copyselection(s); break;
case txtedit_MSelPaste : txtedit_pasteselection(s); break;
case txtedit_MSelCut : txtedit_copyselection(s); /* Fall through */
case txtedit_MSelDelete : txtedit_deleteselection(); break;
case txtedit_MSelSelAll : txtscrap_setselect(s->t, 0, INT_MAX); break;
case txtedit_MSelClear : txtedit_clearselection(s->t); break;
case txtedit_MSelSwapCase : txtedit_swapcase(s->t); break;
case txtedit_MSelIndent : if (cmd[2] != 0) txtedit_indentselection(); break;
default : break;
}
......@@ -3157,12 +3311,6 @@ sscanf(fwidthbuf, "%i", &width) == 1) {
case txtedit_MDisplay :
txtoptmenu_eventproc(s->t, &cmd[1]);
/* Remember that setting of options for the creation of the
next blank window. */
#if FALSE
lastopts_set = TRUE;
txtar_getoptions(s->t, &lastopts);
#endif
break;
default :
......@@ -3219,6 +3367,7 @@ static void txtedit_obeyeventcode(txt t, txtedit_state *s, txt_eventcode e)
unsigned count;
BOOL loop_flag, wasupdated;
txt_eventcode next_e;
#if TRACE
char c;
#endif
......@@ -3246,44 +3395,37 @@ else
{
#if FALSE
/* Cancel any multi-click mode */
s->seltype = txtedit_CHARSEL;
/* Make EXT start a new selection */
s->selectrecent = TRUE;
/* Cancel any multi-click mode */
s->seltype = txtedit_CHARSEL;
/* Make EXT start a new selection */
s->selectrecent = TRUE;
#endif
loop_flag = TRUE;
while (loop_flag)
loop_flag = TRUE;
next_e = e;
while (loop_flag)
{
/* The loop is for when you look ahead in the key buffer,
and have to do something different with what you find. */
{
loop_flag = FALSE;
e = next_e; /* So the state before noticeseveral() is available */
if (e == 13) e = 10; /* RETURN = line feed. */
switch (e) {
default:
/* undo/redo ops are joined together into a single major edit,
for undoing purposes. */
txtundo_separate_major_edits(t);
case akbd_Fn + 8:
case akbd_Fn + 9:
;
break;
};
/* undo/redo ops are joined together into a single major edit,
for undoing purposes. */
switch (e)
{
switch (e) {
#if TRACE
case 23: /* ctl-W -- insert char forwards */
txt_insertchar(t, 'W');
break;
case 1: /* ctl-A -- set top bit of this char. */
c = txt_charatdot(t);
txt_delete(t, 1);
txt_insertchar(t, c + 128);
break;
case 2: /* ctl-B -- poll keyboard. */
if (akbd_pollsh()) return;
if (akbd_pollctl()) return;
......@@ -3292,6 +3434,15 @@ else
case 17: /* ctl-Q -- Text internal print-out-innards. */
txt_insertchar(t, 17);
break;
case akbd_Fn + akbd_Sh + akbd_Ctl + 7:
txt_replaceatend(s->t, 0, "hello there\nhow are you", 22);
break;
case akbd_Fn + akbd_Sh + akbd_Ctl + 6: /* trial force of system error */
{ int *a = (int*) -1;
*a = 1;
};
break;
#endif
/* function keys */
......@@ -3342,29 +3493,39 @@ else
break;
case txt_EXTRACODE + akbd_Fn + akbd_Sh + 2: /* insert/drag file. */
{
wimp_eventstr *ee = wimpt_last_event();
char *filename;
int filetype = xferrecv_checkinsert(&filename);
int filetype;
/* Filter out replies to MDATAREQUEST that we don't fancy */
if (ee->data.msg.hdr.action == wimp_MDATASAVE) {
if (!txtedit_pasteok(t, &ee->data.msg)) break;
}
filetype = xferrecv_checkinsert(&filename);
if (filetype != -1) {
if (akbd_pollsh()) {
/* Shift held down, insert the filename instead */
txt_insertstring(s->t, filename);
txt_movedot(s->t, strlen(filename));
/* 29-Jan-90: add a \n too. Definite improvement. */
txt_insertstring(s->t, "\n");
txt_insertstring(s->t, "\n"); /* add a \n too */
txt_movedot(s->t, 1);
} else {
int size = txt_size(s->t);
/* No shift, xferrecv the file contents */
txtedit_doinsertfile(s, filename, xferrecv_file_is_safe());
xferrecv_insertfileok();
txt_movedot(s->t, txt_size(t) - size); /* move past insertion */
};
} else {
int estsize;
filetype = xferrecv_checkimport(&estsize);
if (filetype != -1) {
txtedit_doimport(s, filetype, estsize);
} else {
txtedit_insertfile(s);
/* Neither insert nor import, ignore it */
};
};
};
......@@ -3389,12 +3550,11 @@ else
case akbd_Fn + 4:
txtedit_find(s);
break;
#if FALSE
/* provided by the Wimp now. */
case akbd_Fn + akbd_Sh + 4:
txtedit_exiteditor(s);
case 19: /* control-S */
txtedit_swapcase(s->t);
break;
#endif
case akbd_Fn + akbd_Ctl + 4:
txtedit_indentselection();
break;
......@@ -3418,6 +3578,7 @@ else
break;
#endif
#if FALSE
case akbd_Fn + 6:
{
txt_index dot = txt_dot(t);
......@@ -3436,8 +3597,10 @@ else
};
};
break;
#endif
case 27: /* escape */
case akbd_Fn + akbd_Sh + 6: /* clear select */
txtmisc_clearselection();
txtedit_clearselection(s->t);
break;
case akbd_Fn + akbd_Ctl + 6:
......@@ -3453,32 +3616,14 @@ else
#endif
break;
case akbd_Fn + 7:
txtedit_copyselection(s);
break;
case akbd_Fn + akbd_Sh + 7:
txtedit_moveselection(t);
break;
#if FALSE
case akbd_Fn + akbd_Ctl + 6: /* split window */
txtedit_splitwindow(s);
break;
#endif
case akbd_Fn + akbd_Ctl + 7:
txtedit_exchangedotandselect(s);
break;
#if TRACE
case akbd_Fn + akbd_Sh + akbd_Ctl + 7:
txt_replaceatend(s->t, 0, "hello there\nhow are you", 22);
break;
case akbd_Fn + akbd_Sh + akbd_Ctl + 6: /* trial force of system error */
{ int *a = (int*) -1;
*a = 1;
};
break;
#endif
case akbd_Fn + 8:
......@@ -3490,20 +3635,11 @@ else
case akbd_Fn + 9:
txtedit__redomajor(s, 20);
break;
#if FALSE
case akbd_Fn + akbd_Ctl + 0:
txtar_movetoback(s->t);
break;
/*
* Addition by Jon to test message passing stuff
* Modified to create new task window
*/
#if FALSE
case akbd_Fn + akbd_Ctl + akbd_Sh + 9:
message_taskwindow("foo");
break;
#endif
/* close key */
case txt_EXTRACODE + akbd_Fn + 127:
......@@ -3524,7 +3660,7 @@ else
int i = strlen(s->filename) - 1;
while (i > 0 && s->filename[i] != '.') i--;
if (i > 0) {
char a[255];
char a[256];
s->filename[i] = 0;
sprintf(a, "filer_opendir %s", s->filename);
wimpt_complain(os_cli(a));
......@@ -3575,23 +3711,24 @@ else
}
};
break;
case 27: /* esc key do nothing */
break;
case akbd_InsertK: /* insert a space */
txt_insertchar(t, ' ');
break;
#if !NEWDELETE
case 127: /* delete key, ^H (backspace) */
case 127: /* delete key */
#endif
case 8:
case 8: /* control-H (backspace) */
if (txt_selectset(t))
{
/* Equivalent to cut */
txtedit_copyselection(s);
txtedit_deleteselection();
}
else
{
int dot = txt_dot(t);
int distance;
BOOL ateof = dot == txt_size(t);
BOOL atnl = txt_charatdot(t) == '\n';
loop_flag = txtedit_noticeseveral((int *)&e, &count);
loop_flag = txtedit_noticeseveral((int *)&next_e, &count);
/* zero if BOF */
if (dot < count) count = dot;
txt_setcharoptions(t, txt_CARET, 0);
......@@ -3624,64 +3761,54 @@ else
case 3: /* control-C */
txtedit_copyselection(s);
break;
case 24: /* control-X */
txtedit_copyselection(s);
/* Fall through */
case 11: /* control-K */
txtedit_deleteselection();
break;
case akbd_InsertK: /* Insert */
case 22: /* control-V */
txtedit_moveselection(t);
txtedit_pasteselection(s);
break;
case 1: /* control-A */
txtscrap_setselect(s->t, 0, INT_MAX);
break;
case 26: /* control-Z */
txtmisc_clearselection();
txtedit_clearselection(s->t);
break;
/* Arrow keys */
case akbd_LeftK:
txt_movehorizontal(t, -1);
case akbd_UpK:
/* Exit selection at left */
if (txt_selectset(t))
txt_setdot(t, txt_selectstart(t));
if (e == akbd_LeftK) { /* LeftK */
txt_movehorizontal(t, -1);
} else { /* UpK */
loop_flag = txtedit_noticeseveral((int *)&next_e, &count);
txt_movevertical(t, 0 - count, NULL);
}
break;
case akbd_RightK:
txt_movehorizontal(t, 1);
break;
case akbd_UpK: /* scroll bar clicks get turned into this */
loop_flag = txtedit_noticeseveral((int *)&e, &count);
txt_movevertical(t, 0 - count, NULL);
break;
case akbd_DownK:
loop_flag = txtedit_noticeseveral((int *)&e, &count);
txt_movevertical(t, count, NULL);
break;
case akbd_Sh + akbd_Ctl + akbd_LeftK:
/* 25-Jan-90 experiment: move all windows at once, upwards */
{
txtedit_state *ss = txtedits;
loop_flag = txtedit_noticeseveral((int *)&e, &count);
while (ss != NULL)
{
txt_movevertical(ss->t, 0 - count, 1);
ss = ss->next;
}
/* Exit selection at right */
if (txt_selectset(t))
txt_setdot(t, txt_selectend(t));
if (e == akbd_RightK) { /* RightK */
txt_movehorizontal(t, 1);
} else { /* DownK */
loop_flag = txtedit_noticeseveral((int *)&next_e, &count);
txt_movevertical(t, count, NULL);
}
loop_flag = FALSE;
break;
case akbd_Sh + akbd_Ctl + akbd_RightK:
/* 25-Jan-90 experiment: move all windows at once, downwards */
{
txtedit_state *ss = txtedits;
loop_flag = txtedit_noticeseveral((int *)&e, &count);
while (ss != NULL)
{
txt_movevertical(ss->t, count, 1);
ss = ss->next;
}
}
loop_flag = FALSE;
break;
case akbd_Sh + akbd_Ctl + akbd_UpK:
case txt_EXTRACODE + akbd_Sh + akbd_Ctl + akbd_UpK:
loop_flag = txtedit_noticeseveral((int *)&e, &count);
loop_flag = txtedit_noticeseveral((int *)&next_e, &count);
#if TRUE
txt_movevertical(t, 0 - count, 1);
loop_flag = FALSE;
......@@ -3694,19 +3821,28 @@ to just do single lines, as fast as we can. */
break;
case akbd_Sh + akbd_Ctl + akbd_DownK:
case txt_EXTRACODE + akbd_Sh + akbd_Ctl + akbd_DownK:
loop_flag = txtedit_noticeseveral((int *)&e, &count);
loop_flag = txtedit_noticeseveral((int *)&next_e, &count);
txt_movevertical(t, count, 1);
break;
#if NEWDELETE
case 127:
#else
case akbd_CopyK: /* delete char */
case akbd_EndK: /* delete char */
#endif
loop_flag = txtedit_noticeseveral((int *)&e, &count);
txt_delete(t, count);
if (txt_selectset(t))
{
/* Equivalent to cut */
txtedit_copyselection(s);
txtedit_deleteselection();
}
else
{
loop_flag = txtedit_noticeseveral((int *)&next_e, &count);
txt_delete(t, count);
#if WORDWRAP
txtedit_normalisepara(s);
txtedit_normalisepara(s);
#endif
}
break;
case akbd_Sh + akbd_LeftK:
txt_setdot(t, txtmisc_bow(t, txt_dot(t)));
......@@ -3716,19 +3852,20 @@ to just do single lines, as fast as we can. */
break;
case akbd_Sh + akbd_UpK:
case txt_EXTRACODE + akbd_Sh + akbd_UpK:
loop_flag = txtedit_noticeseveral((int *)&e, &count);
loop_flag = txtedit_noticeseveral((int *)&next_e, &count);
txt_movevertical(t, 0-(txt_visiblelinecount(t)*count), NULL);
break;
case akbd_Sh + akbd_DownK:
case txt_EXTRACODE + akbd_Sh + akbd_DownK:
loop_flag = txtedit_noticeseveral((int *)&e, &count);
loop_flag = txtedit_noticeseveral((int *)&next_e, &count);
txt_movevertical(t, txt_visiblelinecount(t)*count, NULL);
break;
case akbd_Sh + akbd_CopyK: /* delete word */
case akbd_Sh + akbd_EndK: /* delete word */
{ txt_index to = txt_dot(t);
loop_flag = txtedit_noticeseveral((int *)&e, &count);
loop_flag = txtedit_noticeseveral((int *)&next_e, &count);
while ((count--) > 0) to = txtmisc_eow(t, to);
txt_delete(t, to - txt_dot(t));
txtedit_clearselection(s->t); /* more sane than deleting it */
#if WORDWRAP
txtedit_normalisepara(s);
#endif
......@@ -3750,9 +3887,9 @@ to just do single lines, as fast as we can. */
case akbd_Ctl + akbd_DownK:
txt_setdot(t, INT_MAX);
break;
case akbd_Ctl + akbd_CopyK: /* delete line */
case akbd_Ctl + akbd_EndK: /* delete line */
{ txt_index end = 1 + txtmisc_eol(t, txt_dot(t));
loop_flag = txtedit_noticeseveral((int *)&e, &count);
loop_flag = txtedit_noticeseveral((int *)&next_e, &count);
txt_setdot(t, txtmisc_bol(t, txt_dot(t)));
#if FALSE
/* Unfortunately, the act of moving backwards and then deleting means that
......@@ -3761,6 +3898,7 @@ For the moment, merely slow down deletion. */
while ((--count) > 0 && txt_dot(t) > 0) txt_setdot(t, txtmisc_bol(t, txt_dot(t) - 1));
#endif
txt_delete(t, end - txt_dot(t));
txtedit_clearselection(s->t); /* more sane than deleting it */
#if WORDWRAP
txtedit_normalisepara(s);
#endif
......@@ -3769,8 +3907,10 @@ For the moment, merely slow down deletion. */
case akbd_TabK:
#if TRUE
if (s->wordtab) {
txtedit_clearselection(s->t); /* Word tab mode moves the cursor */
txtmisc_tab(s->t);
} else {
txtedit_deleteselection(); /* Column tab mode inserts spaces */
txtmisc_tabcol(s->t);
};
#else
......@@ -3793,33 +3933,44 @@ For the moment, merely slow down deletion. */
loop_flag = txtedit_keyboardinput(s, &e);
};
break;
};
};
switch (e) {
case 30: /* home key */
#if NEWDELETE
case akbd_EndK:
#endif
case akbd_LeftK: case akbd_RightK:
case akbd_Ctl + akbd_LeftK: case akbd_Ctl + akbd_RightK:
case akbd_Sh + akbd_LeftK: case akbd_Sh + akbd_RightK:
case akbd_UpK: case akbd_DownK:
case akbd_Ctl + akbd_UpK: case akbd_Ctl + akbd_DownK:
case akbd_Sh + akbd_UpK: case akbd_Sh + akbd_DownK:
/* Movers clear the selection */
txtedit_clearselection(s->t);
break;
};
switch (e) {
default:
/* undo/redo ops are joined together into a single major edit,
for undoing purposes. */
txtundo_separate_major_edits(t);
case akbd_Fn + 8:
case akbd_Fn + 9:
break;
};
/* undo/redo ops are joined together into a single major edit,
for undoing purposes. */
}
s->selectrecent = FALSE;
s->seltype = txtedit_CHARSEL;
} /* endwhile */
s->selectrecent = FALSE;
s->seltype = txtedit_CHARSEL;
}
#if EDIT2
{
if (wasupdated != (txt_UPDATED & txt_charoptions(t)))
/* change the title so that the update is displayed */
txtedit_settexttitle(s);
}
if (wasupdated != (txt_UPDATED & txt_charoptions(t)))
/* change the title so that the update is displayed */
txtedit_settexttitle(s);
#else
{
if ((!wasupdated) && (txt_UPDATED & txt_charoptions(t)) != 0)
/* change the title so that the update is displayed */
txtedit_settexttitle(s);
}
if ((!wasupdated) && (txt_UPDATED & txt_charoptions(t)) != 0)
/* change the title so that the update is displayed */
txtedit_settexttitle(s);
#endif
}
......@@ -3828,16 +3979,6 @@ static void txtedit_eventhandler(txt t, void *s)
txtedit_obeyeventcode(t, s, txt_get(t));
}
static void txtedit__poptotop(wimp_w w) {
wimp_wstate s;
wimp_get_wind_state(w, &s);
s.o.behind = -1;
wimp_sendwmessage(
wimp_EOPEN, (wimp_msgstr*) &s.o, w, -1);
}
#ifndef SET_MISC_OPTIONS
static int txtedit__readoptnum(char *buf, int *i) {
/* read a number from the option string. */
......@@ -3902,6 +4043,8 @@ tracef1("newwithoptions of '%s'.\n", (int) filename);
if (filename != 0) s = txtedit_findnamedtxt(filename);
if (s != 0
&& (0 == (txt_UPDATED & txt_charoptions(s->t)))) {
wimp_wstate ws;
wimp_w w;
if (ty.ld == s->ty.ld && ty.ex == s->ty.ex) {
tracef1("non-updated window on '%s' already exists.\n", (int) filename);
} else {
......@@ -3910,7 +4053,11 @@ tracef1("newwithoptions of '%s'.\n", (int) filename);
txt_delete(s->t, INT_MAX);
txtedit_doinsertfile(s, filename, TRUE);
};
txtedit__poptotop(txt_syshandle(s->t));
w = txt_syshandle(s->t);
wimp_get_wind_state(w, &ws);
ws.o.behind = -1; /* pop to top */
wimp_sendwmessage(wimp_EOPEN, (wimp_msgstr*) &ws.o, w, -1);
txt_setcharoptions(s->t, txt_CARET, 0); /* force re-aquisition */
txt_setcharoptions(s->t, txt_CARET, txt_CARET);
return s;
};
......@@ -4073,7 +4220,7 @@ event_attachmenumaker(txt_syshandle(s->t), txtedit_menumaker,
harmless at least. */
txt_setcharoptions(s->t, txt_UPDATED + txt_DISPLAY, txt_DISPLAY);
txtundo_prevent_undo(s->t);
txtundo_purge_undo(s->t);
strcpy(s->filename, filename);
txtedit_settexttitle(s);
......@@ -4090,13 +4237,7 @@ demo hack. */
txtedit_state *txtedit_new(char *filename, int filetype)
{
#if FALSE
return txtedit_newwithoptions(filename, filetype, lastopts_set ? &lastopts : NULL);
#else
return txtedit_newwithoptions(filename, filetype, NULL);
#endif
return txtedit_newwithoptions(filename, filetype, NULL);
}
......@@ -4186,9 +4327,6 @@ if (s == 0) return 0;
txt_eventhandler(t, txtedit_eventhandler, s);
event_attachmenumaker(txt_syshandle(t), txtedit_menumaker,
txtedit_menueventproc, s);
#if FALSE
if (lastopts_set) txtar_setoptions(t, &lastopts); /* a bit of a cheat for task windows! */
#endif
return s;
}
......@@ -4199,24 +4337,65 @@ static BOOL txtedit__datasavedhandler(wimp_eventstr *e, void *handle)
switch(e->e)
{
case wimp_EACK:
if ((e->data.msg.hdr.action == wimp_MDATAREQUEST) &&
(e->data.msg.hdr.my_ref == clipboard_ref) && withinmsel)
{
/* Bounced trying to open the 'Selection' menu, shade 'Paste' option and
show it anyway, the non bounced case is handled by txtedit_pasteok(). */
menu_setflags(m3, txtedit_MSelPaste, FALSE, TRUE);
wimp_create_submenu(menu_syshandle(m3), mselx, msely);
withinmsel = FALSE;
}
return FALSE;
case wimp_ESEND:
case wimp_ESENDWANTACK:
tracef3("Message: task=&%x, your_ref=&%x, type=&%x\n", e->data.msg.hdr.task,
e->data.msg.hdr.your_ref,
e->data.msg.hdr.action);
if (e->data.msg.hdr.action == wimp_MDATASAVED) {
txtedit_state *s;
for (s = txtedits; s; s = s->next) {
int lastref = txt_lastref(s->t);
if (lastref && (lastref == e->data.msg.hdr.your_ref)) {
tracef1("Marking buffer &%p unmodified\n",s->t);
txt_setcharoptions(s->t, txt_UPDATED, 0); /* mark text unmodified */
txtedit_settexttitle(s); /* update title bar */
break;
}
}
return TRUE;
switch (e->data.msg.hdr.action) {
case wimp_MDATASAVED:
{
txtedit_state *s;
for (s = txtedits; s; s = s->next) {
int lastref = txt_lastref(s->t);
if (lastref && (lastref == e->data.msg.hdr.your_ref)) {
tracef1("Marking buffer &%p unmodified\n",s->t);
txt_setcharoptions(s->t, txt_UPDATED, 0); /* mark text unmodified */
txtedit_settexttitle(s); /* update title bar */
break;
}
}
}
return TRUE;
case wimp_MCLAIMENTITY:
if ((wimpt_task() == e->data.msg.hdr.task) ||
(!(e->data.msg.data.claimentity.flags & wimp_MCLAIMENTITY_flags_clipboard)))
return FALSE; /* msg from myself or not a clipboard claim */
if (clipboard_anchor != NULL)
flex_free(&clipboard_anchor); /* free that clipboard */
return TRUE;
case wimp_MDATAREQUEST:
if ((e->data.msg.data.datarequest.flags & wimp_MDATAREQUEST_flags_clipboard) &&
(clipboard_anchor != NULL))
{
/* Someone asked for the clipboard contents and we have text placed on it */
xfersend_close_on_xfer(FALSE, (wimp_w)-1);
xfersend_pipe(0xfff, NULL, flex_size(&clipboard_anchor),
txtedit__saveclipproc,
txtedit__sendclipproc,
NULL /* Not printing */,
e,
NULL /* No handle */
);
return TRUE;
}
return FALSE;
}
}
......
......@@ -46,8 +46,11 @@
#include "flex.h"
#include "swis.h"
#include "wimpt.h"
#include "txt.h"
#include "EditIntern/txtundo.h"
#include "EditIntern/txt1.h"
#include "txtedit.h"
#include "txtscrap.h"
#include "xfersend.h"
#include "xferrecv.h"
#endif
......@@ -80,7 +83,7 @@ else
}
int txtfile_insert(txt t, char *filename, int l, typdat *ty)
BOOL txtfile_insert(txt t, char *filename, int l, typdat *ty)
/* The insert operation works in two phases. First, find out the size of the
file and insert that much junk into it. Then, actually read the contents of
the file directly into the text object memory. It is important to take this
......@@ -112,7 +115,7 @@ if (l < 0) {
er = os_file(&file);
tracef0("the os_file 5 returned.\n");
if (er != 0) { /* read info on pathname */
werr(FALSE, &er->errmess[0]);
werr(FALSE, er->errmess);
return(0);
};
......@@ -180,10 +183,10 @@ if (l < 0) {
er = os_file(&file);
if (er != 0) { /* load into buffer */
werr(FALSE, &er->errmess[0]);
werr(FALSE, er->errmess);
txt_delete(t, txt_size(t) - size);
if (! wasupdated) txt_setcharoptions(t, txt_UPDATED, 0);
result = 0;
result = FALSE;
} else {
ty->ld = file.loadaddr; /* return type to client */
ty->ex = file.execaddr;
......@@ -241,7 +244,7 @@ else
file.end = (int) &a[n];
er = os_file(&file);
if (er != 0) {
werr(FALSE, &er->errmess[0]);
werr(FALSE, er->errmess);
};
if (oldattribs != -1) {
......@@ -385,41 +388,64 @@ static BOOL txtfile__basicimportbufferprocessor(char **buffer, int *size)
return(result);
}
BOOL txtfile_dobasicimport(txtedit_state *s, int estsize, int detokenise, BOOL strip)
BOOL txtfile_basicimport(txtedit_state *s, BOOL insrep, int detokenise, BOOL strip)
{
/* Plan of action is:
1) import everything into a flex buffer
2) detokenise and insert!
*/
int last;
BOOL result;
BOOL result, undo;
txt_index dot;
int size, tsize;
char *import_buffer = malloc(4096); /* do imports in 4K chunks */
estsize = estsize;
if (import_buffer == NULL) {
werr(FALSE, msgs_lookup(MSGS_txt3));
return(FALSE);
}
undo = txtundo_suspend_undo(s->t, TRUE);
tsize = txt_size(s->t);
dot = txt_dot(s->t);
receiver_anchor = NULL; /* no imported data yet */
receiver_size = 0;
if (import_buffer) {
last = xferrecv_doimport(import_buffer, 4096, txtfile__basicimportbufferprocessor);
if (last == -1) {
result = FALSE;
last = xferrecv_doimport(import_buffer, 4096, txtfile__basicimportbufferprocessor);
if (last == -1) {
result = FALSE;
} else {
if (txtfile__basicimportbufferprocessor(&import_buffer, &last)) {
txtfile__basicimportdata(s->t, &receiver_anchor, receiver_size, detokenise, strip);
result = TRUE;
} else result = FALSE;
}
free(import_buffer);
if (receiver_anchor != NULL)
flex_free((flex_ptr)&receiver_anchor);
if (result) {
size = txt_size(s->t) - tsize; /* Delta */
txt_setdot(s->t, dot);
txtundo_suspend_undo(s->t, undo);
txtundo_putnumber(s->t->undostate, size);
txtundo_putcode(s->t->undostate, 'd');
if (size == 0) {
/* Nothing happened overall */
} else {
if (txtfile__basicimportbufferprocessor(&import_buffer, &last)) {
txtfile__basicimportdata(s->t, &receiver_anchor, receiver_size, detokenise, strip);
result = TRUE;
} else result = FALSE;
/* When insertion replaced a selection, must select the new
insertion in its place. */
if (insrep) {
txtscrap_setselect(s->t, dot, dot + size);
} else {
txt_movedot(s->t, size);
txt_show(s->t); /* Force a redraw so caret x/y is recalculated */
}
}
free(import_buffer);
if (receiver_anchor != NULL)
flex_free((flex_ptr)&receiver_anchor);
txtedit_settexttitle(s);
txtundo_separate_major_edits(s->t);
return(result);
} else {
werr(FALSE, msgs_lookup(MSGS_txt3));
return(FALSE);
}
txtedit_settexttitle(s);
txtundo_separate_major_edits(s->t);
return(result);
}
BOOL txtfile_basicinsert(txt t, char *filename, int l, typdat *ty, int detokenise, BOOL strip)
......@@ -447,7 +473,7 @@ BOOL txtfile_basicinsert(txt t, char *filename, int l, typdat *ty, int detokenis
er = os_file(&file);
if (er != 0) {
werr(FALSE, &er->errmess[0]);
werr(FALSE, er->errmess);
result = FALSE;
} else {
result = txtfile__basicimportdata(t, &anchor, file.start, detokenise, strip);
......@@ -644,7 +670,7 @@ BOOL txtfile_savebasicrange(txt t, char *filename, typdat ty, txt_index from, tx
file.end = (int)sender_anchor + end_ptr;
er = os_file(&file);
if (er != 0) {
werr(FALSE, &er->errmess[0]);
werr(FALSE, er->errmess);
}
result = er == 0;
flex_free((flex_ptr)&sender_anchor);
......
......@@ -460,7 +460,7 @@ while (at != size)
}
txt_setcharoptions(t, txt_DISPLAY, txt_DISPLAY);
if (updated) txt_setcharoptions(t, txt_UPDATED, txt_UPDATED);
txtundo_prevent_undo(t);
txtundo_purge_undo(t);
}
......@@ -664,15 +664,6 @@ txtmisc_select3(t, point, begin, end);
}
void txtmisc_clearselection(void)
/* Clear any selection. */
{
txtscrap_setselect(NULL, 0, 0);
}
#if EDIT2
/* -------- Wordwrap -------- */
......@@ -683,192 +674,6 @@ void txtmisc_normalisepara(
);
#endif
/* -------- Operations on Selections -------- */
void txtmisc_deleteselection(int parawidth)
{
txt_marker m;
txt owner;
owner = txtscrap_selectowner();
if (owner != NULL && txt_selectset(owner))
{
txt_newmarker(owner, &m);
txt_setdot(owner, txt_selectstart(owner));
txt_delete(owner, txt_selectend(owner) - txt_selectstart(owner));
txtmisc_normalisepara(owner, parawidth);
txt_movedottomarker(owner, &m);
txt_disposemarker(owner, &m);
txtscrap_setselect(owner, 0, 0);
}
}
#define BIG 256
static void movecopyselection(txt t, int deletesource, int parawidthsrc, int parawidthdst)
/* Two different techniques are used for small and for big operations. Small
ones are quicker to repaint. Bigger ones use FlexiStore as the transitory
space, this is tricky because inserting from FlexiStore might cause the
source to move under your feet if the object expands. */
{
unsigned size;
int n, stored, segsize;
txt owner;
char *a;
void *scrap;
owner = txtscrap_selectowner();
if (owner != NULL)
{
/* determine size */
size = txt_selectend(owner) - txt_selectstart(owner);
if (t == owner && deletesource &&
txt_dot(t) >= txt_selectstart(t) && txt_dot(t) < txt_selectend(t))
/* move with caret in the middle of select, do nothing */
txt_setdot(t, txt_selectend(t));
else
{
/* get temporary space */
stored = TRUE;
if (size <= BIG) {
scrap = malloc(BIG);
if (scrap == 0) {
werr(FALSE, msgs_lookup(MSGS_txt48));
return;
};
} else
if (!flex_alloc(&scrap, size))
{
werr(NULL, msgs_lookup(MSGS_txt48));
stored = FALSE;
};
tracef2("\nRequired size is %d, stored = %d.\n", size, stored);
if (stored)
{
/* Copy the selection into the temporary store */
n = 0;
while (n != size)
{
txt_arrayseg(owner, txt_selectstart(owner) + n, &a, &segsize);
segsize = (segsize < size - n) ? segsize : size - n;
memcpy((char *)scrap + n, a, segsize);
n += segsize;
}
/* Delete the source. */
if (deletesource)
txtmisc_deleteselection(parawidthsrc);
/* >>>> dangerous? If t=owner, definitely a good move. */
{
int prevsize = txt_size(t);
/* Insert the selection into the target */
if (size <= BIG)
{
txt_replacechars(t, 0, scrap, size);
tracef0("small MoveCopy.\n");
}
else
{
tracef0("large MoveCopy.\n");
txtmisc_textinsertfromflexistore(t, &scrap, size);
}
if (txt_size(t) == prevsize + size) {
/* managed to insert: not out of space. */
/* The result becomes the selection */
if (deletesource)
txtscrap_setselect(t, txt_dot(t), txt_dot(t) + size);
txtmisc_normalisepara(t, parawidthdst);
/* NB we're relying on this not changing the size of what we've
inserted: otherwise, moving past the insertion needs a marker. */
/* Move past the result. */
txt_movedot(t, size);
};
};
/* deallocate temporary space */
if (size <= BIG)
free(scrap);
else
flex_free(&scrap);
}
}
}
}
void txtmisc_moveselection(txt t, int parawidthsrc, int parawidthdst)
/* The selection is copied to the caret, then deleted at the source.
The new version is now the selection. */
{
movecopyselection(t, 1, parawidthsrc, parawidthdst);
}
void txtmisc_copyselection(txt t, int parawidth)
/* The selection is copied to the caret. The new version is now the
selection. */
{
movecopyselection(t, NULL, parawidth, parawidth);
}
int txtmisc_textinsertfromflexistore(txt t, flex_ptr anchor, unsigned n)
/* If we just did an insert and this caused an expand and we got moved, the
text would be taken from the wrong place. So, we must turn off display for
this one.
Return FALSE, with situation unchanged, if out of store. */
{
void *prevad;
int prevsize;
prevad = *anchor;
prevsize = txt_size(t);
txt_setcharoptions(t, txt_DISPLAY, 0);
txt_replacechars(t, 0, *anchor, n);
if (txt_size(t) != n + prevsize) {
tracef0("not enough space.\n");
txt_delete(t, txt_size(t) - prevsize);
txt_setcharoptions(t, txt_DISPLAY, txt_DISPLAY);
/* werr(FALSE, "Not enough space."); */
/* 21-Nov-88 WRS: Failure will already have produced an error message. */
return FALSE;
};
if (*anchor != prevad)
{
tracef0("Replace caused movement.\n");
txt_replacechars(t, n, *anchor, n);
}
txt_setcharoptions(t, txt_DISPLAY, txt_DISPLAY);
return(1);
}
/* >>>> do out of store stuff. */
/* -------- Wordwrap. -------- */
#if WORDWRAP
......
......@@ -49,6 +49,7 @@ if (from == to || t == (txt) NULL)
else
{
txt_setselect(owner, 0, 0);
txt_setcharoptions(owner, txt_CARET, txt_CARET);
owner = (txt) NULL;
}
else
......@@ -56,6 +57,7 @@ else
if (owner != (txt) NULL && owner != t)
txt_setselect(owner, 0, 0);
txt_setselect(t, from, to);
txt_setcharoptions(t, txt_CARET, from==to ? txt_CARET : 0);
owner = t;
}
}
......
......@@ -46,6 +46,7 @@ typedef struct txtundo__state {
int tail; /* in [0..size-1], head==tail ? empty. */
int ptr; /* current pointer for undo/redo */
BOOL withinundo;
BOOL suspended;
} txtundo__state;
/*
head==tail -> empty
......@@ -114,14 +115,14 @@ txtundo txtundo_new(void)
u->size = INITIAL_BUF_SIZE;
u->ptr = 0;
u->withinundo = FALSE;
u->suspended = FALSE;
return u;
}
void txtundo_dispose(txtundo *u)
void txtundo_dispose(txtundo u)
{
/* The extra * is for M2-compatibility: it will change. */
flex_free((flex_ptr) &((*u)->buf));
free(*u);
flex_free((flex_ptr) &u->buf);
free(u);
}
void txtundo_setbufsize(txt t, int nbytes)
......@@ -144,7 +145,7 @@ void txtundo_setbufsize(txt t, int nbytes)
};
}
void txtundo_prevent_undo(txt t)
void txtundo_purge_undo(txt t)
{
/* very easy, just empty the buffer. */
txtundo u = t->undostate;
......@@ -153,10 +154,19 @@ void txtundo_prevent_undo(txt t)
u->ptr = 0; /* 20-Dec-88 WRS: otherwise, a following ReDo will get confused... */
}
BOOL txtundo_suspend_undo(txt t, BOOL newstate)
{
BOOL oldstate;
oldstate = t->undostate->suspended;
t->undostate->suspended = newstate;
return oldstate;
}
/* -------- Put operations. -------- */
void txtundo_putcode(txtundo u, char code)
{
if (u->suspended) return;
u->buf[u->head++] = code;
if (u->head == u->size) u->head = 0;
if (u->head == u->tail) {
......@@ -175,6 +185,7 @@ static int min(int a, int b) {return a < b ? a : b;}
void txtundo_putbytes(txtundo u, char* bytes, int n)
{
int blocksize;
if (u->suspended) return;
if (n >= u->size) {
/* We'll never be able to undo this, so forget it. */
tracef1("Undo %i chars impossible, clearing.\n", n);
......@@ -206,6 +217,7 @@ void txtundo_putnumber(txtundo u, int n)
{
/* Chars will be picked up LS byte first, each byte contributing 7 bits, with
all but the last one having top bit set. */
if (u->suspended) return;
tracef1("undo putnumber %i.\n", n);
txtundo_putcode(u, n % 128);
while (1) {
......@@ -227,6 +239,7 @@ static char txtundo__charbefore(txtundo u, int p)
void txtundo_separate_major_edits(txt t)
{
txtundo u = t->undostate;
if (u->suspended) return;
if (u->head != u->tail && txtundo__charbefore(u, u->head) == 's') {
/* already separated */
tracef0("undo sepmajoredits, already separated.\n");
......@@ -347,6 +360,13 @@ txtundo_result txtundo_undo(txt t)
case 's':
result = txtundo_MAJOR;
break;
case 't':
result = txtundo_MINOR;
if (txtscrap_selectowner() != NULL) {
extern void txtedit_swapcase(txt); /* Not in public headers */
txtedit_swapcase(t);
}
break;
case 'm':
if (txtundo__extractnum(u, &n) && txtundo__count_ptr_to_head(u) >= 5) {
txt_setdot(t, n);
......@@ -416,6 +436,7 @@ static int txtundo__skipop(txtundo u, int p)
};
switch (code) {
case 's':
case 't':
break;
case 'd':
if (txtundo__extractnum(u, &n) == 0) tracef0("Undo bug 2.\n");
......
......@@ -60,7 +60,7 @@ typedef struct txt1_str *txt;
/* ------------------------------- txt_new ---------------------------------
* Description: Creates a new txt object, containing no charcters, with a
* Description: Creates a new txt object, containing no characters, with a
* given title (to appear in its window).
*
* Parameters: char *title -- the text title to appear in its window
......@@ -184,13 +184,14 @@ BOOL txt_setbufsize(txt, int);
*/
typedef enum { txt_DISPLAY = 1, /* display changes to text as made */
txt_CARET = 2, /* give visible indictaion of "dot" */
txt_UPDATED = 4 /* set when chars are inserted/deleted */
txt_CARET = 2, /* give visible indication of "dot" */
txt_UPDATED = 4, /* set when chars are inserted/deleted */
txt_READONLY = 8 /* set if marked as read-only */
} txt_charoption;
/* ----------------------------- txt_charoptions ---------------------------
* Description: Informs caller of currenly set charoptions.
* Description: Informs caller of currently set charoptions.
*
* Parameters: txt t -- text object.
* Returns: Currently set charoptions.
......@@ -555,7 +556,7 @@ void txt_newmarker(txt, txt_marker *mark);
* txt_marker *mark -- the marker
* txt_index to -- place to move the marker to
* Returns: void.
* Other Info: The amrker must already point into this text object
* Other Info: The marker must already point into this text object
*
*/
......@@ -610,7 +611,7 @@ void txt_disposemarker(txt, txt_marker*);
*/
/* ---------------------------- txt_selectset ------------------------------
* Description: Informs caller whether there is a selction made in a text.
* Description: Informs caller whether there is a selection made in a text.
*
* Parameters: txt t -- text object.
* Returns: TRUE if there is a selection in this text.
......@@ -803,7 +804,7 @@ void txt_readeventhandler(txt t, txt_event_proc *func, void **handle);
* int *n -- *n == no. of contiguous bytes after "at"
* Returns: void.
* Other Info: It is permissible for the caller of this function to change
* the characters pointed at by *a, provided that a redsiplay
* the characters pointed at by *a, provided that a redisplay
* is prompted (using setcharoptions).
*
*/
......
......@@ -61,7 +61,9 @@ typedef struct txtedit_state
txt_marker selpivot; /* used in mouse op calculations */
txtedit_seltype seltype; /* used in mouse op calculations */
int selectrecent; /* used in mouse op calculations */
#if FALSE
int selectctl; /* used in mouse op calculations */
#endif
char filename[256];
typdat ty;
struct txtedit_state *next; /* chain of all of them. */
......
......@@ -24,6 +24,6 @@
; Copyright (C) Acorn Computers Ltd., 1988.
;
RlibSpace Variable 606
RlibSpace Variable 611
END
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment