Yata - 2da editor

ver 2.8

Undo/Redo + tweaks and nuances

keep an eye on things especially if you’re sorting columns and using Undo/Redo in various combinations – inserting or deleting multiple rows in particular.

ver 2.8.1

– trying to paste text to either the Searchbox or Gotobox with the keyboard [Ctrl+v] caused the currently selected cell to take the text instead.
– Gotobox defaults to “0” if a nonnumeric or negative value is entered.

– Ctrl+mousewheel forces horizontal scroll if applicable.

– don’t overwrite your settings file, it hasn’t changed. Only the ReadMe and executable have been changed.

1 Like

Yata ver.2.8.2

  • clicking a label in the property panel selects the cell in the table (previous behavior was that a cell in the table would be selected only when a field in the property panel was being edited). Note that this auto-selection will be bypassed if more than one cell is currently selected on the table.
  • bugfix: allow shortcut keys for copy and paste [Ctrl+c] [Ctrl+v] to work in the PropertyPanel’s editor (instead of being intercepted by a copy/paste of the table’s selected gridcell).


bugfix for Control press causing exception.

my stupid

yata changelog ver.

  • add CreateRows dialog (receive a bonus DarthVader quote on any error, see screenshot)
  • add shortcut [Ctrl+e] for SaveAs
  • add shortcuts to 2daOps menu
  • add mnemonics to all menus
  • fix/tighten many shortcuts’ Enabled/Disabled determinations
  • tweaks to Clipboard editor (no wordwrap, add Done button)
  • monitor changes on disk to opened files (deleted, moved, renamed, or saved outside of Yata)
  • SaveAll on the File menu (is Beta - be careful, make backups of open files first! SaveAll is Beta)
  • don’t beep when pressing [Enter] on Search or Goto
  • Ctrl+Left/Right: shifts table by visible width left/right
  • update ReadMe.txt

I’m the only guy testing these releases. And all i do is poke at it with my mouse for a while … but the state-space in a multi-tabbed app is, uh, large. So on a large release like this, be wary. Please keep your eye on things,

Do backups.

EDIT: am going to try to make some kind of a differ …

1 Like

In that case you might want to check out WinMerge. It’s a free and open source differencing program and a link to the source can be found here.


thanks Tarot,

it totally passed me by that WinMerge is foss. At the moment such code is a bit extravagant, though; if I can simply get the cells of two loaded tables to show up with a different color (consistently, etc.) – that’s all i’m looking at right now.

sorta like so

… a Merge function is, well, later. Then i might well scrape some calcification off my neurons and have a look,

Another thought is that you could get Yata to spawn an instance of WinMerge with a command line featuring the two 2da files. Purely as a stop-gap until you can get around to writing your own comparison routines.


1 Like

found a bug that’s been lurking for a while … ie. when deleting multiple rows AND the id of the selected row is greater than the id(s) of the subselected rows, the range is negative but there are places where i didn’t account for that.

Workaround: when deleting rows, always select the lesser row first, then subselect [Shift+click] rows with a greater id-value

will be fixed, but am making progress on the differ atm

/// <summary>
/// Handles a single-cell merge operation.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void cellclick_Merge(object sender, EventArgs e)
    YataGrid destTable = null;
    if      (Table == _diff1) destTable = _diff2;
    else if (Table == _diff2) destTable = _diff1;

    if (destTable != null) // safety.
        Cell src = Table.getSelectedCell();
        int r = src.y;
        int c = src.x;

        Cell dst = destTable[r,c];
        destTable.ChangeCellText(dst, src.text);

        _diff1[r,c].diff =
        _diff2[r,c].diff = false;

/heh I still like the idea of spawning WinMerge for big operations.

erm, Isn’t this an error? Surely you need to have something to actually assign to _diff1[r,c].diff.


It’s not an error.

It’s equivalent to

_diff1[r,c].diff = _diff2[r,c].diff = false;

which reads as

_diff2[r,c].diff = false;
_diff1[r,c].diff = _diff2[r,c].diff;

NwScript test 1

void main()
    int a,b;
    a = b = 1;
> Executing: C:\Program Files (x86)\ConTEXT\ConExec.exe "c:\nwn2\asc.exe" -ago -i C:\nwn2 -v1.69 "test.nss"

NWNScriptCompiler - built Jan 29 2014 19:24:04
Copyright (C) 2008-2014 Skywing.
Portions copyright (C) 2002-2003, Edward T. Smith.
Portions copyright (C) 2003, The Open Knights Consortium.
Compiling: test.NSS

test.nss(4): Warning: NSC6021: The standard compiler does not support nested
assignment RHS expressions that are themselves an assignment type expression.
Consider encapsulating the right-hand-side expression in parens (), or
unwrapping the nested assignment for compatibility with the standard compiler.

Total Execution time = 62ms

> Execution finished.

NwScript test 2

void main()
    int a,b;
    a = (b = 1);
> Executing: C:\Program Files (x86)\ConTEXT\ConExec.exe "c:\nwn2\asc.exe" -ago -i C:\nwn2 -v1.69 "test.nss"

NWNScriptCompiler - built Jan 29 2014 19:24:04
Copyright (C) 2008-2014 Skywing.
Portions copyright (C) 2002-2003, Edward T. Smith.
Portions copyright (C) 2003, The Open Knights Consortium.
Compiling: test.NSS

Total Execution time = 31ms

> Execution finished.

/vewy interesting

sorta like so

/// <summary>
/// Starts an external diff/merger program with the two diffed files
/// opened. Usually WinMerge.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void opsclick_ExternalDiff(object sender, EventArgs e)
    if (File.Exists(Settings._diff))
        var diff = new Process();
        diff.StartInfo.FileName = Settings._diff;

        if (_diff1 != null && _diff2 != null
            && File.Exists(_diff1.Fullpath)
            && File.Exists(_diff2.Fullpath))
            diff.StartInfo.Arguments = " \"" + _diff1.Fullpath + "\" \"" + _diff2.Fullpath + "\"";
            diff.StartInfo.Arguments = " \"" + Table.Fullpath + "\"";


thanks for the idea, Tarot, it works lovely  :blossom:

a) do a Yata diff
b) select 2daOps|External diff
c) apply WinMerge, save file
d) Yata’s file-monitor pops up -> reload 2da
e) profit.

- the path to Winmerge needs to be [EDIT] will need to be set manually in Yata’s “settings.cfg” [config file]

I might handle kdiff3 also … will see … WinMerge is more than good enough for 2da files  :|

ps. Turns out that kdiff3 accepts the same cl args … so user choice.

Edit: (rewrite function)

1 Like

Appendix L: Yata diff

Yata version 3+ has an internal differ. A right-click on a table’s tab shows a
popup with several operations including these four:

  • Select diff1 (selects the currently displayed table as diff1)
  • Select diff2 (selects the currently displayed table as diff2)
  • Reset diffs (clears tables of their diff flags)
  • Justify tables (re-widths the cols of the two diffed tables so they are
    visually aligned)

Notes: diff1 must be selected before diff2. Diff2 can be re-selected, but
re-selecting diff1 causes diff2 to be cleared; diff2 must be selected after
diff1. Reloading a 2da causes its diff to be cleared.

Select diff2 causes four noticable things to happen:

  1. cells with texts that differ will be rendered with a teal background color
  2. the tables’ cols will be justified automatically
  3. the tables will scroll in unison if possible
  4. the DifferDialog will appear. It lists any differences between col headers
    and row counts. Additionally a Goto button in the lower left corner of the
    dialog can be used to cycle (forward only) through cell texts that are different
    in the two tables. Note that the count of cell differences includes the ID cols
    but their backgrounds will not be colored teal (since the ID col is a frozen

A right-click on a diffed cell shows a popup with several operations including
these two:

  • merge to other - Ce (copies the text in the selected cell to the other table)
  • merge to other - Ro (copies the texts of the row of the selected cell to the
    other table)

The selected cell’s position (x/y) must be present in both tables. Rows do not
have to be the same length; any cells that overflow will be filled with “****”.

Merges of multiple cells or rows is not allowed. That’s what Appendix M:
WinMerge is for …

Appendix M: WinMerge

The operation under 2da Ops->External diff/merger will be enabled if the path to
your WinMerge executable is specified in Settings.Cfg by the variable “diff=”

  • eg
    diff=C:\Program Files (x86)\WinMerge\WinMergeU.exe

A diff is performed in Yata from its Tab menu (see Appendix L: Yata diff). If
you are doing a diff and the External diff/merger is invoked, WinMerge should
start with the two diffed files loaded.

Note that if you’re not doing a diff in Yata and select the operation, WinMerge
should start with a dialog asking what file you’d like to diff against the
currently displayed 2da.

Also note that kdiff3 accepts the same commandline file arguments as WinMerge,
so the path to its executable can be assigned in Settings.Cfg if preferred.

If a file is saved in the external differ, Yata’s file monitor should pop up
asking what to do (Reload file, Close 2da, or Cancel).

update 2019 may 22

  • implement internal diff/merge operations (right-click a Tab: select diff1, select diff2, reset, justify tables)
  • implement var “diff=” in Settings.Cfg for an external diff/merge program (WinMerge, kdiff3)
  • fix Clear Undo/Redo’s enabled/disabled determination
  • underline the current tab’s text iff the tabcontrol has focus (as an indicator that the grid does not have focus)
  • change shift-page-by-visible-width’s modifier key to Shift+Left/Right (was Ctrl+Left/Right)
  • Shift+Mousewheel shifts table by visible height/width (Ctrl+Mousewheel already forces horizontal scroll if possible)

I’ve been coding and re-coding Yata over the past weeks. But i want to see if anything “obviously stupid” shows before distributing an executable. In the by & by here’s a thing I’ve wanted for Spells.2da for a while:

(edit) change screenshot /wip


2019 june 8

- PropertyPanel: draw the background of frozen fields with a lightgray color
- PropertyPanel: cycle location through all four corners of the table (instead of just top or bottom right)
- PropertyPanel: fix location when the form is resized
- FontDialog: rework (incl/ remove ShowCurrentFontString from the Font menu and display the .NET string in the dialog itself)
- Shift-key reverses Search direction (ditto for GotoLoadchanged and GotoDiff)
- add Save to the right-click tab menu
- add Edit to the right-click cell menu
- add option for a fixedwidth font in Settings.Cfg (“fontf=”)
- add option for a recently opened files list in Settings.Cfg (“recent=”) [see note below.]
- paint frozen fields’ background color as selected, searched, loadchanged, or diffed as applicable
- render the text of a colhead in a different color if the table is sorted by that col
- fix Clipboard menu’s enabled determinations
- close the tab, cell, and/or context menu (if showing) when the table is scrolled
- close the DifferDialog on diff-reset or re-diff
- reworked scrollbars and totally reworked UI invalidations/screen updates – this involved a lot of fiddly stuff and if i missed something it could result in an awkward/unrefreshed UI-state (if screen updates) or throw an exception (if scrollbars). Pls report w/ steps to reproduce if you notice a glitch.
- minor and not so minor code fixes & changes
- update ReadMe.txt

re. PathInfo for Spells.2da: values for the following cols can be chosen via right-click Cell->input:
- School
- Range
- MetaMagic
- TargetType
- ImmunityType (not technically used by NwN2 but it’s a good idea to keep things consistent)
- Category (if Categories.2da is pathed)
- UserType
- AsMetaMagic
- TargetingUI (if SpellTarget.2da is pathed)

Reminder to backup your custom 2das before opening them in Yata (!)

a Note on Settings.Cfg option.
recent=(integer) a count of recently opened file-paths to store. If left
            blank or a value less than 1 is specified, recently opened files will
            not be tracked, while 16 is the hardcoded upper limit. SETTING
            “recent=” TO A VALID VALUE ENABLES YATA TO WRITE THE FILE Recent.Cfg
            TO ITS APPLICATION DIRECTORY. Recent.Cfg stores filepaths (without
            quotes). THE WRITE-OPERATION CAN FAIL for a variety of reasons that I
            really don’t want to be arshed with - hence the option so you can
            decide if it works on your OS.

1 Like

2019 jun 13

  • fix overflow on the Recent files list
  • DifferDialog: show Goto button only if cell-diffs actually occured + tweak format of output text
  • (Paths) InfoInputDialog:
    – list “MetaMagic” Invocation Blasts and Shapes alphabetically
    – fix initial “School” checkbox determinations
    – add Clear button, add MetaMagic groups
  • RowCreatorDialog:
    – fix possible invalid value not generating an error
    – Add at end
    – Insert at ID
    – by final ID
    – by quantity of rows
    – option to fill with currently copied row’s fields

2019 jun 18

  • RowCreatorDialog: add 2 more options to fill
    – with stars (****) [default]
    – with selected row’s fields
  • File menu: add Readonly flagger/deflagger
  • proper disposal of child windows
  • limit size of user-defined fonts when they appear in dialog windows
  • DifferDialog:
    – close dialog if both diffed tables are closed
    – clear any diff2 persistence before doing a re-diff
    – tighten sync of diffed tables when selecting cells/rows/cols or scrolling (beware, very fiddly change)
    – don’t sync tables if they are identical
    – focus the table when the goto-diff button is clicked
    – fix obscure scrollbar exceptions when sync’d
    – add a Reset button to the dialog
    – tighten constructor code
  • relax restrictions for SaveAll enabled
  • shortcut keys added:
    – [F2] opens RowCreator dialog
    – [F4] closes the currently focused tab/table
    – [F9] exports copied row(s) to clipboard
    – [F10] imports clipboard to copied row(s)
    – [F11] opens the clipboard
    – [F12] toggles the currently focused table’s Readonly flag
  • plus assorted tweaks and UI-update fixes

Settings.Cfg has not been changed (since last release that it did change); be careful with your Settings file!

friendly reminder to backup your 2das (particularly since I did some changes in and around the SaveAll routine)

1 Like