/*- * Copyright (c) 1999 Thomas Runge (coto@core.de) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include #include "radio.h" #include "config.h" #if (XmVERSION < 2) enum { XmUNSET, XmSET, XmINDETERMINATE }; #endif #define FRAME_WIDGET "frame" #define STATION_WIDGET "station" #define FREQ_WIDGET "freq" #define DEF_WIDGET "def" static int is_popped; static int is_scanning; static int intern_cnt; static Widget startW; Widget config_dialogW, scrollW, vrowW, targetW, lastTargetFrameW; Widget saveB, applyB, scanB, newEntryB, delEntryB, delAllEntriesB; Pixel fg_color, bg_color, bs_color, ts_color; extern XmString def_label_string; extern char *startStation; extern int startStationPos; static void MakeStationRow(int n, char *name, int freq, int def, int scroll); static void MakeNewEntry(int freq); static void UpdateValues(); static void EnableWidgets(Boolean b) { XtSetSensitive(delEntryB, b); XtSetSensitive(newEntryB, b); XtSetSensitive(delAllEntriesB, b); XtSetSensitive(saveB, b); XtSetSensitive(applyB, b); XtSetSensitive(scanB, b); } static void closeCB(Widget widget, XtPointer clientData, XtPointer callData) { ConfigDialogToggle(); } static void applyCB(Widget widget, XtPointer clientData, XtPointer callData) { UpdateValues(); ConfigDialogToggle(); } static void saveCB(Widget widget, XtPointer clientData, XtPointer callData) { UpdateValues(); SaveRCFile(); ConfigDialogToggle(); } static void scanCB(Widget widget, XtPointer clientData, XtPointer callData) { int oldmute, ofreq, nfreq; EnableWidgets(False); XDefineCursor(dpy, XtWindow(config_dialogW), workingCursor); XmUpdateDisplay(config_dialogW); ofreq = nfreq = frequency; oldmute = SetMute(True); is_scanning = True; SetFrequency(MINFREQ); while(True) { nfreq = frequency; SeekChannel(UP); if(nfreq == frequency) break; /* no station at all */ if(frequency < nfreq) break; /* scan done */ if(is_scanning == False) break; /* stop scan */ MakeNewEntry(frequency); nfreq = frequency; } is_scanning = False; SetFrequency(ofreq); SetMute(oldmute); XSync(dpy, True); XUndefineCursor(dpy, XtWindow(config_dialogW)); EnableWidgets(True); } static void delEntryCB(Widget widget, XtPointer clientData, XtPointer callData) { int n; char wname[32]; Widget tmp; XmPushButtonCallbackStruct *pbcbstr; pbcbstr = (XmPushButtonCallbackStruct*) callData; if(pbcbstr->event->xbutton.state&ShiftMask) { for(n = 0; n < intern_cnt; n++) { sprintf(wname, "*%s%d", FRAME_WIDGET, n); tmp = XtNameToWidget(config_dialogW, wname); if(tmp) XtDestroyWidget(tmp); } startW = NULL; } else if(lastTargetFrameW) XtDestroyWidget(lastTargetFrameW); lastTargetFrameW = NULL; } static void delAllEntriesCB(Widget widget, XtPointer clientData, XtPointer callData) { XmPushButtonCallbackStruct *pbcbstr; pbcbstr = (XmPushButtonCallbackStruct*) callData; pbcbstr->event->xbutton.state |= ShiftMask; delEntryCB(widget, clientData, callData); } static void focusInCB(Widget widget, XtPointer clientData, XtPointer callData) { Widget newTargetFrameW; targetW = widget; XtVaGetValues(widget, XmNuserData, &newTargetFrameW, NULL); if(lastTargetFrameW) XtVaSetValues(lastTargetFrameW, XmNbottomShadowColor, bg_color, XmNtopShadowColor, bg_color, XmNforeground, bg_color, NULL); if(newTargetFrameW) XtVaSetValues(newTargetFrameW, XmNbottomShadowColor, bs_color, XmNtopShadowColor, ts_color, XmNforeground, fg_color, NULL); lastTargetFrameW = newTargetFrameW; } static void startToggleCB(Widget widget, XtPointer clientData, XtPointer callData) { if(startW) XtVaSetValues(startW, XmNset, XmUNSET, NULL); startW = widget; } static void newEntryCB(Widget widget, XtPointer clientData, XtPointer callData) { MakeNewEntry(frequency); } static void MakeNewEntry(int freq) { MakeStationRow(intern_cnt, "*unknown*", freq, 0, True); intern_cnt++; } static void UpdateValues() { int n, cnt, freq; unsigned char set; char wname[32]; Widget tmp; String str; cnt = 0; for(n = 0; n < intern_cnt; n++) { sprintf(wname, "*%s%d", FRAME_WIDGET, n); tmp = XtNameToWidget(config_dialogW, wname); if(!tmp) continue; cnt++; } for(n = 0; n < station.cnt; n++) free(station.name[n]); free(station.name); free(station.freq); free(station.def); free(station_buttons.pos); station.name = (char**)calloc(cnt, sizeof(char*)); station.freq = (int*)calloc(cnt, sizeof(int)); station.def = (int*)calloc(cnt, sizeof(int)); station.cnt = 0; station_buttons.pos = (int*)calloc(n, sizeof(int)); station_buttons.cnt = 0; for(n = 0; n < intern_cnt; n++) { sprintf(wname, "*%s%d", FRAME_WIDGET, n); tmp = XtNameToWidget(config_dialogW, wname); if(!tmp) continue; sprintf(wname, "*%s%d", STATION_WIDGET, n); tmp = XtNameToWidget(config_dialogW, wname); if(tmp) { XtVaGetValues(tmp, XmNvalue, &str, NULL); if(str && strlen(str)) station.name[station.cnt] = strdup(str); else station.name[station.cnt] = strdup("*unknown*"); if(debug) printf("station %d: %s ", n, str); } else station.name[station.cnt] = strdup("*unknown*"); sprintf(wname, "*%s%d", FREQ_WIDGET, n); tmp = XtNameToWidget(config_dialogW, wname); if(tmp) { XtVaGetValues(tmp, XmNvalue, &str, NULL); freq = (int)(100. * atof(str) + 0.5); if(freq < MINFREQ || freq > MAXFREQ) freq = MINFREQ; station.freq[station.cnt] = freq; if(debug) printf("(%u.%02u) ", freq / 100, freq % 100); } else station.freq[station.cnt] = MINFREQ; sprintf(wname, "*%s%d", DEF_WIDGET, n); tmp = XtNameToWidget(config_dialogW, wname); if(tmp) { int def = XmUNSET; XtVaGetValues(tmp, XmNset, &set, NULL); def = (set == XmSET ? TRUE : FALSE); station.def[station.cnt] = def; if(def) station_buttons.pos[station_buttons.cnt++] = station.cnt+1; if(debug) printf(" %s ", def ? "defbtn\n" : "\n"); } else station.def[station.cnt] = FALSE; station.cnt++; } if(startW) { XtVaGetValues(startW, XmNuserData, &startStationPos, NULL); startStation = station.name[startStationPos]; } SortStationList(); GeneratePopupMenu(TRUE); MakeStationButtonWidgets(TRUE); UpdateTitle(); } static void UpdateStations() { int i; if(vrowW) XtDestroyWidget(vrowW); vrowW = XtVaCreateManagedWidget("scroll_win", xmRowColumnWidgetClass, scrollW, XmNorientation, XmVERTICAL, NULL); for(i = 0; i < station.cnt; i++) MakeStationRow(i, station.name[i], station.freq[i], station.def[i], False); intern_cnt = station.cnt; } static void MakeStationRow(int n, char *name, int freq, int def, int scroll) { Widget frameW, rowW, conf_stationW, conf_freqW, conf_defW, conf_startW; char wname[32]; char buf[16]; sprintf(wname, "%s%d", FRAME_WIDGET, n); frameW = XtVaCreateManagedWidget(wname, xmFrameWidgetClass, vrowW, NULL); XtVaSetValues(frameW, XmNbottomShadowColor, bg_color, XmNtopShadowColor, bg_color, XmNforeground, bg_color, NULL); rowW = XtVaCreateManagedWidget("entry_row", xmRowColumnWidgetClass, frameW, XmNorientation, XmHORIZONTAL, NULL); sprintf(wname, "%s%d", STATION_WIDGET, n); conf_stationW = XtVaCreateManagedWidget(wname, xmTextFieldWidgetClass, rowW, XmNvalue, name, XmNuserData, (XtPointer) frameW, NULL); XtAddCallback(conf_stationW, XmNfocusCallback, focusInCB, (XtPointer)NULL); sprintf(wname, "%s%d", FREQ_WIDGET, n); sprintf(buf, "%u.%02u ", freq / 100, freq % 100); conf_freqW = XtVaCreateManagedWidget(wname, xmTextFieldWidgetClass, rowW, XmNvalue, buf, XmNuserData, (XtPointer) frameW, NULL); XtAddCallback(conf_freqW, XmNfocusCallback, focusInCB, (XtPointer)NULL); sprintf(wname, "%s%d", DEF_WIDGET, n); conf_defW = XtVaCreateManagedWidget(wname, xmToggleButtonWidgetClass, rowW, XmNset, def ? XmSET : XmUNSET, XmNlabelString, def_label_string, XmNuserData, (XtPointer) frameW, NULL); XtAddCallback(conf_defW, XmNarmCallback, focusInCB, (XtPointer)NULL); conf_startW = XtVaCreateManagedWidget("start", xmToggleButtonWidgetClass, rowW, XmNindicatorType, XmONE_OF_MANY, XmNuserData, (XtPointer) n, NULL); XtAddCallback(conf_startW, XmNarmCallback, startToggleCB, (XtPointer)NULL); if(startStationPos == n) { XtCallCallbacks(conf_startW, XmNarmCallback, (XtPointer)NULL); XtVaSetValues(conf_startW, XmNset, XmSET, NULL); } #ifdef HAS_XPM if(skin) SkinToWidgets(frameW, skin); #endif if(scroll) { XmScrollVisible(scrollW, frameW, 0, 0); XmProcessTraversal(conf_stationW, XmTRAVERSE_CURRENT); } } static void MakeInterface(Widget topl) { Widget mainW, cancelB, confSepW, label_formW, label_frameW; Widget statLabelW, freqLabelW, defLabelW; Position x, y; extern void _XEditResCheckMessages(Widget, XtPointer, XEvent*, Boolean*); intern_cnt = 0; lastTargetFrameW = NULL; vrowW = NULL; XtVaGetValues(topl, XmNx, &x, XmNy, &y, NULL); config_dialogW = XtVaCreatePopupShell("config_dialog", transientShellWidgetClass, topl, XmNx, x, XmNy, y, XmNdeleteResponse, XmDO_NOTHING, XtNiconPixmap, icon_pm, XtNiconMask, icon_pm_mask, NULL); XtAddEventHandler(config_dialogW, (EventMask)0, True, _XEditResCheckMessages, NULL); mainW = XtVaCreateManagedWidget("config_main", xmFormWidgetClass, config_dialogW, NULL); saveB = XtVaCreateManagedWidget("save_button", xmPushButtonWidgetClass, mainW, XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 2, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 33, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 2, NULL); XtAddCallback(saveB, XmNactivateCallback, saveCB, (XtPointer)NULL); applyB = XtVaCreateManagedWidget("apply_button", xmPushButtonWidgetClass, mainW, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 33, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 66, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 2, NULL); XtAddCallback(applyB, XmNactivateCallback, applyCB, (XtPointer)NULL); cancelB = XtVaCreateManagedWidget("cancel_button", xmPushButtonWidgetClass, mainW, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 66, XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 2, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 2, NULL); XtAddCallback(cancelB, XmNactivateCallback, closeCB, (XtPointer)NULL); confSepW = XtVaCreateManagedWidget("conf_separator", xmSeparatorWidgetClass, mainW, XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 3, XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 3, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, cancelB, NULL); delAllEntriesB = XtVaCreateManagedWidget("delAllEntries_button", xmPushButtonWidgetClass, mainW, XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 2, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 50, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, confSepW, XmNbottomOffset, 2, NULL); XtAddCallback(delAllEntriesB, XmNactivateCallback, delAllEntriesCB, (XtPointer)NULL); scanB = XtVaCreateManagedWidget("scan_button", xmPushButtonWidgetClass, mainW, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 50, XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 2, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, confSepW, XmNbottomOffset, 2, NULL); XtAddCallback(scanB, XmNactivateCallback, scanCB, (XtPointer)NULL); delEntryB = XtVaCreateManagedWidget("delEntry_button", xmPushButtonWidgetClass, mainW, XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 2, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 50, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, delAllEntriesB, XmNbottomOffset, 2, NULL); XtAddCallback(delEntryB, XmNactivateCallback, delEntryCB, (XtPointer)NULL); newEntryB = XtVaCreateManagedWidget("newEntry_button", xmPushButtonWidgetClass, mainW, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 50, XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 2, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, delAllEntriesB, XmNbottomOffset, 2, NULL); XtAddCallback(newEntryB, XmNactivateCallback, newEntryCB, (XtPointer)NULL); label_frameW = XtVaCreateManagedWidget("label_frame", xmFrameWidgetClass, mainW, XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 2, XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 2, XmNtopAttachment, XmATTACH_FORM, XmNtopOffset, 2, NULL); label_formW = XtVaCreateManagedWidget("label_form", xmFormWidgetClass, label_frameW, NULL); statLabelW = XtVaCreateManagedWidget("statLabel", xmLabelWidgetClass, label_formW, XmNalignment, XmALIGNMENT_CENTER, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 33, NULL); freqLabelW = XtVaCreateManagedWidget("freqLabel", xmLabelWidgetClass, label_formW, XmNalignment, XmALIGNMENT_CENTER, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 33, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 66, NULL); defLabelW = XtVaCreateManagedWidget("defLabel", xmLabelWidgetClass, label_formW, XmNalignment, XmALIGNMENT_CENTER, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 66, XmNrightAttachment, XmATTACH_FORM, NULL); scrollW = XtVaCreateManagedWidget("scroll_w", xmScrolledWindowWidgetClass, mainW, XmNscrollingPolicy, XmAUTOMATIC, XmNvisualPolicy, XmCONSTANT, XmNleftAttachment, XmATTACH_FORM, XmNleftOffset, 2, XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, 2, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, label_frameW, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, newEntryB, XmNbottomOffset, 2, NULL); XtVaGetValues(scrollW, XmNforeground, &fg_color, XmNbackground, &bg_color, XmNbottomShadowColor, &bs_color, XmNtopShadowColor, &ts_color, NULL); } void ConfigDialogToggle() { if(!config_dialogW) { Atom wmDeleteAtom; is_popped = False; MakeInterface(toplevel); AddTooltipsToWidgets(); #ifdef HAS_XPM if(skin) SkinToWidgets(config_dialogW, skin); #endif wmDeleteAtom = XmInternAtom(dpy, "WM_DELETE_WINDOW", False); XmAddWMProtocolCallback(config_dialogW, wmDeleteAtom, closeCB, (XtPointer)NULL); } if(is_popped) { is_popped = False; is_scanning = False; XtPopdown(config_dialogW); } else { is_popped = True; UpdateStations(); lastTargetFrameW = NULL; #ifdef HAS_XPM if(skin) SkinToWidgets(config_dialogW, skin); #endif XtPopup(config_dialogW, XtGrabNone); } } void conf_scroll_up(Widget w, XEvent *event, String *params, Cardinal *paramscnt) { if(!is_popped) return; XtCallActionProc(scrollW, "SWUpPage", NULL, NULL, 0); } void conf_scroll_down(Widget w, XEvent *event, String *params, Cardinal *paramscnt) { if(!is_popped) return; XtCallActionProc(scrollW, "SWDownPage", NULL, NULL, 0); }