/* search.c * Handles the search window popup */ #include <stdio.h> #include <Xos.h> #include <Intrinsic.h> #include <StringDefs.h> #include <Xfuncs.h> #include <Xatom.h> #include <Xmu/Atoms.h> #include <Xmu/StdSel.h> #include <Shell.h> #include <Xaw/Command.h> #include <Xaw/Label.h> #include <Xaw/Form.h> #include <Xaw/Box.h> #include <Xaw/AsciiText.h> #include <Xaw/Paned.h> #include <cursorfont.h> /* for _XawTextGetSTRING(), except actually including it gets messy */ /*#include <Xaw/TextP.h>*/ #include "defs.h" #include "externs.h" #include "game.h" #include "widgets.h" #include "search.h" #include "convert.h" #include "multikanji.h" #include "strokesearch.h" #include "radsearch.h" #include "readfile.h" #include "searchwidgets.h" #include "learn.h" #include "utils.h" #include "init.h" #include "log.h" /* I dont like doing this. But there doesnt seem to be a reliable * way to tell a widget "be the entire width of the form" that * I have found */ #define SEARCHWIDTH 450 Cursor textcursor; Widget search_popup=NULL; Widget searchstatusline=NULL; Widget searchwidgets[NUM_OF_W]; Widget searchnumbers[NUM_OF_N]; Widget searchkanjiW,searchokuW; /* display current kanji here */ /* note.. if your compiler bitches about this initialization... * just remove the "={{0,0}}". * It will probably get initialized to 0,0 anyways * kanastring is the string held by the "type romaji here" widget. */ XChar2b kanastring[MAXKANALENGTH]={{0,0}}; /* flag, if we only match kanji/kana at beginning of translation */ int match_onlyatstart=0, match_onlyactive=0; static char *searchAccel = " <Key>Return: do-find()"; /* This gets called after clicking on the "search" button, or * using the keyboard accelerator. It pops up the search window. */ void SearchCallback(Widget w,XtPointer client_data, XtPointer call_data) { static int search_up = -1; static Position rel_x,rel_y; Position x,y; /* sometimes we are called with w==NULL by hand */ if(search_up==-1){ /* first time init.. */ rel_x = GetXtrmNumber("search_popupx","Search_popupx"); rel_y = GetXtrmNumber("search_popupy","Search_popupy"); setup_deletewindow(search_popup); search_up=0; } if(isMapped(search_popup)==False){ /* Map in! */ XtTranslateCoords(toplevel,rel_x,rel_y,&x,&y); /* it seems some window managers let you have extreme * negative coordinates for pop-ups. sigh */ if(x<0) x=0; if(y<0) y=0; XtVaSetValues(search_popup, XtNx,x, XtNy,y, NULL); XtMapWidget(search_popup); setstatus("Bringing up search window..."); } else { XtUnmapWidget(search_popup); } } /* handle toggle for "match only if kana STARTS a phrase" */ void ToggleMatchstart(Widget w,XtPointer client_data, XtPointer call_data) { match_onlyatstart=!match_onlyatstart; ReverseButton(w); } /* handle toggle for "match only active kanji" */ void ToggleActivesearch(Widget w,XtPointer client_data, XtPointer call_data) { match_onlyactive=!match_onlyactive; ReverseButton(w); } /* deal with matchkanji button. */ /* Find all matches for what is currently being displayed by the search win*/ void Handle_matchkanji(Widget w,XtPointer client_data, XtPointer call_data) { findkanjiall(lastsearch->kanji); } /* Handle toggle callback for "[usefile]" toggle button */ /* Parallel func to multiUcallback() */ static void ToggleUsefile(Widget w,XtPointer client_data, XtPointer call_data) { int kcount=trans_to_index(lastsearch); SetUseKanji(kcount, !InUsefile(kcount)); if(InUsefile(kcount)){ HighlightButton(w); } else { UnhighlightButton(w); } DisplayLearnChar(); /* on the off-chance the Learn window shows same*/ RefreshMultiLabels(); CountKanji(); } /* Callback for button to "Show usefile" */ void ShowUsefile(Widget w,XtPointer client_data, XtPointer call_data) { setstatus("Showing usefile..."); dousefilefind(); } /* Update the labels for the info widgets at the top of search window.*/ /* Assumes variable "lastsearch" points to currently desired TRANSLATION */ void UpdateSearchlabels() { TRANSLATION This=lastsearch; int kanjinum=0, kindex; XChar2b radlist[MAXRADICALS+1]; if(search_popup==NULL) return; if(This==NULL){ return; } XtVaSetValues(searchkanjiW,XtNlabel,This->kanji, XtNwidth,KANJIWIDTH,XtNheight,KANJIWIDTH,NULL); SetWidgetNumberval(searchnumbers[G_INPUT],(int)This->grade_level); SetWidgetNumberval(searchnumbers[F_INPUT],(int)This->frequency); SetWidgetNumberval(searchnumbers[H_INPUT],(int)This->Hindex); SetWidgetNumberval(searchnumbers[N_INPUT],(int)This->Nindex); SetWidgetHexval(searchnumbers[U_INPUT],(int)This->Uindex); kindex=trans_to_index(This); if(InUsefile(kindex)) { HighlightButton(searchnumbers[INUSEFILE]); } else { UnhighlightButton(searchnumbers[INUSEFILE]); } /* assume if kanji entry is ONE char long, that we * can use that byte as old kdrill/kanjidic index * ('#x' window) */ if(This->kanji != NULL){ if(This->kanji[1].byte1 == 0) { kanjinum = This->kanji[0].byte1; kanjinum = kanjinum <<8; kanjinum |= This->kanji[0].byte2; } } if(kanjinum == NOKANJI) { kanjinum = 0; } SetWidgetHexval(searchnumbers[POUND_INPUT], kanjinum); if(romajiswitch==1) { char stringbuff[MAXROMAJI+1]; /*translate all kana into romaji */ /* translate to buffer, then set widget string*/ kanatoromaji(This->pronunciation, stringbuff); XtVaSetValues(searchwidgets[KANA_W], XtNencoding,XawTextEncoding8bit, XtNfont,englishfont, NULL); XtVaSetValues(searchwidgets[KANA_W], XtNlabel,stringbuff, NULL); } else { XtVaSetValues(searchwidgets[KANA_W], XtNencoding, XawTextEncodingChar2b, XtNfont,smallkfont, NULL); XtVaSetValues(searchwidgets[KANA_W], XtNlabel,This->pronunciation,NULL); } XtVaSetValues(searchwidgets[ENGLISH_W], XtNlabel,This->english,NULL); XtVaSetValues(searchnumbers[RADLIST_D],XtNlabel,"\0\0",NULL); if(kanjinum!=0){ radlist[0].byte1=0; /* a single kanji, should have radicals associated with it*/ FindRadicals(This->kanji[0],radlist); if(radlist[0].byte1 != 0){ XtVaSetValues(searchnumbers[RADLIST_D], XtNlabel,radlist,NULL); } } } /* clear labels of "current kanji" display, in top of search window */ void clearsearchlabels() { XChar2b blank = {0x0, 0x0}; XtVaSetValues(searchkanjiW, XtNlabel," ", NULL); XtVaSetValues(searchwidgets[ENGLISH_W],XtNlabel,"",NULL); SetWidgetNumberval(searchnumbers[G_INPUT],0); SetWidgetNumberval(searchnumbers[F_INPUT],0); SetWidgetNumberval(searchnumbers[POUND_INPUT],0); SetWidgetNumberval(searchnumbers[H_INPUT],0); SetWidgetNumberval(searchnumbers[N_INPUT],0); SetWidgetNumberval(searchnumbers[U_INPUT],0); XtVaSetValues(searchkanjiW,XtNlabel,&blank, XtNwidth,KANJIWIDTH,XtNheight,KANJIWIDTH,NULL); } /* printsearch: * Given an index, make search window print out appropriate stuff. * printsearch(0) means "clear windows". * * This also sets the lastsearch static global!! */ void printsearch(TRANSLATION This) { if(isMapped(search_popup)==False){ /* pop up window, if it isnt already */ SearchCallback(search_popup,NULL,NULL); } if(This==NULL){ return; } lastsearch = This; UpdateSearchlabels(); } /* SearchRefresh() * called by romajicallback, when user toggles romaji/kana display */ void SearchRefresh() { UpdateSearchlabels(); if(isMapped(search_popup)) printsearch(lastsearch); } /* stolen from xclipboard */ long TextLength (w) Widget w; { return XawTextSourceScan (XawTextGetSource (w), (XawTextPosition) 0, XawstAll, XawsdRight, 1, TRUE); } /* * This is basically a hand-coded "hextoi()" function. * I dont know of a ubiquitous "hex to int" function like * atoi * It is fairly inflexible: it wants EXACTLY 4 hex digits. values passed back as bits 0-7 is "byte1" * 8-15 is "byte2" */ static CARD16 unescape_kanji(char *string){ int kchar[4]; /* temp buffer, really */ int count; CARD16 newval; if(strlen(string)<4){ fprintf(stderr,"unescape_kanji passed bad string\n"); return 0; } for(count=0; count<4; count++){ if(('A' <= string[count]) && (string[count] <='F')){ kchar[count]=string[count] - 'A' + 10; } else if(('a' <= string[count]) && (string[count] <='f')){ kchar[count]=string[count] - 'a' + 10; } else { kchar[count]=string[count] - '0'; } } newval=(kchar[0]<<12) +(kchar[1]<<8) +(kchar[2]<<4) +kchar[3]; return newval; } /* take various formats of JIS, etc, * [from cut-n-paste] * convert to what we expect, and call * findkanjiall() on resulting string, IF we recognize something. * * We Assume buffer is AT LEAST 2 bytes long !!! * * POSSIBILITIES: * 1. "raw" JIS, that looks to us like * 0xffffff##, 0xffffff## * * 2. prefaced SJIS, that looks to us like * 0x1b, 0x2d, 0x41, 0xffffff##, 0xffffff## * * 2.1 prefaced JIS, that looks to us like * 0x1b, 0x2d, 0x41, 0x####, 0x####, 0x1b, 0x28 * * 3. A different (older?) kind of prefaced JIS,that looks like * 0x1b, 0x24, 0x29, 0x42, blahblahblah * * 4. stripped JIS (from rxvt), that is going to be tricky to tell. * * return 1 on recognizeable JIS string, or 0 otherwise. */ static int doJISConvert(char *inputstring){ /* only handle up to three encoded chars. Ignore more. */ XChar2b kstring[4]; char *strstart=NULL; int kstr_ndx; bzero(kstring, sizeof(XChar2b) * 4); /* SPECIAL CASES: We have an ascii-hex-encoded string here */ /* It is probably actually UNICODE */ /* pan newsreader actually uses its own funky encoding: \x{xxxxx} [maybe this was gtk1? pan+gtk2 uses mozilla style now] Mozilla/firefox seems to use \u6559\u80b2 ?? */ if(strncmp("\\u",inputstring,2) == 0){ strstart=&inputstring[2]; } if(strncmp("\\x{",inputstring,3) == 0){ strstart=&inputstring[3]; } if(strstart != NULL){ /* this takes only a SINGLE CHAR, unfortunately */ CARD16 tmpval=unescape_kanji(strstart); if(tmpval != 0){ kstring[0].byte1=(tmpval&0xff00)>>8; kstring[0].byte2=(tmpval&0xff); } /* and is there a second char available? */ strstart=&strstart[4]; if(strncmp("\\u",strstart,2) == 0){ strstart=&strstart[2]; } if(strncmp("\\x{",strstart,3) == 0){ strstart=&strstart[3]; } if(strstart != NULL){ tmpval=unescape_kanji(strstart); if(tmpval != 0){ kstring[1].byte1=(tmpval&0xff00)>>8; kstring[1].byte2=(tmpval&0xff); } } if(kstring[0].byte1 !=0){ findunicodestring(kstring); return 1; } } /* Otherwise, we have lightly encoded, or raw, JIS to parse */ if(inputstring[0]&0xffffff00){ strstart=&inputstring[0]; } else if(strncmp("\x1b\x24\x29\x42",inputstring,4) == 0){ strstart=&inputstring[4]; } else if(strncmp("\x1b\x2d\x41",inputstring,3) == 0){ strstart=&inputstring[3]; } else if(strncmp("\x1b\x2d\x42",inputstring,3) == 0){ /* We should never normally see this, because * the Xaw routines seem to autoconvert this to the * 0xffffff format instead */ strstart=&inputstring[3]; } if((strstart==NULL) && (kstring[0].byte1==0)){ /* ugh. Unfortunately, rxvt hands us unencoded stuff, * which in theory might just be plain ascii. * Attempt to treat it as JIS, if first char hits * a known kanji */ int tmpndx=0; tmpndx=(inputstring[0]<<8) |(inputstring[1]&0xff); if((tmpndx>MAXKANJIALLOWED) ||(tmpndx< MINKANJIALLOWED)){ return 0; } if(translations[tmpndx] == NULL){ return 0; } strstart=&inputstring[0]; } /* Okay, we have valid string. Convert up to 3 chars to JIS * format that we use internally, so we can search on it */ kstr_ndx=0; while(kstr_ndx<3){ if((strstart[0]==0) || strstart[1]==0) { break; } kstring[kstr_ndx].byte1=*strstart++ & 0x7f; kstring[kstr_ndx].byte2=*strstart++ & 0x7f; kstr_ndx++; } if(kstr_ndx==0) return 0; kstring[kstr_ndx].byte1=0; kstring[kstr_ndx].byte2=0; findkanjiall(&kstring[0]); return 1; } /* copy cut-n-paste buffer into local storage, and do search on it * if possible. * Triggered by pasteCallback() */ void copybuffer(Widget w, XtPointer client_data, Atom *selection, Atom *type, XtPointer value, unsigned long *length, int *format) { int buflen=(int)*length; char *valuestring=(char*)value; if(*type==0){ #ifdef DEBUG puts("DEBUG copybuffer has *type=0. returning."); #endif return; } if(buflen==0){ #ifdef DEBUG puts("DEBUG: paste len==0. ignoring"); #endif return; } if(buflen<2){ #ifdef DEBUG puts("DEBUG: paste len==1. ignoring"); #endif XtFree(value); return; } #ifdef DEBUG puts("copybuffer: values of XtNstring pasted are:"); while(bufparse <buflen) { printf("%.2x.",valuestring[bufparse++]); } puts(""); printf(" total string len == %d\n", buflen); #endif doJISConvert(valuestring); XtFree(value); } /* "Handler" for "<paste kanji>" button in search window. * Completely obsoletes the old nasty Handle_searchPasted() hack I had before. * This takes the high-level X clipboard stuff, and hands it over to * copybuffer() */ void Handle_paste(Widget widget, XtPointer closure, XEvent *e, Boolean *cont) { Time timestamp; Atom clipboardatom; timestamp=CurrentTime; /* puts("DEBUG: using XA_CLIPBOARD for cutnpaste"); clipboardatom=XA_CLIPBOARD(display); */ clipboardatom=XA_PRIMARY; /* I originally used XA_STRING as the 'type', but * that did not work with kterm. * Once I changed to XA_TEXT(), it seems to work for both * kterm, AND netscape4.x * * call copybuffer() with the value. */ XtGetSelectionValue(widget, clipboardatom, XA_TEXT(display), copybuffer, NULL, timestamp); } /* This gets called when someone presses a mousebutton in the big kanji * display string, in the search popup. * Our job is to split up the string into multiple kanji, and * popopulate the multikanji popup, so that the user can deconstruct * the string into separate kanji */ void Handle_kanji_split(Widget widget, XtPointer closure, XEvent *e, Boolean *cont) { split_kanji_search(); } /************************************************************* * Widget Creation Below Here * *************************************************************/ /* make the G, F, # , etc, for the search popup */ void makenumbers(Widget parent){ searchnumbers[G_LABEL] = XtVaCreateWidget("0",labelWidgetClass,parent, XtNlabel,"G:", XtNborderWidth,0, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); /* G_INPUT is read-only, not really "INPUT". * but keep as asciiText so UpdateSearchLabels() * can have a uniform code layout. */ searchnumbers[G_INPUT] = XtVaCreateWidget("sn1",asciiTextWidgetClass,parent, XtNfromHoriz,searchnumbers[G_LABEL], XtNstring," ", XtNdisplayCaret,False, XtNwidth,30, /* leave this short, match mainwin */ XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[H_LABEL] = XtVaCreateWidget("sn6",labelWidgetClass,parent, XtNfromVert,searchnumbers[G_LABEL], XtNlabel,"H:", XtNborderWidth,0, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[H_INPUT] = XtVaCreateWidget("sn7",asciiTextWidgetClass,parent, XtNfromVert,searchnumbers[G_LABEL], XtNfromHoriz,searchnumbers[G_LABEL], XtNstring," ", XtNwidth,INPUTWIDTH, XtNeditType,XawtextEdit, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[F_LABEL] = XtVaCreateWidget("sn2",labelWidgetClass,parent, XtNfromHoriz,searchnumbers[H_INPUT], XtNlabel,"F:", XtNborderWidth,0, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[F_INPUT] = XtVaCreateWidget("sn3",asciiTextWidgetClass,parent, XtNfromHoriz,searchnumbers[F_LABEL], XtNstring,"", XtNwidth,INPUTWIDTH, XtNeditType,XawtextEdit, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[N_LABEL] = XtVaCreateWidget("sn8",labelWidgetClass,parent, XtNfromVert,searchnumbers[G_LABEL], XtNfromHoriz,searchnumbers[H_INPUT], XtNlabel,"N:", XtNborderWidth,0, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[N_INPUT] = XtVaCreateWidget("sn9",asciiTextWidgetClass,parent, XtNfromVert,searchnumbers[G_LABEL], XtNfromHoriz,searchnumbers[F_LABEL], XtNstring," ", XtNwidth,INPUTWIDTH, XtNeditType,XawtextEdit, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[POUND_LABEL] = XtVaCreateWidget("sn4",labelWidgetClass,parent, XtNfromHoriz,searchnumbers[F_INPUT], XtNfromHoriz,searchnumbers[N_INPUT], XtNlabel,"#x:", XtNborderWidth,0, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[POUND_INPUT] = XtVaCreateWidget("sn5",asciiTextWidgetClass,parent, XtNfromHoriz,searchnumbers[POUND_LABEL], XtNstring,"", XtNwidth,INPUTWIDTH, XtNeditType,XawtextEdit, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[U_LABEL] = XtVaCreateWidget("sn10",labelWidgetClass,parent, XtNfromVert,searchnumbers[G_LABEL], XtNfromHoriz,searchnumbers[F_INPUT], XtNfromHoriz,searchnumbers[N_INPUT], XtNlabel,"Ux:", XtNborderWidth,0, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[U_INPUT] = XtVaCreateWidget( "11",asciiTextWidgetClass,parent, XtNfromVert,searchnumbers[G_LABEL], XtNfromHoriz,searchnumbers[POUND_LABEL], XtNstring," ", XtNwidth,INPUTWIDTH, XtNeditType,XawtextEdit, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[INUSEFILE] = XtVaCreateWidget( "12",commandWidgetClass,parent, XtNlabel, "usefile", XtNfromHoriz,searchnumbers[U_INPUT], XtNhorizDistance, 20, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[SHOWUSEFILE] = XtVaCreateWidget( "12",commandWidgetClass,parent, XtNlabel, "show u.", XtNshapeStyle,XawShapeRoundedRectangle, XtNcornerRoundPercent,50, XtNfromHoriz,searchnumbers[U_INPUT], XtNfromVert,searchnumbers[INUSEFILE], XtNhorizDistance, 20, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[RADLIST_L] = XtVaCreateManagedWidget("radlist_l", labelWidgetClass, parent, XtNlabel,"Radicals:", XtNborderWidth, 0, XtNfromVert,searchnumbers[H_LABEL], XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchnumbers[RADLIST_D] = XtVaCreateManagedWidget("radlist_d", labelWidgetClass, parent, XtNfromVert,searchnumbers[H_LABEL], XtNfromHoriz,searchnumbers[RADLIST_L], XtNlabel," ", XtNencoding,XawTextEncodingChar2b, XtNfont,smallkfont, XtNright, XawChainRight, XtNleft, XawChainLeft, NULL); XtManageChildren(searchnumbers,NUM_OF_N); } /* make topstuff: * Make widgets dealing with "current kanji", at top of search popup */ void maketopsearchstuff(Widget parent){ Widget numbersform,matchbutton; searchkanjiW = XtVaCreateManagedWidget("kanjilarge", labelWidgetClass, parent, XtNwidth,SEARCHWIDTH - 100, XtNheight,KANJIWIDTH, XtNlabel,"", XtNencoding,XawTextEncodingChar2b, XtNfont,largekfont, XtNright, XawChainRight, XtNleft, XawChainLeft, NULL); /* want to handle just middle button on this one */ XtAddEventHandler(searchkanjiW, ButtonPressMask,False,Handle_kanji_split,NULL); matchbutton = XtVaCreateManagedWidget("matchkanjib", commandWidgetClass,parent, XtNfromHoriz,searchkanjiW, XtNlabel, "match", XtNright, XawChainRight, XtNleft, XawChainRight, NULL); XtAddCallback(matchbutton, XtNcallback, Handle_matchkanji, NULL); numbersform = XtVaCreateManagedWidget("numform", formWidgetClass, parent, XtNresizeToPreferred, True, XtNfromVert,searchkanjiW, XtNright, XawChainLeft, XtNleft, XawChainLeft, XtNtop,XawChainTop, XtNbottom,XawChainTop, NULL); makenumbers(numbersform); } /* define the label and input widgets for inputting english * and kana. At the TOP LEVEL of the search window. * * For kana, the "label" is actually a button that will bring up the * special kana input window. User can then point-and-click. * * Returns "lowest" (southernmost) widget, so status line can be * "below" that. */ Widget makesearchinputs(Widget parent) { Widget kanjisform, searchinputform; Widget optsform, optslabel; searchinputform=XtVaCreateManagedWidget("searchinputform", formWidgetClass,parent, XtNfromVert, searchwidgets[ENGLISH_W], XtNvertDistance,10, XtNresizeToPreferred, True, XtNright, XawChainRight, XtNleft, XawChainLeft, XtNtop,XawChainTop, XtNbottom,XawChainTop, NULL); searchwidgets[SEARCH_ENG_L] = XtVaCreateManagedWidget("searchenglishlabel", labelWidgetClass, searchinputform, XtNjustify, XtJustifyRight, XtNlabel, "English search", XtNborderWidth, 0, XtNleft, XawChainLeft, XtNright, XawChainLeft, NULL); searchwidgets[SEARCH_ENG_W] = XtVaCreateManagedWidget("searchenglish", asciiTextWidgetClass, searchinputform, XtNfromHoriz, searchwidgets[SEARCH_ENG_L], XtNfont, englishfont, XtNeditType, XawtextEdit, XtNleft, XawChainLeft, XtNright, XawChainRight, /*XtNstring," ",*/ XtNwidth, 150, NULL); /************************************************************/ kanjisform= XtVaCreateManagedWidget("searchkanjif", formWidgetClass,searchinputform, XtNfromVert, searchwidgets[SEARCH_ENG_L], XtNvertDistance, 10, XtNleft, XawChainLeft, XtNright, XawChainLeft, XtNtop,XawChainTop, XtNbottom,XawChainTop, NULL); searchwidgets[SEARCH_KANJI_L] = XtVaCreateManagedWidget("searchkanjibutton", commandWidgetClass, kanjisform, XtNjustify, XtJustifyRight, XtNlabel, "Kanji search ", XtNright, XawChainRight, NULL); searchwidgets[SEARCH_SKIP_W] = XtVaCreateManagedWidget("searchskipbutton", commandWidgetClass, kanjisform, XtNlabel, "Kanji SKIP search", XtNfromHoriz, searchwidgets[SEARCH_KANJI_L], XtNleft, XawChainRight, XtNright, XawChainRight, NULL); searchwidgets[SEARCH_STROKE_W] = XtVaCreateManagedWidget("searchstrokebutton", commandWidgetClass,kanjisform, XtNjustify, XtJustifyRight, XtNlabel, "Stroke count ", XtNfromVert, searchwidgets[SEARCH_KANJI_L], XtNright, XawChainRight, NULL); searchwidgets[SEARCH_KANJIPASTE] = XtVaCreateManagedWidget("searchkanji", labelWidgetClass,kanjisform, XtNlabel," <paste kanji> ", XtNfromVert, searchwidgets[SEARCH_KANJI_L], XtNfromHoriz, searchwidgets[SEARCH_STROKE_W], XtNleft, XawChainRight, XtNright, XawChainRight, NULL); searchwidgets[SEARCH_RADICAL_W] = XtVaCreateManagedWidget("searchradicals", commandWidgetClass,kanjisform, XtNlabel,"Radical search", XtNfromVert, searchwidgets[SEARCH_STROKE_W], XtNright, XawChainRight, NULL); /* and now the kana search input widgets. gets a bit messy here */ searchwidgets[KANA_FORM]=XtVaCreateManagedWidget("kanasearchgroup", formWidgetClass, searchinputform, XtNresizeToPreferred, True, XtNfromVert, kanjisform, XtNvertDistance, 10, XtNborderWidth, 1, XtNright, XawChainRight, XtNleft, XawChainLeft, XtNtop,XawChainTop, XtNbottom,XawChainTop, NULL); searchwidgets[SEARCH_KANA_L] = XtVaCreateManagedWidget("searchkanalabel", labelWidgetClass, searchwidgets[KANA_FORM], XtNlabel, "Kana searches", XtNborderWidth,0, XtNright, XawChainLeft, XtNleft, XawChainLeft, NULL); searchwidgets[SEARCH_KANA_B] = XtVaCreateManagedWidget("searchkanabutton", commandWidgetClass, searchwidgets[KANA_FORM], XtNfromHoriz,searchwidgets[SEARCH_KANA_L], XtNhorizDistance,20, XtNlabel, "Popup Kana table", XtNright, XawChainRight, XtNleft, XawChainRight, /* These dont work as I want */ /* XtNresizable, False, */ NULL); searchwidgets[SEARCH_KANA_W] = XtVaCreateManagedWidget("searchkana", labelWidgetClass, searchwidgets[KANA_FORM], XtNwidth, SEARCHWIDTH - 150, XtNlabel,"\0", /*XtNlabel, "!z",*/ /* 0x217a */ XtNfromVert, searchwidgets[SEARCH_KANA_L], XtNfont, smallkfont, XtNencoding, XawTextEncodingChar2b, XtNjustify, XtJustifyLeft, XtNcursor, textcursor, XtNright, XawChainRight, XtNleft, XawChainLeft, NULL); /************************************************************/ optsform=XtVaCreateManagedWidget("searchoptsform", formWidgetClass, parent, XtNresizeToPreferred, True, XtNfromVert, searchwidgets[ENGLISH_W], XtNvertDistance,10, XtNfromHoriz, searchinputform, XtNborderWidth, 1, XtNleft, XawChainRight, XtNright, XawChainRight, XtNtop,XawChainTop, XtNbottom,XawChainTop, NULL); optslabel=XtVaCreateManagedWidget("searchoptslabel", labelWidgetClass, optsform, XtNlabel, " Match ", XtNborderWidth, 0, /*XtNjustify,XawCenter */ /* default */ NULL); searchwidgets[SEARCH_ACTIVEFILTER]= XtVaCreateManagedWidget("filter_toggle", commandWidgetClass, optsform, XtNfromVert, optslabel, XtNlabel, "active", NULL); searchwidgets[SEARCH_STARTTOG]= XtVaCreateManagedWidget("atstart_toggle", commandWidgetClass, optsform, XtNfromVert, searchwidgets[SEARCH_ACTIVEFILTER], XtNlabel, "initial", NULL); /* This possibly now has the wrong value.(?) sigh. */ /*XtManageChildren(searchwidgets,SEARCH_ENG_W+1);*/ XtAddCallback(searchwidgets[SEARCH_KANA_B], XtNcallback, Showinputkana, NULL); XtAddCallback(searchwidgets[SEARCH_KANJI_L], XtNcallback, Showinputkanji, NULL); XtAddCallback(searchwidgets[SEARCH_SKIP_W], XtNcallback, ShowSKIP, NULL); XtAddCallback(searchwidgets[SEARCH_STROKE_W], XtNcallback, Showstroke, NULL); XtAddCallback(searchwidgets[SEARCH_RADICAL_W], XtNcallback, ShowRadicalinput, NULL); XtAddCallback(searchwidgets[SEARCH_STARTTOG], XtNcallback, ToggleMatchstart, NULL); XtAddCallback(searchwidgets[SEARCH_ACTIVEFILTER], XtNcallback, ToggleActivesearch, NULL); XtAddCallback(searchnumbers[INUSEFILE], XtNcallback, ToggleUsefile, NULL); XtAddCallback(searchnumbers[SHOWUSEFILE], XtNcallback, ShowUsefile, NULL); /* XtAddCallback(searchwidgets[SEARCH_KANJIPASTE], XtNcallback, pasteCallback, NULL); */ /* want to handle any/all buttons */ XtAddEventHandler(searchwidgets[SEARCH_KANJIPASTE], ButtonPressMask,False,Handle_paste,NULL); XtAddEventHandler(searchwidgets[SEARCH_KANA_W], KeyPressMask, False, Handle_romajikana,NULL); return searchinputform; } /* This is the only exported "make widgets" routine */ void MakeSearchPopup() { XtAccelerators Accel; Widget searchform,lastsearchinput; textcursor=XCreateFontCursor(display,XC_xterm); #ifdef OLDWAY search_popup = XtVaCreatePopupShell("kdrill_search", transientShellWidgetClass, toplevel, NULL); #else search_popup = XtVaCreateWidget("kdrill_search", /*shellWidgetClass,*/ topLevelShellWidgetClass, toplevel, NULL); XtSetMappedWhenManaged(search_popup,False); #endif searchform = XtVaCreateManagedWidget("searchform", formWidgetClass, search_popup, NULL); searchwidgets[NFORM_W] = XtVaCreateManagedWidget("northform", formWidgetClass, searchform, XtNresizeToPreferred, True, XtNborderWidth,2, XtNright, XawChainRight, XtNleft, XawChainLeft, XtNtop,XawChainTop, XtNbottom,XawChainTop, NULL); /* make everything in the top box: kanji, frequency, grade, etc*/ maketopsearchstuff(searchwidgets[NFORM_W]); /* now make the wide output display widgets, below the main * kanji display, at the top. */ searchwidgets[KANA_W] = XtVaCreateManagedWidget("searchkana", labelWidgetClass, searchform, XtNlabel," ", XtNfromVert,searchwidgets[NFORM_W], XtNvertDistance,20, XtNencoding,XawTextEncodingChar2b, XtNfont,smallkfont, XtNwidth,SEARCHWIDTH, XtNleft, XawChainLeft, XtNright, XawChainRight, XtNtop,XawChainTop, XtNbottom,XawChainTop, NULL); searchwidgets[ENGLISH_W] = XtVaCreateManagedWidget("searchenglish", labelWidgetClass, searchform, XtNlabel," ", XtNfromVert,searchwidgets[KANA_W], XtNfont,englishfont, XtNwidth,SEARCHWIDTH, XtNleft, XawChainLeft, XtNright, XawChainRight, XtNtop,XawChainTop, XtNbottom,XawChainTop, NULL); /* This makes other searchwidgets[] stuffs, below the static * display we just made, above. */ lastsearchinput=makesearchinputs(searchform); searchstatusline = XtVaCreateManagedWidget("searchstatus", labelWidgetClass, searchform, XtNlabel,"Search popup", XtNwidth,SEARCHWIDTH, XtNborderWidth,2, XtNfromVert, lastsearchinput, XtNresize,True, XtNleft, XawChainLeft, XtNright, XawChainRight, XtNtop,XawChainTop, XtNbottom,XawChainTop, NULL); Accel = XtParseAcceleratorTable(searchAccel); XtOverrideTranslations(searchwidgets[SEARCH_ENG_W],Accel); XtOverrideTranslations(searchnumbers[F_INPUT],Accel); XtOverrideTranslations(searchnumbers[POUND_INPUT],Accel); XtOverrideTranslations(searchnumbers[H_INPUT],Accel); XtOverrideTranslations(searchnumbers[N_INPUT],Accel); XtOverrideTranslations(searchnumbers[U_INPUT],Accel); MakeKanainputPopup(); MakeKanjiinputPopup(); MakeStrokeinputPopup(); MakeSKIPInputPopup(); }