/************************************************************************
					ＸＷｉｎｄｏｗツールボックス

				ダイアログ・ユーティリティ・モジュール

			 		  Programmed by Y.Nishida

												[ Dec.09, 1993 ]
 ************************************************************************/

#include <string.h>
#include <ctype.h>
#include "ToolBox.h"

typedef struct {
	short  icon;
	short  count;
	String *message;
} AlertRecord,*AlertRecPtr;

/************************************************************************
	シフトＪＩＳをＪＩＳコードに変換する.
 ************************************************************************/

static void SetKanji(kanji,string)
XChar2b *kanji;
unchar *string;
{
	int high = *string;
	int low  = *(string+1);

	high -= (high <= 0x9f) ? 0x71 : 0xb1;
	high  = high * 2 + 1;

	if (low >  0x7f) low -= 1;

	if (low >= 0x9e) {
		low  -= 0x7d;
		high += 1;
	} else {
		low -= 0x1f;
	}
	kanji->byte1 = high;
	kanji->byte2 = low;
}

/************************************************************************
	日本語文字列の表示を行なう.
 ************************************************************************/

static int DrawJString(windowID,posx,posy,string)
Window windowID;
int posx,posy;
String *string;
{
	XChar2b buffer[256];
	int count = 0;

	while (iskanji(**string)) {
		SetKanji(&buffer[count],(unchar *)*string);
		*string += 2;
		count	+= 1;
	}
	if (count > 0) {
		XDrawImageString16(display,windowID,appliGPort,posx,posy,buffer,count);
		posx += XTextWidth16(appliFont,buffer,count);
	}
	return(posx);
}

/************************************************************************
	英語文字列の表示を行なう.
 ************************************************************************/

static int DrawEString(windowID,posx,posy,string)
Window windowID;
int posx,posy;
String *string;
{
	char *msgptr = *string;
	int  count	 = 0;

	while (!iskanji(**string)) {
		if (**string == '\0') break;
		if (**string == '\n') break;
		*string += 1;
		count	+= 1;
	}
	if (count > 0) {
		XDrawImageString(display,windowID,systemGPort,posx,posy,msgptr,count);
		posx += XTextWidth(systemFont,msgptr,count);
	}
	return(posx);
}

/************************************************************************
	日本語と英語の混合文字列の表示を行なう.
 ************************************************************************/

static void DrawString(windowID,homex,posx,posy,string)
Window windowID;
int homex,*posx,*posy;
String string;
{
	while (*string != '\0') {
		*posx = DrawJString(windowID,*posx,*posy,&string);
		*posx = DrawEString(windowID,*posx,*posy,&string);

		if (*string == '\n') {
			string += 1;
			*posx	= homex;
			*posy  += 20;
		}
	}
}

/************************************************************************
	テキストの表示を行なう.
 ************************************************************************/

extern void PrintText(window,posx,posy,count,text)
WindowPtr window;
int posx,posy,count;
String *text;
{
	int index;
	int homex = posx;

	for (index=0; index<count; index++) {
		DrawString(GetWindowID(window),homex,&posx,&posy,text[index]);
	}
}

/************************************************************************
	文字列の表示を行なう.
 ************************************************************************/

extern void PrintString(window,posx,posy,string)
WindowPtr window;
int posx,posy;
String string;
{
	DrawString(GetWindowID(window),posx,&posx,&posy,string);
}

/************************************************************************
	ダイアログへのキー入力を処理する.
	（リターン・キーが押された時は１番目のボタンが押されたことになる.
	  もしテキスト・エディットが存在すればＴＥに処理を渡す。）
 ************************************************************************/

extern void InputDialog(event,wcore)
XEventPtr event;
WCorePtr wcore;
{
	char buffer[256];
	KeySym symbol;
	WindowPtr window = (WindowPtr)wcore;

	if (XLookupString((XKeyEvent *)event,buffer,256,&symbol,(XComposeStatus *)NULL) == 1) {
		if (buffer[0] == '\r') {
			ControlPtr ctrl = window->control;

			if (ctrl != NULL) (*ctrl->ctrlProc)((WCorePtr)ctrl,0);
			return;
		}
	}
	if (window->activeTE != NULL) {
		InputTextEdit(event,window);
	}
}

/************************************************************************
	モーダル・ダイアログの処理を行なう.
 ************************************************************************/

extern int ModalDialog(window)
WindowPtr window;
{
	XEvent event;
	WCorePtr wcore;
	WCorePtr wmain = (WCorePtr)window;

	XSelectInput(display,((WCorePtr)window)->windowID,ExposureMask | KeyPressMask);
	ShowApplWindow(window);

	for (window->flags = 0; window->flags == 0; ) {
		XNextEvent(display,&event);
		if (XFindContext(display,event.xany.window,eventContext,(caddr_t *)&wcore) == 0) {

			if (wcore == wmain)	{
				(*wcore->eventProc)(&event,wcore);
			}
			else if (wcore->parentID == wmain->windowID && event.type != KeyPress) {
				(*wcore->eventProc)(&event,wcore);
			}
			else {
				switch (event.type) {
					case	  KeyPress: (*wmain->eventProc)(&event,wmain);	break;
					case	KeyRelease:
					case   ButtonPress:
					case ButtonRelease:
					case  MotionNotify: break;
							   default: (*wcore->eventProc)(&event,wcore);	break;
				}
			}
		}
	}
	return(window->flags);
}

/************************************************************************
	アラート・ダイアログのボタン処理を行なう.
 ************************************************************************/

static void AlertButtonProc(wcore,type)
WCorePtr wcore;
int type;
{
	ControlPtr ctrl  = (ControlPtr)wcore;
	WindowPtr parent = GetWindowPtr(wcore->parentID);

	if (parent != NULL) parent->flags = ctrl->refCon;
}

/************************************************************************
	アラート・ダイアログの描画を行なう.
 ************************************************************************/

static void DrawAlertDialog(event,wcore)
XEventPtr event;
WCorePtr wcore;
{
	int index,posy;

	if (event->type == Expose && event->xexpose.count == 0) {
		WindowPtr window  = (WindowPtr)wcore;
		ControlPtr ctrl	  = window->control;
		AlertRecPtr alert = (AlertRecPtr)window->refCon;

		XClearWindow(display,wcore->windowID);
		XDrawRectangle(display,wcore->windowID,systemGPort, 3, 3,wcore->width-7,wcore->height-7);

		if (alert->icon > 0) {
			XCopyPlane(display,systemPicture[19+alert->icon],wcore->windowID,systemGPort,0,0,32,32,10,10,1);
		}
		PrintText(window,60,30,alert->count,alert->message);

		XSetLineAttributes(display,systemGPort,3,LineSolid,CapRound,JoinRound);
		XDrawRectangle(display,wcore->windowID,systemGPort,wcore->width-94,wcore->height-39,79,29);
		XSetLineAttributes(display,systemGPort,0,LineSolid,CapButt ,JoinMiter);
	}
}

/************************************************************************
	アラート・ダイアログへのイベント処理を行なう.
 ************************************************************************/

static void AlertDialogEvent(event,wcore)
XEventPtr event;
WCorePtr wcore;
{
	switch (event->type) {
		case   Expose: DrawAlertDialog(event,wcore);	break;
		case KeyPress: InputDialog(event,wcore);		break;
	}
}

/************************************************************************
	アラートの処理を行なう.
 ************************************************************************/

extern int AlertDialog(px,py,width,height,button,icon,count,message)
int px,py,width,height,button,icon,count;
String *message;
{
	int result;
	XEvent event;
	WCorePtr wcore;
	AlertRecord alertWork;
	WindowPtr dialog = NewApplWindow(px,py,width,height,"",0,(long)&alertWork,AlertDialogEvent);

	CreatePushButton(dialog,width-90,height-35,70,20,"OK",1,AlertButtonProc);
	if (button > 0) {
		CreatePushButton(dialog,width-180,height-35,70,20,"Cancel",2,AlertButtonProc);
	}
	if (button > 1) {
		CreatePushButton(dialog,width-270,height-35,70,20,"Discard",3,AlertButtonProc);
	}
	alertWork.icon	  = icon;
	alertWork.count	  = count;
	alertWork.message = message;

	result = ModalDialog(dialog);
	DisposeApplWindow(dialog);
	return(result);
}

/************************************************************************
	新アラートの処理を行なう.
 ************************************************************************/

extern int AlertDialog2(px,py,width,height,icon,nbuttons,button,nmessages,message)
int px,py,width,height,icon,nbuttons,nmessages;
String *button,*message;
{
	XEvent event;
	WCorePtr wcore;
	AlertRecord alertWork;
	int result,count;

	int buttonPosx	 = width  - 90;
	int buttonPosy	 = height - 35;
	WindowPtr dialog = NewApplWindow(px,py,width,height,"",0,(long)&alertWork,AlertDialogEvent);

	for (count=1; count<=nbuttons; button++,count++) {
		CreatePushButton(dialog,buttonPosx,buttonPosy,70,20,*button,count,AlertButtonProc);
		buttonPosx -= 90;
		if (buttonPosx < 10) {
			buttonPosx  = width - 90;
			buttonPosy -= 30;
		}
	}
	alertWork.icon	  = icon;
	alertWork.count	  = nmessages;
	alertWork.message = message;

	result = ModalDialog(dialog);
	DisposeApplWindow(dialog);
	return(result);
}
