
/* MenuText.c */

/* Musical Notation Editor for X, Chris Cannam 1994 */
/* Functions to handle actions from Words menu options */


#include "General.h"
#include "Widgets.h"
#include "Menu.h"
#include "Stave.h"
#include "StaveEdit.h"
#include "StavePrivate.h"
#include "ItemList.h"
#include "Yawn.h"


static void TextMenuText(TextPosnTag tag)
{
  MajorStaveRec *mstave  = (MajorStaveRec *)stave;
  ItemList       start   = mstave->sweep.from.left;
  ItemList       end     = mstave->sweep.to.left;
  int            staveNo = mstave->sweep.stave;
  String         text;
  Item          *item;

  Begin("TextMenuTextAbove");

  if (!stave || !mstave->sweep.swept || start != end) {
    XBell(display, 70);
    End;
  }

  if (!(text = YGetUserInput
	(topLevel, "Enter text:",
	 NULL, YOrientHorizontal, tag == TextAboveBarLine ?
	 "Bar - Label" : "Text - Add Text options"))) End;

  item = (Item *)NewText(NULL, XtNewString(text), tag);

  if (start)
    if (Next(start)) Insert(NewItemList(item), Next(start));
    else Nconc(start, NewItemList(item));
  else mstave->music[staveNo] =
    (ItemList)First(Nconc(NewItemList(item), mstave->music[staveNo]));

  FileMenuMarkChanged(stave, True);
  StaveResetFormatting(stave, staveNo);
  StaveRefreshAsDisplayed(stave);
  End;
}



void TextMenuTextAbove(Widget w, XtPointer a, XtPointer b)
{
  Begin("TextMenuTextAbove");

  TextMenuText(TextAboveStave);

  End;
}


void TextMenuTextAboveBig(Widget w, XtPointer a, XtPointer b)
{
  Begin("TextMenuTextAboveBig");

  TextMenuText(TextAboveStaveLarge);

  End;
}


void TextMenuTextBelow(Widget w, XtPointer a, XtPointer b)
{
  Begin("TextMenuTextBelow");

  TextMenuText(TextBelowStave);

  End;
}


void TextMenuTextBelowI(Widget w, XtPointer a, XtPointer b)
{
  Begin("TextMenuTextBelowI");

  TextMenuText(TextBelowStaveItalic);

  End;
}


void BarMenuLabel(Widget w, XtPointer a, XtPointer b)
{
  int            barNo;
  StaveEltList   barList;
  MajorStaveRec *mstave = (MajorStaveRec *)stave;

  Begin("BarMenuLabel");

  if (!stave || !mstave->sweep.swept ||
      mstave->sweep.to.left != mstave->sweep.from.left) {
    XBell(display, 70);
    End;
  }

  for (barNo = 0, barList = mstave->bar_list;
       barList && barNo < mstave->sweep.from.bar->bar.number;
       barList = (StaveEltList)Next(barList), ++barNo);

  if (!barList || !BarValid(barList->bars[mstave->sweep.stave])) {
    XBell(display, 70);
    End;
  }

  if (Prev(barList->bars[mstave->sweep.stave]->group.start))
    mstave->sweep.from.left = mstave->sweep.to.left =
      iPrev(barList->bars[mstave->sweep.stave]->group.start);
  else mstave->sweep.from.left = mstave->sweep.to.left = NULL;

  TextMenuText(TextAboveBarLine);

  End;
}



void TextMenuUnlabelGroup(Widget w, XtPointer a, XtPointer b)
{
  MajorStaveRec *mstave  = (MajorStaveRec *)stave;
  ItemList       start   = mstave->sweep.from.left;
  ItemList       end     = mstave->sweep.to.left;
  int            staveNo = mstave->sweep.stave;
  ItemList       list;
  Boolean        haveText = False;

  Begin("TextMenuUnlabelGroup");

  if (!stave || !mstave->sweep.swept || !end || start == end) {
    XBell(display, 70);
    End;
  }

  if (start) list = iNext(start);
  else       list = mstave->music[staveNo];

  while (list) {

    if (list->item->object_class == TextClass) {

      haveText = True;
      mstave->music[staveNo] =
	(ItemList)First(ItemListExpungeGroups(mstave->music[staveNo],
					      iPrev(list), list));
      list = (ItemList)Remove(list);

    } else list = iNext(list);

    if (list && Prev(list) && end == iPrev(list)) break;
  }

  if (!haveText) {
    IssueMenuComplaint("There is no text within that group.");
    End;
  }

  FileMenuMarkChanged(stave, True);
  StaveResetFormatting(stave, staveNo);
  StaveRefreshAsDisplayed(stave);
  End;
}


void TextMenuUnlabelBar(Widget w, XtPointer a, XtPointer b)
{
  MajorStaveRec *mstave  = (MajorStaveRec *)stave;
  int            staveNo = mstave->sweep.stave;
  int            barNo;
  StaveEltList   barList;
  ItemList       list;
  Boolean        haveText = False;

  Begin("TextMenuUnlabelBar");

  if (!stave || !mstave->sweep.swept ||
      mstave->sweep.from.left != mstave->sweep.to.left) {
    XBell(display, 70);
    End;
  }

  for (barNo = 0, barList = mstave->bar_list;
       barList && barNo < mstave->sweep.from.bar->bar.number;
       barList = (StaveEltList)Next(barList), ++barNo);

  if (!barList || !BarValid(barList->bars[staveNo])) {
    XBell(display, 70);
    End;
  }

  list = barList->bars[staveNo]->group.start;

  while (list) {

    if (list->item->object_class == TextClass) {

      haveText = True;
      mstave->music[staveNo] =
	(ItemList)First(ItemListExpungeGroups(mstave->music[staveNo],
					      iPrev(list), list));
      list = (ItemList)Remove(list);

    } else list = iNext(list);

    if (list && Prev(list) &&
	barList->bars[staveNo]->group.end == iPrev(list)) break;
  }

  if (!haveText) {
    IssueMenuComplaint("There is no text in that bar.");
    End;
  }

  FileMenuMarkChanged(stave, True);
  StaveResetFormatting(stave, staveNo);
  StaveRefreshAsDisplayed(stave);
  End;
}


void TextMenuUnlabelStaff(Widget w, XtPointer a, XtPointer b)
{
  MajorStaveRec *mstave  = (MajorStaveRec *)stave;
  int            staveNo = mstave->sweep.stave;
  ItemList       list;
  Boolean        haveText = False;

  Begin("TextMenuUnlabelStaff");

  if (!stave || !mstave->sweep.swept ||
      mstave->sweep.from.left != mstave->sweep.to.left) {
    XBell(display, 70);
    End;
  }

  if (YQuery(topLevel,
	     "Are you sure you want to clear all the text in the staff?",
	     2, 1, 1, "Yes", "No", "Text - Clear Staff") != 0) End;

  list = mstave->music[staveNo];

  while (list) {

    if (list->item->object_class == TextClass) {

      haveText = True;
      mstave->music[staveNo] =
	(ItemList)First(ItemListExpungeGroups(mstave->music[staveNo],
					      iPrev(list), list));
      list = (ItemList)Remove(list);

    } else list = iNext(list);
  }

  if (!haveText) {
    IssueMenuComplaint("There is no text on that staff.");
    End;
  }

  FileMenuMarkChanged(stave, True);
  StaveResetFormatting(stave, staveNo);
  StaveRefreshAsDisplayed(stave);
  End;
}


void BarMenuUnlabel(Widget w, XtPointer a, XtPointer b)
{
  MajorStaveRec *mstave  = (MajorStaveRec *)stave;
  int            staveNo = mstave->sweep.stave;
  int            barNo;
  StaveEltList   barList;
  ItemList       list;
  Boolean        haveText = False;

  Begin("BarMenuUnlabel");

  if (!stave || !mstave->sweep.swept ||
      mstave->sweep.from.left != mstave->sweep.to.left) {
    XBell(display, 70);
    End;
  }

  for (barNo = 0, barList = mstave->bar_list;
       barList && barNo < mstave->sweep.from.bar->bar.number;
       barList = (StaveEltList)Next(barList), ++barNo);

  if (!barList || !BarValid(barList->bars[staveNo])) {
    XBell(display, 70);
    End;
  }

  list = barList->bars[staveNo]->group.start;

  while (list) {

    if (list->item->object_class == TextClass &&
	((Text *)list->item)->text.position == TextAboveBarLine) {

      haveText = True;

      if (mstave->music[staveNo] == list)
	mstave->music[staveNo] = iNext(list);
      list = (ItemList)Remove(list);

    } else list = iNext(list);

    if (list && Prev(list) &&
	barList->bars[staveNo]->group.end == iPrev(list)) break;
  }

  if (!haveText) {
    IssueMenuComplaint("That bar isn't labelled.");
    End;
  }

  FileMenuMarkChanged(stave, True);
  StaveResetFormatting(stave, staveNo);
  StaveRefreshAsDisplayed(stave);
  End;
}
