/* This file is a whole module unto itself. * It's like an "object", that will store up to MAXMULTI different kanji * translations. * (or at least pointers thereof) * * User can pick whether these translations will be displayed in terms * of kanji, kana, or english. * Clicking on one will set the search window to display that entry. * * Basic functions from the outside: * void MakeMulti(); [create X Widget] * void ShowMulti(); [ make window visible ] * void AddMultiTranslation(TRANSLATION); [ add to current list] * void ClearAllMulti(); * int getMultiMax(); [ return value of MAXMULTI define] * int getMultiCount(); [ return number of translations in current list] * * And one PRIVATE function that is public because of callbacks: * multicallback(int) * * Note: it is expected behaviour that routines outside this file, * will call AddMultiTranslation() a buncha times, but then * call ShowMulti() when they are all done adding. This allows * us to put cleanup routines in ShowMulti() */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* shouldnt be neccessary, but it is. sigh. */ #include "defs.h" #include "externs.h" #include "game.h" #include "init.h" #include "utils.h" #include "log.h" #include "readfile.h" #include "learn.h" #include "searchwidgets.h" /* MAXMULTI == max translation lines we will hold in multi-window */ /* If external routine wants to know this value, call getMultiMax() */ #define MAXMULTI 200 static Widget transwin[MAXMULTI]; /* user clicks to select translation*/ static TRANSLATION transptrs[MAXMULTI]; /* info in each transwin */ static Widget usefiletoggles[MAXMULTI]; /* is each one in usefile? */ static int transcount=0; static int overflow=0; /* number of added translations over MAXMULTI */ Widget multikanab, multikanjib, multienglishb; Widget multiclose; static int displaymode=GUESS_ENGLISH; static Widget multi_popup; static Widget multi_form; static Widget multi_viewport; static Widget multi_status; void RefreshMultiLabels(); void AddMultiTranslation(TRANSLATION nt); /************************************************************/ void ShowMulti(){ static int doneinit=0; XtPopup(multi_popup, XtGrabNone); if(doneinit==0){ setup_deletewindow(multi_popup); doneinit=1; } XawFormDoLayout(multi_form,True); } void HideMulti(){ XtPopdown(multi_popup); } /* resizing isn't behaving. so I'll force it to never go too small. * Hopefully. * Always have string more than 30 chars long. space-pad the end. */ static void setmultistatus(char *string){ #define FORCEWIDE #ifdef FORCEWIDE char statusbuff[50]; int stringlen=strlen(string); if(stringlen>49) stringlen=49; if(multi_status==NULL) return; strcpy(statusbuff, " "); bcopy(string, statusbuff, stringlen); XtVaSetValues(multi_status, XtNlabel,statusbuff, NULL); #else /* STUPID */ XtVaSetValues(multi_status, XtNlabel,string, NULL); #endif /* STUPID */ } void ClearAllMulti(){ int tc; overflow=0; /* for(tc=transcount -1; tc>=0; tc--){*/ for(tc=MAXMULTI -1; tc>=0; tc--){ XUnmapWindow(XtDisplay(transwin[tc]), XtWindow(transwin[tc])); XtVaSetValues(usefiletoggles[tc], XtNfromVert, NULL, NULL); /*XXX XUnmapWindow(XtDisplay(usefiletoggles[tc]), XtWindow(usefiletoggles[tc])); XtVaSetValues(transwin[tc], XtNfromVert, NULL, NULL); */ } bzero(transptrs, sizeof(transptrs)); transcount=0; /* Scroll up to top. Otherwise, it gets stuck at prev pos. */ XawViewportSetCoordinates(multi_viewport, 0, 0); setmultistatus("No matches"); } /* This callback handles both "Change what mode you display", and * 'Hey, show me this one in detail' */ void multicallback(Widget button, XtPointer data, XtPointer call_data){ int newmode=-1; int buttoncount; if(button==multiclose){ HideMulti(); return; } if(button==multikanab){ newmode=GUESS_KANA; } if(button==multikanjib){ newmode=GUESS_KANJI; } if(button==multienglishb){ newmode=GUESS_ENGLISH; } if(newmode!=-1){ /* * disable this optimization, becuase we want * romaji/kana to switch more easily if(newmode==displaymode) return; */ displaymode = newmode; RefreshMultiLabels(); return; } for(buttoncount=0;buttoncount50){ formwidth-=50; } for(transcount=0;transcount0){ /* we use this for XtNfromVert offset */ prevbutton=transwin[transcount-1]; } newbutton=XtVaCreateManagedWidget(buttname, commandWidgetClass, multi_form, XtNfromVert,prevbutton, XtNwidth, formwidth, XtNshapeStyle,XawShapeRoundedRectangle, XtNcornerRoundPercent,20, /* this is to get the height always right*/ XtNencoding,XawTextEncodingChar2b, XtNfont,largekfont, XtNleft,XawChainLeft, XtNright,XawChainRight, XtNlabel,"\0\0\0\0", NULL); XtAddCallback(newbutton, XtNcallback, multicallback, NULL); transwin[transcount]=newbutton; newu=XtVaCreateManagedWidget(buttname, commandWidgetClass, multi_form, XtNfromVert,prevbutton, XtNfromHoriz,newbutton, XtNleft,XawChainRight, XtNright,XawChainRight, XtNencoding,XawTextEncoding8bit, XtNfont,englishfont, XtNlabel,"u", NULL); XtAddCallback(newu, XtNcallback, multiUcallback, (XtPointer)transcount); usefiletoggles[transcount]=newu; } XawFormDoLayout(multi_form, True); /* Want to do this here. * But need to do this at end of MakeMulti (our calling function) * instead */ /* ClearAllMulti(); */ } #define VWIDTH 400 #define VHEIGHT 300 /* called ONCE at start of program*/ void MakeMulti(){ Widget multitop, buttonform; multi_popup=XtVaCreatePopupShell("multi_popup", topLevelShellWidgetClass, search_popup, XtNwidth, 350, XtNheight, 500, NULL); multitop=XtVaCreateManagedWidget("multitopform", formWidgetClass, multi_popup, NULL); multi_viewport=XtVaCreateManagedWidget("multiport", viewportWidgetClass, multitop, XtNforceBars, True, XtNallowHoriz,False, XtNallowVert,True, XtNwidth, VWIDTH, XtNheight, VHEIGHT, XtNbottom,XawChainBottom, XtNright,XawChainRight, XtNleft,XawChainLeft, NULL); /* This is what holds the multiple buttons, that show * all the different matches to a search * YES, we DO need to seed this with an initial height, otherwize * we get irritating behavior the first time we are used. */ multi_form=XtVaCreateManagedWidget("multikanjiform", formWidgetClass, /*boxWidgetClass,*/ multi_viewport, NULL); /* make all the little things inside multi_form */ createallmulti(); multi_status=XtVaCreateManagedWidget("multistatus", labelWidgetClass, multitop, XtNfromVert, multi_viewport, XtNtop, XawChainBottom, XtNbottom,XawChainBottom, XtNleft,XawChainLeft, XtNright,XawChainRight, XtNlabel, "Status ", XtNwidth, VWIDTH, NULL); buttonform=XtVaCreateManagedWidget("multibform", formWidgetClass, multitop, XtNfromVert, multi_status, XtNtop, XawChainBottom, XtNbottom,XawChainBottom, XtNleft,XawChainLeft, XtNright,XawChainLeft, XtNresizable, False, XtNborderWidth,0, NULL); multikanjib=XtVaCreateManagedWidget("multikanjib", commandWidgetClass, buttonform, XtNshapeStyle,XawShapeEllipse, XtNlabel,"Kanji", XtNresize, False, NULL); multienglishb=XtVaCreateManagedWidget("multienglishb", commandWidgetClass, buttonform, XtNshapeStyle,XawShapeEllipse, XtNfromHoriz, multikanjib, XtNlabel,"English", XtNresize, False, NULL); multikanab=XtVaCreateManagedWidget("multikanab", commandWidgetClass, buttonform, XtNshapeStyle,XawShapeEllipse, XtNfromHoriz, multienglishb, XtNlabel,"Kana meaning", XtNresize, False, NULL); multiclose=XtVaCreateManagedWidget("multiclose", commandWidgetClass, buttonform, /*XtNfromVert, multi_status,*/ XtNfromHoriz, multikanab, XtNlabel,"Close", XtNhorizDistance, 60, XtNshapeStyle,XawShapeRoundedRectangle, XtNcornerRoundPercent,10, XtNborderWidth, 2, NULL); XtAddCallback(multiclose, XtNcallback, multicallback, NULL); XtAddCallback(multikanab, XtNcallback, multicallback, NULL); XtAddCallback(multikanjib, XtNcallback, multicallback, NULL); XtAddCallback(multienglishb, XtNcallback, multicallback, NULL); /* HAVE TO DO THIS NOW, otherwise layout doesn't happen the first * time */ XtRealizeWidget(multi_popup); /* must do this AFTER widgets have been created */ ClearAllMulti(); } /* Sometimes, it is good to allow external functions to override * current display setting. * Like if we are doing radical search, for example. * Caller should call this AFTER having done the normal AddTranslations loop, * because this will take care of refreshing display if neccessary. */ void SetMultiMode(int mode){ switch(mode){ case GUESS_ENGLISH: case GUESS_KANJI: case GUESS_KANA: if(displaymode!=mode){ displaymode=mode; RefreshMultiLabels(); } break; default: puts("ERROR: SetMultiMode passed in invalid mode?!"); } } /* run through all the widgets we have, and set labels appropriately. * kinda like printallchoices() * I just LOOOOVE code reuse :-) * Call this when usefile status, or kana/romaji status changes. */ void RefreshMultiLabels(){ int lc; for(lc=0;lc=MAXMULTI){ char msgbuff[100]; overflow++; sprintf(msgbuff, "(only showing %d of %d)", MAXMULTI, MAXMULTI+overflow); setmultistatus(msgbuff); return; } transptrs[transcount]=trans; kindex=trans_to_index(trans); if(transcount>0){ XtVaSetValues(transwin[transcount], XtNfromVert,transwin[transcount-1], NULL); XtVaSetValues(usefiletoggles[transcount], XtNfromVert,transwin[transcount-1], NULL); } if(InUsefile(kindex)){ HighlightButton(usefiletoggles[transcount]); } else { UnhighlightButton(usefiletoggles[transcount]); } switch(displaymode){ case GUESS_ENGLISH: setenglabel(transwin[transcount], transptrs[transcount]); break; case GUESS_KANA: setkanalabel(transwin[transcount], transptrs[transcount]); break; case GUESS_KANJI: setkanjilabel(transwin[transcount], transptrs[transcount]); break; } XMapWindow(XtDisplay(transwin[transcount]), XtWindow(transwin[transcount])); XMapWindow(XtDisplay(usefiletoggles[transcount]), XtWindow(usefiletoggles[transcount])); transcount++; sprintf(statusprompt,"%d matches",transcount); setmultistatus(statusprompt); } int getMultiMax(){ return MAXMULTI; } int getMultiCount(){ return transcount; }