/*! * Display zum Setzen und Anfahren der Stackpunkte */ void drive_stack_display(void) { display_cursor(1, 1); display_printf("Stack %5d %5d", pos.x, pos.y); display_cursor(2, 1); display_puts("Save/Del : 3/8"); display_cursor(3, 1); display_puts("GoBack/Forward: 4/7"); display_cursor(4, 1); display_puts("Start WayPushPos: 5"); drivestack_disp_key_handler(); // Aufruf des Key-Handlers }
/** * Zeigt Informationen ueber Resets an */ void reset_info_display(void) { display_cursor(1, 1); display_printf("#Resets:%3u | (C)SR:", ctbot_eeprom_read_byte(&resetsEEPROM)); display_cursor(2, 1); display_printf("PORF :%d WDRF :%d", binary(mcucsr, 0), binary(mcucsr, 3)); display_cursor(3, 1); display_printf("EXTRF:%d JTRF :%d", binary(mcucsr, 1), binary(mcucsr, 4)); display_cursor(4, 1); display_printf("BORF :%d #SResets:%3u", binary(mcucsr, 2), soft_resets); }
/** * Display fuer das uBasic-Verhalten */ void ubasic_display(void) { display_cursor(1, 1); display_puts("- uBasic -"); #ifdef RC5_CODE_PLAY display_cursor(2, 1); display_puts("PLAY:Run Prog"); #endif display_cursor(3, 1); display_puts("1-9:bas1..9.txt"); #ifdef RC5_CODE_STOP display_cursor(4, 1); display_puts("STOPP:Prog abbrechen"); #endif ubasic_disp_key_handler(); // Aufruf des Key-Handlers }
/** * Faehrt den Bot sauber herunter */ void ctbot_shutdown(void) { LOG_INFO("Shutting c't-Bot down..."); motor_set(BOT_SPEED_STOP, BOT_SPEED_STOP); #ifdef MAP_AVAILABLE map_flush_cache(); #endif #ifdef LOG_MMC_AVAILABLE log_flush(); #endif #ifdef BOT_FS_AVAILABLE botfs_close_volume(); #endif #ifdef DISPLAY_AVAILABLE display_clear(); display_cursor(1, 1); display_puts("SYSTEM HALTED."); #endif // DISPLAY_AVAILABLE ENA_off(0xff); ctbot_shutdown_low(); }
/** * Zeigt die aktuelle Speicherbelegung an. * Achtung, die Stackgroesse bezieht sich auf den Stack *dieser* Funktion! * Die Heapgroesse stimmt nur, wenn es dort keine Luecken gibt (z.b. durch free()) */ void ram_display(void) { unsigned char * sp = (unsigned char *) SP; extern unsigned char __data_start; extern unsigned char __bss_start; extern unsigned char __heap_start; extern unsigned char * __brkval; #ifdef RC5_AVAILABLE #ifdef LOG_AVAILABLE extern unsigned char __data_end; extern unsigned char __bss_end; if (RC5_Code == RC5_CODE_1) { LOG_DEBUG("__data_start = 0x%04x", &__data_start); LOG_DEBUG("__data_end = 0x%04x", &__data_end); LOG_DEBUG("__bss_start = 0x%04x", &__bss_start); LOG_DEBUG("__bss_end = 0x%04x", &__bss_end); LOG_DEBUG("__heap_start = 0x%04x", &__heap_start); LOG_DEBUG("__heap_end = 0x%04x", __brkval); LOG_DEBUG("SP = 0x%04x", sp); LOG_DEBUG("RAMEND = 0x%04x", RAMEND); RC5_Code = 0; } #endif // RC5_AVAILABLE #endif // LOG_AVAILABLE size_t data_size = (size_t) (&__bss_start - &__data_start); size_t bss_size = (size_t) (&__heap_start - &__bss_start); display_cursor(1, 1); display_puts("bss/data:"); display_cursor(1, 10); display_printf("%5u/%5u", bss_size, data_size); display_cursor(2, 1); display_puts("heap:"); display_cursor(2, 16); size_t heap_size = __brkval == NULL ? 0 : (size_t) (__brkval - &__heap_start); display_printf("%5u", heap_size); display_cursor(3, 1); size_t ram_size = (size_t) ((unsigned char *) (RAMEND + 1) - &__data_start); size_t stack_size = (size_t) ((unsigned char *) RAMEND - sp); display_puts("stack:"); #ifdef OS_DEBUG size_t stack_size_max = ram_size - (os_stack_unused(__brkval + __malloc_margin) + data_size + bss_size + heap_size); display_cursor(3, 10); display_printf("%5u/%5u", stack_size, stack_size_max); #else display_cursor(3, 16); display_printf("%5u", stack_size); #endif // OS_DEBUG display_cursor(4, 1); size_t frei = ram_size - (data_size + bss_size + heap_size + stack_size); display_puts("free/ram:"); display_cursor(4, 10); display_printf("%5u/%5u", frei, ram_size); }
Wndo *wait_wndo_input(ULONG ioflags) /* this is like wait input but loads cursors and io state as it passes * windows returns pointer to window under cursor NULL if over screen * leaves iostate set to whatever the last hit window was */ { Wndo *iowndo = NULL; display_cursor(); anim_wait_input(ioflags,ANY_INPUT,-1,anim_check_wndos,&iowndo); undisplay_cursor(); return(iowndo); }
/* Show the widget */ void GUI_TextInput:: Display(bool full_redraw) { SDL_Rect r; if(full_redraw && focused) { r = area; SDL_FillRect(surface, &r, selected_bgcolor); } GUI_Text::Display(full_redraw); if(focused) display_cursor(); }
t_bunny_response main_game_loop(t_data *data) { display_interface(data); if (data->chat_toggle) { display_cursor(data); ++data->cursor_toggle; } if (++data->count >= MAX_COUNT) data->count = 0; if (data->player->knife.is_selected || !(data->count % 4)) data->event.bits.shot = play_sound(data); if (!((data->count + 2) % 4) && data->player->rifle.is_selected && data->event.bits.shoting) data->event.bits.shot = ((data->count + 2) % 4) || can_shot(data); return (GO_ON); }
/** * Zeigt ein paar Infos an, die man nicht naeher zuordnen kann */ void misc_display(void) { /* Anzeige der Bot-Adresse (aenderbar) */ display_cursor(1, 1); display_puts("bot_addr="); #ifdef KEYPAD_AVAILABLE if (RC5_Code == RC5_CODE_MUTE) { gui_keypad_request(change_bot_addr_callback, 1, 1, 10); #ifdef PC display_cursor(1, 10); #endif display_puts(" "); // clean new_address = 1; RC5_Code = 0; } if (new_address == 0) #endif // KEYPAD_AVAILABLE { #ifdef PC display_cursor(1, 10); #endif display_printf("0x%x", get_bot_address()); } #ifdef BEHAVIOUR_AVAILABLE display_cursor(2, 1); display_printf("TS=%+4d %+4d", target_speed_l, target_speed_r); #endif #ifdef SRF10_AVAILABLE display_cursor(2, 15); display_printf("US%4u", sensSRF10); #endif display_cursor(3, 1); display_printf("RC=%+4d %+4d", sensEncL, sensEncR); display_cursor(4, 1); display_printf("Speed=%+4d", v_center); display_cursor(4, 12); display_printf("%4u:%03u", timer_get_s(), timer_get_ms()); }
Wndo *wait_menu_input(ULONG ioflags) /* this is like wait wndo input but only looks at current group if it is * a requestor group */ { Mugroup *mg; FUNC afunc; Wndo *iowndo = NULL; display_cursor(); mg = (Mugroup *)see_head(&(icb.input_screen->gstack)); if(mg != NULL && mg->flags & MUG_REQUESTOR) afunc = anim_check_menus; else afunc = anim_check_wndos; anim_wait_input(ioflags,ANY_INPUT,-1,afunc,&iowndo); undisplay_cursor(); return(iowndo); }
void displayThread(void *args) { BK_U8B *command; BK_S8B *data; BK_U8B len; while(1) { if(msgQueueMsgReadNoWait(commandMQ,&command,&len)) { if(len == 1) { display_cmd(*command); } BK_free(command); } if(msgQueueMsgReadNoWait(dataMQ,&data,&len)) { if(len > 2) { if(*data != -1) { display_cursor(data[0],data[1]); data ++; len -=2; } data++; while(len > 0) { display_data(*data); len--; data++; } } } done(); } }
/*! * Hauptprogramm des Bots. Diese Schleife kuemmert sich um seine Steuerung. */ int main (void){ #endif #ifdef PC /*! * Hauptprogramm des Bots. Diese Schleife kuemmert sich um seine Steuerung. */ int main (int argc, char *argv[]){ int ch; int start_server = 0; /*!< Wird auf 1 gesetzt, falls -s angegeben wurde */ char *hostname = NULL; /*!< Speichert den per -t uebergebenen Hostnamen zwischen */ // Die Kommandozeilenargumente komplett verarbeiten while ((ch = getopt(argc, argv, "hst:")) != -1) { switch (ch) { case 's': // Servermodus [-s] wird verlangt start_server = 1; break; case 't': // Hostname, auf dem ct-Sim laeuft wurde // uebergeben. Der String wird in hostname // gesichert. { const int len = strlen(optarg); hostname = malloc(len + 1); if (NULL == hostname) exit(1); strcpy(hostname, optarg); } break; case 'h': default: // -h oder falscher Parameter, Usage anzeigen usage(); } } argc -= optind; argv += optind; if (start_server != 0) // Soll der TCP-Server gestartet werden? { printf("ARGV[0]= %s\n",argv[1]); tcp_server_init(); tcp_server_run(); } else { printf("c't-Bot\n"); if (hostname) // Hostname wurde per Kommandozeile uebergeben tcp_hostname = hostname; else { // Der Zielhost wird per default durch das Macro IP definiert und // tcp_hostname mit einer Kopie des Strings initialisiert. tcp_hostname = malloc(strlen(IP) + 1); if (NULL == tcp_hostname) exit(1); strcpy(tcp_hostname, IP); } } #endif #ifdef TEST_AVAILABLE_MOTOR uint16 calls=0; /*!< Im Testfall zaehle die Durchlaeufe */ #endif #ifdef LOG_AVAILABLE printf("Logging is on ("); #ifdef LOG_UART_AVAILABLE printf("UART"); #endif #ifdef LOG_CTSIM_AVAILABLE printf("CTSIM"); #endif #ifdef LOG_DISPLAY_AVAILABLE printf("DISPLAY"); #endif #ifdef LOG_STDOUT_AVAILABLE printf("STDOUT"); #endif printf(")\n"); #else printf("Logging is off!\n "); #endif init(); #ifdef WELCOME_AVAILABLE display_cursor(1,1); display_printf("c't-Roboter"); LED_set(0x00); #ifdef LOG_AVAILABLE LOG_DEBUG(("Hallo Welt!")); #endif #endif #ifdef TEST_AVAILABLE_COUNTER display_screen=2; resets=eeprom_read_byte(&resetsEEPROM)+1; eeprom_write_byte(&resetsEEPROM,resets); /* Lege den Grund für jeden Reset im EEPROM ab */ eeprom_write_byte(&resetInfoEEPROM+resets,reset_flag); #endif /*! Hauptschleife des Bot */ for(;;){ #ifdef MCU bot_sens_isr(); #endif #ifdef TEST_AVAILABLE show_sensors(); #endif // Testprogramm, dass den Bot erst links, dann rechtsrum dreht #ifdef TEST_AVAILABLE_MOTOR calls++; if (calls == 1) motor_set(BOT_SPEED_SLOW,-BOT_SPEED_SLOW); else if (calls == 501) motor_set(-BOT_SPEED_SLOW,BOT_SPEED_SLOW); else if (calls== 1001) motor_set(BOT_SPEED_STOP,BOT_SPEED_STOP); else #endif // hier drin steckt der Verhaltenscode #ifdef BEHAVIOUR_AVAILABLE if (sensors_initialized ==1 ) bot_behave(); else printf("sensors not initialized\n"); #endif #ifdef MCU #ifdef BOT_2_PC_AVAILABLE // static int16 lastTimeCom =0; bot_2_pc_inform(); // Den PC ueber Sensorern und aktuatoren informieren bot_2_pc_listen(); // Kommandos vom PC empfangen // if (timer_get_s() != lastTimeCom) { // sollte genau 1x pro Sekunde zutreffen // lastTimeCom = timer_get_s(); // } #endif #endif #ifdef LOG_AVAILABLE //LOG_DEBUG(("LOG TIME %d s", timer_get_s())); #endif // Alles Anzeigen #ifdef DISPLAY_AVAILABLE display(); #endif #ifdef PC wait_for_time(100000); #endif #ifdef MCU // delay(10); #endif } /*! Falls wir das je erreichen sollten ;-) */ return 1; }
void ast2xml(struct ast* ast){ delay(2000); if(ast == NULL){ display_clear(); display_cursor(1,1); display_printf("NULL"); return; } switch(ast->type){ case UNARY: break; case BINARY: break; case IDENT: break; case LITERAL: switch(ast->_literal.type){ case DOUBLE: break; case INT: display_clear(); display_cursor(1,1); display_printf("int %d",ast->_literal._int); break; default: break; } break; case ASSIGN: break; case CALL: display_clear(); display_cursor(1,1); display_printf("call %s",ast->_call.name); ast2xml(ast->_call.params); break; case IF: break; case WHILE: break; case LIST: display_clear(); display_cursor(1,1); display_printf("list begin"); struct ast* list = ast; while(list != NULL){ ast2xml(list->_list.item); list = list->_list.next; } display_clear(); display_cursor(1,1); display_printf("list end"); break; case VARDEC: break; case FUNCDEC: //char* parent_name = ast->_funcdec.parent==NULL?"":ast->_funcdec.parent->_funcdec.name; //fprintf(file,"<Funcdec name=\"%s\" parent=\"%s\" declared_type=\"%s\">\n",ast->_funcdec.name,parent_name , type_name(ast->_funcdec.declared_type)); display_clear(); display_cursor(1,1); display_printf("fdec begin %s", ast->_funcdec.name); ast2xml(ast->_funcdec.params); display_clear(); display_cursor(1,1); display_printf("vars begin"); ast2xml(ast->_funcdec.variables); display_clear(); display_cursor(1,1); display_printf("vars end"); delay(2000); display_clear(); display_cursor(1,1); display_printf("func begin"); ast2xml(ast->_funcdec.functions); display_clear(); display_cursor(1,1); display_printf("func end"); delay(2000); display_clear(); display_cursor(1,1); display_printf("body begin"); if(!ast->_funcdec.is_native){ ast2xml(ast->_funcdec.body); }else{ delay(2000); display_clear(); display_cursor(1,1); display_printf("native"); } delay(2000); display_clear(); display_cursor(1,1); display_printf("body end"); delay(2000); display_clear(); display_cursor(1,1); display_printf("fdec end"); break; case PARAM: display_clear(); display_cursor(1,1); display_printf("param %s", ast->_param.name); break; default: break; } delay(2000); }
/*! * Zeigt ein paar Informationen an */ void display(void){ #ifdef DISPLAY_BEHAVIOUR_AVAILABLE /*! * Definitionen fuer die Verhaltensanzeige */ #undef TEST_AVAILABLE_COUNTER Behaviour_t *ptr = behaviour; int8 colcounter = 0; int8 linecounter = 0; int8 firstcol = 0; #endif #ifdef TEST_AVAILABLE_COUNTER static int counter=0; #endif if (display_update >0) #ifdef DISPLAY_SCREENS_AVAILABLE switch (display_screen) { case 0: #endif display_cursor(1,1); display_printf("P=%03X %03X D=%03d %03d ",sensLDRL,sensLDRR,sensDistL,sensDistR); display_cursor(2,1); display_printf("B=%03X %03X L=%03X %03X ",sensBorderL,sensBorderR,sensLineL,sensLineR); display_cursor(3,1); display_printf("R=%2d %2d F=%d K=%d T=%d ",sensEncL % 10,sensEncR %10,sensError,sensDoor,sensTrans); display_cursor(4,1); display_printf("I=%04X M=%05d %05d",RC5_Code,sensMouseX,sensMouseY); #ifdef DISPLAY_SCREENS_AVAILABLE break; case 1: #ifdef TIME_AVAILABLE display_cursor(1,1); display_printf("Zeit: %04d:%03d", timer_get_s(), timer_get_ms()); #endif display_cursor(2,1); display_printf("TS=%+4d %+4d",target_speed_l,target_speed_r); #ifdef SRF10_AVAILABLE display_cursor(2,15); display_printf("US%+4d",sensSRF10); #endif display_cursor(3,1); display_printf("RC=%+4d %+4d",sensEncL,sensEncR); display_cursor(4,1); display_printf("Speed= %04d %04d",v_left,v_right); break; case 2: display_cursor(1,1); #ifdef DISPLAY_BEHAVIOUR_AVAILABLE /*! * zeilenweise Anzeige der Verhalten */ display_printf("Verhalten (Pri/Akt)%d",behaviour_page); colcounter = 0; linecounter = 2; /* je nach Seitenwahl die ersten Saetze ueberlesen bis richtige Seite */ firstcol = (behaviour_page -1)*6; /*! * max. 3 Zeilen mit 6 Verhalten anzeigbar wegen Ueberschrift * Seitensteuerung bei mehr Verhalten */ while((ptr != NULL)&& (linecounter<5)) { if ((ptr->priority > 2) &&(ptr->priority <= 200)) { if (colcounter >= firstcol) { display_cursor(linecounter,((colcounter % 2)* 12)+1); display_printf(" %3d,%2d",ptr->priority,ptr->active_new); colcounter++; /* bei colcounter 0 neue Zeile */ if (colcounter % 2 == 0) linecounter++; } else colcounter ++; } ptr = ptr->next; } #endif #ifdef TEST_AVAILABLE_COUNTER display_printf("Screen 3"); display_cursor(2,1); display_printf("count %d",counter++); display_cursor(3,1); display_printf("Reset-Counter %d",resets); #endif break; case 3: display_cursor(1,1); #ifdef DISPLAY_SCREEN_RESETINFO /* Zeige den Grund fuer Resets an */ display_printf("MCUCSR - Register"); display_cursor(2,1); display_printf("PORF :%d WDRF :%d",binary(reset_flag,0),binary(reset_flag,3)); display_cursor(3,1); display_printf("EXTRF:%d JTRF :%d",binary(reset_flag,1),binary(reset_flag,4)); display_cursor(4,1); display_printf("BORF :%d",binary(reset_flag,2)); #else display_printf("Screen 4"); #endif break; case 4: /* Wird zur Ausgabe von Loggings verwendet. */ break; } #endif }
/*! * @brief Drehzahlregelung fuer die Motoren des c't-Bots * @author Benjamin Benz ([email protected] * @date 01.05.06 * Getrennte Drehzahlregelung fuer linken und rechten Motor sorgt fuer konstante Drehzahl und somit annaehernd * fuer Geradeauslauf * Feintuning von Kp, Ki, Kd verbessert die Genauigkeit und Schnelligkeit der Regelung * Querkopplung der Motoren verbessert Gleichlauf, beispielsweise x*(sensEncL - sensEncR) * in jeden Regler einbauen */ void speed_control(void){ int8 Kp=0; int8 Ki=0; int16 StellwertL=motor_left; /*!< Stellwert links*/ int16 StellwertR=motor_right; /*!< Stellwert rechts*/ volatile static int16 lastEncoderL=0; /*!< vorhergehender Wert von sensEncL */ volatile static int8 lastErrL=0; /*!< letzter Drehzahlfehler links */ volatile static int8 last2ErrL=0; /*!< vorletzter Drehzahlfehler links */ volatile static int16 lastEncoderR=0; /*!< vorhergehender Wert von sensEncR */ volatile static int8 lastErrR=0; /*!< letzter Drehzahlfehler rechts */ volatile static int8 last2ErrR=0; /*!< vorletzter Drehzahlfehler rechts */ int16 err=0; // aktuelle Abweichung vom Soll-Wert int16 encoderRate=0; // IST-Wert [Encoder-ticks/Aufruf] // Wir arbeiten mit verschiedenen PID-Parametern fuer verschiedene Geschwindigkeitsabschnitte if (encoderTargetRateL <= PID_LOW_RATE){ Kp=PID_LOW_Kp; Ki=PID_LOW_Ki; } else { if (encoderTargetRateL >= PID_HIGH_RATE) { Kp=PID_HIGH_Kp; Ki=PID_HIGH_Ki; } else { Kp=(PID_HIGH_Kp+PID_LOW_Kp)/2; Ki=(PID_HIGH_Ki+PID_LOW_Ki)/2; } } //Regler links if (encoderTargetRateL == 0){ StellwertL=0; err=0; lastErrL = 0; } else { encoderRate = sensEncL-lastEncoderL; // aktuelle Ist-Wert berechnen [Encoder-ticks/aufruf] lastEncoderL = sensEncL; // Anzahl der Encoderpulse merken fuer naechsten Aufruf merken err = encoderTargetRateL - encoderRate; // Regelabweichung links // Stellwert Berechnen StellwertL += (Kp * (err - lastErrL)) / 10; // P-Beitrag StellwertL += (Ki * (err + lastErrL)/2 ) /10; // I-Beitrag // StellwertL += Kd * (errL - 2 * lastErrL + last2ErrL); // D-Beitrag //berechneten Stellwert auf zulaessige Groesse begrenzen if (StellwertL > PWMMAX) StellwertL = PWMMAX; if (StellwertL < -PWMMAX) StellwertL = -PWMMAX; #ifdef DISPLAY_REGELUNG_AVAILABLE if (display_screen==DISPLAY_REGELUNG_AVAILABLE){ display_cursor(1,1); display_printf("%03d/%03d ",encoderRate,encoderTargetRateL); display_cursor(2,1); display_printf("e =%03d ",err); display_cursor(3,1); display_printf("L =%04d ", StellwertL); } #endif } last2ErrL = lastErrL; // alten N-2 Fehler merken lastErrL = err; // alten N-1 Fehler merken //Regler rechts if (encoderTargetRateR == 0){ StellwertR=0; err=0; lastErrR=0; } else { encoderRate = sensEncR-lastEncoderR; // aktuelle Ist-Wert berechnen [Encoder-ticks/aufruf] lastEncoderR = sensEncR; // Anzahl der Encoderpulse merken fuer naechsten Aufruf merken err = encoderTargetRateR - encoderRate; // Regelabweichung links // Stellwert Berechnen StellwertR += (Kp * (err - lastErrR))/10; // P-Beitrag StellwertR += (Ki * (err + lastErrR)/2)/10; // I-Beitrag // StellwertR += Kd * (err - 2 * lastErrR + last2ErrR); // D-Beitrag //berechneten Stellwert auf zulaessige Groesse begrenzen if (StellwertR > PWMMAX) StellwertR = PWMMAX; if (StellwertR < -PWMMAX) StellwertR = -PWMMAX; #ifdef DISPLAY_REGELUNG_AVAILABLE if (display_screen==DISPLAY_REGELUNG_AVAILABLE){ display_cursor(1,10); display_printf("%03d/%03d ",encoderRate,encoderTargetRateR); display_cursor(2,10); display_printf("e =%03d ",err); display_cursor(3,10); display_printf("R =%04d ", StellwertR); } #endif } last2ErrR = lastErrR; // alten N-2 Fehler merken lastErrR = err; // alten N-1 Fehler merken #ifdef DISPLAY_REGELUNG_AVAILABLE if (display_screen==DISPLAY_REGELUNG_AVAILABLE){ display_cursor(4,1); display_printf("Kp=%03d Ki=%03d", Kp, Ki); } #endif // Und nun den Wert setzen bot_motor(StellwertL,StellwertR); }
LONG do_menuloop(Wscreen *screen,register Menuhdr *mh,Button *initb, Menuhdr *pull, FUNC default_doclick ) /* the big loop that is given a pointer to an unopened menu header * to start the loop with. as long as there is at least 1 menu or a pull in the * group left it will continue looping. if its the bottom level for the * screen it will wait until group0 is empty also */ { Mouset mset; Mugroup mg; register Dlnode *next; register Wndo *w, *hitwndo; if(screen->glevel) enable_wrefresh(screen); get_mouset(&mset); push_group(screen,&mg); if((mg.retcode = startloop_open(&mg,mh,initb,pull)) < 0) goto error; find_wndo_cursor(screen); while(mg.num_menus) { if(icb.mcurs_up <= 0) display_cursor(); mac_wait_input(ANY_INPUT,ANY_INPUT&(~MMOVE)); hitwndo = NULL; /* no hits yet */ if(JSTHIT(KEYHIT)) { /* check for hidden menus that want keys */ for(mh = (Menuhdr *)(mg.menuhdrs.head); NULL != (next = ((Dlnode *)mh)->next); mh = (Menuhdr *)next ) { mh = TOSTRUCT(Menuhdr,node,mh); if(!(mh->flags & MENU_KEYSONHIDE)) continue; if(mh->mw != NULL || !(mh->ioflags & KEYHIT)) continue; /* ate key! reset mouse wait again */ if(do_doitfunc(screen,mh->domenu,mh)) goto reset_mouse; } } for(w = (Wndo *)(screen->wilist.head); next = ((Dlnode *)w)->next; w = (Wndo *)next ) { w = TOSTRUCT(Wndo,W_node,w); if(w->flags & WNDO_HIDDEN) continue; if(ptin_wndo(w,icb.sx,icb.sy)) { if(hitwndo == NULL) { hitwndo = w; load_wndo_iostate(w); } } if(ISINPUT(KEYHIT)) /* keys take priority */ { if(w->doit != NULL && (KEYHIT & w->ioflags)) { if(w != hitwndo) load_wndo_mouset(w); if(do_wndodoit(w)) goto reset_mouse; } } else if(hitwndo != NULL) /* w == hitwndo here */ { if(ISINPUT(w->ioflags)) /* wants and got non key */ { if(w->doit != NULL) { if(!do_wndodoit(w)) break; goto reset_mouse; } goto continue_big_loop; } break; } } if(default_doclick == NULL || !JSTHIT(ANY_CLICK)) continue; if(!do_doitfunc(screen,default_doclick,NULL)) continue; reset_mouse: /* this is here because a window may be closed etc if input is * processed */ find_wndo_cursor(screen); continue_big_loop: continue; } if(icb.mcurs_up > 0) undisplay_cursor(); error: pop_group(&mg); load_mouset(&mset); if(screen->glevel) { disable_wrefresh(screen); } return(mg.retcode); }
LONG do_reqloop(Wscreen *screen,register Menuhdr *mh,Button *initb, Menuhdr *pull, FUNC default_doclick) /***** call to open put up a requestor menu and input loop on the stack *** * will disable all input switching to other windows until it is removed * via mb_close_ok() etc and will always re-show the group if it is all hidden * by a feelme or optme it will restore the mouse settings to the ones * present on entry it will return the retcode from the last menu close * or group close (on the current group) or Err_abort if it was canceled * by a right click or space bar */ { Mouset mset; Mugroup mg; Menuwndo *mw; Menuwndo *hitwndo; register Dlnode *next; int altmouset; if(screen->glevel) enable_wrefresh(screen); get_mouset(&mset); push_group(screen,&mg); mg.flags |= MUG_REQUESTOR; if((mg.retcode = startloop_open(&mg,mh,initb,pull)) < 0) goto error; find_menu_cursor(&mg); while(mg.num_menus) { if(!(mg.non_hidden)) show_group(&mg); /* make sure something is visible */ if(icb.mcurs_up <= 0) display_cursor(); mac_wait_input(ANY_INPUT,ANY_INPUT&(~MMOVE)); hitwndo = NULL; /* no hits yet */ altmouset = 0; for(mh = (Menuhdr *)(mg.menuhdrs.head); NULL != (next = ((Dlnode *)mh)->next); mh = (Menuhdr *)next ) { mh = TOSTRUCT(Menuhdr,node,mh); if((mw = mh->mw) != NULL) { if(hitwndo == NULL) /* first one hit is it */ { if(cursin_menu(mh)) { hitwndo = mw; load_wndo_iostate(&(mw->w)); } } } if(ISINPUT(KEYHIT & mh->ioflags)) /* keys take priority */ { if(mw != NULL) { altmouset = 1; load_wndo_mouset(&(mw->w)); if(do_wndodoit(&mw->w)) goto reset_mouse; } else if(mh->flags & MENU_KEYSONHIDE) /* always get keys */ { if(do_doitfunc(screen,mh->domenu,mh)) goto reset_mouse; } } } if(hitwndo != NULL) { if(ISINPUT(hitwndo->w.ioflags & ~KEYHIT)) { if(!do_wndodoit(&hitwndo->w)) goto check_default_io; goto continue_big_loop; } } /* if we got to here we didn't hit a window or do a key !! * check for abort ! */ if((!hitwndo && JSTHIT(MBRIGHT)) || (JSTHIT(KEYHIT) && is_abortkey())) { do_doitfunc(screen,do_closegroup,&mg); break; } check_default_io: if( default_doclick != NULL && JSTHIT(ANY_CLICK) && do_doitfunc(screen,default_doclick,NULL)) { goto reset_mouse; } if(altmouset) goto reset_mouse; if(hitwndo == NULL) load_wndo_iostate(NULL); goto continue_big_loop; reset_mouse: find_menu_cursor(&mg); continue_big_loop: continue; } if(icb.mcurs_up > 0) undisplay_cursor(); error: pop_group(&mg); load_mouset(&mset); if(screen->glevel) { disable_wrefresh(screen); } return(mg.retcode); }