GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
/****************************************************************************1**2*W xcmds.c XGAP Source Frank Celler3**4**5*Y Copyright 1995-1997, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany6*Y Copyright 1997, Frank Celler, Huerth, Germany7*/8#include "utils.h" /* utility functions */910#include "popdial.h" /* popup dialogs */11#include "gapgraph.h" /* gap graphic sheet */12#include "gaptext.h" /* gap text sheet */13#include "xgap.h"14#include "pty.h"15#include "selfile.h"1617#include "xcmds.h"1819/****************************************************************************20**2122*F * * * * * * * * * * * * * local variables * * * * * * * * * * * * * * *23*/242526/****************************************************************************27**2829*V DialogOkCancel . . . . . . . . . . . . . . . . . Cancel/OK popup dialog30*/31static TypePopupDialog DialogOkCancel;323334/****************************************************************************35**36*V GapWindows . . . . . . . . . . . . . . . . . . . list of all gap windows37*/38static TypeList GapWindows;394041/****************************************************************************42**43*V HugeFont . . . . . . . . . . . . . . . . . . . huge font for text output44*/45static XFontStruct * HugeFont;464748/****************************************************************************49**50*V LargeFont . . . . . . . . . . . . . . . . . . large font for text output51*/52static XFontStruct * LargeFont;535455/****************************************************************************56**57*V NormalFont . . . . . . . . . . . . . . . . . normal font for text output58*/59XFontStruct * NormalFont;606162/****************************************************************************63**64*V PopupMenus . . . . . . . . . . . . . . . . . . . list of all popup menus65*/66static TypeList PopupMenus;676869/****************************************************************************70**71*V RunCursor . . . . . . . . . . . . cursor used when GAP is accepting input72*/73static Cursor RunCursor;747576/****************************************************************************77**78*V SleepCursor . . . . . . . . . cursor used when GAP isn't accepting input79*/80static Cursor SleepCursor;818283/****************************************************************************84**85*V SmallFont . . . . . . . . . . . . . . . . . . small font for text output86*/87static XFontStruct * SmallFont;888990/****************************************************************************91**92*V TextSelectors . . . . . . . . . . . . . . . . list of all text selectors93*/94static TypeList TextSelectors;959697/****************************************************************************98**99*V TinyFont . . . . . . . . . . . . . . . . . . . tiny font for text output100*/101static XFontStruct * TinyFont;102103104/****************************************************************************105**106107*F * * * * * * * * * * * * communication with GAP * * * * * * * * * * * * *108*/109110111/****************************************************************************112**113114*F AnswerGap( <format>, <arg1>, <arg2>, <arg3>, <arg4> ) . . . return answer115*/116#define ANSWER_GAP(a,b,c,d,e) \117AnswerGap( a, (Long)(b), (Long)(c), (Long)(d), (Long)(e) )118119static Boolean AnswerGap (120String format,121Long a1,122Long a2,123Long a3,124Long a4 )125{126Int arg;127Int len;128Int m;129Int n;130Long args[4];131String ptr;132String qtr;133String str;134String wtr;135Char hdr[14];136137/* give debug information */138DEBUG( D_COMM, ( "AnswerGap( \"%s\", ... )\n", format ) );139140/* compute length of return string */141args[0] = a1; args[1] = a2; args[2] = a3; args[3] = a4;142len = 12;143arg = 0;144for ( ptr = format; *ptr; ptr++ )145{146if ( arg == 4 )147return False;148switch ( *ptr )149{150case 'O':151case 'o': len += 9; break;152case 'E':153case 'e': len += 9; break;154case 'D':155case 'd': len += 9; arg++; break;156case 'S':157case 's': len += 9 + strlen((String)args[arg++]); break;158default : return False;159}160}161162/* allocate a string of length <len> */163str = XtMalloc(len);164165/* parse arguments again */166arg = 0;167qtr = str;168for ( ptr = format; *ptr; ptr++ )169{170switch ( *ptr )171{172case 'O':173case 'o':174strcpy( qtr, "I0+" );175qtr += 3;176break;177case 'E':178case 'e':179strcpy( qtr, "I1+" );180qtr += 3;181break;182case 'D':183case 'd':184*qtr++ = 'I';185n = (Int)args[arg++];186for ( m = ( 0 < n ) ? n : -n; 0 < m; m /= 10 )187*qtr++ = '0' + (m%10);188if ( n < 0 )189*qtr++ = '-';190else191*qtr++ = '+';192break;193case 'S':194case 's':195*qtr++ = 'S';196wtr = (String)(args[arg++]);197for ( m = strlen(wtr); 0 < m; m /= 10 )198*qtr++ = '0' + (m%10);199*qtr++ = '+';200while ( *wtr )201*qtr++ = *wtr++;202break;203}204}205*qtr = '\0';206207/* write header */208hdr[0] = '@';209hdr[1] = 'a';210qtr = hdr+2;211for ( m = strlen(str); 0 < m; m/= 10 ) {212*qtr++ = '0' + (m%10);213}214*qtr++ = '+';215*qtr = '\0';216WriteGap( hdr, strlen(hdr) );217218/* write result back to gap process */219WriteGap( str, strlen(str) );220XtFree(str);221return True;222}223224225/****************************************************************************226**227*F ParseInt( <buf>, <val> ) . . . . . . . . . . . . . . . get a int value228*/229static Boolean ParseInt (230String * buf,231Int * val )232{233Int mult;234235if ( *(*buf)++ != 'I' )236return False;237*val = 0;238mult = 1;239do240{241if ( **buf == '+' )242{243(*buf)++;244return True;245}246else if ( **buf == '-' )247{248(*buf)++;249*val = -*val;250return True;251}252else if ( '0' <= **buf && **buf <= '9' )253*val += mult * (*((*buf)++)-'0');254else255return False;256mult = mult * 10;257} while (1);258}259260261/****************************************************************************262**263*F ParseString( <buf>, <str>, <len> ) . . . . . . . get a string from <ptr>264*/265static Boolean ParseString (266String * buf,267String * str,268Int * len )269{270Int i;271Int m;272String ptr;273274if ( (*buf)[0] != 'S' )275return False;276ptr = (*buf)+1;277for ( m=1,*len=0; '0' <= *ptr && *ptr <= '9'; ptr++,m *= 10 )278*len += ( *ptr - '0' ) * m;279*buf = ptr+1;280*str = XtMalloc( (*len)+1 );281for ( ptr = *str, i = *len; 0 < i; i--, ptr++, (*buf)++ )282if ( **buf == '@' )283{284(*buf)++;285if ( **buf == '@' )286*ptr = **buf;287else288*ptr = (**buf) - 'A';289}290else291*ptr = **buf;292*ptr = 0;293return True;294}295296297/****************************************************************************298**299*F GapWindowCmd( <cstr>, <len> ) . . . . . . . execute window command <cstr>300*/301extern TypeWindowCommand WindowCommands[];302303Boolean GapWindowCmd (304String cstr,305Int len )306{307Boolean ret;308Int ca;309Int ci;310Int cs;311Int i;312String pa;313String str = cstr+3;314TypeArg arg;315TypeWindowCommand * cmd;316char name[4];317318/* give debug information */319name[0] = cstr[0]; name[1] = cstr[1]; name[2] = cstr[2]; name[3] = 0;320DEBUG( D_XCMD, ( "GapWindowCmd( \"%s\" )\n", name ) );321322/* try to find the command in <WindowCommands> */323cmd = WindowCommands;324while ( cmd->name )325if ( !strncmp( cmd->name, name, 3 ) )326break;327else328cmd++;329if ( !cmd->name )330return ANSWER_GAP( "esss", "unknown command '", name, "'", 0 );331332/* parse arguments */333arg.opts = 0;334ci = cs = 0;335ca = 1;336pa = cmd->args;337while ( *pa )338{339if ( *pa == '*' )340{341arg.opts = str;342break;343}344else if ( *pa == 'S' || *pa == 's' )345{346if ( !ParseString( &str, &(arg.sargs[cs]), &len ) )347{348ret = ANSWER_GAP("eds",ca,".th arg must be a string",0,0);349goto free_strings;350}351else352cs++;353}354else if ( *pa == '#' )355{356if ( !ParseInt( &str, &i ) )357{358ret = ANSWER_GAP("eds",ca,".th arg must be a window nr",0,0);359goto free_strings;360}361arg.iargs[ci++] = i;362if ( LEN(GapWindows) <= arg.iargs[0] || arg.iargs[0] < 0 )363{364ret = ANSWER_GAP( "es", "illegal window number", 0, 0, 0 );365goto free_strings;366}367arg.win = (TypeGapWindow*)(ELM(GapWindows,arg.iargs[0]));368if ( ! arg.win->used )369{370ret = ANSWER_GAP( "es", "window not used", 0, 0, 0 );371goto free_strings;372}373}374else if ( *pa == 'T' )375{376if ( !ParseInt( &str, &i ) )377{378ret = ANSWER_GAP("eds",ca,".th arg must be a selector",0,0);379goto free_strings;380}381arg.iargs[ci++] = i;382if ( LEN(TextSelectors) <= arg.iargs[0] || arg.iargs[0] < 0 )383{384ret = ANSWER_GAP( "es", "illegal selector number", 0, 0, 0 );385goto free_strings;386}387arg.sel = (TypeTextSelector*)(ELM(TextSelectors,arg.iargs[0]));388if ( arg.sel == 0)389{390ret = ANSWER_GAP( "es", "selector not used", 0, 0, 0 );391goto free_strings;392}393}394else if ( *pa == 'F' )395{396if ( !ParseInt( &str, &i ) )397{398ret = ANSWER_GAP("eds",ca,".th arg must be an integer",0,0);399goto free_strings;400}401arg.iargs[ci++] = i;402switch ( (int)arg.iargs[ci-1] )403{404case 1: arg.font = TinyFont; break;405case 2: arg.font = SmallFont; break;406case 3: arg.font = NormalFont; break;407case 4: arg.font = LargeFont; break;408case 5: arg.font = HugeFont; break;409default:410ret = ANSWER_GAP( "eds", ca,411".th arg must be a font number", 0, 0 );412goto free_strings;413break;414}415}416else417{418if ( !ParseInt( &str, &i ) )419{420ret = ANSWER_GAP("eds",ca,".th arg must be an integer",0,0);421goto free_strings;422}423arg.iargs[ci++] = i;424}425ca++;426pa++;427}428if ( *pa != '*' && *str )429{430ret = ANSWER_GAP( "es", "too many arguments", 0, 0, 0 );431goto free_strings;432}433434435/* call command */436ret = cmd->func( &arg );437438/* free argument strings */439free_strings:440for ( i = 0; i < cs; i++ )441XtFree( arg.sargs[i] );442return ret;443}444445446/****************************************************************************447**448449*F * * * * * * * * * * * functions for TextSelectors * * * * * * * * * * * *450*/451452453/****************************************************************************454**455456*F FunOpenSelector( <name>, <list>, <buttons> ) . open a new text selector457*/458static void ButtonSelected (459Widget w,460XtPointer cl,461XtPointer ca )462{463Int i = ((Int) ((Long)cl&0xffff)) % 256;464Int n = ((Int) ((Long)cl&0xffff)) / 256;465char buf[128];466467DEBUG( D_XCMD, ("ButtonSelected( #%ld, #%ld )\n", (long)n, (long)i) );468sprintf( buf, "ButtonSelected(%ld,%ld);\n", (long)n, (long)i );469SimulateInput(buf);470}471472static void TextSelected (473Widget w,474XtPointer cl,475XtPointer ca )476{477XawListReturnStruct * ret = (XawListReturnStruct*) ca;478Int n = (Int) ((Long)cl&0xffff);479Int m = (Int) ret->list_index;480char buf[128];481482DEBUG( D_XCMD, ("TextSelected( #%ld, $%ld )\n", (long)n, (long)m+1 ) );483sprintf( buf, "TextSelected(%ld,%ld);\n", (long)n, (long)m+1 );484SimulateInput(buf);485}486487static void NotifyClick (488Widget w,489XEvent * evt,490String * str,491Cardinal * n )492{493XawListReturnStruct * ret;494Int i;495char buf[128];496497/* get currently selected */498ret = XawListShowCurrent(w);499500/* if something is set, return */501if ( ret->list_index != XAW_LIST_NONE )502return;503504/* find widget */505for ( i = 0; i < LEN(TextSelectors); i++ )506if ( ((TypeTextSelector*)ELM(TextSelectors,i))->list == w )507{508sprintf( buf, "TextSelected(%ld,0);\n", (long)i );509SimulateInput(buf);510return;511}512513}514515static char ButtonPressTrans[] =516"<Btn1Down>,<Btn1Up>: Notify() NotifyClick()";517518static Boolean FunOpenSelector (519TypeArg * arg )520{521Int i;522Int n;523String name = arg->sargs[0];524String ptr;525String qtr;526TypeTextSelector * selector;527Widget box;528Widget button;529Widget paned;530Widget viewport;531char buf[512];532533/* give debug info */534DEBUG( D_XCMD, ( "OpenSelector( \"%s\", \"%s\", \"%s\" )\n",535arg->sargs[0], arg->sargs[1], arg->sargs[2] ) );536537/* create a new selector entry */538selector = (TypeTextSelector*) XtMalloc( sizeof(TypeTextSelector) );539540/* create a new top level shell */541selector->top = XtAppCreateShell(542"TextSelector", "XGap", topLevelShellWidgetClass,543GapDisplay, 0, 0 );544545/* create a "paned" for the menu and text window */546paned = XtVaCreateManagedWidget(547"textSelector", panedWidgetClass, selector->top, (String)NULL );548549/* create a headline */550XtVaCreateManagedWidget(551"textSelectorTitle", labelWidgetClass, paned,552XtNlabel, (XtArgVal)name, (String)NULL );553554555/* create a viewport for the text selectors */556viewport = XtVaCreateManagedWidget(557"textSelectorViewport", viewportWidgetClass, paned,558XtNallowHoriz, (XtArgVal)False,559XtNallowVert, (XtArgVal)True,560XtNuseBottom, (XtArgVal)True,561XtNshowGrip, (XtArgVal)False,562(String)NULL );563564/* compute number of entries */565for ( i = 2, qtr = arg->sargs[1]; *qtr; qtr++ )566if ( *qtr == '|' )567i++;568selector->text = (String*) XtMalloc(i*sizeof(String));569570/* parse text */571for ( ptr = arg->sargs[1], i = 0; *ptr; i++ )572{573qtr = buf;574while ( *ptr && *ptr != '|' )575*qtr++ = *ptr++;576*qtr = 0;577if ( *ptr ) ptr++;578DEBUG( D_XCMD, ( " entry = \"%s\"\n", buf ) );579selector->text[i] = (String) XtMalloc(strlen(buf)+1);580strcpy( selector->text[i], buf );581}582selector->text[i] = 0;583584/* find free entry in <TextSelectors> */585for ( n = 0; n < LEN(TextSelectors); n++ )586if ( ELM(TextSelectors,n) == 0 )587break;588if ( n == LEN(TextSelectors) )589AddList( TextSelectors, selector );590else591ELM(TextSelectors,n) = selector;592593/* create a list widget containing the text */594selector->list = XtVaCreateManagedWidget(595"textSelectorList", listWidgetClass, viewport,596XtNlist, (XtArgVal)selector->text,597XtNdefaultColumns, (XtArgVal)1,598XtNforceColumns, (XtArgVal)True,599(String)NULL );600XtOverrideTranslations( selector->list,601XtParseTranslationTable(ButtonPressTrans) );602XtAddCallback( selector->list, XtNcallback, TextSelected,603(XtPointer)(n&0xffffL) );604605/* create a box containing the buttons */606box = XtVaCreateManagedWidget(607"textSelectorBox", boxWidgetClass, paned,608XtNorientation, (XtArgVal)XtorientHorizontal,609XtNshowGrip, (XtArgVal)False,610XtNskipAdjust, (XtArgVal)True,611XtNresizeToPreferred, (XtArgVal)True,612(String)NULL );613614/* parse buttons */615selector->buttons = List(0);616for ( ptr = arg->sargs[2], i = 1; *ptr; i++ )617{618qtr = buf;619while ( *ptr && *ptr != '|' )620*qtr++ = *ptr++;621*qtr = 0;622if ( *ptr ) ptr++;623DEBUG( D_XCMD, ( " button = \"%s\"\n", buf ) );624button = XtVaCreateManagedWidget(625"textSelectorButton", commandWidgetClass, box,626XtNlabel, (XtArgVal)buf,627XtNshapeStyle, (XtArgVal)XmuShapeOval,628(String)NULL );629XtAddCallback(button,XtNcallback,ButtonSelected,630(XtPointer)((i+n*256)&0xffffL));631AddList( selector->buttons, button );632}633634635/* realize the window and return the number */636XtRealizeWidget(selector->top);637638/* add window to list and return window number */639return ANSWER_GAP( "od", n, 0, 0, 0 );640}641642643/****************************************************************************644**645*F FunCloseSelector( <sel> ) . . . . . . . . . destroy an open text selector646*/647static Boolean FunCloseSelector (648TypeArg * arg )649{650Int i;651652/* give debug info */653DEBUG( D_XCMD, ( "CloseSelector( #%ld )\n", (long)arg->iargs[0] ) );654655/* destroy top level shell (this will destroy all children) */656XtDestroyWidget(arg->sel->top);657658/* clear text */659for ( i = 0; arg->sel->text[i]; i++ )660XtFree( arg->sel->text[i] );661XtFree( (char*) arg->sel->text );662663/* clear button list */664XtFree( (char*) arg->sel->buttons->ptr );665XtFree( (char*) arg->sel->buttons );666667/* clear entry in <TextSelectors> */668ELM(TextSelectors,arg->iargs[0]) = 0;669XtFree((char*)arg->sel);670671/* return OK */672return AnswerGap( "o", 0, 0, 0, 0 );673}674675676/****************************************************************************677**678*F FunChangeList( <sel>, <buttons> ) . . . . change list in text selector679*/680static Boolean FunChangeList (681TypeArg * arg )682{683Int i;684String ptr;685String qtr;686String * text;687char buf[512];688689/* give debug info */690DEBUG( D_XCMD, ( "ChangeList( #%ld, \"%s\" )\n", (long)arg->iargs[0],691arg->sargs[0] ) );692693/* compute number of entries */694for ( i = 2, qtr = arg->sargs[0]; *qtr; qtr++ )695if ( *qtr == '|' )696i++;697text = (String*) XtMalloc(i*sizeof(String));698699/* parse text */700for ( ptr = arg->sargs[0], i = 0; *ptr; i++ )701{702qtr = buf;703while ( *ptr && *ptr != '|' )704*qtr++ = *ptr++;705*qtr = 0;706if ( *ptr ) ptr++;707DEBUG( D_XCMD, ( " entry = \"%s\"\n", buf ) );708text[i] = (String) XtMalloc(strlen(buf)+1);709strcpy( text[i], buf );710}711text[i] = 0;712713/* change list */714XawListChange( arg->sel->list, text, 0, 0, True );715716/* clear old text */717for ( i = 0; arg->sel->text[i]; i++ )718XtFree( arg->sel->text[i] );719XtFree( (char*) arg->sel->text );720arg->sel->text = text;721722/* return OK */723return AnswerGap( "o", 0, 0, 0, 0 );724}725726727/****************************************************************************728**729*F FunEnableButton( <sel>, <but>, <enable> ) . . . . enable/disable a button730*/731static Boolean FunEnableButton (732TypeArg * arg )733{734Int i;735Widget entry;736737/* give debug info */738DEBUG( D_XCMD, ( "EnableButton( #%ld, #%ld, #%ld )\n",739(long)arg->iargs[0], (long)arg->iargs[1], (long)arg->iargs[2] ) );740741/* check button number */742i = arg->iargs[1]-1;743if ( LEN(arg->sel->buttons) <= i || i < 0 )744return ANSWER_GAP( "es", "illegal button number", 0, 0, 0 );745entry = ELM(arg->sel->buttons,i);746747/* enable/disable */748if ( arg->iargs[2] )749XtVaSetValues( entry, XtNsensitive, (XtArgVal)True, (String)NULL );750else751XtVaSetValues( entry, XtNsensitive, (XtArgVal)False, (String)NULL );752753/* return OK */754return AnswerGap( "o", 0, 0, 0, 0 );755}756757758/****************************************************************************759**760*F FunUnhighlihtSelector( <sel> ) . . . . . . . . . . .. unhighlight entry761*/762static Boolean FunUnhighlihtSelector (763TypeArg * arg )764{765/* give debug info */766DEBUG( D_XCMD, ( "Unhighlight( #%ld )\n", (long)arg->iargs[0] ) );767768/* unhighlight entry */769XawListUnhighlight(arg->sel->list);770771/* return OK */772return AnswerGap( "o", 0, 0, 0, 0 );773}774775776/****************************************************************************777**778779*F * * * * * * * * * * * functions for PopupMenus * * * * * * * * * * * * *780*/781782783/****************************************************************************784**785786*F FunPopupShell( <name>, <str> ) . . . . . . . . . . create a popup shell787*/788static Int ChosenPane = 0;789790static void PaneChosen (791Widget w,792XtPointer cl,793XtPointer ca )794{795TypePaneData * pd = (TypePaneData*) cl;796797DEBUG( D_XCMD, ( "PaneChosen( #%ld, #%ld )\n", (long)pd->popup,798(long)pd->pane ) );799ChosenPane = pd->pane;800}801802static void PopingDown (803Widget w,804XtPointer cl,805XtPointer ca )806{807DEBUG( D_XCMD, ( "PopingDown\n" ) );808ANSWER_GAP( "od", ChosenPane, 0, 0, 0 );809}810811static char PopingDownTrans[] =812"<BtnUp>: notify() MenuPopdown() unhighlight()";813814static Boolean FunPopupShell (815TypeArg * arg )816{817Int i;818String ptr;819String qtr;820TypeMenu * menu;821TypePaneData * pd;822Widget pane;823Widget pshell;824char buf[128];825826/* search for an identical popup shell */827for ( i = 0; i < LEN(PopupMenus); i++ )828{829menu = ELM(PopupMenus,i);830if ( ! strcmp( menu->name, arg->sargs[0] )831&& ! strcmp( menu->string, arg->sargs[1]) )832break;833}834if ( i < LEN(PopupMenus) )835return ANSWER_GAP( "od", i, 0, 0, 0 );836837/* create a shell */838pshell = XtVaCreatePopupShell( "pshell", simpleMenuWidgetClass,839XGap, XtNcursor, (XtArgVal)CursorTL,840(String)NULL );841XtOverrideTranslations( pshell,842XtParseTranslationTable(PopingDownTrans) );843844/* create headline */845DEBUG( D_XCMD, ( "PopupShell( \"%s\", ... )\n", arg->sargs[0] ) );846XtVaCreateManagedWidget( "menulabel", smeBSBObjectClass, pshell,847XtNsensitive, (XtArgVal)False,848XtNlabel, (XtArgVal)(arg->sargs[0]),849(String)NULL );850XtVaCreateManagedWidget( "line", smeLineObjectClass, pshell, (String)NULL );851852/* add popdown callback */853XtAddCallback( pshell, XtNpopdownCallback, PopingDown, 0 );854855/* create menu entries */856menu = (TypeMenu*) XtMalloc( sizeof(TypeMenu) );857menu->shell = pshell;858menu->entries = List(0);859menu->name = XtMalloc(strlen(arg->sargs[0])+1);860menu->string = XtMalloc(strlen(arg->sargs[1])+1);861strcpy( menu->name, arg->sargs[0] );862strcpy( menu->string, arg->sargs[1] );863for ( ptr = arg->sargs[1], i = 1; *ptr; i++ )864{865qtr = buf;866while ( *ptr && *ptr != '|' )867*qtr++ = *ptr++;868*qtr = 0;869if ( *ptr ) ptr++;870DEBUG( D_XCMD, ( " entry = \"%s\"\n", buf ) );871pane = XtVaCreateManagedWidget( "menupane", smeBSBObjectClass,872pshell, XtNlabel, (XtArgVal)buf,873(String)NULL );874pd = (TypePaneData*) XtMalloc( sizeof(TypePaneData) );875pd->pane = i;876pd->popup = LEN(PopupMenus);877pd->shell = pshell;878XtAddCallback( pane, XtNcallback, PaneChosen, pd );879AddList( menu->entries, (void*) pd );880}881882/* add shell to popup shell list */883AddList( PopupMenus, (void*) menu );884return ANSWER_GAP( "od", LEN(PopupMenus)-1, 0, 0, 0 );885}886887888/****************************************************************************889**890*F FunShowPopup( <nr> ) . . . . . . . . . . . . . . . . popup a popup shell891*/892static Boolean FunShowPopup (893TypeArg * arg )894{895Dimension w1, h1, bw;896Int x, y, x2, y2;897Position tmp;898UInt bt;899Widget popup;900Window child;901Window root;902903/* check popup number */904if ( LEN(PopupMenus) <= arg->iargs[0] || arg->iargs[0] < 0 )905return ANSWER_GAP("esd","illegal popup menu ",arg->iargs[0],0,0);906popup = ((TypeMenu*)ELM(PopupMenus,arg->iargs[0]))->shell;907908/* get size of popup dialog */909XtVaGetValues( popup,910XtNwidth, (XtArgVal)&w1,911XtNheight, (XtArgVal)&h1,912XtNborderWidth, (XtArgVal)&bw,913(String)NULL );914915/* compute screen position */916XQueryPointer( GapDisplay, MyRootWindow,917&root, &child, &x, &y, &x2, &y2, &bt );918tmp = DisplayWidth( GapDisplay, GapScreen );919if ( x+w1 > tmp )920x = tmp-w1;921tmp = DisplayHeight( GapDisplay, GapScreen );922if ( y+h1 > tmp )923y = tmp-h1;924925/* popup the popup shell */926XtVaSetValues( popup, XtNx, (XtArgVal)(x-10), XtNy, (XtArgVal)(y-10),927(String)NULL );928XawSimpleMenuClearActiveEntry( popup );929XtPopupSpringLoaded( popup );930XtGrabPointer( popup, True, ButtonPressMask|ButtonReleaseMask,931GrabModeAsync, GrabModeAsync, None, None, CurrentTime );932933/* reset 'ChosenPane' */934ChosenPane = 0;935936/* gap will be answered by 'PopingDown' */937return True;938}939940941/****************************************************************************942**943944*F * * * * * * * * * * * * functions for Dialogs * * * * * * * * * * * * * *945*/946947948/****************************************************************************949**950951*F FunShowDialog( <nr>, <msg>, <def> ) . . . . . . . . . . show popup dialog952*/953static Boolean FunShowDialog (954TypeArg * arg )955{956Int first;957Int res;958String str;959#ifndef NO_FILE_SELECTOR960static String tmp = 0;961#endif962963/* OK/Cancel dialog */964if ( arg->iargs[0] == 1 )965{966first = 4;967res = PopupDialog( DialogOkCancel, arg->sargs[0],968arg->sargs[1], &str );969}970971/* filename dialog */972else if ( arg->iargs[0] == 2 )973{974# ifdef NO_FILE_SELECTOR975first = 4;976res = PopupDialog( DialogOkCancel, arg->sargs[0],977arg->sargs[1], &str );978# else979980/* free memory from the previous run */981if ( tmp ) {982XtFree(tmp);983tmp = NULL;984}985986/* call the file selector */987if ( *(arg->sargs[1]) )988res = XsraSelFile(XGap,arg->sargs[0],arg->sargs[1],0,&str);989else990res = XsraSelFile(XGap,arg->sargs[0],0,0,&str);991992/* ok is first button */993first = 1;994if ( res != first )995str = "";996else997tmp = str;998999# endif1000}10011002/* unkown dialog */1003else1004return ANSWER_GAP("esd","illegal popup dialog ",arg->iargs[0],0,0);10051006/* return the result */1007return ANSWER_GAP( "ods", (res==first)?0:1, str, 0, 0 );1008}100910101011/****************************************************************************1012**10131014*F * * * * * * * * * * * * functions for Windows * * * * * * * * * * * * * *1015*/101610171018/****************************************************************************1019**10201021*F CloseWindow( <win> ) . . . . . . . . . . . . . . . close an open window1022*/1023static void CloseWindow (1024TypeGapWindow * win )1025{1026Int i;1027Int j;1028TypeMenu * menu;10291030/* set <used> to false */1031win->used = False;10321033/* free all menus */1034for ( i = 0; i < LEN(win->menus); i++ )1035if ( (menu=ELM(win->menus,i)) != 0 )1036{1037for ( j = 0; j < LEN(menu->entries); j++ )1038XtFree((char*)ELM(menu->entries,j));1039XtFree((char*)menu->entries->ptr);1040XtFree((char*)menu->entries);1041XtFree((char*)menu);1042}1043XtFree((char*)win->menus->ptr);1044XtFree((char*)win->menus);10451046/* destroy top level shell (this will destroy all children) */1047XtDestroyWidget(win->top);1048}104910501051/****************************************************************************1052**1053*F MouseClickWindow( <talk>, <cd>, <evt>, <ctd> ) . . handle a mouse click1054*/1055static void MouseClickWindow (1056Widget talk,1057XtPointer cd,1058XEvent * evt,1059Boolean * ctd )1060{1061Int bn;1062TypeGapWindow * gap = ELM(GapWindows,(Int)((Long)cd&0xffff));1063char buf[100];10641065/* we only have a two button mouse */1066if ( evt->xbutton.button == Button1 )1067bn = 1;1068else if ( evt->xbutton.button == Button3 )1069bn = 2;1070else1071return;10721073/* check boundaries */1074if ( gap->width <= evt->xbutton.x || gap->height <= evt->xbutton.y )1075return;10761077/* give debug information */1078DEBUG( D_XCMD, ( "MouseClickWindow( %ld, %ld, %ld, %ld )\n", (long)cd,1079(long)(evt->xbutton.x), (long)(evt->xbutton.y), (long)bn ) );10801081/* construct gap command */1082sprintf( buf, "PointerButtonDown(%ld,%ld,%ld,%ld);\n", (long)cd,1083(long)evt->xbutton.x, (long)evt->xbutton.y, (long)bn );1084SimulateInput(buf);1085}108610871088/****************************************************************************1089**1090*F WmDeleteWindow( <w>, <event>, <pars>, <n> ) . . . . . . wm delete request1091*/1092static char * WmDeleteWindowTranslation =1093"<Message>WM_PROTOCOLS: WmDeleteWindow()\n";10941095static void WmDeleteWindow (1096Widget w,1097XEvent * event,1098String * pars,1099Cardinal * n )1100{1101TypeGapWindow * win;1102Int i;11031104if ( event->type == ClientMessage1105&& event->xclient.data.l[0] != WmDeleteWindowAtom )1106return;1107for ( i = 0; i < LEN(GapWindows); i++ )1108{1109win = (TypeGapWindow*)ELM(GapWindows,i);1110if ( win->used && win->top == w )1111break;1112}1113if ( i < LEN(GapWindows) )1114CloseWindow(win);1115}111611171118/****************************************************************************1119**1120*F FunOpenWindow( <name>, <width>, <height> ) . open a new window, external1121*/1122static Widget CreateTitleWindow (1123Widget paned )1124{1125return XtVaCreateManagedWidget(1126"xgapWindowText",1127labelWidgetClass, paned,1128XtNlabel, (XtArgVal)"GAP window",1129XtNskipAdjust, (XtArgVal)True,1130XtNshowGrip, (XtArgVal)False,1131(String)NULL );1132}113311341135static Boolean FunOpenWindow (1136TypeArg * arg )1137{1138Int h = arg->iargs[1];1139Int w = arg->iargs[0];1140Short h1;1141Short w1;1142String name = arg->sargs[0];1143String title;1144TypeGapWindow * window;1145Widget button;1146Widget paned;11471148/* check arguments */1149if ( arg->iargs[0] < 1 || arg->iargs[1] < 1 )1150return ANSWER_GAP( "esdsd", "illegal window dimensions ",1151arg->iargs[0], "x", arg->iargs[1] );1152/* give debug info */1153DEBUG( D_XCMD, ( "OpenWindow( \"%s\", %ld, %ld )\n", arg->sargs[0],1154(long)arg->iargs[0], (long)arg->iargs[1] ) );11551156/* setup a new window structure, this structure will live forever */1157window = (TypeGapWindow*) XtMalloc( sizeof(TypeGapWindow) );1158window->line_width = 0;1159window->color = C_BLACK;1160window->menus = List(0);1161window->used = True;1162window->text = 0;11631164/* find title position */1165XtVaGetValues( GapTalk, XtNtitlePosition, (XtArgVal)&title, (String)NULL );11661167/* create a new top level shell */1168window->top = XtVaAppCreateShell(1169"XGap", "GraphicSheet",1170topLevelShellWidgetClass, GapDisplay,1171(String)NULL );11721173/* create a "paned" for the menu and text window */1174paned = XtVaCreateManagedWidget(1175"xgapWindow", panedWidgetClass, window->top, (String)NULL );11761177/* add TOP tile */1178if ( *title == 'T' || *title == 't' )1179window->text = CreateTitleWindow(paned);11801181/* create a menu box for the menu buttons */1182window->box = XtVaCreateManagedWidget(1183"xgapWindowMenu", boxWidgetClass, paned,1184XtNskipAdjust, (XtArgVal)True,1185XtNresizeToPreferred, (XtArgVal)True,1186XtNshowGrip, (XtArgVal)False,1187(String)NULL );11881189/* create a dummy menu button */1190button = XtVaCreateManagedWidget( "dummy", commandWidgetClass,1191window->box, XtNx, (XtArgVal)0,1192(String)NULL );11931194/* add MIDDLE tile */1195if ( *title == 'M' || *title == 'm' )1196window->text = CreateTitleWindow(paned);11971198/* create a viewport for the window */1199window->viewport = XtVaCreateManagedWidget(1200"xgapWindowViewport",1201viewportWidgetClass, paned,1202XtNallowHoriz, (XtArgVal)True,1203XtNallowVert, (XtArgVal)True,1204XtNuseBottom, (XtArgVal)True,1205XtNshowGrip, (XtArgVal)False,1206XtNresizable, (XtArgVal)True,1207(String)NULL );12081209/* create a drawable */1210window->draw = XtVaCreateManagedWidget(1211"xgapWindowDrawable",1212gapGraphicWidgetClass, window->viewport,1213XtNwidth, (XtArgVal)w,1214XtNheight, (XtArgVal)h,1215(String)NULL );1216window->width = w;1217window->height = h;12181219/* fix dimensions of viewport */1220XtVaGetValues( window->viewport, XtNwidth, (XtArgVal)&w1,1221XtNheight, (XtArgVal)&h1,1222(String)NULL );1223w1 = ( w1 < w ) ? w1 : w;1224h1 = ( h1 < h ) ? h1 : h;1225XtVaSetValues( window->viewport, XtNwidth, (XtArgVal)w1,1226XtNheight, (XtArgVal)h1, (String)NULL );12271228/* add BOTTOM tile */1229if ( window->text == 0 )1230window->text = CreateTitleWindow(paned);12311232/* realize the window and return the number */1233XtRealizeWidget(window->top);12341235/* add event handler for mouse clicks */1236XtAddEventHandler( window->draw, ButtonPressMask,1237False, MouseClickWindow,1238(XtPointer)(LEN(GapWindows)&0xffffL) );12391240/* set handler for WM_DELETE_WINDOW */1241XSetWMProtocols(GapDisplay,XtWindow(window->top),&WmDeleteWindowAtom,1);1242XtOverrideTranslations(1243window->top,1244XtParseTranslationTable(WmDeleteWindowTranslation) );12451246/* remove dummy button and dummy text */1247XtDestroyWidget(button);1248XtVaSetValues( window->text, XtNlabel, (XtArgVal)name, (String)NULL );12491250/* define cursor */1251XDefineCursor( GapDisplay, XtWindow(window->top), SleepCursor );12521253/* add window to list and return window number */1254AddList( GapWindows, (void*) window );1255return ANSWER_GAP( "od", LEN(GapWindows)-1, 0, 0, 0 );1256}125712581259/****************************************************************************1260**1261*F FunCloseWindow( <win> ) . . . . . . . . . close an open window, external1262*/1263static Boolean FunCloseWindow (1264TypeArg * arg )1265{1266/* give debug info */1267DEBUG( D_XCMD, ( "CloseWindow( #%ld )\n", (long)arg->iargs[0] ) );12681269/* close window */1270CloseWindow(arg->win);12711272/* return OK */1273return AnswerGap( "o", 0, 0, 0, 0 );1274}12751276/****************************************************************************1277**1278*F FunAddTitle( <win>, <str> ) . . . . . . . . . . . . . . add a (sub) title1279*/1280static Boolean FunAddTitle (1281TypeArg * arg )1282{1283XtVaSetValues( arg->win->text, XtNlabel, (XtArgVal)(arg->sargs[0]),1284(String)NULL );1285return ANSWER_GAP( "o", 0, 0, 0, 0 );1286}128712881289/****************************************************************************1290**1291*F FunColorModel() . . . . . . . color model used for gap graphics, external1292*/1293static Boolean FunColorModel (1294TypeArg * arg )1295{1296return ANSWER_GAP( "od", GCColorModel(GapDisplay), 0, 0, 0 );1297}129812991300/****************************************************************************1301**1302*F FunFastUpdate( <win>, <flag> ) . . . . . . . . . en-/disable fast update1303*/1304static Boolean FunFastUpdate (1305TypeArg * arg )1306{1307Boolean flag;13081309flag = ( arg->iargs[1] == 0 ) ? False : True;1310if ( arg->win->fast_update != flag )1311{1312arg->win->fast_update = flag;1313GGFastUpdate( arg->win->draw, flag );1314}1315return ANSWER_GAP( "o", 0, 0, 0, 0 );1316}1317131813191320/****************************************************************************1321**1322*F FunFontInfo( <win>, <fid> ) . . . . . . . . . . information about fonts1323*/1324static Boolean FunFontInfo (1325TypeArg * arg )1326{1327XFontStruct * font = arg->font;13281329return ANSWER_GAP( "oddd", font->ascent, font->descent,1330font->max_bounds.width, 0 );1331}133213331334/****************************************************************************1335**1336*F FunQueryPointer( <win> ) . . . . . . . . . . . . . . . . . query pointer1337*/1338static Boolean FunQueryPointer (1339TypeArg * arg )1340{1341Int x, y, x2, y2;1342UInt bt;1343UInt md;1344UInt pt;1345Window child;1346Window root;13471348/* query pointer */1349XQueryPointer( XtDisplay(arg->win->draw), XtWindow(arg->win->draw),1350&root, &child, &x, &y, &x2, &y2, &pt );13511352/* and make a sanity check */1353if ( arg->win->width < x2 || x2 < 0 )1354x2 = -1;1355if ( arg->win->height < y2 || y2 < 0 )1356y2 = -1;13571358/* check mouse buttons */1359bt = 0;1360if ( pt & Button1Mask )1361bt |= 1;1362if ( pt & Button3Mask )1363bt |= 2;13641365/* check modifier keys */1366md = 0;1367if ( pt & ShiftMask )1368md |= 1;1369if ( pt & ControlMask )1370md |= 2;1371if ( pt & Mod1Mask )1372md |= 4;13731374/* gap will be answered by 'PopingDown' */1375return ANSWER_GAP( "odddd", x2, y2, bt, md );1376}137713781379/****************************************************************************1380**1381*F FunResize( <win>, <width>, <height> ) . . . . . . . . . . . resize window1382*/1383static Boolean FunResize (1384TypeArg * arg )1385{1386ViewportWidget viewport = (ViewportWidget)arg->win->viewport;1387Widget dummy;13881389/* check arguments */1390if ( arg->iargs[1] < 1 || arg->iargs[2] < 1 )1391return ANSWER_GAP( "esdsd", "illegal window dimensions ",1392arg->iargs[1], "x", arg->iargs[2] );13931394/* resize window */1395arg->win->width = arg->iargs[1];1396arg->win->height = arg->iargs[2];1397GGResize( arg->win->draw, arg->iargs[1], arg->iargs[2] );13981399/* try to update scrollbars */1400XtUnmanageChild(arg->win->draw);1401dummy = XtVaCreateManagedWidget(1402"xgapWindowDrawable",1403gapGraphicWidgetClass, (Widget)viewport,1404XtNwidth, (XtArgVal)(arg->win->width),1405XtNheight, (XtArgVal)(arg->win->height),1406(String)NULL );1407XtUnmanageChild(dummy);1408XtManageChild(arg->win->draw);1409XtDestroyWidget(dummy);14101411/* and return */1412return ANSWER_GAP( "o", 0, 0, 0, 0 );1413}141414151416/****************************************************************************1417**14181419*F * * * * * * * * * * * * * functions for Menus * * * * * * * * * * * * * *1420*/142114221423/****************************************************************************1424**14251426*F FunMenu( <win>, <name>, <str> ) . . . . . . . . . . . create a menu entry1427*/1428static void MenuClick (1429Widget w,1430XtPointer cl,1431XtPointer ca )1432{1433TypeMenuData * pd = (TypeMenuData*) cl;1434char buf[128];14351436DEBUG( D_XCMD, ("MenuSelected( #%ld, #%ld, #%ld )\n", (long)pd->window,1437(long)pd->popup, (long)pd->pane) );1438sprintf( buf, "MenuSelected( %ld, %ld, %ld );\n", (long)pd->window,1439(long)pd->popup, (long)pd->pane );1440SimulateInput(buf);1441}14421443static Boolean FunMenu (1444TypeArg * arg )1445{1446Int i;1447String ptr;1448String qtr;1449TypeMenu * menu;1450TypeMenuData * pd;1451Widget button;1452Widget pane;1453Widget pshell;1454char buf[128];14551456/* create a menu button */1457DEBUG( D_XCMD, ( "Menu( \"%s\", ... )\n", arg->sargs[0] ) );1458button = XtVaCreateManagedWidget( "menuButton", menuButtonWidgetClass,1459arg->win->box,1460XtNlabel, (XtArgVal)(arg->sargs[0]),1461XtNshapeStyle, (XtArgVal)XmuShapeOval,1462XtNleftBitmap, (XtArgVal)MenuSymbol,1463(String)NULL );14641465/* create a shell */1466pshell = XtVaCreatePopupShell( "menu", simpleMenuWidgetClass,1467button, XtNcursor, (XtArgVal)CursorTL,1468(String)NULL );14691470/* create menu entries */1471menu = (TypeMenu*) XtMalloc( sizeof(TypeMenu) );1472menu->button = button;1473menu->shell = pshell;1474menu->entries = List(0);1475for ( ptr = arg->sargs[1], i = 1; *ptr; )1476{1477qtr = buf;1478while ( *ptr && *ptr != '|' )1479*qtr++ = *ptr++;1480*qtr = 0;1481if ( *ptr ) ptr++;1482DEBUG( D_XCMD, ( " entry = \"%s\"\n", buf ) );1483if ( *buf == '-' )1484XtVaCreateManagedWidget( "line", smeLineObjectClass, pshell,1485(String)NULL );1486else1487{1488pane = XtVaCreateManagedWidget( buf, smeBSBObjectClass,1489pshell,1490XtNlabel, (XtArgVal)buf,1491XtNrightMargin, (XtArgVal)14,1492XtNrightBitmap,1493(XtArgVal)EmptyMarkSymbol,1494(String)NULL );1495pd = (TypeMenuData*) XtMalloc( sizeof(TypeMenuData) );1496pd->window = arg->iargs[0];1497pd->pane = i;1498pd->popup = LEN(arg->win->menus);1499pd->shell = pane;1500XtAddCallback( pane, XtNcallback, MenuClick, pd );1501i++;1502AddList( menu->entries, (void*) pd );1503}1504}15051506/* add shell to popup shell list */1507AddList( arg->win->menus, (void*) menu );1508return ANSWER_GAP( "od", LEN(arg->win->menus)-1, 0, 0, 0 );1509}151015111512/****************************************************************************1513**1514*F FunDeleteMenu( <win>, <menu> ) . . . . . . . . . . . . . . delete a menu1515*/1516static Boolean FunDeleteMenu (1517TypeArg * arg )1518{1519TypeMenu * menu;1520Int j;15211522/* check menu number */1523DEBUG( D_XCMD, ( "CheckMenuEntry( #%ld, #%ld, #%ld, %ld )\n",1524(long)arg->iargs[0], (long)arg->iargs[1], (long)arg->iargs[2],1525(long)arg->iargs[3] ) );1526if ( LEN(arg->win->menus) <= arg->iargs[1] || arg->iargs[1] < 0 )1527return ANSWER_GAP("esd","illegal menu number ",arg->iargs[1],0,0);1528menu = (TypeMenu*)ELM(arg->win->menus,arg->iargs[1]);1529if ( menu == 0 )1530return ANSWER_GAP( "esds", "menu ", arg->iargs[1],1531" is no longer used", 0 );15321533/* delete this entry */1534ELM( arg->win->menus, arg->iargs[1] ) = 0;1535for ( j = 0; j < LEN(menu->entries); j++ )1536XtFree((char*)ELM(menu->entries,j));1537XtFree((char*)menu->entries->ptr);1538XtFree((char*)menu->entries);1539XtDestroyWidget(menu->button);1540XtFree((char*)menu);1541return ANSWER_GAP( "o", 0, 0, 0, 0 );1542}154315441545/****************************************************************************1546**1547*F FunCheckMenuEntry( <win>, <menu>, <entry>, <check> ) . . add check mark1548*/1549static Boolean FunCheckMenuEntry (1550TypeArg * arg )1551{1552TypeMenu * menu;1553Widget entry;15541555/* check menu number */1556DEBUG( D_XCMD, ( "CheckMenuEntry( #%ld, #%ld, #%ld, %ld )\n",1557(long)arg->iargs[0], (long)arg->iargs[1], (long)arg->iargs[2],1558(long)arg->iargs[3] ) );1559if ( LEN(arg->win->menus) <= arg->iargs[1] || arg->iargs[1] < 0 )1560return ANSWER_GAP("esd","illegal menu number ",arg->iargs[1],0,0);1561menu = (TypeMenu*)ELM(arg->win->menus,arg->iargs[1]);1562if ( menu == 0 )1563return ANSWER_GAP( "esds", "menu ", arg->iargs[1],1564" is no longer used", 0 );15651566/* check menu entry number */1567if ( LEN(menu->entries) < arg->iargs[2] || arg->iargs[2] <= 0 )1568return ANSWER_GAP("esd","illegal menu entry ",arg->iargs[2],0,0);1569entry = ((TypeMenuData*)ELM(menu->entries,arg->iargs[2]-1))->shell;15701571/* set or clear check mark */1572if ( arg->iargs[3] )1573XtVaSetValues( entry, XtNrightBitmap, (XtArgVal)CheckMarkSymbol,1574(String)NULL );1575else1576XtVaSetValues( entry, XtNrightBitmap, (XtArgVal)EmptyMarkSymbol,1577(String)NULL );1578return ANSWER_GAP( "o", 0, 0, 0, 0 );1579}158015811582/****************************************************************************1583**1584*F FunEnableMenuEntry( <win>, <menu>, <entry>, <check> ) . . enable/disable1585*/1586static Boolean FunEnableMenuEntry (1587TypeArg * arg )1588{1589TypeMenu * menu;1590Widget entry;15911592/* check menu number */1593DEBUG( D_XCMD, ( "EnableMenuEntry( #%ld, #%ld, #%ld, %ld )\n",1594(long)arg->iargs[0], (long)arg->iargs[1], (long)arg->iargs[2],1595(long)arg->iargs[3] ) );1596if ( LEN(arg->win->menus) <= arg->iargs[1] || arg->iargs[1] < 0 )1597return ANSWER_GAP("esd","illegal menu number ",arg->iargs[1],0,0);1598menu = (TypeMenu*)ELM(arg->win->menus,arg->iargs[1]);1599if ( menu == 0 )1600return ANSWER_GAP( "esds", "menu ", arg->iargs[1],1601" is no longer used", 0 );16021603/* check menu entry number */1604if ( LEN(menu->entries) < arg->iargs[2] || arg->iargs[2] <= 0 )1605return ANSWER_GAP("esd","illegal menu entry ",arg->iargs[2],0,0);1606entry = ((TypeMenuData*)ELM(menu->entries,arg->iargs[2]-1))->shell;16071608/* set or clear check mark */1609if ( arg->iargs[3] )1610XtVaSetValues( entry, XtNsensitive, (XtArgVal)True, (String)NULL );1611else1612XtVaSetValues( entry, XtNsensitive, (XtArgVal)False, (String)NULL );1613return ANSWER_GAP( "o", 0, 0, 0, 0 );1614}161516161617/****************************************************************************1618**16191620*F * * * * * * * * * * * functions for GraphicObjects * * * * * * * * * * *1621*/162216231624/****************************************************************************1625**16261627*D CHECK_BBOX( <obj> ) . . . . . . . . . . check dimensions of bounding box1628*/1629#define CHECK_BBOX(obj) obj->x = ( obj->x < 0 ) ? 0 : obj-> x; \1630obj->y = ( obj->y < 0 ) ? 0 : obj-> y163116321633/****************************************************************************1634**1635*F FunClearAll( <win> ) . . . . . . . . . . . . . . . . . clear all objects1636*/1637static Boolean FunClearAll (1638TypeArg * arg )1639{1640GGFreeAllObjects( arg->win->draw );1641return ANSWER_GAP( "o", 0, 0, 0, 0 );1642}164316441645/****************************************************************************1646**1647*F FunRemoveObjects( <win>, <obj>, ... ) . . . . . remove a window object1648*/1649static Boolean FunRemoveObjects (1650TypeArg * arg )1651{1652String str;1653Int n;16541655/* return if no optional args are given */1656if ( (str=arg->opts) == 0 )1657return ANSWER_GAP( "es", "no objects given", 0, 0, 0 );16581659/* give debug info */1660DEBUG( D_XCMD, ("RemoveObject( #%ld, %s )\n",(long)arg->iargs[0],str) );16611662/* remove objects */1663if ( !arg->win->fast_update )1664GGStartRemove(arg->win->draw);1665while ( *str )1666{1667if ( !ParseInt( &str, &n ) )1668{1669if ( !arg->win->fast_update )1670GGStopRemove(arg->win->draw);1671return ANSWER_GAP( "es", "illegal argument", 0, 0, 0 );1672}1673if ( GGRemoveObject( arg->win->draw, n ) )1674{1675if ( !arg->win->fast_update )1676GGStopRemove(arg->win->draw);1677return ANSWER_GAP("esds","illegal object number: '",n,"'",0);1678}1679}1680if ( !arg->win->fast_update )1681GGStopRemove(arg->win->draw);1682return ANSWER_GAP( "o", 0, 0, 0, 0 );1683}168416851686/****************************************************************************1687**1688*F FunSetLineWidth( <win>, <wdt> ) . . . . . set line width for next objects1689*/1690static Boolean FunSetLineWidth (1691TypeArg * arg )1692{1693arg->win->line_width = ( arg->iargs[1] <= 1 ) ? 0 : arg->iargs[1];1694return ANSWER_GAP( "o", 0, 0, 0, 0 );1695}169616971698/****************************************************************************1699**1700*F FunSetColor( <win>, <col> ) . . . . . . . . . set color for next objects1701*/1702static Boolean FunSetColor (1703TypeArg * arg )1704{1705if ( arg->iargs[1] < 0 )1706arg->win->color = C_BLACK;1707else if ( C_LAST < arg->iargs[1] )1708arg->win->color = C_BLACK;1709else1710arg->win->color = arg->iargs[1];1711return ANSWER_GAP( "o", 0, 0, 0, 0 );1712}171317141715/****************************************************************************1716**1717*F FunDrawBox( <win>, <x1>, <y1>, <x2>, <y2> ) . . . draw a filled rectangle1718*/1719static Boolean FunDrawBox (1720TypeArg * arg )1721{1722TypeGapGraphicObject * obj;1723Int n;17241725/* create a line object */1726obj = (TypeGapGraphicObject*) XtMalloc( sizeof(TypeGapGraphicObject) );17271728/* convert <x> and <y> coordinates to X windows style */1729obj->type = T_BOX;1730obj->color = arg->win->color;1731obj->desc.rect.x1 = MIN( arg->iargs[1], arg->iargs[3] );1732obj->desc.rect.y1 = MIN( arg->iargs[2], arg->iargs[4] );1733obj->desc.rect.x2 = MAX( arg->iargs[1], arg->iargs[3] );1734obj->desc.rect.y2 = MAX( arg->iargs[2], arg->iargs[4] );1735obj->x = MIN( obj->desc.rect.x1, obj->desc.rect.x2 )-1;1736obj->y = MIN( obj->desc.rect.y1, obj->desc.rect.y2 )-1;1737obj->w = MAX( obj->desc.rect.x1, obj->desc.rect.x2 )+1;1738obj->h = MAX( obj->desc.rect.y1, obj->desc.rect.y2 )+1;1739CHECK_BBOX(obj);1740DEBUG( D_XCMD, ( "DrawBox( #%ld, %ld, %ld, %ld )\n",1741(long)arg->iargs[0], (long)arg->iargs[1],1742(long)arg->iargs[2], (long)arg->iargs[3] ) );17431744/* use 'GGAddObject' to draw the object */1745n = GGAddObject( arg->win->draw, obj );1746return ANSWER_GAP( "od", n, 0, 0, 0 );1747}174817491750/****************************************************************************1751**1752*F FunDrawCircle( <win>, <x>, <y>, <r> ) . . . . . . . . . . . draw a circle1753*/1754static Boolean FunDrawCircle (1755TypeArg * arg )1756{1757TypeGapGraphicObject * obj;1758Int n;1759Int w;17601761/* create a circle object */1762obj = (TypeGapGraphicObject*) XtMalloc( sizeof(TypeGapGraphicObject) );17631764/* convert <x> and <y> coordinates to X windows style */1765obj->type = T_CIRCLE;1766obj->color = arg->win->color;1767obj->desc.circle.r = 2 * arg->iargs[3];1768obj->desc.circle.x = arg->iargs[1] - arg->iargs[3];1769obj->desc.circle.y = arg->iargs[2] - arg->iargs[3];1770w = obj->desc.circle.w = arg->win->line_width;1771obj->x = obj->desc.circle.x - w - 1;1772obj->y = obj->desc.circle.y - w - 1;1773obj->w = obj->desc.circle.r+1 + 2*w + 2;1774obj->h = obj->desc.circle.r+1 + 2*w + 2;1775CHECK_BBOX(obj);1776DEBUG( D_XCMD, ( "DrawCircle( #%ld, %ld, %ld, %ld )\n",1777(long)arg->iargs[0], (long)arg->iargs[1],1778(long)arg->iargs[2], (long)arg->iargs[3] ) );17791780/* use 'GGAddObject' to draw the object */1781n = GGAddObject( arg->win->draw, obj );1782return ANSWER_GAP( "od", n, 0, 0, 0 );1783}178417851786/****************************************************************************1787**1788*F FunDrawDisc( <win>, <x>, <y>, <r> ) . . . . . . . . . . draw a solid disc1789*/1790static Boolean FunDrawDisc (1791TypeArg * arg )1792{1793TypeGapGraphicObject * obj;1794Int n;17951796/* create a disc object */1797obj = (TypeGapGraphicObject*) XtMalloc( sizeof(TypeGapGraphicObject) );17981799/* convert <x> and <y> coordinates to X windows style */1800obj->type = T_DISC;1801obj->color = arg->win->color;1802obj->desc.disc.r = 2 * arg->iargs[3];1803obj->desc.disc.x = arg->iargs[1] - arg->iargs[3];1804obj->desc.disc.y = arg->iargs[2] - arg->iargs[3];1805obj->x = obj->desc.disc.x;1806obj->y = obj->desc.disc.y;1807obj->w = obj->desc.disc.r+1;1808obj->h = obj->desc.disc.r+1;1809CHECK_BBOX(obj);1810DEBUG( D_XCMD, ( "DrawCircle( #%ld, %ld, %ld, %ld )\n",1811(long)arg->iargs[0], (long)arg->iargs[1],1812(long)arg->iargs[2], (long)arg->iargs[3] ) );18131814/* use 'GGAddObject' to draw the object */1815n = GGAddObject( arg->win->draw, obj );1816return ANSWER_GAP( "od", n, 0, 0, 0 );1817}181818191820/****************************************************************************1821**1822*F FunDrawLine( <win>, <x1>, <y1>, <x2>, <y2> ) . . . . . . . . draw a line1823*/1824static Boolean FunDrawLine (1825TypeArg * arg )1826{1827TypeGapGraphicObject * obj;1828Int n;1829Int w;18301831/* create a line object */1832obj = (TypeGapGraphicObject*) XtMalloc( sizeof(TypeGapGraphicObject) );1833obj->type = T_LINE;1834obj->color = arg->win->color;1835obj->desc.line.x1 = arg->iargs[1];1836obj->desc.line.y1 = arg->iargs[2];1837obj->desc.line.x2 = arg->iargs[3];1838obj->desc.line.y2 = arg->iargs[4];1839w = obj->desc.line.w = arg->win->line_width;1840obj->x = MIN( obj->desc.line.x1, obj->desc.line.x2 ) - w;1841obj->y = MIN( obj->desc.line.y1, obj->desc.line.y2 ) - w;1842obj->w = MAX( obj->desc.line.x1, obj->desc.line.x2 ) - obj->x + 1 + 2*w;1843obj->h = MAX( obj->desc.line.y1, obj->desc.line.y2 ) - obj->y + 1 + 2*w;1844CHECK_BBOX(obj);1845DEBUG( D_XCMD, ( "DrawLine( #%ld, %ld, %ld, %ld, %ld )\n",1846(long)arg->iargs[0], (long)obj->desc.line.x1,1847(long)obj->desc.line.y1, (long)obj->desc.line.x2,1848(long)obj->desc.line.y2 ) );18491850/* use 'GGAddObject' to draw the object */1851n = GGAddObject( arg->win->draw, obj );1852return ANSWER_GAP( "od", n, 0, 0, 0 );1853}1854185518561857/****************************************************************************1858**1859*F FunDrawRectangle( <win>, <x1>, <y1>, <x2>, <y2> ) . . . draw a rectangle1860*/1861static Boolean FunDrawRectangle (1862TypeArg * arg )1863{1864TypeGapGraphicObject * obj;1865Int n;1866Int w;18671868/* create a line object */1869obj = (TypeGapGraphicObject*) XtMalloc( sizeof(TypeGapGraphicObject) );18701871/* convert <x> and <y> coordinates to X windows style */1872obj->type = T_RECT;1873obj->color = arg->win->color;1874obj->desc.rect.x1 = MIN( arg->iargs[1], arg->iargs[3] );1875obj->desc.rect.y1 = MIN( arg->iargs[2], arg->iargs[4] );1876obj->desc.rect.x2 = MAX( arg->iargs[1], arg->iargs[3] );1877obj->desc.rect.y2 = MAX( arg->iargs[2], arg->iargs[4] );1878w = obj->desc.rect.w = arg->win->line_width;1879obj->x = MIN( obj->desc.rect.x1, obj->desc.rect.x2 ) - w;1880obj->y = MIN( obj->desc.rect.y1, obj->desc.rect.y2 ) - w;1881obj->w = MAX( obj->desc.rect.x1, obj->desc.rect.x2 ) - obj->x + 1 + 2*w;1882obj->h = MAX( obj->desc.rect.y1, obj->desc.rect.y2 ) - obj->y + 1 + 2*w;1883CHECK_BBOX(obj);1884DEBUG( D_XCMD, ( "DrawRectangle( #%ld, %ld, %ld, %ld )\n",1885(long)arg->iargs[0], (long)arg->iargs[1],1886(long)arg->iargs[2], (long)arg->iargs[3] ) );18871888/* use 'GGAddObject' to draw the object */1889n = GGAddObject( arg->win->draw, obj );1890return ANSWER_GAP( "od", n, 0, 0, 0 );1891}189218931894/****************************************************************************1895**1896*F FunDrawText( <win>, <fid>, <x>, <y>, <str> ) . . . . . . draw text <str>1897*/1898static Boolean FunDrawText (1899TypeArg * arg )1900{1901TypeGapGraphicObject * obj;1902XFontStruct * font = arg->font;1903Int n;19041905/* create a TEXT object */1906obj = (TypeGapGraphicObject*) XtMalloc( sizeof(TypeGapGraphicObject) );19071908/* convert <x> and <y> coordinates to X windows style */1909obj->type = T_TEXT;1910obj->color = arg->win->color;1911obj->desc.text.x = arg->iargs[2];1912obj->desc.text.y = arg->iargs[3];1913obj->desc.text.font = font->fid;1914obj->desc.text.len = strlen(arg->sargs[0]);1915obj->desc.text.str = XtMalloc(obj->desc.text.len+1);1916strcpy( obj->desc.text.str, arg->sargs[0] );1917obj->x = arg->iargs[2] - 1;1918obj->y = arg->iargs[3] - font->ascent - 1;1919obj->w = obj->desc.text.len*font->max_bounds.width + 2;1920obj->h = font->descent + font->ascent + 2;1921CHECK_BBOX(obj);1922DEBUG( D_XCMD, ( "DrawText( #%ld, %ld, %ld, %s )\n",1923(long)arg->iargs[0], (long)arg->iargs[1],1924(long)arg->iargs[2], arg->sargs[0] ) );19251926/* use 'GGAddObject' to draw the object */1927n = GGAddObject( arg->win->draw, obj );1928return ANSWER_GAP( "od", n, 0, 0, 0 );1929}193019311932/****************************************************************************1933**19341935*F FunPlaybackFile( <filename> ) . . . . . . . . . playback file <filename>1936*/1937static Boolean FunPlaybackFile (1938TypeArg * arg )1939{1940return PlaybackFile(arg->sargs[0]) ?1941ANSWER_GAP( "o", 0, 0, 0, 0 )1942: ANSWER_GAP( "es", "cannot open file", 0, 0, 0 );1943}194419451946/****************************************************************************1947**1948*F FunResumePlayback() . . . . . . . . . . . . . . . resume playback of file1949*/1950static Boolean FunResumePlayback (1951TypeArg * arg )1952{1953return ResumePlayback() ?1954ANSWER_GAP( "o", 0, 0, 0, 0 )1955: ANSWER_GAP( "es", "no playback in progress", 0, 0, 0 );1956}195719581959/****************************************************************************1960**19611962*F * * * * * * * * * * interface to the main program * * * * * * * * * * *1963*/196419651966/****************************************************************************1967**19681969*V WindowCommands[] . . . . . . . . . . . . . . . list of window commands1970*/1971TypeWindowCommand WindowCommands[] =1972{1973{ "XAT", "#S", FunAddTitle },1974{ "XCA", "#", FunClearAll },1975{ "XCL", "TS", FunChangeList },1976{ "XCM", "#III", FunCheckMenuEntry },1977{ "XCN", "", FunColorModel },1978{ "XCO", "#I", FunSetColor },1979{ "XCS", "T", FunCloseSelector },1980{ "XCW", "#", FunCloseWindow },1981{ "XDB", "#IIII", FunDrawBox },1982{ "XDC", "#III", FunDrawCircle },1983{ "XDD", "#III", FunDrawDisc },1984{ "XDL", "#IIII", FunDrawLine },1985{ "XDM", "#I", FunDeleteMenu },1986{ "XDR", "#IIII", FunDrawRectangle },1987{ "XDT", "#FIIS", FunDrawText },1988{ "XEB", "TII", FunEnableButton },1989{ "XEM", "#III", FunEnableMenuEntry },1990{ "XFI", "F", FunFontInfo },1991{ "XFU", "#I", FunFastUpdate },1992{ "XLW", "#I", FunSetLineWidth },1993{ "XME", "#SS", FunMenu },1994{ "XOS", "SSS", FunOpenSelector },1995{ "XOW", "SII", FunOpenWindow },1996{ "XPF", "S", FunPlaybackFile },1997{ "XPS", "SS" , FunPopupShell },1998{ "XQP", "#", FunQueryPointer },1999{ "XRE", "#II", FunResize },2000{ "XRP", "", FunResumePlayback },2001{ "XRO", "#*", FunRemoveObjects },2002{ "XSD", "ISS", FunShowDialog },2003{ "XSP", "I", FunShowPopup },2004{ "XUS", "T", FunUnhighlihtSelector },2005{ 0L, 0L, 0L }2006};200720082009/****************************************************************************2010**2011*V PrivateActions . . . . . . . . . . . . . . . . . . . . action functions2012*/2013static XtActionsRec PrivateActions[] =2014{2015{ "NotifyClick", NotifyClick },2016{ "WmDeleteWindow", WmDeleteWindow }2017};201820192020/****************************************************************************2021**2022*F InitXCMDS() . . . . . . . . . . . . . . . initalize all global variables2023*/2024void InitXCMDS ()2025{20262027/* get the fonts form the database for <GapTalk> */2028XtVaGetValues( GapTalk,2029XtNtinyFont, (XtArgVal)&TinyFont,2030XtNsmallFont, (XtArgVal)&SmallFont,2031XtNnormalFont, (XtArgVal)&NormalFont,2032XtNlargeFont, (XtArgVal)&LargeFont,2033XtNhugeFont, (XtArgVal)&HugeFont,2034(String)NULL );20352036/* create lists for windows, popups, and selectors */2037GapWindows = List(0);2038PopupMenus = List(0);2039TextSelectors = List(0);20402041/* create cursors */2042SleepCursor = XCreateFontCursor( GapDisplay, XC_watch );2043RunCursor = XCreateFontCursor( GapDisplay, XC_top_left_arrow );20442045/* create popup dialogs */2046DialogOkCancel = CreatePopupDialog( AppContext, XGap, "OkCancelDialog",2047PD_OK | PD_CANCEL, PD_OK, 0 );20482049/* register private actions */2050XtAppAddActions( AppContext, PrivateActions, XtNumber(PrivateActions) );2051}205220532054/****************************************************************************2055**2056*F UpdateXCMDS( <state> ) . . . . . . . . . . gap is/isn't accepting input2057*/2058void UpdateXCMDS ( state )2059Boolean state;2060{2061TypeGapWindow * win;2062Int i;20632064/* GAP accepts input */2065if ( state )2066{2067for ( i = 0; i < LEN(GapWindows); i++ )2068{2069win = ELM( GapWindows, i );2070if ( win && win->used == True )2071XDefineCursor( GapDisplay, XtWindow(win->top), RunCursor );2072}2073}20742075/* GAP doesn't accept input */2076else2077{2078for ( i = 0; i < LEN(GapWindows); i++ )2079{2080win = ELM( GapWindows, i );2081if ( win && win->used == True )2082XDefineCursor( GapDisplay, XtWindow(win->top), SleepCursor );2083}2084}2085}208620872088/****************************************************************************2089**2090*F ExitXCMDS() . . . . . . . . . . . . . . . . . clear all global variables2091*/2092void ExitXCMDS ()2093{2094TypeArg arg;2095TypeMenu * menu;2096Int i;2097Int j;20982099/* clear list of windows and popups */2100for ( i = 0; i < LEN(GapWindows); i++ )2101{2102arg.win = ELM(GapWindows,i);2103if ( arg.win->used )2104FunCloseWindow(&arg);2105XtFree((char*)ELM(GapWindows,i));2106}2107XtFree((char*)GapWindows);2108for ( i = 0; i < LEN(TextSelectors); i++ )2109{2110arg.sel = ELM(TextSelectors,i);2111if ( arg.sel != 0 )2112{2113FunCloseSelector(&arg);2114XtFree((char*)ELM(TextSelectors,i));2115}2116}2117XtFree((char*)TextSelectors);2118for (i = 0; i < LEN(PopupMenus); i++ )2119if ( (menu = ELM(PopupMenus,i)) != 0 )2120{2121for ( j = 0; j < LEN(menu->entries); j++ )2122XtFree((char*)ELM(menu->entries,j));2123XtFree((char*)menu->entries);2124XtFree((char*)menu);2125}2126XtFree((char*)PopupMenus);2127}212821292130/****************************************************************************2131**21322133*E xcmds.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here2134*/213521362137