/** xstyles.c - (c) 1994 Copyright by John R. Punin
 *
 * ASHE
 * 
 * This file has the routines to implement the items in the
 * 
 * Menus Styles and Lists
 * 
 * John R. Punin      April -30 - 1994
 *
*/
#include "xhtml.h"
#include "xfile.h"
#include "xheader.h"
#include "xmarkup.h"
#include "xstyles.h"

/*
   
   NAME : routines_styles
   PARAMETERS : int item_no
                Item number of the menu Styles
   RETURN : void
   DESCRIPTION :This is a Callback function that is called when
                one of the items of the Styles menu is selected.
		This function creates a Dialog Window to be 
		used for all items. Each item change the label
		of the dialog widget

*/

void 
routines_styles(Widget w, int item_no, XtPointer call_data)
{
   Widget dialog;
   XmString mstring,u,t;
   enum commands command;
   char *mstr;
   HTMLED *he;
   Widget parent = XtParent(w);

   XtVaGetValues(parent,XmNuserData,&he,NULL);

   if(strcmp(XtName(parent),"menu_doc"))
      t = Initial_text(item_no,&command);
   else
      t = Initial_text(item_no+10,&command);

   he->user_data = (XtPointer)command;
   mstr = XmTextGetSelection(he->textarea);
   if(mstr)
   {
      dialog = XmCreatePromptDialog(he->textarea,"notice_header",NULL,0);
      mstring = XmStringCreateLtoR(mstr,XmSTRING_DEFAULT_CHARSET);
      XtFree(mstr);
      u = XmStringConcat(t,mstring);
      
      XmStringFree(mstring);
      XtVaSetValues(dialog,
		    XmNselectionLabelString,u,NULL);
      XmStringFree(u);
      /* When the user choose a size of the header, call set_header */

      XtAddCallback(dialog, XmNokCallback,
		    (XtCallbackProc)set_style,(XtPointer)he);
      
      /* If the user selects cancel, just destroy the header dialog */
      XtAddCallback(dialog, XmNcancelCallback,
		    (XtCallbackProc)XtDestroyWidget,NULL);
      
      /* Nor help neither text is available.... */
      XtUnmanageChild(XmSelectionBoxGetChild(dialog,XmDIALOG_HELP_BUTTON));
      XtUnmanageChild(XmSelectionBoxGetChild(dialog,XmDIALOG_TEXT));
      XtManageChild(dialog);
      XWarpPointer(XtDisplay(he->textarea),XtWindow(he->textarea),
		   XtWindow(dialog),
                   0,0,800,800,20,20);
   }
   else
      set_style(w,(XtPointer)he,NULL);
   if(t) XmStringFree(t);
}
/*
   
   NAME : set_style
   PARAMETERS : enum commands command
                Code of the command that is executed
   RETURN : void
   DESCRIPTION :This is a Callback function that is called when
                the Ok button is selected in the style Dialog
		widget. Depending of the command the correspondent
		tags are inserted in the selected text.

*/
void 
set_style(Widget w, XtPointer client_data,XtPointer unused)
{
   HTMLED *he = (HTMLED *)client_data;
   enum commands command = (enum commands)he->user_data;
   char *strleft,*stright;
   XmTextPosition left=0,right=0;
   int len=0;
   strleft = XtMalloc(20);
   stright = XtMalloc(20);
   Command_text(command,strleft,stright);
   he->last_command = command;

   if(XmTextGetSelectionPosition(he->textarea,&left,&right))
   {
      if(right<=left)
	 left = right = XmTextGetInsertionPosition(he->textarea);
   }
   else
      left = right = XmTextGetInsertionPosition(he->textarea);
   if(left!=right)
      len = right - left;
   
   XmTextInsert(he->textarea,right,stright);
   XmTextInsert(he->textarea,left,strleft);
   if(len==0)
      len += strlen(strleft);
   else
      len += strlen(strleft)+strlen(stright);
   XmTextSetInsertionPosition(he->textarea,left+len);
   ChangeInsertionpoint(command,left,he);
   XtFree(strleft);   XtFree(stright);
   XmProcessTraversal(he->textarea,XmTRAVERSE_CURRENT); 
}
void 
ChangeInsertionpoint(enum commands command,XmTextPosition left,HTMLED *he)
{
   switch(command)
   {
   case ORLIST:
   case UNLIST:
      XmTextSetInsertionPosition(he->textarea,left+10);
      break;
   default:
      break;
      
   }
}

/*
   
   NAME : Command_text
   PARAMETERS : enum commands command
                Command to be executed
                char *sl
		Left Tag
		char *sr
		Right Tag
   RETURN : void
   DESCRIPTION :This function set the left and right tags
                depending of the command

*/
void 
Command_text(enum commands command,char *sl,char *sr)
{
   switch(command)
   {
   case EM:
      strcpy(sl,"<EM>");
      strcpy(sr,"</EM>");
      break;
   case STRONG:
      strcpy(sl,"<STRONG>");
      strcpy(sr,"</STRONG>");
      break;
   case CODE:
      strcpy(sl,"<CODE>");
      strcpy(sr,"</CODE>");
      break;
   case CITE:
      strcpy(sl,"<CITE>");
      strcpy(sr,"</CITE>");
      break;
   case BLOCKQ:
      strcpy(sl,"\n<BLOCKQUOTE>\n");
      strcpy(sr,"\n</BLOCKQUOTE>\n");
      break;
   case ADDR:
      strcpy(sl,"<ADDRESS>");
      strcpy(sr,"</ADDRESS>");
      break;
   case BOLD:
      strcpy(sl,"<B>");
      strcpy(sr,"</B>");
      break;
   case ITALIC:
      strcpy(sl,"<I>");
      strcpy(sr,"</I>");
      break;
   case UNDER:
      strcpy(sl,"<U>");
      strcpy(sr,"</U>");
      break;
   case TT:
      strcpy(sl,"<TT>");
      strcpy(sr,"</TT>");
      break;

   case UNLIST:
      strcpy(sl,"\n<UL>\n<LI>");
      strcpy(sr,"\n</UL>\n");
      break;
   case ORLIST:
      strcpy(sl,"\n<OL>\n<LI>");
      strcpy(sr,"\n</OL>\n");
      break;
   case HTML:
      strcpy(sl,"<HTML>\n");
      strcpy(sr,"\n</HTML>\n");
      break;
   case HEAD:
      strcpy(sl,"<HEAD>\n");
      strcpy(sr,"\n</HEAD>");
      break;
   case BODY:
      strcpy(sl,"<BODY>\n");
      strcpy(sr,"\n</BODY>");
      break;
   default:
      break;
   }
}
/* Set the Label and the command of the Style Dialog Widget */
XmString
Initial_text(int item_no,enum commands *command)
{
   char str[50];
   switch(item_no)
   {
   case 0:strcpy(str,"Emphasis Text is : \n"); *command = EM;break;
   case 1:strcpy(str,"Strong Text is : \n"); *command = STRONG;break;
   case 2:strcpy(str,"Code Text is : \n"); *command = CODE;break;
   case 3:strcpy(str,"Cite Text is : \n"); *command = CITE;break;
   case 4:strcpy(str,"Blockquote Text is : \n"); *command = BLOCKQ;break;
   case 5:strcpy(str,"Address Text is : \n"); *command = ADDR;break;
   case 6:strcpy(str,"Bold Text is : \n"); *command = BOLD;break;
   case 7:strcpy(str,"Italic Text is : \n"); *command = ITALIC;break;
   case 8:strcpy(str,"Underline Text is : \n"); *command = UNDER;break;
   case 9:strcpy(str,"Typewriter Text is : \n"); *command = TT;break;
      /* this is Document Submenu */
   case 10:strcpy(str,"HTML Text is : \n"); *command = HTML;break;
   case 11:strcpy(str,"Head Text is : \n"); *command = HEAD;break;
   case 12:strcpy(str,"Body Text is : \n"); *command = BODY;break;
   default: break;
      

   }
   return(XmStringCreateLtoR(str,XmSTRING_DEFAULT_CHARSET));
}
/* 
   NAME : routines_list
   PARAMETERS : int item_no
                Item number of the menu Lists
   RETURN : void
   DESCRIPTION :This is a Callback function that is called when
                one of the items of the Lists menu is selected.
*/
void
routines_lists(Widget w, int item_no, XtPointer call_data)
{
   HTMLED *he;
   Widget parent = XtParent(w);

   XtVaGetValues(parent,XmNuserData,&he,NULL);
   
   switch(item_no)
   {
   case 0:
      set_definition_list(w,he); break;
   case 1:
      set_definition_entry(w,he); break;
   case 2:
   case 3:
      set_simple_list(w,item_no,he); break;
   case 4:
      set_simple_entry(w,he); break;
   }
}

/*
   
   NAME : set_definition_list
   PARAMETERS : Widget w
                From what widget this function is called.
   RETURN : void
   DESCRIPTION : This function inserts the definition list
                 where the insertion cursor is

*/
      
void 
set_definition_list(Widget w,HTMLED *he)
{
   XmTextPosition left;
   he->last_command = DEFLIST;
   left = XmTextGetInsertionPosition(he->textarea);
   XmTextInsert(he->textarea,left,"\n<DL>\n<DT>\n<DD>\n</DL>\n");
   XmTextSetInsertionPosition(he->textarea,left+10);
   XmProcessTraversal(he->textarea,XmTRAVERSE_CURRENT); 
}
/*
   
   NAME : set_definition_entry
   PARAMETERS : Widget w
                From what widget this function is called.
   RETURN : void
   DESCRIPTION : This function inserts the term of definition list
                 where the insertion cursor is

*/
void 
set_definition_entry(Widget w,HTMLED *he)
{
   XmTextPosition left;
   he->last_command = TERM;
   left = XmTextGetInsertionPosition(he->textarea);
   XmTextInsert(he->textarea,left,"\n<DT>\n<DD>\n");
   XmTextSetInsertionPosition(he->textarea,left+5);
   XmProcessTraversal(he->textarea,XmTRAVERSE_CURRENT); 
   
}
/*
   
   NAME : set_simple_list
   PARAMETERS : Widget w
                From what widget this function is called.
		int item_no
		0 if it is ordered list or 1 if it is
		unordered list
   RETURN : void
   DESCRIPTION : This function inserts a bulleted or numbered list
                 where the insertion cursor is depending on item_no

*/
void 
set_simple_list(Widget w,int item_no,HTMLED *he)
{ 
   Widget dialog;
   XmString mstring,u,t=NULL;
   char *mstr;
   enum commands command;
   t = Initial_list(item_no,&command);
   he->user_data = (XtPointer)command;
   
   mstr = XmTextGetSelection(he->textarea);
   if(mstr)
   {
      dialog = XmCreatePromptDialog(he->textarea,"notice_header",NULL,0);
      mstring = XmStringCreateLtoR(mstr,XmSTRING_DEFAULT_CHARSET);
      u = XmStringConcat(t,mstring);
      
      XmStringFree(mstring);
      XtVaSetValues(dialog,
		    XmNselectionLabelString,u,NULL);
      XmStringFree(u);
      /* When the user choose a ordered_list, call set_type_list */

      XtAddCallback(dialog, XmNokCallback,(XtCallbackProc)set_style,(XtPointer)he);
      
      /* If the user selects cancel, just destroy the header dialog */
      XtAddCallback(dialog, XmNcancelCallback,(XtCallbackProc)XtDestroyWidget,NULL);
      
      /* Nor help neither text is available.... */
      XtUnmanageChild(XmSelectionBoxGetChild(dialog,XmDIALOG_HELP_BUTTON));
      XtUnmanageChild(XmSelectionBoxGetChild(dialog,XmDIALOG_TEXT));
      XtManageChild(dialog);
      XWarpPointer(XtDisplay(he->textarea),XtWindow(he->textarea),
		   XtWindow(dialog),
                   0,0,800,800,20,20);
   }
   else
      set_style(w,(XtPointer)he,NULL);
   if(t) XmStringFree(t);

}
/*
   
   NAME : Initial_list
   PARAMETERS : int item_no,
                Bulleted or Numbered list
                enum commands *command
                command to be executed
   RETURN : void
   DESCRIPTION : This function set the name of the 
                 label in the list Dialog widget. It
		 takes the selected text as a first item
*/
XmString
Initial_list(int item_no,enum commands *command)
{
   char str[50];
   if(item_no == 2)
   {
      *command = UNLIST;
      strcpy(str,"Unordered list is :\n\nFirst Item :\n\t");
   }
   else if(item_no==3)
   {
      *command = ORLIST;
      strcpy(str,"Ordered list is :\n\nFirst Item :\n\t");
   }
   return(XmStringCreateLtoR(str,XmSTRING_DEFAULT_CHARSET));
}
/*
   
   NAME : set_simple_entry
   PARAMETERS : Widget w
                From what widget this function is called.
   RETURN : void
   DESCRIPTION : This function inserts the labeled item list
                 where the insertion cursor is

*/
void 
set_simple_entry(Widget w,HTMLED *he)
{
   XmTextPosition left = XmTextGetInsertionPosition(he->textarea);
   he->last_command = ITEM;
   XmTextInsert(he->textarea,left,"\n<LI>");
   XmTextSetInsertionPosition(he->textarea,left+5);
   XmProcessTraversal(he->textarea,XmTRAVERSE_CURRENT); 
}

/********************************************************************
   This routines to help you to add HTML characters items to 
   the menu characters.

   Feel Free to add any special characters that you like it.

   Please, see the binding keys before you add any binding keys for
   characters.

   For more information about HTML characters, see the help menu
   on characters. 

*********************************************************************/
void 
BuildCharactersMenu(Widget menubar, HTMLED *he)
{
   /* Sixth menu is the Characters menu */
   XmString less_than = XmStringCreateSimple("Less than");
   XmString less_than_acc = XmStringCreateSimple("Ctrl-L");
   XmString greater_than= XmStringCreateSimple("Greater than");
   XmString greater_than_acc = XmStringCreateSimple("Ctrl-G");
   XmString ampersand = XmStringCreateSimple("Ampersand");
   XmString ampersand_acc = XmStringCreateSimple("Ctrl-&");
   XmString quote = XmStringCreateSimple("Quote");
   XmString quote_acc = XmStringCreateSimple("Ctrl-Q");

   /* Add new XmString characters and new acc for characters */


   XmVaCreateSimplePulldownMenu(menubar,"characters_menu",6,
				(XtCallbackProc)routines_carac,
	   XmVaPUSHBUTTON, less_than, '\0', "Ctrl Shift<Key> l",less_than_acc,
    XmVaPUSHBUTTON, greater_than, '\0', "Ctrl Shift <Key> g",greater_than_acc,
	  XmVaPUSHBUTTON, ampersand, '\0', "Ctrl Shift <Key> 7",ampersand_acc,
		   XmVaPUSHBUTTON, quote, '\0',"Ctrl Shift <Key> q",quote_acc,
		   XmNuserData,he,
       NULL);

   /* Make sure to free the XmStrings */
   XmStringFree(quote);XmStringFree(quote_acc);
   XmStringFree(ampersand);XmStringFree(ampersand_acc);
   XmStringFree(less_than); XmStringFree(less_than_acc);
   XmStringFree(greater_than); XmStringFree(greater_than_acc);
   
}

/* Please, do not modify this routine */
void 
routines_carac(Widget w, int item_no, XtPointer call_data)
{
   XmTextPosition pos;  
   HTMLED *he;
   String carac = get_character(item_no);
   Widget parent = XtParent(w);

   XtVaGetValues(parent,XmNuserData,&he,NULL);

   pos = XmTextGetInsertionPosition(he->textarea);
   he->last_command = CARAC;
   
   XmTextInsert(he->textarea,pos,carac);
   XmTextSetInsertionPosition(he->textarea,pos + strlen(carac)); 
   XmProcessTraversal(he->textarea,XmTRAVERSE_CURRENT);
   XtFree(carac);
}

char *
get_character(int item_no)
{
   String carac = XtMalloc(20);

   switch(item_no)
   {
   case 0:
      strcpy(carac,"&lt;"); break;
   case 1:
      strcpy(carac,"&gt;"); break;
   case 2:
      strcpy(carac,"&amp;"); break;
   case 3:
      strcpy(carac,"&quot;"); break;
      /* Add new cases for new HTML characters */
   }
   return(carac);
}
