/* Copyright (C) 1996,1997,1998,1999 by Salvador E. Tropea (SET),
   see copyrigh file for details */
#if defined( Uses_TCEditor_Class )

#if defined( Uses_TFindCDialogRec ) && !defined( __TFindCDialogRec__ )
#define __TFindCDialogRec__

struct TFindCDialogRec
{
 TFindCDialogRec( const char *str, unsigned flgs, unsigned insel,
                  unsigned from_where )
   {
    strcpy( find, str );
    options = flgs;
    in_sel = insel;
    from = from_where;
   }
 char find[maxFindStrLen];
 unsigned short options;
 unsigned short in_sel;
 unsigned short from;
};

#endif  // Uses_TFindCDialogRec


#if defined( Uses_TReplaceCDialogRec ) && !defined( __TReplaceCDialogRec__ )
#define __TReplaceCDialogRec__

struct TReplaceCDialogRec
{
 TReplaceCDialogRec( const char *str, const char *rep, unsigned flgs,
                     unsigned insel, unsigned from_where )
    {
     strcpy( find, str );
     strcpy( replace, rep );
     options = flgs;
     in_sel = insel;
     from = from_where;
    }
 char find[maxFindStrLen];
 char replace[maxReplaceStrLen];
 unsigned short options;
 unsigned short in_sel;
 unsigned short from;
};

#endif  // Uses_TReplaceCDialogRec



#if defined( Uses_LineLengthArray ) && !defined( __LineLengthArray__ )
#define __LineLengthArray__

class LineLengthArray
{
public:
 LineLengthArray();
 ~LineLengthArray();
 uint16 operator [](unsigned pos) { return elArray[pos]; };
 uint16 safeLen(unsigned pos) { return pos>=Length ? 0 : elArray[pos]; };
 void set(unsigned pos, uint16 val);
 void insert(unsigned pos, uint16 val);
 void del(unsigned pos);
 void deleteRange(unsigned from,unsigned to);
 uint32 getAttr(unsigned line) { return elArrayAttr[line]; };
 void setAttr(unsigned line, uint32 val);
 void setAll(unsigned line, uint16 length, uint32 attr);
 unsigned Length;
 uint16 *elArray;
 uint32 *elArrayAttr;

protected:
 void Resize(unsigned size);
 unsigned MaxPos;
};

#endif // Uses_LineLengthArray


#if defined( Uses_TCEditor ) && !defined( __TCEditor__ )
#define __TCEditor__

class TRect;
class TScrollBar;
class TSIndicator;
class TIndicator;
class TEvent;
class TSubMenu;

const int MaxRecMacroLen=250;
const int MaxXYRingStack=12;

class XYRingStack
{
public:
 XYRingStack();
 void push(uint32 x, uint32 y);
 int  pop(uint32 &x, uint32 &y);

protected:
 uint32 Xarray[MaxXYRingStack];
 uint32 Yarray[MaxXYRingStack];
 int pushPos,basePos;
};

class TCEditor : public TViewPlus
{
public:

    TCEditor( const TRect&, TScrollBar *, TScrollBar *, TSIndicator *, const char * );

    virtual ~TCEditor();
    virtual void shutDown();
    char bufChar( unsigned Pos )    { return buffer[Pos]; };
    unsigned bufPtr( unsigned Pos ) { return Pos; };
    virtual void changeBounds( const TRect& );
    virtual void convertEvent( TEvent& );
    Boolean cursorVisible();
    void deleteSelect();
    virtual void doneBuffer();
    virtual void draw();
    virtual TPalette& getPalette() const;

    // Handle event is divided in sub handle
    virtual void handleEvent( TEvent& );
    void handleMouse(TEvent &event);
    void handleKey(TEvent &event);
    int  handleCommand(ushort command);

    virtual void initBuffer();
    Boolean insertBuffer( char *, unsigned, unsigned, Boolean, Boolean, Boolean moveToEnd=True );
    virtual Boolean insertFrom( TCEditor * );
    Boolean insertText( const void *, unsigned, Boolean );
    unsigned CopySelToBuffer(char *b, unsigned l);
    void scrollTo( int, int );
    Boolean search( const char *, unsigned );
    virtual Boolean setBufSize( unsigned );
    void setCmdState( uint16 command, Boolean enable );
    void setSelect( unsigned, unsigned, Boolean);
    virtual void setState( uint16 aState, Boolean enable );
    void trackCursor( Boolean );
    void undo();
    virtual void updateCommands(int full=0);
    virtual void updateRectCommands();

    Boolean clipCopy();
    Boolean clipWinCopy();
    void clipCut();
    void clipPaste();
    void clipWinPaste();
    void deleteRange( unsigned , unsigned, Boolean );
    void doUpdate();
    void doSearchReplace();
    void drawLines( int, int, unsigned );
    void find();
    Boolean hasSelection() { return Boolean(selStart<selEnd); };
    Boolean hasVisibleSelection() { return Boolean(!selHided && selStart<selEnd); };
//{ return Boolean(IslineInEdition ? selLineStart<selLineEnd : selStart<selEnd); };
    void hideSelect();
    Boolean isClipboard() { return Boolean(clipboard == this); };
    void lock() { lockCount++; };
    void newLine();
    unsigned nextWordC( unsigned );
    int goEndWord();
    char *WordUnderCursor(unsigned maxLength=256, unsigned options=0);
    Boolean StringUnderCursor(uint32 &word_start, uint32 &word_end);
    void replace();
    void setBufLen( unsigned );
    void startSelect();
    void toggleInsMode( Boolean allowUndo );
    void unlock();
    void update( uchar );
    void checkScrollBar( const TEvent&, TScrollBar *, int& );
    unsigned LenWithoutCRLF(unsigned yInFile,char *lineStart);
    void ExpandAllTabs(void);
    void CompactBuffer();
    void SourceToHTML(FILE *f, unsigned *pal, unsigned flags);
    uint16 CompactFlags(void);
    void ExpandFlags(uint16 t,Boolean allowUndo=True);
    Boolean selRectCopy(Boolean allowUndo=True);
    Boolean selRectPaste(struct selRecSt *st, int X, int Y, Boolean allowUndo=True);
    Boolean selRectDelete(int X1, int Y1, int X2, int Y2, Boolean allowUndo=True);
    void selRectToUpper();
    void selRectToLower();
    void UndoRectangularPasteClear(UndoCell &un);
    Boolean FillUndoForRectangularPasteClear(int Height,struct UndoCell &un,UndoState st);
    Boolean FillUndoForRectangularStartEnd(UndoState st);
    void undoOneAction();
    void RevertModifFlagInUndo();
    void RemapCodePageBuffer(int sourID, int destID, ushort ops);
    //   Global options managment, global to allow setting while there isn't any editor
    // opened.
    static void SetGlobalOptions(void);
    static void ExpandGlobalOptions(GlobalOptionsRect *temp);
    static void CompactGlobalOptions(GlobalOptionsRect *temp);
    void ExpandGlobalOptionsLocally(GlobalOptionsRect *temp);

    TScrollBar  *hScrollBar;
    TScrollBar  *vScrollBar;
    TSIndicator *indicator;
    TIndicator  *OldIndicator;
    char *buffer;
    unsigned bufSize;
    unsigned bufLen;
    unsigned gapLen;
    unsigned selStart;
    unsigned selEnd;
    unsigned curPtr;
    TPoint delta;
    TPoint limit;
    unsigned drawPtr;
    unsigned delCount;
    unsigned insCount;
    Boolean isValid;
    Boolean canUndo;
    Boolean modified;
    Boolean selecting;
    Boolean overwrite;
    Boolean isReadOnly;

    Boolean autoIndent;               // Indent when ENTER is pressed
    static Boolean staticAutoIndent;  // the static version
    Boolean intelIndent;              // try to be smart in the autoindent
    static Boolean staticIntelIndent; // the static version
    unsigned tabSize;                 // The size of the tabulator
    static unsigned staticTabSize;    // the static version
    Boolean UseTabs;                  // True if when we press Tab an ascii 9 is inserted
    static Boolean staticUseTabs;     // the static version
    Boolean PersistentBlocks;         // True if the blocks isn't deleted after a move
    static Boolean staticPersistentBlocks;  // the static version
    Boolean ShowMatchPair;            // True if the editor highlights the match pair
    static Boolean staticShowMatchPair;     // the static version
    Boolean ShowMatchPairFly;
    static Boolean staticShowMatchPairFly;
    static Boolean staticNoMoveToEndPaste;  //  True if the cursor is moved to the end of
                                            // the pasted area.
    Boolean TransparentSel;           // True if you can see through the slelection
    static Boolean staticTransparentSel; // the static version
    Boolean OptimalFill;             // When True the editor tries to fill all the gaps
                                     // with tabs instead of spaces
    static Boolean staticOptimalFill;// the static version
    Boolean WrapLine;                // If True wraps the line after WrapCol columns
    static Boolean staticWrapLine;   // static version
    int WrapCol;                     // Column to wrap
    static int staticWrapCol;        // Default column
    Boolean SeeTabs;                 // If true the tabs are painted to be visible
    static  Boolean staticSeeTabs;   // the static version
    static  char    oTabChar;        // When selected the tabs are drawed as a character
                                     // that's the PC437 code for it.
    static  char    TabChar;         // That's the value for the current codepage
    Boolean NoInsideTabs;               // When True the cursor can't be inside a tab
    static  Boolean staticNoInsideTabs; // the static version
    Boolean IsaUNIXFile;             // True if we are in DOS an the file was UNIX
    Boolean IsaCompressedFile;       // True if we loaded a .gz file and hence we must
                                     // save a compressed file.

    static TEditorDialog editorDialog;
    static unsigned editorFlags;
    static unsigned fromFlags;
    static unsigned whereFlags;
    static char near findStr[maxFindStrLen];
    static char near replaceStr[maxReplaceStrLen];
    static TCEditor * near clipboard;
    static TCommandSet cmdsAux;     // This is used to quickly enable/disable all the
                                    // editor commands when it get/releases the focus
    uchar lockCount;
    uchar updateFlags;
    int keyState;
    unsigned WantedCol;
    void formatLine(void *, unsigned, int, unsigned short, unsigned, uint32, unsigned);
    void formatLineHighLight(void *, unsigned, int, unsigned short, unsigned, uint32,unsigned);
    void formatLineHighLightPascal(void *,unsigned,int,unsigned short,unsigned,uint32,unsigned);
    void formatLineHighLightClipper(void *,unsigned,int,unsigned short,unsigned,uint32,unsigned);
    void formatLineHighLightGeneric( void *,unsigned,int,unsigned short,unsigned,uint32,unsigned);
    unsigned lineMove( unsigned p, int count );
    void TurnOffHighLight(void) {  formatLinePtr=&TCEditor::formatLine; SyntaxHL=shlNoSyntax; SHLValueSelected=-1; };
    void TurnOnCHighLight(void);
    void TurnOnPascalHighLight(void);
    void TurnOnClipperHighLight(void);
    void TurnOnGenericHighLight(void);
    void SetHighlightTo(shlState sHL, int subSHL=0);
    void CacheSyntaxHLData(int id);
    void *SearchPMTrigger(char *trg);
    void ChoosePMacroFromList(void);
    void RecalculateLineAttributes(void);
    void ProfileEditor(void);
    void CacheColors(void);

    void InsertCharInLine(char cVal, Boolean allowUndo=True);
    void MakeEfectiveLineInEdition();
    char *ColToPointer();
    char *ColToPointer(int &Dif);
    char *ColToPointerPost();
    int  PosLeftChar();
    int  FixPosCharLeft();
    int  nextWord();
    int  prevWord(Boolean moveCursor=True);
    void MoveCursor(char *ori,char *dest);
    void EditLine();
    void deleteRange(char *from,char *to,Boolean allowUndo=True);
    void deleteRangeLineInEdition(char *from,char *to,int x);
    int  LineWidth();
    int  LineWidth(char *s, char *d);
    void insertSpaces( unsigned length, int X, Boolean canUseTabs=True );
    void MoveLinesUp(int i);
    void MoveLinesDown(int i);
    void SetStartOfSelecting(unsigned startOffSet);
    void UpdateSelecting(void);
    void MoveToMouse( TPoint m, uchar selMode );
    void MoveCursorTo(unsigned x, unsigned y);
    void GoAndSelectLine(int line);
    int  IsFirstCharInLine(void);
    void GotoOffSet(unsigned o);
    void JumpEndOfText();
    void ResetCursorPosition(void);
    void IndentBlock(char *Fill, Boolean allowUndo=True);
    void UnIndentBlock(unsigned Amount, Boolean allowUndo=True);
    void ArbitraryIndent();
    void BackSpace(Boolean allowUndo=True);
    void ExpandMacro(void);
    void ExpandPMacro(void *pm, char *s=0);
    void MacroGenerateCode(void);
    int TestPropagation(uint32 OldAttr,uint32 NewAttr,char *proxLine, uint32 proxLineNum);
    int SearchCloseSymbol(char open, char close);
    int SearchCloseSymbolXY(char open, char close, int &X, int &Y, char *pos=0);
    int SearchOpenSymbol(char open, char close);
    int SearchOpenSymbolXY(char open, char close, int &X, int &Y, char *pos=0);
    void SearchMatchOnTheFly();
    Boolean clipReplace(void);
    int GoFirstCharInLine(void);
    void SelWordUnderCursor(void);
    int nextCWord();
    void addToUndo(UndoState st, void *p=NULL);
    void freeUndoCell(int Index);
    void flushUndoInfo();
    void redo(void);
    void UndoSaveFinalState(UndoCell &un);
    void UndoSaveStartState(UndoCell &un);
    void BlockToUpper(Boolean allowUndo);
    void BlockToLower(Boolean allowUndo);
    void SetCharCase(int option);
    int  AdjustBufEditFor(int lar);
    void Beep(void);
    void AdjustLineSel(uint32 pos,int dif,Boolean IncludeStart=False,Boolean toLeft=True);
    void AdjustDrawPtr(void);
    void updateCrossCur(void);
    void setStatusLine(char *s);
    void RecalculateXofLineInEdit(void);
    Boolean hasRectSel(void) { return Boolean(!selRectHided && Xr1<Xr2 && Yr1<=Yr2); };
    unsigned GetOffSetOffLine(int y);
    int FindLineForOffSet(unsigned offset, unsigned &rest);
    int EnsureXDontTab(char *s,int x,int w,char **stop);
    void lockUndo(void) { undoLockCount++; };
    void unlockUndo(void);
    void SetSpecialLines(int *a) { SpecialLines=a; };
    void PasteEmacsMode();
    void QuotedPrintDecode();
    // File handle members
    Boolean loadFile(Boolean setSHL=False);
    Boolean save();
    Boolean saveAs(Boolean Unix=False);
    Boolean saveAsUNIX() { return saveAs(True); };
    Boolean saveSameTime();
    Boolean saveFile(Boolean Unix=False, Boolean noChangeTime=False);
    virtual Boolean valid( ushort );
    char fileName[PATH_MAX];

    LineLengthArray lenLines; // pseudo-Array with all the line-lengths
    uint32 totalLines;        // Total number of lines
    uint32 drawLine;          // first displayed line
    uint32 lineInEdition;     // Line number in edition process
    char  *curLinePtr;        // Pointer to the start of the line where the
                              // cursor is.
    char  *bufEdit;           // Buffer to edit a line
    uint16 bufEditLen;        // Allocated memory for bufEdit
    char  *inEditPtr;         // Pointer to the cursor inside the line edition
                              // buffer
    Boolean IslineInEdition;  // There is a line under edition?
    static int DontPurge;     // Special flag to avoid the extra spaces purge feature
                              // that's an experimental patch (ugly).
    TPoint curPos;            // Position of cursor inside the file
    int    restCharsInLine;   // Number of chars between inEditPtr and the end
                              // of the buffer.
    unsigned selLineStart;    // selStart in a line
    unsigned selLineEnd;      // selEnd in a line
    unsigned selNewStart;     // The value of selXXX when the line in edition
    unsigned selNewEnd;       // will be put in the buffer
    Boolean  selHided;       // True if the selection is invisible
    uint32 selStartOffSet;   // The start of a selecting operation
    void SetMarker(unsigned marker);
    unsigned Markers[10];    // 0=does't exist != It's a marker
    int MarkersInLine[10];   // -1 Isn't in this line other offset in the line

    XYRingStack CurPosStack; // Cursor position stack, works as a ring
    void PushCursorPosition();
    int  PopCursorPosition();

    uint32 attrInEdit;       // Attributes for the line in edition
    Boolean NotExpandingMacro; // False if we are expanding a pseudo macro to
                               // avoid an alteration of the selected area
    //uchar     ForceSelection;  // Force to set this selecting mode instead
                               // of use the shifts in handleEvent
    //uchar     ForcingSelection;  // Enables the other

    UndoCell UndoArray[MAX_UNDO];    // Array with the undo info
    UndoState UndoSt;                // Actual State
    int UndoBase,UndoActual,UndoTop; // Index in the array

    // a pointer to the function to format the line to be displayed.
    void (TCEditor::*formatLinePtr)(void *, unsigned, int, unsigned short, unsigned, uint32, unsigned );
    // a pointer to the function to format calculate the s. hl. attributes
    unsigned (*LineMeassure)(char *, char *, uint32 &);
    shlState SyntaxHL;        // Says the type of syntax highlight used
    int      GenericSHL;      // What sub-type if the type is generic
    int SHLValueSelected;     // That's the position in the array of the detected SHL
    static unsigned char SHLTableUse[4];  // A conversion table to know what generic shl uses an internal SHL
    static strSHL  *SHLArray;   // Array of configurable SHLs
    static strSHL   strC;       // Cached Syntax HL values
    static int      strCid;     // What element is cached
    static shlState strCtype;   // What type is cached (all or just user words)
    static int      SHLCant;    // Number of SHLs defined
    static TStringCollection *SHLGenList; // Names of the SHLs tp choose one
    static dflOptions dflOps;   // Default options settings for SHL=none

    static  Boolean Recording;
    static  TSArray<unsigned int> MacroArray;
    static  int     MacroCount;

    static unsigned LoadingVersion;   // That's the version of the desktop file opened
                             // Is here to comunicate the value between the
                             // ::read functions
    // CrossCursor
    Boolean CrossCursorInCol,CrossCursorInRow;
    static Boolean staticCrossCursorInCol;
    static Boolean staticCrossCursorInRow;
    int CrossCursorCol,CrossCursorRow;
    char CrossCursorBuf[setMaxScreenY];
    char CrossCursorBufR[setMaxScreenX];
    int CrossCursorY2,CrossCursorX2;
    Boolean CrossCurInCacheC,CrossCurInCacheR;

    // Status Line
    Boolean IsStatusLineOn;
    int     StatusLinePos;    // 1 means is at the end 0 at top
    static char StatusLine[setMaxScreenX*2];

    // New search options
    static ushort SearchInSel;
    static ushort FromWhere;
    static ushort RegExStyle;
    static ushort ReplaceStyle;
    static ushort CanOptimizeRegEx;
    unsigned StartOfSearch;
    unsigned selStartF,selEndF;
    Boolean IsFoundOn;
    static int    CompileSearch(char *searchStr, char *replaceStr=0);
    static uint32 MakeASearch(char *text, uint32 len, int &matchLen);
    static char  *GetTheReplace(int &mustDelete, uint32 &len);
    static int    CompileReplace(char *replaceStr);
    static char  *GetNormalReplace(int &mustDelete, uint32 &len);
    static char  *GetSpecialReplace(int &mustDelete, uint32 &len,char *(*GetHit)(int numHit, int &lenHit));
    static int    CompileRegEx(char *searchStr);
    static int    CompileNormal(char *searchStr);
    static uint32 MakeANormalSearch(char *block, uint32 size, int &matchLen);
    static uint32 MakeARegExSearch(char *block, uint32 size, int &matchLen);
    #ifdef SUP_PCRE
    static int    CompilePCRE(char *searchStr);
    static uint32 MakeAPCRESearch(char *block, uint32 size, int &matchLen);
    #endif
    static void   FreeRegExMemory(void);

    // Highligth of one char
    int XHLCO,YHLCO,XHLCC,YHLCC,XHLCo,YHLCo,XHLCc,YHLCc;
    Boolean IsHLCOn;
    char OldHLAttr,OldHLAttro;

    // Rectangular selection
    int Xr1,Yr1,Xr2,Yr2;     // Start and end point of the rect. sel
    Boolean selRectHided;    // To hide the sel
    struct selRecSt *selRectClip;

    // Groups of undo
    int undoLockCount;
    int undoGroupCount;

    // To keep track of the position of some line
    int *SpecialLines;

    // The modification time of the disk copy of the file
    // 0 if the file isn't in disk
    time_t DiskTime;
    // device and starting inode of the file. 0 on new files.
    dev_t  DeviceOfFile;
    ino_t  INodeOfFile;
    // attributes of the file from stat under Linux or _chmod in DOS
    mode_t ModeOfFile;

    // If 1 the colors are allready cached
    static int colorsCached;

    // For the pseudo macros by now only one
    static TPMCollection *PMColl;

    static const char *backupExt;
    // Menu that will be displayed when the right button of the mouse is pressed
    // It should be set by the TApplication, by default is 0 and the behavior is
    // the same used for the left button.
    static TSubMenu *RightClickMenu;

    void ShowLength();

    SetDefStreamMembersCommon(TCEditor,TViewPlus)
};

SetDefStreamOperators(TCEditor)

#endif  // Uses_TCEditor


#if (defined(Uses_TFindCDialogRec) || defined(Uses_TReplaceCDialogRec)) && \
    !defined(__TRegexDialogRec__) && defined(Uses_TCEditor)
#define __TRegexDialogRec__
struct TRegexDialogRec
{
 ushort regStyle;
 ushort repStyle;
 ushort optimize;
};

inline
void regexRecCreate(TRegexDialogRec &r)
{
 r.regStyle=TCEditor::RegExStyle;
 r.repStyle=TCEditor::ReplaceStyle;
 r.optimize=TCEditor::CanOptimizeRegEx;
}

inline
void regexRecUpdate(TRegexDialogRec &r)
{
 TCEditor::RegExStyle=r.regStyle;
 TCEditor::ReplaceStyle=r.repStyle;
 TCEditor::CanOptimizeRegEx=r.optimize;
}
#endif



#if defined( Uses_TCEditWindow ) && !defined( __TCEditWindow__ )
#define __TCEditWindow__

// That's a structure to hold the most important information of an
// esitor window.
// The coordinates are short because a 32768 screen is big enough ;-)
typedef struct
{
 uchar version,dummy;
 uchar shl,subshl;
 short origin_x,origin_y;
 short size_x,size_y;
 short cursor_x,cursor_y;
 short zorigin_x,zorigin_y;
 short zsize_x,zsize_y;
 ushort ed_flags,prj_flags;
} EditorResume;

#define CopyEditorResume(dst,sou) memcpy(dst,sou,sizeof(EditorResume))

class TCEditWindow : public TWindow
{

public:

    TCEditWindow( const TRect&, const char *, int );
    virtual void close();
    virtual const char *getTitle( short );
    virtual void handleEvent( TEvent& );
    virtual void sizeLimits( TPoint& min, TPoint& max );
    virtual TPalette& getPalette() const;

    void FillResume(EditorResume &r);
    void ApplyResume(EditorResume &r);

    TCEditor *editor;

private:

    static const char * near clipboardTitle;
    static const char * near untitled;

    SetDefStreamMembersNoConst(TCEditWindow)
};

SetDefStreamOperators(TCEditWindow)

void ReadResume(EditorResume &r, ipstream& is);
void SaveResume(EditorResume &r, opstream& os);
void FillResumeWith(EditorResume &r,TPoint &origin,TPoint &size,TPoint &cursor);

#endif  // Uses_TCEditWindow

#endif
