/* twpsk - A gui application for PSK * Copyright (C) 1999 Ted Williams WA0EIR * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, * USA. * * Version: 2.1 - Aug 2002 */ #include "twpskWids.h" #include "twpskCB.h" #include "decoderWids.h" #include "../server/server.h" #define SCOPE_HEIGHT 80 extern Wids pskwids; extern TwpskCB twpskCB; extern Position winlocs[3][2]; extern DecoderWid decoderwids; extern Position xb, yb; static void closeProc(Widget w, XtPointer clientdata, XtPointer /*calldata*/ ) { DecoderWid *dec = (DecoderWid *)clientdata; commControl(dec->commChannel, COMM_MODE, MO_DISABLED); // close channel XtPopdown( dec->getMainWid() ); dec->visible = 0; } /* Scope redraw callback */ static void decScopeCB (Widget /*w*/, XtPointer cdata, XtPointer /*cbs*/) { ((DecoderWid *)cdata)->getScope().drawcirc(); } /* QPSK selection changed callback */ static void decQpskCB (Widget /*w*/, XtPointer cdata, XtPointer cbs) { XmToggleButtonCallbackStruct *ptr = (XmToggleButtonCallbackStruct *) cbs; commControl(((DecoderWid *)cdata)->commChannel, COMM_QPSK, ptr->set); } /* AFC selection changed callback */ static void decAfcCB (Widget /*w*/, XtPointer cdata, XtPointer cbs) { XmToggleButtonCallbackStruct *ptr = (XmToggleButtonCallbackStruct *) cbs; commControl(((DecoderWid *)cdata)->commChannel, COMM_AFC, ptr->set); } /* Up/Down-Arrow callback */ static void decArrowCB (Widget w, XtPointer cdata, XtPointer cbs) { DecoderWid *dec = (DecoderWid *)cdata; float freq, delta; String str; unsigned char direction; XmArrowButtonCallbackStruct *cbsPtr = (XmArrowButtonCallbackStruct *)cbs; XButtonPressedEvent *event = (XButtonPressedEvent *) cbsPtr->event; XtVaGetValues (w, XmNarrowDirection, &direction, NULL); if (event->state & ShiftMask) /* if shifted click */ delta = 8.0; /* change by 8 */ else delta = 1.0; /* else change by 1 */ if (cbsPtr->click_count == 2) /* if double click, changes by 7 */ delta = 7.0; /* cuz already been changed by 1 */ XtVaGetValues (dec->rxfreqwid, XmNvalue, &str, NULL); /* Get the freq */ freq = atof(str); /* convert to a float */ if (direction == XmARROW_UP) freq = freq + delta; else freq = freq - delta; sprintf (str, "%4.1f", freq); /* float to a string */ XmTextFieldSetString (dec->rxfreqwid, str); /* set new freq in rx class */ commControl(dec->commChannel, COMM_FREQ, (int)(freq*100)); } /* callback to "exchange secondary and main windows" */ static void swapCB (Widget w, XtPointer cdata, XtPointer cbs) { extern Pixel lightBG; int mainval, otherval; DecoderWid *dec = (DecoderWid *)cdata; XmTextPosition lastPos; /* exchange low level psk31_receiver objects */ commControl(COMM_RXCH, COMM_SWAP, dec->commChannel); /* following setXXX functions invoke a commControl request * to set the values on the corresponding psk31_receiver object. * this is unnecessary as those objects have been swap, but it * doesn't do any harm... */ /* exchange Text */ char *mainstr, *otherstr; Widget mainText = pskwids.getRxText(); Widget secText = dec->getTextWid(); otherstr = (char*)XmTextGetString (secText); mainstr = (char*)XmTextGetString(mainText); XmTextDisableRedisplay (mainText); XmTextDisableRedisplay (secText); XmTextSetString (secText, mainstr); XmTextSetString (mainText, otherstr); XtFree(otherstr); XtFree(mainstr); XmTextEnableRedisplay (mainText); XmTextEnableRedisplay (secText); lastPos = XmTextGetLastPosition (secText); XmTextShowPosition (secText, lastPos); XmTextSetInsertionPosition (secText, lastPos); lastPos = XmTextGetLastPosition (mainText); XmTextShowPosition (mainText, lastPos); XmTextSetInsertionPosition (mainText, lastPos); /* clear any scrolling operations */ pskwids.setRxScrollFlag (!SCROLLING); dec->setRxScrollFlag (!SCROLLING); XtVaSetValues (mainText, XmNbackground, lightBG, NULL); XtVaSetValues (secText , XmNbackground, lightBG, NULL); /* exchange QPSK button */ mainval = pskwids.getQPSK(); otherval = dec->getQPSK(); pskwids.setQPSK(otherval); dec->setQPSK(mainval); /* exchange AFC button */ mainval = pskwids.getAFC(); otherval = dec->getAFC(); pskwids.setAFC(otherval); dec->setAFC(mainval); /* exchange frequency */ float mainf, otherf; mainf = pskwids.getFreq(); otherf = dec->getFreq(); pskwids.setFreq(otherf); dec->setFreq(mainf); } Widget DecoderWid::shell; void DecoderWid::updateDisplay(float freq, int DCD, int IMD) { if( hasfocus==0 && fabs(freq-curfreq)>0.05 ) { curfreq = freq; sprintf(str, "%4.1f", freq); XmTextFieldSetString (rxfreqwid, str); } XtVaSetValues(DCDwid, XmNset, DCD?1:0, NULL); } void DecoderWid::move(int x, int y) { XtVaSetValues(dialogShell, XmNx, x, XmNy, y, NULL); } void DecoderWid::buildWidgets(Widget shell, AppRes *appRes, int chan) { Dimension height, width; rxScrollFlag = 0; ch = chan; /* create diag shell without decorations! */ dialogShell = XtVaCreatePopupShell("TWPSK Secondary PSK31 Decoder", xmDialogShellWidgetClass, shell, XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU, XmNmappedWhenManaged, False, NULL); mainForm = XtVaCreateWidget("mainForm", xmFormWidgetClass, dialogShell, XmNverticalSpacing, SPACING, XmNhorizontalSpacing, SPACING, XmNdialogStyle, XmDIALOG_MODELESS, NULL); bottomForm = XtVaCreateWidget ("bottomForm", xmFormWidgetClass, mainForm, XmNtopAttachment, XmATTACH_NONE, XmNtopOffset, 0, XmNleftAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 0, XmNrightAttachment, XmATTACH_FORM, XmNhorizontalSpacing, SPACING, XmNverticalSpacing, SPACING, NULL); dscope.SCOPE_WIDTH = SCOPE_HEIGHT; dscope.BORDER_WIDTH = 2; scopeDA = XtVaCreateManagedWidget ("scopeDA", xmDrawingAreaWidgetClass, bottomForm, XmNheight, dscope.SCOPE_WIDTH, XmNwidth, dscope.SCOPE_WIDTH, XmNtopAttachment, XmATTACH_FORM, XmNtopOffset, 0, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 0, XmNrightAttachment, XmATTACH_NONE, NULL); rxFreqCombo = XtVaCreateWidget("rxFreqCombo", /* for rx combo */ xmFormWidgetClass, bottomForm, XmNtopAttachment, XmATTACH_FORM, XmNtopOffset, 0, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, scopeDA, XmNrightAttachment, XmATTACH_NONE, XmNbottomAttachment, XmATTACH_NONE, NULL); strcpy(str,"1000.0"); rxfreqwid = XtVaCreateManagedWidget ("rx2FreqText", xmTextFieldWidgetClass, rxFreqCombo, XmNhighlightOnEnter, True, XmNmaxLength, 6, XmNcolumns, 6, XmNvalue, str, XmNmarginHeight, 10, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL); /* up arrow for rx freq */ rxUpArrow = XtVaCreateManagedWidget ("rxUpArrow", xmArrowButtonWidgetClass, rxFreqCombo, XmNwidth, ARROW_WIDTH, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_POSITION, XmNbottomPosition, 50, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, rxfreqwid, XmNrightAttachment, XmATTACH_NONE, NULL); /* down arr for rx freq */ rxDownArrow = XtVaCreateManagedWidget ("rxUpArrow", xmArrowButtonWidgetClass, rxFreqCombo, XmNwidth, ARROW_WIDTH, XmNarrowDirection, XmARROW_DOWN, XmNtopAttachment, XmATTACH_POSITION, XmNtopPosition, 50, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, rxfreqwid, XmNrightAttachment, XmATTACH_NONE, NULL); AFCwid = XtVaCreateManagedWidget ("AFC", xmToggleButtonWidgetClass, rxFreqCombo, XmNset, True, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, rxDownArrow, XmNrightAttachment, XmATTACH_NONE, NULL); pbForm = XtVaCreateWidget("pbForm", xmFormWidgetClass, /* for PBs */ bottomForm, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, rxFreqCombo, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, scopeDA, XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET, XmNrightWidget, rxFreqCombo, XmNrightOffset, 0, XmNbottomAttachment, XmATTACH_FORM, NULL); swapBtn = XtVaCreateManagedWidget ("<-> Main", xmPushButtonWidgetClass, pbForm, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 45, NULL); closeBtn = XtVaCreateManagedWidget("Close", xmPushButtonWidgetClass, pbForm, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 55, XmNrightAttachment, XmATTACH_FORM, NULL); /* rx scrolled Window */ rxTextSW = XtVaCreateWidget ("rxTextSW", xmScrolledWindowWidgetClass, mainForm, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, bottomForm, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL); /* rx text widget */ rxText = XtVaCreateManagedWidget ("rxText", xmTextWidgetClass, rxTextSW, XmNrows, 4, XmNeditMode, XmMULTI_LINE_EDIT, XmNeditable, False, XmNwordWrap, True, XmNcursorPositionVisible, False, XmNautoShowCursorPosition, False, XmNscrollHorizontal, False, XmNshadowThickness, 2, XmNuserData, (XtPointer)this, NULL); /* get the scrollbar widget id */ XtVaGetValues (rxTextSW, XmNverticalScrollBar, &rxScrollBar, NULL); XtVaSetValues (rxScrollBar, XmNuserData, this, NULL); modeForm = XtVaCreateManagedWidget ("modeForm", xmFormWidgetClass, bottomForm, XmNverticalSpacing, SPACING, XmNtopAttachment, XmATTACH_FORM, XmNtopOffset, 0, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, rxFreqCombo, XmNbottomAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 0, NULL); DCDwid = XtVaCreateManagedWidget ("DCD", xmToggleButtonWidgetClass, modeForm, XmNtopAttachment, XmATTACH_FORM, XmNtopOffset, 0, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNshadowThickness, 2, NULL); QPSKwid = XtVaCreateManagedWidget ("QPSK", xmToggleButtonWidgetClass, modeForm, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, DCDwid, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNshadowThickness, 2, NULL); /* * Create the popup menu to clear second rx text widgets */ xs[0] = XmStringCreateLocalized ("Rx Text"); xs[1] = XmStringCreateLocalized ("Clear"); clrRxPopup = XmVaCreateSimplePopupMenu(rxText, "clrRx", clrTextCB, XmVaTITLE, xs[0], XmVaSEPARATOR, XmVaPUSHBUTTON, xs[1], ' ', NULL, NULL, NULL); XtVaSetValues (clrRxPopup, /* userdata is text window to clear */ XmNuserData, rxText, NULL); XmStringFree (xs[0]); XmStringFree (xs[1]); /* Add Callbacks */ /* * AFC and QPSK TB Callbacks */ XtAddCallback(AFCwid, XmNvalueChangedCallback, decAfcCB, (XtPointer)this); XtAddCallback(QPSKwid, XmNvalueChangedCallback, decQpskCB, (XtPointer)this); /* * Up/Down Arrows for Rx Freq */ XtAddCallback(rxDownArrow, XmNactivateCallback, decArrowCB, (XtPointer)this); XtAddCallback(rxUpArrow, XmNactivateCallback, decArrowCB, (XtPointer)this); /* * Swap and Close Callbacks */ XtAddCallback(swapBtn, XmNactivateCallback,swapCB,(XtPointer)this); XtAddCallback(closeBtn, XmNactivateCallback, closeProc, (XtPointer)this); /* * rxFreq Callbacks */ XtAddCallback(rxfreqwid, XmNfocusCallback, rxFreqFocusCB, (XtPointer)this); XtAddCallback(rxfreqwid, XmNlosingFocusCallback, rxFreqFocusCB, (XtPointer)this); XtAddCallback(rxfreqwid, XmNmodifyVerifyCallback, freqTextCB, (XtPointer)this); XtAddCallback(rxfreqwid, XmNactivateCallback, freqTextCB, (XtPointer)this); /* * Rx ScrollBar Callbacks */ XtAddCallback (rxScrollBar, XmNdragCallback, rxScrollBarCB, (XtPointer) this); XtAddCallback (rxScrollBar, XmNincrementCallback, rxScrollBarCB, (XtPointer) this); XtAddCallback (rxScrollBar, XmNdecrementCallback, rxScrollBarCB, (XtPointer) this); XtAddCallback (rxScrollBar, XmNpageIncrementCallback, rxScrollBarCB, (XtPointer) this); XtAddCallback (rxScrollBar, XmNpageDecrementCallback, rxScrollBarCB, (XtPointer) this); XtAddCallback (rxScrollBar, XmNtoTopCallback, rxScrollBarCB, (XtPointer) this); XtAddCallback (rxScrollBar, XmNtoBottomCallback, rxScrollBarCB, (XtPointer) this); /* * Scope Expose Callback */ XtAddCallback(scopeDA, XmNexposeCallback, decScopeCB, (XtPointer)this); /* * Event handler for clearing rx windows */ XtAddEventHandler (rxText, ButtonPressMask, False, popupHandler, (XtPointer) clrRxPopup); XtManageChild (pbForm); XtManageChild (modeForm); XtManageChild (rxFreqCombo); XtManageChild (bottomForm); XtManageChild (rxTextSW); XtManageChild (mainForm); /* TJW new way to move decoder */ /* Get desired X-Y location for the channel and then */ XtVaSetValues (dialogShell, XmNx, winlocs[ch][0] - twpskCB.getBorderX(), XmNy, winlocs[ch][1] - twpskCB.getBorderY(), NULL); /* get height and width and make it the minimums */ XtVaGetValues (dialogShell, XmNheight, &height, XmNwidth, &width, NULL); XtVaSetValues (dialogShell, XmNminHeight, height, XmNminWidth, width, NULL); dscope.SCOPE_WIDTH = SCOPE_HEIGHT; dscope.BORDER_WIDTH = 2; dscope.setup(shell, scopeDA); dscope.drawcirc(); dscope.drawline(90, 4, 1); }