Logo Search packages:      
Sourcecode: kdrill version File versions  Download package

multikanji.c

/* 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 <Xos.h>
#include <Intrinsic.h>
#include <StringDefs.h>
#include <Xlib.h>
#include <Xutil.h>
#include <Xfuncs.h>

#include <Shell.h>
#include <Xaw/Command.h>
#include <Xaw/Label.h>
#include <Xaw/Form.h>
#include <Xaw/Box.h>
#include <Xaw/Viewport.h>

#include <stdio.h> /* 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;buttoncount<transcount; buttoncount++){
            if(button== transwin[buttoncount]){
                  printsearch(transptrs[buttoncount]);
                  return;
            }
      }

      puts("Error: multicallback got click on unrecognized button?");
      
}

/* This handles a click on a usefile toggle button, 
 * in the multikanji popup.
 * Parallel function to ToggleUsefile()
 */
void multiUcallback(Widget button, XtPointer data, XtPointer call_data){
      TRANSLATION trans=transptrs[(int)data];
      int kindex=trans_to_index(trans);

      SetUseKanji(kindex,!InUsefile(kindex));

      if(InUsefile(kindex)){
            HighlightButton(button);
      } else {
            UnhighlightButton(button);
      }

      /* Just in case this is for the currently displayed search line*/
      UpdateSearchlabels();
      DisplayLearnChar();

      CountKanji();
}



/* just create the line-item buttons, not "everything" */
/* We pre-create all the buttons, and hide them when not in use.*/
void createallmulti(){
      Widget newbutton,newu;
      Widget prevbutton=NULL;
      int formwidth=GetWidgetWidth(multi_popup);
      char buttname[10],uname[10];
      int transcount;


      if(formwidth>50){
            formwidth-=50;
      }

      
      for(transcount=0;transcount<MAXMULTI;transcount++){
            sprintf(buttname, "multi%x\n", (unsigned int)transcount);
            sprintf(uname, "multiU%x\n", (unsigned int)transcount);

            if(transcount>0){
                  /* 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<transcount;lc++){
            switch(displaymode){
               case GUESS_ENGLISH:
                  setenglabel(transwin[lc], transptrs[lc]);
                  break;
               case GUESS_KANA:
                  setkanalabel(transwin[lc], transptrs[lc]);
                  break;
               case GUESS_KANJI:
                  setkanjilabel(transwin[lc], transptrs[lc]);
                  break;
            }
            if(InUsefile(trans_to_index(transptrs[lc]))){
                  HighlightButton(usefiletoggles[lc]);
            } else {
                  UnhighlightButton(usefiletoggles[lc]);

            }
      }
}

/* We ignore attempts to add more than our MAXMULTI value */
void AddMultiTranslation(TRANSLATION trans){
      int kindex;
      char statusprompt[20];
      /*int formwidth=GetWidgetWidth(multi_popup);*/


      if(transcount>=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;
}



Generated by  Doxygen 1.6.0   Back to index